Merge from Trond
[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= (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 *ptr, memcached_string_st *string, size_t initial_size)
36 {
37 memcached_return rc;
38
39 /* Saving malloc calls :) */
40 if (string)
41 memset(string, 0, sizeof(memcached_string_st));
42 else
43 {
44 string= ptr->call_calloc(ptr, 1, sizeof(memcached_string_st));
45
46 if (string == NULL)
47 return NULL;
48 string->is_allocated= true;
49 }
50 string->block_size= MEMCACHED_BLOCK_SIZE;
51 string->root= ptr;
52
53 rc= memcached_string_check(string, initial_size);
54 if (rc != MEMCACHED_SUCCESS)
55 {
56 ptr->call_free(ptr, string);
57 return NULL;
58 }
59
60 WATCHPOINT_ASSERT(string->string == string->end);
61
62 return string;
63 }
64
65 memcached_return memcached_string_append_character(memcached_string_st *string,
66 char character)
67 {
68 memcached_return rc;
69
70 rc= memcached_string_check(string, 1);
71
72 if (rc != MEMCACHED_SUCCESS)
73 return rc;
74
75 *string->end= character;
76 string->end++;
77
78 return MEMCACHED_SUCCESS;
79 }
80
81 memcached_return memcached_string_append(memcached_string_st *string,
82 const char *value, size_t length)
83 {
84 memcached_return rc;
85
86 rc= memcached_string_check(string, length);
87
88 if (rc != MEMCACHED_SUCCESS)
89 return rc;
90
91 WATCHPOINT_ASSERT(length <= string->current_size);
92 WATCHPOINT_ASSERT(string->string);
93 WATCHPOINT_ASSERT(string->end >= string->string);
94
95 memcpy(string->end, value, length);
96 string->end+= length;
97
98 return MEMCACHED_SUCCESS;
99 }
100
101 char *memcached_string_c_copy(memcached_string_st *string)
102 {
103 char *c_ptr;
104
105 if (memcached_string_length(string) == 0)
106 return NULL;
107
108 c_ptr= string->root->call_malloc(string->root, (memcached_string_length(string)+1) * sizeof(char));
109
110 if (c_ptr == NULL)
111 return NULL;
112
113 memcpy(c_ptr, memcached_string_value(string), memcached_string_length(string));
114 c_ptr[memcached_string_length(string)]= 0;
115
116 return c_ptr;
117 }
118
119 memcached_return memcached_string_reset(memcached_string_st *string)
120 {
121 string->end= string->string;
122
123 return MEMCACHED_SUCCESS;
124 }
125
126 void memcached_string_free(memcached_string_st *ptr)
127 {
128 if (ptr == NULL)
129 return;
130
131 if (ptr->string)
132 ptr->root->call_free(ptr->root, ptr->string);
133
134 if (ptr->is_allocated)
135 ptr->root->call_free(ptr->root, ptr);
136 else
137 memset(ptr, 0, sizeof(memcached_string_st));
138 }