1/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15
16/*
17 Code for handling strings with can grow dynamicly.
18 Copyright Monty Program KB.
19 By monty.
20*/
21
22#include "mysys_priv.h"
23#include <m_string.h>
24
25my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str,
26 size_t init_alloc, size_t alloc_increment)
27{
28 size_t length;
29 DBUG_ENTER("init_dynamic_string");
30
31 if (!alloc_increment)
32 alloc_increment=128;
33 length=1;
34 if (init_str && (length= strlen(init_str)+1) < init_alloc)
35 init_alloc=((length+alloc_increment-1)/alloc_increment)*alloc_increment;
36 if (!init_alloc)
37 init_alloc=alloc_increment;
38
39 if (!(str->str=(char*) my_malloc(init_alloc,MYF(MY_WME))))
40 DBUG_RETURN(TRUE);
41 str->length=length-1;
42 if (init_str)
43 memcpy(str->str,init_str,length);
44 str->max_length=init_alloc;
45 str->alloc_increment=alloc_increment;
46 DBUG_RETURN(FALSE);
47}
48
49
50my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str)
51{
52 uint length=0;
53 DBUG_ENTER("dynstr_set");
54
55 if (init_str && (length= (uint) strlen(init_str)+1) > str->max_length)
56 {
57 str->max_length=((length+str->alloc_increment-1)/str->alloc_increment)*
58 str->alloc_increment;
59 if (!str->max_length)
60 str->max_length=str->alloc_increment;
61 if (!(str->str=(char*) my_realloc(str->str,str->max_length,MYF(MY_WME))))
62 DBUG_RETURN(TRUE);
63 }
64 if (init_str)
65 {
66 str->length=length-1;
67 memcpy(str->str,init_str,length);
68 }
69 else
70 str->length=0;
71 DBUG_RETURN(FALSE);
72}
73
74
75my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size)
76{
77 DBUG_ENTER("dynstr_realloc");
78
79 if (!additional_size) DBUG_RETURN(FALSE);
80 if (str->length + additional_size > str->max_length)
81 {
82 str->max_length=((str->length + additional_size+str->alloc_increment-1)/
83 str->alloc_increment)*str->alloc_increment;
84 if (!(str->str=(char*) my_realloc(str->str,str->max_length,MYF(MY_WME))))
85 DBUG_RETURN(TRUE);
86 }
87 DBUG_RETURN(FALSE);
88}
89
90
91my_bool dynstr_append(DYNAMIC_STRING *str, const char *append)
92{
93 return dynstr_append_mem(str,append,(uint) strlen(append));
94}
95
96
97my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append,
98 size_t length)
99{
100 char *new_ptr;
101 DBUG_ENTER("dynstr_append_mem");
102 if (str->length+length >= str->max_length)
103 {
104 size_t new_length=(str->length+length+str->alloc_increment)/
105 str->alloc_increment;
106 new_length*=str->alloc_increment;
107 if (!(new_ptr=(char*) my_realloc(str->str,new_length,MYF(MY_WME))))
108 DBUG_RETURN(TRUE);
109 str->str=new_ptr;
110 str->max_length=new_length;
111 }
112 memcpy(str->str + str->length,append,length);
113 str->length+=length;
114 str->str[str->length]=0; /* Safety for C programs */
115 DBUG_RETURN(FALSE);
116}
117
118
119my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n)
120{
121 str->length-=n;
122 str->str[str->length]= '\0';
123 return FALSE;
124}
125
126/*
127 Concatenates any number of strings, escapes any OS quote in the result then
128 surround the whole affair in another set of quotes which is finally appended
129 to specified DYNAMIC_STRING. This function is especially useful when
130 building strings to be executed with the system() function.
131
132 @param str Dynamic String which will have addtional strings appended.
133 @param append String to be appended.
134 @param ... Optional. Additional string(s) to be appended.
135
136 @note The final argument in the list must be NullS even if no additional
137 options are passed.
138
139 @return True = Success.
140*/
141
142my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...)
143{
144#ifdef __WIN__
145 LEX_CSTRING quote= { C_STRING_WITH_LEN("\"") };
146 LEX_CSTRING replace= { C_STRING_WITH_LEN("\\\"") };
147#else
148 LEX_CSTRING quote= { C_STRING_WITH_LEN("\'") };
149 LEX_CSTRING replace= { C_STRING_WITH_LEN("'\"'\"'") };
150#endif /* __WIN__ */
151 my_bool ret= TRUE;
152 va_list dirty_text;
153
154 ret&= dynstr_append_mem(str, quote.str, quote.length); /* Leading quote */
155 va_start(dirty_text, append);
156 while (append != NullS)
157 {
158 const char *cur_pos= append;
159 const char *next_pos= cur_pos;
160
161 /* Search for quote in each string and replace with escaped quote */
162 while(*(next_pos= strcend(cur_pos, quote.str[0])) != '\0')
163 {
164 ret&= dynstr_append_mem(str, cur_pos, (uint) (next_pos - cur_pos));
165 ret&= dynstr_append_mem(str, replace.str, replace.length);
166 cur_pos= next_pos + 1;
167 }
168 ret&= dynstr_append_mem(str, cur_pos, (uint) (next_pos - cur_pos));
169 append= va_arg(dirty_text, char *);
170 }
171 va_end(dirty_text);
172 ret&= dynstr_append_mem(str, quote.str, quote.length); /* Trailing quote */
173
174 return ret;
175}
176
177my_bool dynstr_append_quoted(DYNAMIC_STRING *str,
178 const char *append, size_t len,
179 char quote)
180{
181 size_t additional= (str->alloc_increment ? str->alloc_increment : 10);
182 size_t lim= additional;
183 size_t i;
184 if (dynstr_realloc(str, len + additional + 2))
185 return TRUE;
186 str->str[str->length++]= quote;
187 for (i= 0; i < len; i++)
188 {
189 register char c= append[i];
190 if (c == quote || c == '\\')
191 {
192 if (!lim)
193 {
194 if (dynstr_realloc(str, additional))
195 return TRUE;
196 lim= additional;
197 }
198 lim--;
199 str->str[str->length++]= '\\';
200 }
201 str->str[str->length++]= c;
202 }
203 str->str[str->length++]= quote;
204 return FALSE;
205}
206
207
208void dynstr_free(DYNAMIC_STRING *str)
209{
210 if (str->str) /* Safety to allow double free */
211 my_free(str->str);
212 str->str= NULL;
213}
214
215
216/* Give over the control of the dynamic string to caller */
217
218void dynstr_reassociate(DYNAMIC_STRING *str, char **ptr, size_t *length,
219 size_t *alloc_length)
220{
221 *ptr= str->str;
222 *length= str->length;
223 *alloc_length= str->max_length;
224 str->str=0;
225}
226