xref: /PHP-7.2/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 #include <php.h>
34 
35 static const char rcsid[] = "#(@) $Id$";
36 
37 
38 #define SIMPLESTRING_INCR 32
39 
40 /****h* ABOUT/simplestring
41  * NAME
42  *   simplestring
43  * AUTHOR
44  *   Dan Libby, aka danda  (dan@libby.com)
45  * CREATION DATE
46  *   06/2000
47  * HISTORY
48  *   $Log$
49  *   Revision 1.3  2002/08/22 01:25:50  sniper
50  *   kill some compile warnings
51  *
52  *   Revision 1.2  2002/07/05 04:43:53  danda
53  *   merged in updates from SF project.  bring php repository up to date with xmlrpc-epi version 0.51
54  *
55  *   Revision 1.4  2002/02/13 20:58:50  danda
56  *   patch to make source more windows friendly, contributed by Jeff Lawson
57  *
58  *   Revision 1.3  2001/09/29 21:58:05  danda
59  *   adding cvs log to history section
60  *
61  *   10/15/2000 -- danda -- adding robodoc documentation
62  * PORTABILITY
63  *   Coded on RedHat Linux 6.2.  Builds on Solaris x86.  Should build on just
64  *   about anything with minor mods.
65  * NOTES
66  *   This code was written primarily for xmlrpc, but has found some other uses.
67  *
68  *   simplestring is, as the name implies, a simple API for dealing with C strings.
69  *   Why would I write yet another string API?  Because I couldn't find any that were
70  *   a) free / GPL, b) simple/lightweight, c) fast, not doing unnecessary strlens all
71  *   over the place.  So.  It is simple, and it seems to work, and it is pretty fast.
72  *
73  *   Oh, and it is also binary safe, ie it can handle strings with embedded NULLs,
74  *   so long as the real length is passed in.
75  *
76  *   And the masses rejoiced.
77  *
78  * BUGS
79  *   there must be some.
80  ******/
81 
82 #include <stdlib.h>
83 #include <string.h>
84 #include <limits.h>
85 #include "simplestring.h"
86 
87 #define my_free(thing)  if(thing) {efree(thing); thing = 0;}
88 
89 /*----------------------**
90 * Begin String Functions *
91 *-----------------------*/
92 
93 /****f* FUNC/simplestring_init
94  * NAME
95  *   simplestring_init
96  * SYNOPSIS
97  *   void simplestring_init(simplestring* string)
98  * FUNCTION
99  *   initialize string
100  * INPUTS
101  *   string - pointer to a simplestring struct that will be initialized
102  * RESULT
103  *   void
104  * NOTES
105  * SEE ALSO
106  *   simplestring_free ()
107  *   simplestring_clear ()
108  * SOURCE
109  */
simplestring_init(simplestring * string)110 void simplestring_init(simplestring* string) {
111    memset(string, 0, sizeof(simplestring));
112 }
113 /******/
114 
simplestring_init_str(simplestring * string)115 static void simplestring_init_str(simplestring* string) {
116    string->str = (char*)emalloc(SIMPLESTRING_INCR);
117    if(string->str) {
118       string->str[0] = 0;
119       string->len = 0;
120       string->size = SIMPLESTRING_INCR;
121    }
122    else {
123       string->size = 0;
124    }
125 }
126 
127 /****f* FUNC/simplestring_clear
128  * NAME
129  *   simplestring_clear
130  * SYNOPSIS
131  *   void simplestring_clear(simplestring* string)
132  * FUNCTION
133  *   clears contents of a string
134  * INPUTS
135  *   string - the string value to clear
136  * RESULT
137  *   void
138  * NOTES
139  *   This function is very fast as it does not de-allocate any memory.
140  * SEE ALSO
141  *
142  * SOURCE
143  */
simplestring_clear(simplestring * string)144 void simplestring_clear(simplestring* string) {
145    if(string->str) {
146       string->str[0] = 0;
147    }
148    string->len = 0;
149 }
150 /******/
151 
152 /****f* FUNC/simplestring_free
153  * NAME
154  *   simplestring_free
155  * SYNOPSIS
156  *   void simplestring_free(simplestring* string)
157  * FUNCTION
158  *   frees contents of a string, if any. Does *not* free the simplestring struct itself.
159  * INPUTS
160  *   string - value containing string to be free'd
161  * RESULT
162  *   void
163  * NOTES
164  *   caller is responsible for allocating and freeing simplestring* struct itself.
165  * SEE ALSO
166  *   simplestring_init ()
167  * SOURCE
168  */
simplestring_free(simplestring * string)169 void simplestring_free(simplestring* string) {
170    if(string && string->str) {
171       my_free(string->str);
172       string->len = 0;
173    }
174 }
175 /******/
176 
177 #ifndef SIZE_MAX
178 #define SIZE_MAX ((size_t)-1)
179 #endif
180 /****f* FUNC/simplestring_addn
181  * NAME
182  *   simplestring_addn
183  * SYNOPSIS
184  *   void simplestring_addn(simplestring* string, const char* add, int add_len)
185  * FUNCTION
186  *   copies n characters from source to target string
187  * INPUTS
188  *   target  - target string
189  *   source  - source string
190  *   add_len - number of characters to copy
191  * RESULT
192  *   void
193  * NOTES
194  * SEE ALSO
195  *   simplestring_add ()
196  * SOURCE
197  */
simplestring_addn(simplestring * target,const char * source,size_t add_len)198 void simplestring_addn(simplestring* target, const char* source, size_t add_len) {
199    size_t newsize = target->size, incr = 0;
200    if(target && source) {
201       if(!target->str) {
202          simplestring_init_str(target);
203       }
204 
205       if((SIZE_MAX - add_len) < target->len || (SIZE_MAX - add_len - 1) < target->len) {
206     	  /* check for overflows, if there's a potential overflow do nothing */
207     	  return;
208       }
209 
210       if(target->len + add_len + 1 > target->size) {
211          /* newsize is current length + new length */
212          newsize = target->len + add_len + 1;
213          incr = target->size * 2;
214 
215          /* align to SIMPLESTRING_INCR increments */
216          if (incr) {
217             newsize = newsize - (newsize % incr) + incr;
218          }
219          if(newsize < (target->len + add_len + 1)) {
220         	 /* some kind of overflow happened */
221         	 return;
222          }
223          target->str = (char*)erealloc(target->str, newsize);
224 
225          target->size = target->str ? newsize : 0;
226       }
227 
228       if(target->str) {
229          if(add_len) {
230             memcpy(target->str + target->len, source, add_len);
231          }
232          target->len += add_len;
233          target->str[target->len] = 0; /* null terminate */
234       }
235    }
236 }
237 /******/
238 
239 /****f* FUNC/simplestring_add
240  * NAME
241  *   simplestring_add
242  * SYNOPSIS
243  *   void simplestring_add(simplestring* string, const char* add)
244  * FUNCTION
245  *   appends a string of unknown length from source to target
246  * INPUTS
247  *   target - the target string to append to
248  *   source - the source string of unknown length
249  * RESULT
250  *   void
251  * NOTES
252  * SEE ALSO
253  *   simplestring_addn ()
254  * SOURCE
255  */
simplestring_add(simplestring * target,const char * source)256 void simplestring_add(simplestring* target, const char* source) {
257    if(target && source) {
258       simplestring_addn(target, source, strlen(source));
259    }
260 }
261 /******/
262 
263 
264 /*----------------------
265 * End String Functions *
266 *--------------------**/
267