0911b409ea47cb8f3f5734137700b1b41e68fcc6
[m6w6/libmemcached] / libmemcached / memcached_string.c
1 #include "common.h"
2
3 inline static memcached_return _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= (size_t) (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 new_value= string->root->call_realloc(string->root, string->string, new_size);
22
23 if (new_value == NULL)
24 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
25
26 string->string= new_value;
27 string->end= string->string + current_offset;
28
29 string->current_size+= (string->block_size * adjust);
30 }
31
32 return MEMCACHED_SUCCESS;
33 }
34
35 memcached_string_st *memcached_string_create(memcached_st *memc, memcached_string_st *string, size_t initial_size)
36 {
37 memcached_return rc;
38
39 /* Saving malloc calls :) */
40 if (string)
41 {
42 WATCHPOINT_ASSERT(memc->options.is_safe && string->options.is_initialized == false);
43
44 memset(string, 0, sizeof(memcached_string_st));
45 }
46 else
47 {
48 string= memc->call_calloc(memc, 1, sizeof(memcached_string_st));
49
50 if (string == NULL)
51 {
52 return NULL;
53 }
54
55 string->options.is_allocated= true;
56 }
57 string->block_size= MEMCACHED_BLOCK_SIZE;
58 string->root= memc;
59
60 rc= _string_check(string, initial_size);
61 if (rc != MEMCACHED_SUCCESS)
62 {
63 memc->call_free(memc, string);
64 return NULL;
65 }
66
67 string->options.is_initialized= true;
68
69 WATCHPOINT_ASSERT(string->string == string->end);
70
71 return string;
72 }
73
74 memcached_return memcached_string_append_character(memcached_string_st *string,
75 char character)
76 {
77 memcached_return rc;
78
79 rc= _string_check(string, 1);
80
81 if (rc != MEMCACHED_SUCCESS)
82 return rc;
83
84 *string->end= character;
85 string->end++;
86
87 return MEMCACHED_SUCCESS;
88 }
89
90 memcached_return memcached_string_append(memcached_string_st *string,
91 const char *value, size_t length)
92 {
93 memcached_return rc;
94
95 rc= _string_check(string, length);
96
97 if (rc != MEMCACHED_SUCCESS)
98 return rc;
99
100 WATCHPOINT_ASSERT(length <= string->current_size);
101 WATCHPOINT_ASSERT(string->string);
102 WATCHPOINT_ASSERT(string->end >= string->string);
103
104 memcpy(string->end, value, length);
105 string->end+= length;
106
107 return MEMCACHED_SUCCESS;
108 }
109
110 char *memcached_string_c_copy(memcached_string_st *string)
111 {
112 char *c_ptr;
113
114 if (memcached_string_length(string) == 0)
115 return NULL;
116
117 c_ptr= string->root->call_malloc(string->root, (memcached_string_length(string)+1) * sizeof(char));
118
119 if (c_ptr == NULL)
120 return NULL;
121
122 memcpy(c_ptr, memcached_string_value(string), memcached_string_length(string));
123 c_ptr[memcached_string_length(string)]= 0;
124
125 return c_ptr;
126 }
127
128 memcached_return memcached_string_reset(memcached_string_st *string)
129 {
130 string->end= string->string;
131
132 return MEMCACHED_SUCCESS;
133 }
134
135 void memcached_string_free(memcached_string_st *ptr)
136 {
137 if (ptr == NULL)
138 return;
139
140 if (ptr->string)
141 {
142 ptr->root->call_free(ptr->root, ptr->string);
143 }
144
145 if (memcached_is_allocated(ptr))
146 {
147 ptr->root->call_free(ptr->root, ptr);
148 }
149 else
150 {
151 ptr->options.is_initialized= false;
152 memset(ptr, 0, sizeof(memcached_string_st));
153 }
154 }
155
156 memcached_return memcached_string_check(memcached_string_st *string, size_t need)
157 {
158 return _string_check(string, need);
159 }
160