]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxSWIG/SWIG/sstring.cxx
Since I have made several changes to SWIG over the years to accomodate
[wxWidgets.git] / wxPython / wxSWIG / SWIG / sstring.cxx
1 /*******************************************************************************
2 * Simplified Wrapper and Interface Generator (SWIG)
3 *
4 * Author : David Beazley
5 *
6 * Department of Computer Science
7 * University of Chicago
8 * 1100 E 58th Street
9 * Chicago, IL 60637
10 * beazley@cs.uchicago.edu
11 *
12 * Please read the file LICENSE for the copyright and terms by which SWIG
13 * can be used and distributed.
14 *******************************************************************************/
15
16 #include "internal.h"
17 #include <ctype.h>
18
19 //-----------------------------------------------------------------------
20 // char *copy_string(char *str)
21 //
22 // Makes a copy of string str. Returns a pointer to it.
23 //-----------------------------------------------------------------------
24
25 char *copy_string(char *str) {
26 char *res = 0;
27 if (str) {
28 res = new char[strlen(str)+1];
29 strcpy(res,str);
30 }
31 return res;
32 }
33
34 //-----------------------------------------------------------------------
35 // void format_string(char *str)
36 //
37 // Replace all of the escape sequences in the string str. It is
38 // assumed that the new string is smaller than the original!
39 //-----------------------------------------------------------------------
40
41 void format_string(char *str) {
42 char *newstr, *c,*c1;
43 int state;
44 if (!str) return;
45 newstr = copy_string(str);
46 c = newstr;
47 c1 = str;
48 state = 0;
49 while (*c) {
50 switch(state) {
51 case 0:
52 if (*c == '\\')
53 state = 1;
54 else {
55 *(c1++) = *c;
56 state = 0;
57 }
58 break;
59 case 1:
60 // We're in a simple escape sequence figure out what to do
61 switch(*c) {
62 case 'n':
63 *(c1++) = '\n';
64 break;
65 case 'f':
66 *(c1++) = '\f';
67 break;
68 case 'r':
69 *(c1++) = '\r';
70 break;
71 case 't':
72 *(c1++) = '\t';
73 break;
74 case '\\':
75 *(c1++) = '\\';
76 break;
77 case '\"':
78 *(c1++) = '\"';
79 break;
80 case '\'':
81 *(c1++) = '\'';
82 break;
83 default:
84 *(c1++) = '\\';
85 *(c1++) = *c;
86 }
87 state = 0;
88 break;
89 default:
90 *(c1++) = *c;
91 state = 0;
92 }
93 c++;
94 }
95 *c1 = 0;
96 delete newstr;
97 }
98
99 // ---------------------------------------------------------------------------
100 // $Header$
101 // sstring.cxx
102 //
103 // SWIG String class.
104 // This class is used to construct long strings when writing
105 // wrapper functions. It also "mimicks" the C++ streams I/O
106 // library for creating strings. For example :
107 //
108 // str << "hi there" << 3 << "\n";
109 //
110 // Will append the given strings to str.
111 //
112 // The idea here is to provide a mechanism for writing wrapper
113 // functions as strings before writing them out to a file.
114 //
115 // ---------------------------------------------------------------------------
116 #define INIT_MAXSIZE 64
117
118 // ---------------------------------------------------------------
119 // Pools. This is a list of available strings for memory allocation
120 // and deletion.
121 // ---------------------------------------------------------------
122
123 struct StrMem {
124 char *str;
125 int len;
126 };
127
128 #define POOLSIZE 100
129
130 static StrMem pool[POOLSIZE];
131 static int pool_index = 0;
132
133 // Returns an item from the pool that can accomodate len
134 static char *get_pool(int len, int &newlen) {
135 int i,j;
136 char *nc;
137 if (pool_index < 1) {
138 newlen = len;
139 return new char[len];
140 }
141 i = pool_index-1;
142 j = 0;
143 while(i >= 0) {
144 if ((pool[i].len >= len) && (pool[i].len <= 4*len)) {
145 nc = pool[i].str;
146 newlen = pool[i].len;
147 pool[i].str = pool[pool_index-1].str;
148 pool[i].len = pool[pool_index-1].len;
149 pool_index--;
150 return nc;
151 }
152 j++;
153 i--;
154 }
155 newlen = len;
156 return new char[len];
157 }
158
159 // Puts an item onto the pool
160
161 static void put_pool(char *str, int len) {
162 if (len < INIT_MAXSIZE) {
163 delete [] str;
164 return;
165 }
166 if (pool_index == POOLSIZE) {
167 delete [] pool[pool_index-1].str;
168 pool_index--;
169 }
170 pool[pool_index].str = str;
171 pool[pool_index].len = len;
172 if (pool_index != POOLSIZE)
173 pool_index++;
174 }
175
176 // ---------------------------------------------------------------
177 // String::String()
178 //
179 // Create a new string with nothing in it
180 // ---------------------------------------------------------------
181
182 String::String() {
183 maxsize = INIT_MAXSIZE;
184 str = get_pool(maxsize,maxsize); // May return a pool that is larger
185 str[0] = 0;
186 len = 0;
187 }
188
189 // ---------------------------------------------------------------
190 // String::String(const char *s)
191 //
192 // Create a new string copied from a normal C-style string
193 // ---------------------------------------------------------------
194
195 String::String(const char *s) {
196 int max = INIT_MAXSIZE;
197 int l = 0;
198 if (s) {
199 l = (int) strlen(s);
200 if ((l+1) > max) max = l+1;
201 }
202 str = get_pool(max,maxsize);
203 if (s) {
204 strcpy(str,s);
205 len = l;
206 } else {
207 str[0] = 0;
208 len = 0;
209 }
210 }
211
212 // ---------------------------------------------------------------
213 // String::~String(const char *s)
214 //
215 // Destroy a string
216 // ---------------------------------------------------------------
217
218 String::~String() {
219 put_pool(str,maxsize);
220 }
221
222 // ---------------------------------------------------------------
223 // String::add(const char *newstr)
224 //
225 // Concatenate newstr onto the current string
226 // ---------------------------------------------------------------
227
228 void String::add(const char *newstr) {
229 int newlen;
230 char *nstr = 0;
231 int newmaxsize;
232 int l;
233
234 l = (int) strlen(newstr);
235 newlen = len+l + 1;
236 if (newlen >= maxsize-1) {
237 newmaxsize = 2*maxsize;
238 if (newlen >= newmaxsize -1) newmaxsize = newlen + 1;
239 nstr = get_pool(newmaxsize,newmaxsize);
240 strcpy(nstr,str);
241 put_pool(str,maxsize);
242 maxsize = newmaxsize;
243 str = nstr;
244 }
245 strcpy(str+len,newstr);
246 len += l;
247 }
248
249 // ---------------------------------------------------------------
250 // String::add(char)
251 //
252 // Adds a single character to the current string
253 // ---------------------------------------------------------------
254
255 void String::add(char nc) {
256 int newlen;
257 char *nstr = 0;
258 int newmaxsize;
259
260 newlen = len+ 1;
261 if (newlen >= maxsize-1) {
262 newmaxsize = 2*maxsize;
263 if (newlen >= newmaxsize -1) newmaxsize = newlen + 1;
264 nstr = get_pool(newmaxsize,newmaxsize);
265 strcpy(nstr,str);
266 put_pool(str,maxsize);
267 maxsize = newmaxsize;
268 str = nstr;
269 }
270 str[len++] = nc;
271 str[len] = 0;
272 }
273
274 // -----------------------------------------------------------------
275 // String::insert(const char *newstr)
276 //
277 // Inserts a string into the front of a string. (Primarily used
278 // for documentation generation)
279 // -----------------------------------------------------------------
280
281 void String::insert(const char *newstr) {
282 int newlen;
283 char *nstr = 0;
284 int newmaxsize;
285 int i,l;
286
287 l = strlen(newstr);
288 newlen = len + l + 1;
289 if (newlen >= maxsize-1) {
290 newmaxsize = 2*maxsize;
291 if (newlen >= newmaxsize -1) newmaxsize = newlen + 1;
292 nstr = get_pool(newmaxsize,newmaxsize);
293 strcpy(nstr,str);
294 put_pool(str,maxsize);
295 maxsize = newmaxsize;
296 str = nstr;
297 }
298
299 /* Shift all of the characters over */
300
301 for (i = len -1; i >= 0; i--) {
302 str[i+l] = str[i];
303 }
304
305 /* Now insert the new string */
306
307 strncpy(str,newstr,l);
308 len += l;
309 str[len] = 0;
310
311 }
312
313 // -----------------------------------------------------------------
314 // char *String::get()
315 //
316 // Get the current value of the string
317 // -----------------------------------------------------------------
318
319 char *String::get() const {
320 return str;
321 }
322
323 // -----------------------------------------------------------------
324 // String &operator<<(...)
325 //
326 // Shorthand for appending to the end of a string
327 // -----------------------------------------------------------------
328
329 String &operator<<(String &t,const char *s) {
330 t.add(s);
331 return t;
332 }
333
334
335 String &operator<<(String &t,const char s) {
336 t.add(s);
337 return t;
338 }
339
340 String &operator<<(String &t,const int a) {
341 char temp[64];
342 sprintf(temp,"%d",a);
343 t.add(temp);
344 return t;
345 }
346
347 String &operator<<(String &t, String &s) {
348 t.add(s.get());
349 return t;
350 }
351
352 String &String::operator=(const char *s) {
353 int newlen;
354
355 if (s) {
356 newlen = strlen(s);
357 if ((newlen >= maxsize) && (str)) {
358 put_pool(str,maxsize);
359 str = get_pool(newlen+1,maxsize);
360 maxsize = newlen+1;
361 }
362 strcpy(str,s);
363 len = newlen;
364 } else {
365 str[0] = 0;
366 len = 0;
367 }
368 return *this;
369 }
370
371 // -----------------------------------------------------------------
372 // String &operator>>(...)
373 //
374 // Shorthand for inserting into the beginning of a string
375 // -----------------------------------------------------------------
376
377 String &operator>>(const char *s, String &t) {
378 t.insert(s);
379 return t;
380 }
381
382 String &operator>>(String &s, String &t) {
383 t.insert(s.get());
384 return t;
385 }
386
387 // -----------------------------------------------------------------
388 // void String::untabify()
389 //
390 // Expand all tabs into spaces. This is useful for producing
391 // documentation and other things.
392 // -----------------------------------------------------------------
393
394 void String::untabify() {
395 char *s;
396 char *c;
397 int pos;
398 int i;
399 int oldmaxsize;
400 // Copy the current string representation
401
402 s = str;
403 oldmaxsize = maxsize;
404
405 // Reset the internal state of this string
406
407 len = 0;
408 str = get_pool(maxsize,maxsize);
409 str[0]= 0;
410
411 // Now walk down the old string and expand tabs. Tabs are usually place
412 // every 8 characters.
413
414 pos = 0;
415 c = s;
416 while (*c) {
417 if (*c == '\n') {
418 pos = -1;
419 }
420 if (*c == '\t') {
421 // Expand the character
422 for (i = 0; i < (8 - (pos % 8)); i++) {
423 this->add(' ');
424 }
425 pos+=(8-(pos % 8));
426 } else {
427 this->add(*c);
428 pos++;
429 }
430 c++;
431 }
432
433 // Blow away the old string
434 put_pool(s,oldmaxsize);
435 }
436
437
438 // -----------------------------------------------------------------
439 // void String::replace(const char *token, const char *rep)
440 //
441 // Search for tokens in a string and replace them with rep.
442 // This probably isn't the fastest implementation, but fortunately
443 // SWIG rarely calls this function.
444 // -----------------------------------------------------------------
445
446 void String::replace(const char *token, const char *rep) {
447 char *s, *c, *t;
448 int oldmaxsize = maxsize;
449 // Copy the current string representation
450
451 s = str;
452
453 // Now walk down the old string and search for tokens
454
455 c = s;
456 t = strstr(c,token);
457 if (t) {
458 len = 0;
459 str = get_pool(maxsize,maxsize);
460 while (t) {
461 // Found a token in string s
462 // Dump characters into our string
463 char temp;
464 temp = *t;
465 *t = 0;
466 this->add(c);
467 c = t;
468 *t = temp;
469
470 // Now dump the replacement string into place
471
472 this->add(rep);
473
474 // Jump over the token
475
476 c+=strlen(token);
477 t = strstr(c,token);
478 }
479 // Attach rest of the string
480 if (*c)
481 this->add(c);
482 put_pool(s,oldmaxsize);
483 }
484 }
485
486
487 // -----------------------------------------------------------------
488 // void String::replaceid(char *token, char *rep)
489 //
490 // Searches for valid identifiers matching token and replaces
491 // them with rep. Unlike replace() tokens must be a valid C
492 // identifier (surrounded by whitespace).
493 // -----------------------------------------------------------------
494
495 void String::replaceid(const char *token, const char *rep) {
496 char *s, *c, *t;
497 int whitespace, tokenlen;
498 int oldmaxsize = maxsize;
499 // Copy the current string representation
500
501 s = str;
502
503 // Reset the internal state of this string
504
505 tokenlen = strlen(token);
506
507 // Now walk down the old string and search for tokens
508
509 c = s;
510 t = strstr(c,token);
511 if (t) {
512 len = 0;
513 str = get_pool(maxsize,maxsize);
514 while (t) {
515 // Found a token in string s
516 // Dump characters into our string
517
518 whitespace = 1;
519 while (c != t) {
520 this->add(*c);
521 if (!(isalpha(*c) || (*c == '_') || (*c == '$'))) whitespace = 1;
522 else whitespace = 0;
523 c++;
524 }
525
526 if (whitespace) {
527 // Check to see if there is whitespace afterwards
528 if ((!c[tokenlen]) || (!(isalnum(c[tokenlen]) || (c[tokenlen] == '_') || (c[tokenlen] == '$')))) {
529 this->add(rep);
530 } else {
531 this->add(token);
532 }
533 c+=tokenlen;
534 } else {
535 this->add(*c);
536 c++;
537 }
538 t = strstr(c,token);
539 }
540
541 // Attach rest of the string
542 if (*c)
543 this->add(c);
544
545 // Delete the old string
546 put_pool(s,oldmaxsize);
547 }
548 }
549
550
551 // -----------------------------------------------------------------
552 // void String::strip()
553 //
554 // Intelligently strips whitespace from a string. Will not strip
555 // whitespace if it is between two characters that are part of a
556 // legal C identifier. For example 'unsigned int'.
557 // -----------------------------------------------------------------
558
559 void String::strip() {
560 char *s = str; // Old pointer value
561 char *c, lastchar = 0;
562 int whitespace = 0;
563 int oldmaxsize = maxsize;
564
565 str = get_pool(maxsize,maxsize); // Get a new string.
566 len = 0;
567
568 c = s;
569 while(*c) {
570 if (!isspace(*c)) {
571 // See if this character doesn't violate our whitespace rules
572 if (whitespace) {
573 if (isalnum(lastchar) || (lastchar == '_') || (lastchar == '$')) {
574 if (isalnum(*c) || (*c == '_') || (*c == '$'))
575 this->add(' ');
576 }
577 }
578 this->add(*c);
579 lastchar = *c;
580 whitespace = 0;
581 } else {
582 whitespace = 1;
583 }
584 c++;
585 }
586 put_pool(s,oldmaxsize);
587 }