xref: /PHP-7.0/ext/xmlrpc/libxmlrpc/simplestring.c (revision 3b78cabc)
1 /*
2   This file is part of libXMLRPC - a C library for xml-encoded function calls.
3 
4   Author: Dan Libby (dan@libby.com)
5   Epinions.com may be contacted at feedback@epinions-inc.com
6 */
7 
8 /*
9   Copyright 2000 Epinions, Inc.
10 
11   Subject to the following 3 conditions, Epinions, Inc.  permits you, free
12   of charge, to (a) use, copy, distribute, modify, perform and display this
13   software and associated documentation files (the "Software"), and (b)
14   permit others to whom the Software is furnished to do so as well.
15 
16   1) The above copyright notice and this permission notice shall be included
17   without modification in all copies or substantial portions of the
18   Software.
19 
20   2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF
21   ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY
22   IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR
23   PURPOSE OR NONINFRINGEMENT.
24 
25   3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
26   SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
27   OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING
28   NEGLIGENCE), EVEN IF EPINIONS, INC.  IS AWARE OF THE POSSIBILITY OF SUCH
29   DAMAGES.
30 
31 */
32 
33 
34 static const char rcsid[] = "#(@) $Id$";
35 
36 
37 #define SIMPLESTRING_INCR 32
38 
39 /****h* ABOUT/simplestring
40  * NAME
41  *   simplestring
42  * AUTHOR
43  *   Dan Libby, aka danda  (dan@libby.com)
44  * CREATION DATE
45  *   06/2000
46  * HISTORY
47  *   $Log$
48  *   Revision 1.3  2002/08/22 01:25:50  sniper
49  *   kill some compile warnings
50  *
51  *   Revision 1.2  2002/07/05 04:43:53  danda
52  *   merged in updates from SF project.  bring php repository up to date with xmlrpc-epi version 0.51
53  *
54  *   Revision 1.4  2002/02/13 20:58:50  danda
55  *   patch to make source more windows friendly, contributed by Jeff Lawson
56  *
57  *   Revision 1.3  2001/09/29 21:58:05  danda
58  *   adding cvs log to history section
59  *
60  *   10/15/2000 -- danda -- adding robodoc documentation
61  * PORTABILITY
62  *   Coded on RedHat Linux 6.2.  Builds on Solaris x86.  Should build on just
63  *   about anything with minor mods.
64  * NOTES
65  *   This code was written primarily for xmlrpc, but has found some other uses.
66  *
67  *   simplestring is, as the name implies, a simple API for dealing with C strings.
68  *   Why would I write yet another string API?  Because I couldn't find any that were
69  *   a) free / GPL, b) simple/lightweight, c) fast, not doing unnecessary strlens all
70  *   over the place.  So.  It is simple, and it seems to work, and it is pretty fast.
71  *
72  *   Oh, and it is also binary safe, ie it can handle strings with embedded NULLs,
73  *   so long as the real length is passed in.
74  *
75  *   And the masses rejoiced.
76  *
77  * BUGS
78  *   there must be some.
79  ******/
80 
81 #include <stdlib.h>
82 #include <string.h>
83 #include <limits.h>
84 #include "simplestring.h"
85 
86 #define my_free(thing)  if(thing) {free(thing); thing = 0;}
87 
88 /*----------------------**
89 * Begin String Functions *
90 *-----------------------*/
91 
92 /****f* FUNC/simplestring_init
93  * NAME
94  *   simplestring_init
95  * SYNOPSIS
96  *   void simplestring_init(simplestring* string)
97  * FUNCTION
98  *   initialize string
99  * INPUTS
100  *   string - pointer to a simplestring struct that will be initialized
101  * RESULT
102  *   void
103  * NOTES
104  * SEE ALSO
105  *   simplestring_free ()
106  *   simplestring_clear ()
107  * SOURCE
108  */
simplestring_init(simplestring * string)109 void simplestring_init(simplestring* string) {
110    memset(string, 0, sizeof(simplestring));
111 }
112 /******/
113 
simplestring_init_str(simplestring * string)114 static void simplestring_init_str(simplestring* string) {
115    string->str = (char*)malloc(SIMPLESTRING_INCR);
116    if(string->str) {
117       string->str[0] = 0;
118       string->len = 0;
119       string->size = SIMPLESTRING_INCR;
120    }
121    else {
122       string->size = 0;
123    }
124 }
125 
126 /****f* FUNC/simplestring_clear
127  * NAME
128  *   simplestring_clear
129  * SYNOPSIS
130  *   void simplestring_clear(simplestring* string)
131  * FUNCTION
132  *   clears contents of a string
133  * INPUTS
134  *   string - the string value to clear
135  * RESULT
136  *   void
137  * NOTES
138  *   This function is very fast as it does not de-allocate any memory.
139  * SEE ALSO
140  *
141  * SOURCE
142  */
simplestring_clear(simplestring * string)143 void simplestring_clear(simplestring* string) {
144    if(string->str) {
145       string->str[0] = 0;
146    }
147    string->len = 0;
148 }
149 /******/
150 
151 /****f* FUNC/simplestring_free
152  * NAME
153  *   simplestring_free
154  * SYNOPSIS
155  *   void simplestring_free(simplestring* string)
156  * FUNCTION
157  *   frees contents of a string, if any. Does *not* free the simplestring struct itself.
158  * INPUTS
159  *   string - value containing string to be free'd
160  * RESULT
161  *   void
162  * NOTES
163  *   caller is responsible for allocating and freeing simplestring* struct itself.
164  * SEE ALSO
165  *   simplestring_init ()
166  * SOURCE
167  */
simplestring_free(simplestring * string)168 void simplestring_free(simplestring* string) {
169    if(string && string->str) {
170       my_free(string->str);
171       string->len = 0;
172    }
173 }
174 /******/
175 
176 #ifndef SIZE_MAX
177 #define SIZE_MAX ((size_t)-1)
178 #endif
179 /****f* FUNC/simplestring_addn
180  * NAME
181  *   simplestring_addn
182  * SYNOPSIS
183  *   void simplestring_addn(simplestring* string, const char* add, int add_len)
184  * FUNCTION
185  *   copies n characters from source to target string
186  * INPUTS
187  *   target  - target string
188  *   source  - source string
189  *   add_len - number of characters to copy
190  * RESULT
191  *   void
192  * NOTES
193  * SEE ALSO
194  *   simplestring_add ()
195  * SOURCE
196  */
simplestring_addn(simplestring * target,const char * source,size_t add_len)197 void simplestring_addn(simplestring* target, const char* source, size_t add_len) {
198    size_t newsize = target->size, incr = 0;
199    if(target && source) {
200       if(!target->str) {
201          simplestring_init_str(target);
202       }
203 
204       if((SIZE_MAX - add_len) < target->len || (SIZE_MAX - add_len - 1) < target->len) {
205     	  /* check for overflows, if there's a potential overflow do nothing */
206     	  return;
207       }
208 
209       if(target->len + add_len + 1 > target->size) {
210          /* newsize is current length + new length */
211          newsize = target->len + add_len + 1;
212          incr = target->size * 2;
213 
214          /* align to SIMPLESTRING_INCR increments */
215          if (incr) {
216             newsize = newsize - (newsize % incr) + incr;
217          }
218          if(newsize < (target->len + add_len + 1)) {
219         	 /* some kind of overflow happened */
220         	 return;
221          }
222          target->str = (char*)realloc(target->str, newsize);
223 
224          target->size = target->str ? newsize : 0;
225       }
226 
227       if(target->str) {
228          if(add_len) {
229             memcpy(target->str + target->len, source, add_len);
230          }
231          target->len += add_len;
232          target->str[target->len] = 0; /* null terminate */
233       }
234    }
235 }
236 /******/
237 
238 /****f* FUNC/simplestring_add
239  * NAME
240  *   simplestring_add
241  * SYNOPSIS
242  *   void simplestring_add(simplestring* string, const char* add)
243  * FUNCTION
244  *   appends a string of unknown length from source to target
245  * INPUTS
246  *   target - the target string to append to
247  *   source - the source string of unknown length
248  * RESULT
249  *   void
250  * NOTES
251  * SEE ALSO
252  *   simplestring_addn ()
253  * SOURCE
254  */
simplestring_add(simplestring * target,const char * source)255 void simplestring_add(simplestring* target, const char* source) {
256    if(target && source) {
257       simplestring_addn(target, source, strlen(source));
258    }
259 }
260 /******/
261 
262 
263 /*----------------------
264 * End String Functions *
265 *--------------------**/
266