1
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
5
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are
11
* * Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
14
* * Redistributions in binary form must reproduce the above
15
* copyright notice, this list of conditions and the following disclaimer
16
* in the documentation and/or other materials provided with the
19
* * The names of its contributors may not be used to endorse or
20
* promote products derived from this software without specific prior
23
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
#include <libgearman/common.h>
44
#define GEARMAN_BLOCK_SIZE 1024*4
46
inline static gearman_return_t _string_check(gearman_vector_st *string, const size_t need)
49
return GEARMAN_INVALID_ARGUMENT;
51
if (need && need > size_t(string->current_size - size_t(string->end - string->string)))
53
size_t current_offset= size_t(string->end - string->string);
58
/* This is the block multiplier. To keep it larger and surive division errors we must round it up */
59
adjust= (need - size_t(string->current_size - size_t(string->end - string->string))) / GEARMAN_BLOCK_SIZE;
62
new_size= sizeof(char) * size_t((adjust * GEARMAN_BLOCK_SIZE) + string->current_size);
63
/* Test for overflow */
66
return GEARMAN_MEMORY_ALLOCATION_FAILURE;
69
new_value= static_cast<char *>(realloc(string->string, new_size));
70
if (new_value == NULL)
72
return GEARMAN_MEMORY_ALLOCATION_FAILURE;
75
string->string= new_value;
76
string->end= string->string + current_offset;
78
string->current_size+= (GEARMAN_BLOCK_SIZE * adjust);
81
return GEARMAN_SUCCESS;
84
static inline void _init_string(gearman_vector_st *self)
86
self->current_size= 0;
87
self->end= self->string= NULL;
90
gearman_vector_st *gearman_string_create(gearman_vector_st *self, const char *str, size_t initial_size)
95
self= gearman_string_create(self, initial_size);
100
if (gearman_failed(gearman_string_append(self, str, initial_size)))
102
gearman_string_free(self);
109
gearman_vector_st *gearman_string_create(gearman_vector_st *self, size_t initial_size)
111
/* Saving malloc calls :) */
114
gearman_set_allocated(self, false);
118
self= static_cast<gearman_vector_st *>(malloc(sizeof(gearman_vector_st)));
125
gearman_set_allocated(self, true);
130
if (gearman_failed(_string_check(self, initial_size)))
132
if (gearman_is_allocated(self))
146
gearman_vector_st *gearman_string_clone(const gearman_vector_st *self)
151
gearman_vector_st *clone= gearman_string_create(NULL, gearman_string_length(self));
155
if (gearman_string_length(self))
157
if (gearman_failed(gearman_string_append(clone, gearman_string_value(self), gearman_string_length(self))))
159
gearman_string_free(clone);
167
gearman_return_t gearman_string_append_character(gearman_vector_st *string, char character)
172
if (gearman_failed(rc= _string_check(string, 1 +1))) // Null terminate
177
*string->end= character;
181
return GEARMAN_SUCCESS;
184
gearman_return_t gearman_string_append(gearman_vector_st *string,
185
const char *value, size_t length)
189
if (gearman_failed(rc= _string_check(string, length +1)))
194
memcpy(string->end, value, length);
195
string->end+= length;
196
*string->end= 0; // Add a NULL
198
return GEARMAN_SUCCESS;
201
char *gearman_string_c_copy(gearman_vector_st *string)
205
if (gearman_string_length(string) == 0)
208
c_ptr= static_cast<char *>(malloc((gearman_string_length(string) +1) * sizeof(char)));
213
memcpy(c_ptr, gearman_string_value(string), gearman_string_length(string));
214
c_ptr[gearman_string_length(string)]= 0;
219
void gearman_string_reset(gearman_vector_st *string)
222
string->end= string->string;
225
void gearman_string_free(gearman_vector_st *ptr)
235
if (ptr->options.is_allocated)
241
gearman_return_t gearman_string_check(gearman_vector_st *string, size_t need)
243
return _string_check(string, need);
246
size_t gearman_string_length(const gearman_vector_st *self)
251
return size_t(self->end - self->string);
254
const char *gearman_string_value(const gearman_vector_st *self)
262
gearman_string_t gearman_string(const gearman_vector_st *self)
265
gearman_string_t passable= { gearman_string_value(self), gearman_string_length(self) };
269
gearman_string_t gearman_string_take_string(gearman_vector_st *self)
272
gearman_string_t passable= gearman_string(self);