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 
init_dynamic_string(DYNAMIC_STRING * str,const char * init_str,size_t init_alloc,size_t alloc_increment)25 my_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 
dynstr_set(DYNAMIC_STRING * str,const char * init_str)50 my_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 
dynstr_realloc(DYNAMIC_STRING * str,size_t additional_size)75 my_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 
dynstr_append(DYNAMIC_STRING * str,const char * append)91 my_bool dynstr_append(DYNAMIC_STRING *str, const char *append)
92 {
93   return dynstr_append_mem(str,append,(uint) strlen(append));
94 }
95 
96 
dynstr_append_mem(DYNAMIC_STRING * str,const char * append,size_t length)97 my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append,
98 			  size_t length)
99 {
100   char *new_ptr;
101   if (str->length+length >= str->max_length)
102   {
103     size_t new_length=(str->length+length+str->alloc_increment)/
104       str->alloc_increment;
105     new_length*=str->alloc_increment;
106     if (!(new_ptr=(char*) my_realloc(str->str,new_length,MYF(MY_WME))))
107       return TRUE;
108     str->str=new_ptr;
109     str->max_length=new_length;
110   }
111   memcpy(str->str + str->length,append,length);
112   str->length+=length;
113   str->str[str->length]=0;			/* Safety for C programs */
114   return FALSE;
115 }
116 
117 
dynstr_trunc(DYNAMIC_STRING * str,size_t n)118 my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n)
119 {
120   str->length-=n;
121   str->str[str->length]= '\0';
122   return FALSE;
123 }
124 
125 /*
126   Concatenates any number of strings, escapes any OS quote in the result then
127   surround the whole affair in another set of quotes which is finally appended
128   to specified DYNAMIC_STRING.  This function is especially useful when
129   building strings to be executed with the system() function.
130 
131   @param str Dynamic String which will have addtional strings appended.
132   @param append String to be appended.
133   @param ... Optional. Additional string(s) to be appended.
134 
135   @note The final argument in the list must be NullS even if no additional
136   options are passed.
137 
138   @return True = Success.
139 */
140 
dynstr_append_os_quoted(DYNAMIC_STRING * str,const char * append,...)141 my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...)
142 {
143 #ifdef __WIN__
144   const char *quote_str= "\"";
145   const uint  quote_len= 1;
146 #else
147   const char *quote_str= "\'";
148   const uint  quote_len= 1;
149 #endif /* __WIN__ */
150   my_bool ret= TRUE;
151   va_list dirty_text;
152 
153   ret&= dynstr_append_mem(str, quote_str, quote_len); /* Leading quote */
154   va_start(dirty_text, append);
155   while (append != NullS)
156   {
157     const char  *cur_pos= append;
158     const char *next_pos= cur_pos;
159 
160     /* Search for quote in each string and replace with escaped quote */
161     while(*(next_pos= strcend(cur_pos, quote_str[0])) != '\0')
162     {
163       ret&= dynstr_append_mem(str, cur_pos, (uint) (next_pos - cur_pos));
164       ret&= dynstr_append_mem(str ,"\\", 1);
165       ret&= dynstr_append_mem(str, quote_str, quote_len);
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_len); /* Trailing quote */
173 
174   return ret;
175 }
176 
177 
dynstr_free(DYNAMIC_STRING * str)178 void dynstr_free(DYNAMIC_STRING *str)
179 {
180   my_free(str->str);
181   str->str= NULL;
182 }
183