Merge in additional documentation.
[awesomized/libmemcached] / libmemcached / string.c
1 /* LibMemcached
2 * Copyright (C) 2006-2009 Brian Aker
3 * All rights reserved.
4 *
5 * Use and distribution licensed under the BSD license. See
6 * the COPYING file in the parent directory for full text.
7 *
8 * Summary: String structure used for libmemcached.
9 *
10 */
11
12 #include "common.h"
13
14 inline static memcached_return_t _string_check(memcached_string_st *string, size_t need)
15 {
16 if (need && need > (size_t)(string->current_size - (size_t)(string->end - string->string)))
17 {
18 size_t current_offset= (size_t) (string->end - string->string);
19 char *new_value;
20 size_t adjust;
21 size_t new_size;
22
23 /* This is the block multiplier. To keep it larger and surive division errors we must round it up */
24 adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / MEMCACHED_BLOCK_SIZE;
25 adjust++;
26
27 new_size= sizeof(char) * (size_t)((adjust * MEMCACHED_BLOCK_SIZE) + string->current_size);
28 /* Test for overflow */
29 if (new_size < need)
30 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
31
32 new_value= libmemcached_realloc(string->root, string->string, new_size);
33
34 if (new_value == NULL)
35 {
36 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
37 }
38
39 string->string= new_value;
40 string->end= string->string + current_offset;
41
42 string->current_size+= (MEMCACHED_BLOCK_SIZE * adjust);
43 }
44
45 return MEMCACHED_SUCCESS;
46 }
47
48 static inline void _init_string(memcached_string_st *self)
49 {
50 self->current_size= 0;
51 self->end= self->string= NULL;
52 }
53
54 memcached_string_st *memcached_string_create(const memcached_st *memc, memcached_string_st *self, size_t initial_size)
55 {
56 memcached_return_t rc;
57
58 WATCHPOINT_ASSERT(memc);
59
60 /* Saving malloc calls :) */
61 if (self)
62 {
63 WATCHPOINT_ASSERT(self->options.is_initialized == false);
64
65 self->options.is_allocated= false;
66 }
67 else
68 {
69 self= libmemcached_malloc(memc, sizeof(memcached_string_st));
70
71 if (self == NULL)
72 {
73 return NULL;
74 }
75
76 self->options.is_allocated= true;
77 }
78 self->root= (memcached_st *)memc;
79
80 _init_string(self);
81
82 rc= _string_check(self, initial_size);
83 if (rc != MEMCACHED_SUCCESS)
84 {
85 if (rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
86 {
87 memcached_set_errno(self->root, errno, NULL);
88 }
89 libmemcached_free(memc, self);
90
91 return NULL;
92 }
93
94 self->options.is_initialized= true;
95
96 WATCHPOINT_ASSERT(self->string == self->end);
97
98 return self;
99 }
100
101 memcached_return_t memcached_string_append_character(memcached_string_st *string,
102 char character)
103 {
104 memcached_return_t rc;
105
106 rc= _string_check(string, 1);
107
108 if (rc != MEMCACHED_SUCCESS)
109 {
110 return rc;
111 }
112
113 *string->end= character;
114 string->end++;
115
116 return MEMCACHED_SUCCESS;
117 }
118
119 memcached_return_t memcached_string_append(memcached_string_st *string,
120 const char *value, size_t length)
121 {
122 memcached_return_t rc;
123
124 rc= _string_check(string, length);
125
126 if (rc != MEMCACHED_SUCCESS)
127 {
128 return rc;
129 }
130
131 WATCHPOINT_ASSERT(length <= string->current_size);
132 WATCHPOINT_ASSERT(string->string);
133 WATCHPOINT_ASSERT(string->end >= string->string);
134
135 memcpy(string->end, value, length);
136 string->end+= length;
137
138 return MEMCACHED_SUCCESS;
139 }
140
141 char *memcached_string_c_copy(memcached_string_st *string)
142 {
143 char *c_ptr;
144
145 if (memcached_string_length(string) == 0)
146 return NULL;
147
148 c_ptr= libmemcached_malloc(string->root, (memcached_string_length(string)+1) * sizeof(char));
149
150 if (c_ptr == NULL)
151 return NULL;
152
153 memcpy(c_ptr, memcached_string_value(string), memcached_string_length(string));
154 c_ptr[memcached_string_length(string)]= 0;
155
156 return c_ptr;
157 }
158
159 memcached_return_t memcached_string_reset(memcached_string_st *string)
160 {
161 string->end= string->string;
162
163 return MEMCACHED_SUCCESS;
164 }
165
166 void memcached_string_free(memcached_string_st *ptr)
167 {
168 if (ptr == NULL)
169 return;
170
171 if (ptr->string)
172 {
173 libmemcached_free(ptr->root, ptr->string);
174 }
175
176 if (memcached_is_allocated(ptr))
177 {
178 libmemcached_free(ptr->root, ptr);
179 }
180 else
181 {
182 ptr->options.is_initialized= false;
183 }
184 }
185
186 memcached_return_t memcached_string_check(memcached_string_st *string, size_t need)
187 {
188 return _string_check(string, need);
189 }
190
191 size_t memcached_string_length(const memcached_string_st *self)
192 {
193 return (size_t)(self->end - self->string);
194 }
195
196 size_t memcached_string_size(const memcached_string_st *self)
197 {
198 return self->current_size;
199 }
200
201 const char *memcached_string_value(const memcached_string_st *self)
202 {
203 return self->string;
204 }
205
206 char *memcached_string_value_mutable(const memcached_string_st *self)
207 {
208 return self->string;
209 }
210
211 void memcached_string_set_length(memcached_string_st *self, size_t length)
212 {
213 self->end= self->string + length;
214 }