New version update
[m6w6/libmemcached] / libmemcached / memcached_string.c
1 #include "common.h"
2
3 memcached_return memcached_string_check(memcached_string_st *string, size_t need)
4 {
5 if (need && need > (size_t)(string->current_size - (size_t)(string->end - string->string)))
6 {
7 size_t current_offset= string->end - string->string;
8 char *new_value;
9 size_t adjust;
10 size_t new_size;
11
12 /* This is the block multiplier. To keep it larger and surive division errors we must round it up */
13 adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / string->block_size;
14 adjust++;
15
16 new_size= sizeof(char) * (size_t)((adjust * string->block_size) + string->current_size);
17 /* Test for overflow */
18 if (new_size < need)
19 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
20
21 if (string->root->call_realloc)
22 new_value= (char *)string->root->call_realloc(string->root, string->string, new_size);
23 else
24 new_value= (char *)realloc(string->string, new_size);
25
26 if (new_value == NULL)
27 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
28
29 string->string= new_value;
30 string->end= string->string + current_offset;
31
32 string->current_size+= (string->block_size * adjust);
33 }
34
35 return MEMCACHED_SUCCESS;
36 }
37
38 memcached_string_st *memcached_string_create(memcached_st *ptr, memcached_string_st *string, size_t initial_size)
39 {
40 memcached_return rc;
41
42 /* Saving malloc calls :) */
43 if (string)
44 {
45 memset(string, 0, sizeof(memcached_string_st));
46 string->is_allocated= MEMCACHED_NOT_ALLOCATED;
47 }
48 else
49 {
50 if (ptr->call_malloc)
51 string= (memcached_string_st *)ptr->call_malloc(ptr, sizeof(memcached_string_st));
52 else
53 string= (memcached_string_st *)malloc(sizeof(memcached_string_st));
54
55 if (string == NULL)
56 return NULL;
57 memset(string, 0, sizeof(memcached_string_st));
58 string->is_allocated= MEMCACHED_ALLOCATED;
59 }
60 string->block_size= MEMCACHED_BLOCK_SIZE;
61 string->root= ptr;
62
63 rc= memcached_string_check(string, initial_size);
64 if (rc != MEMCACHED_SUCCESS)
65 {
66 if (ptr->call_free)
67 ptr->call_free(ptr, string);
68 else
69 free(string);
70
71 return NULL;
72 }
73
74 WATCHPOINT_ASSERT(string->string == string->end);
75
76 return string;
77 }
78
79 memcached_return memcached_string_append_character(memcached_string_st *string,
80 char character)
81 {
82 memcached_return rc;
83
84 WATCHPOINT_ASSERT(string->is_allocated != MEMCACHED_USED);
85
86 rc= memcached_string_check(string, 1);
87
88 if (rc != MEMCACHED_SUCCESS)
89 return rc;
90
91 *string->end= ' ';
92 string->end++;
93
94 return MEMCACHED_SUCCESS;
95 }
96
97 memcached_return memcached_string_append(memcached_string_st *string,
98 char *value, size_t length)
99 {
100 memcached_return rc;
101
102 WATCHPOINT_ASSERT(string->is_allocated != MEMCACHED_USED);
103
104 rc= memcached_string_check(string, length);
105
106 if (rc != MEMCACHED_SUCCESS)
107 return rc;
108
109 WATCHPOINT_ASSERT(length <= string->current_size);
110 WATCHPOINT_ASSERT(string->string);
111 WATCHPOINT_ASSERT(string->end >= string->string);
112
113 memcpy(string->end, value, length);
114 string->end+= length;
115
116 return MEMCACHED_SUCCESS;
117 }
118
119 size_t memcached_string_backspace(memcached_string_st *string, size_t remove)
120 {
121 WATCHPOINT_ASSERT(string->is_allocated != MEMCACHED_USED);
122
123 if (string->end - string->string > remove)
124 {
125 size_t difference;
126
127 difference= string->end - string->string;
128 string->end= string->string;
129
130 return difference;
131 }
132 string->end-= remove;
133
134 return remove;
135 }
136
137 char *memcached_string_c_copy(memcached_string_st *string)
138 {
139 char *c_ptr;
140
141 WATCHPOINT_ASSERT(string->is_allocated != MEMCACHED_USED);
142
143 if (memcached_string_length(string) == 0)
144 return NULL;
145
146 if (string->root->call_malloc)
147 c_ptr= (char *)string->root->call_malloc(string->root, (memcached_string_length(string)+1) * sizeof(char));
148 else
149 c_ptr= (char *)malloc((memcached_string_length(string)+1) * sizeof(char));
150
151 if (c_ptr == NULL)
152 return NULL;
153
154 memcpy(c_ptr, memcached_string_value(string), memcached_string_length(string));
155 c_ptr[memcached_string_length(string)]= 0;
156
157 return c_ptr;
158 }
159
160 memcached_return memcached_string_reset(memcached_string_st *string)
161 {
162 WATCHPOINT_ASSERT(string->is_allocated != MEMCACHED_USED);
163 string->end= string->string;
164
165 return MEMCACHED_SUCCESS;
166 }
167
168 void memcached_string_free(memcached_string_st *ptr)
169 {
170 if (ptr == NULL)
171 return;
172
173 if (ptr->string)
174 {
175 if (ptr->root->call_free)
176 ptr->root->call_free(ptr->root, ptr->string);
177 else
178 free(ptr->string);
179 }
180
181 if (ptr->is_allocated == MEMCACHED_ALLOCATED)
182 {
183 if (ptr->root->call_free)
184 ptr->root->call_free(ptr->root, ptr);
185 else
186 free(ptr);
187 }
188 else
189 ptr->is_allocated= MEMCACHED_USED;
190 }