1 /* Part of XPCE --- The SWI-Prolog GUI toolkit
2
3 Author: Jan Wielemaker and Anjo Anjewierden
4 E-mail: jan@swi.psy.uva.nl
5 WWW: http://www.swi.psy.uva.nl/projects/xpce/
6 Copyright (c) 1985-2002, University of Amsterdam
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12
13 1. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <h/kernel.h>
36 #include <h/str.h>
37
38 #undef min
39 #define min(a, b) ((a) < (b) ? (a) : (b))
40
41 #define sameEncoding(s1, s2) \
42 if ( s1->iswide != s2->iswide ) \
43 return FALSE;
44
45
46 /*******************************
47 * ALLOC *
48 *******************************/
49
50 inline int
str_allocsize(PceString s)51 str_allocsize(PceString s)
52 { int len;
53
54 len = isstrA(s) ? s->s_size : s->s_size*sizeof(charW);
55
56 return ((len + sizeof(long))/sizeof(long))*sizeof(long);
57 }
58
59
60 inline void
str_pad(PceString s)61 str_pad(PceString s) /* only 8-bit strings */
62 { if ( isstrA(s) )
63 { int from = s->s_size;
64 int len = str_allocsize(s);
65
66 while(from < len)
67 s->s_textA[from++] = '\0';
68 } else
69 { int from = s->s_size;
70 int len = str_allocsize(s)/sizeof(charW);
71
72 while(from < len)
73 s->s_textW[from++] = '\0';
74 }
75 }
76
77
78 void
str_alloc(PceString s)79 str_alloc(PceString s)
80 { s->s_textA = alloc(str_allocsize(s));
81 s->s_readonly = FALSE;
82 str_pad(s);
83 }
84
85
86 #define STR_RING_SIZE 16
87 static char *str_ring[STR_RING_SIZE] = {NULL};
88 int str_ring_ptr = 0;
89
90 static void
str_ring_alloc(PceString s)91 str_ring_alloc(PceString s)
92 { int size = str_allocsize(s);
93
94 if ( !str_ring[str_ring_ptr] )
95 { str_ring[str_ring_ptr] = pceMalloc(size);
96 } else
97 { str_ring[str_ring_ptr] = pceRealloc(str_ring[str_ring_ptr], size);
98 }
99 s->s_textA = (charA*)str_ring[str_ring_ptr];
100 s->s_readonly = TRUE;
101
102 if ( ++str_ring_ptr == STR_RING_SIZE )
103 str_ring_ptr = 0;
104 }
105
106
107 void
str_unalloc(PceString s)108 str_unalloc(PceString s)
109 { if ( s->s_textA && !s->s_readonly )
110 { unalloc(str_allocsize(s), s->s_textA);
111 s->s_textA = NULL;
112 }
113 }
114
115
116 PceString
str_init(PceString s,PceString proto,charA * data)117 str_init(PceString s, PceString proto, charA *data)
118 { str_cphdr(s, proto);
119 s->s_text = data;
120
121 return s;
122 }
123
124
125 PceString
fstr_inithdr(PceString s,int iswide,void * data,int len)126 fstr_inithdr(PceString s, int iswide, void *data, int len)
127 { str_inithdr(s, iswide);
128 s->s_text = data;
129 s->s_size = len;
130
131 return s;
132 }
133
134
135 status
str_set_n_ascii(PceString str,size_t len,char * text)136 str_set_n_ascii(PceString str, size_t len, char *text)
137 { if ( len > STR_MAX_SIZE )
138 return errorPce(NIL, NAME_stringTooLong, toInt(len));
139
140 str_inithdr(str, FALSE);
141 str->s_size = (int)len;
142 str->s_textA = (charA *) text;
143
144 succeed;
145 }
146
147
148 status
str_set_n_wchar(PceString str,size_t len,wchar_t * text)149 str_set_n_wchar(PceString str, size_t len, wchar_t *text)
150 { if ( len > STR_MAX_SIZE )
151 return errorPce(NIL, NAME_stringTooLong, toInt(len));
152
153 str_inithdr(str, TRUE);
154 str->s_size = (int)len;
155 str->s_textW = text;
156
157 succeed;
158 }
159
160
161 status
str_set_ascii(PceString str,char * text)162 str_set_ascii(PceString str, char *text)
163 { size_t len = strlen(text);
164
165 return str_set_n_ascii(str, len, text);
166 }
167
168
169 status
str_set_utf8(PceString str,const char * text)170 str_set_utf8(PceString str, const char *text)
171 { const char *s = text;
172 const char *e = &text[strlen(s)];
173 int iswide = FALSE;
174 int len = 0;
175
176 while(s<e)
177 { int chr;
178
179 s = utf8_get_char(s, &chr);
180 if ( chr > 0xff )
181 iswide = TRUE;
182 len++;
183 }
184
185 str_inithdr(str, iswide);
186 str->s_size = len;
187 str_ring_alloc(str); /* NOTE: temporary space */
188
189 for(len=0, s=text; s<e; len++)
190 { int chr;
191
192 s = utf8_get_char(s, &chr);
193 str_store(str, len, chr);
194 }
195
196 succeed;
197 }
198
199
200 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
201 str_set_static(): initialise a string from a static C-string
202 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
203
204 status
str_set_static(PceString str,const char * text)205 str_set_static(PceString str, const char *text)
206 { size_t len = strlen(text);
207
208 if ( len > STR_MAX_SIZE )
209 return errorPce(NIL, NAME_stringTooLong, toInt(len));
210
211 str_inithdr(str, FALSE);
212 str->s_readonly = TRUE;
213 str->s_size = (int)len;
214 str->s_textA = (charA *) text;
215
216 succeed;
217 }
218
219
220 status
str_iswide(PceString s)221 str_iswide(PceString s)
222 { if ( s->s_iswide )
223 { const charW *w = s->s_textW;
224 const charW *e = &w[s->s_size];
225
226 while(w<e)
227 { if ( *w++ > 0xff )
228 succeed;
229 }
230 }
231
232 fail;
233 }
234
235
236
237 /*******************************
238 * COPY STUFF *
239 *******************************/
240
241 void
str_ncpy(PceString dest,int at,PceString src,int from,int len)242 str_ncpy(PceString dest, int at, PceString src, int from, int len)
243 { if ( dest->s_iswide == src->s_iswide ) /* same size */
244 { if ( isstrA(dest) )
245 memcpy(&dest->s_textA[at], &src->s_textA[from], len * sizeof(charA));
246 else
247 cpdata(&dest->s_textW[at], &src->s_textW[from], charW, len);
248 } else if ( dest->s_iswide ) /* 8bit --> wide */
249 { const charA *s = &src->s_textA[from];
250 const charA *e = &s[len];
251 charW *d = &dest->s_textW[at];
252
253 while(s<e)
254 *d++ = *s++;
255 } else /* wide --> 8bit (may truncate) */
256 { const charW *s = &src->s_textW[from];
257 const charW *e = &s[len];
258 charA *d = &dest->s_textA[at];
259
260 while(s<e)
261 *d++ = *s++;
262 }
263 }
264
265
266 void
str_cpy(PceString dest,PceString src)267 str_cpy(PceString dest, PceString src)
268 { str_cphdr(dest, src);
269 str_ncpy(dest, 0, src, 0, src->s_size);
270 }
271
272
273 charA *
str_textp(PceString s,int i)274 str_textp(PceString s, int i)
275 { return isstrA(s) ? &s->s_textA[i] : (charA *)&s->s_textW[i];
276 }
277
278
279 /*******************************
280 * CASE MANIPULATION *
281 *******************************/
282
283 void
str_upcase(PceString str,int from,int to)284 str_upcase(PceString str, int from, int to)
285 { if ( isstrA(str) )
286 { charA *s = &str->s_textA[from];
287
288 for(; from < to; from++, s++)
289 *s = toupper(*s);
290 } else
291 { charW *s = &str->s_textW[from];
292
293 for(; from < to; from++, s++)
294 *s = towupper(*s);
295 }
296 }
297
298
299 void
str_downcase(PceString str,int from,int to)300 str_downcase(PceString str, int from, int to)
301 { if ( isstrA(str) )
302 { charA *s = &str->s_textA[from];
303
304 for(; from < to; from++, s++)
305 *s = tolower(*s);
306 } else
307 { charW *s = &str->s_textW[from];
308
309 for(; from < to; from++, s++)
310 *s = towlower(*s);
311 }
312 }
313
314
315 /*******************************
316 * COMPARE *
317 *******************************/
318
319 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
320 int str_cmp(PceString s1, PceString s2)
321 returns < 0 if s1 is before s2, == 0 if equal and > 0 if s2 is
322 before s2.
323
324 int str_eq(PceString s1, PceString s2)
325 returns != 0 if s1 equals s2.
326 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
327
328 int
str_cmp(PceString s1,PceString s2)329 str_cmp(PceString s1, PceString s2)
330 { int n = min(s1->s_size, s2->s_size);
331
332 if ( s1->s_iswide == s2->s_iswide )
333 { if ( isstrA(s1) )
334 { int d;
335
336 if ( (d=strncmp((const char*)s1->s_textA, (const char*)s2->s_textA, n)) == 0 )
337 return s1->s_size - s2->s_size;
338
339 return d;
340 } else
341 { charW *d1 = s1->s_textW;
342 charW *d2 = s2->s_textW;
343 int d;
344
345 while(n-- > 0)
346 if ( (d = (*d1++ - *d2++)) )
347 return d;
348
349 return s1->s_size - s2->s_size;
350 }
351 } else /* inconsistent encoding */
352 { int i;
353
354 for(i=0; i<n; i++)
355 { wint_t c1 = str_fetch(s1, i);
356 wint_t c2 = str_fetch(s2, i);
357
358 if ( c1 != c2 )
359 return c1 -c2;
360 }
361
362 return s1->s_size - s2->s_size;
363 }
364 }
365
366
367 int
str_icase_cmp(PceString s1,PceString s2)368 str_icase_cmp(PceString s1, PceString s2)
369 { int n = min(s1->s_size, s2->s_size);
370
371 if ( s1->s_iswide == s2->s_iswide )
372 { if ( isstrA(s1) )
373 { charA *d1 = s1->s_textA;
374 charA *d2 = s2->s_textA;
375 int d;
376
377 for(; n-- > 0; d1++, d2++)
378 if ( (d = (tolower(*d1) - tolower(*d2))) )
379 return d;
380
381 return s1->s_size - s2->s_size;
382 } else
383 { charW *d1 = s1->s_textW;
384 charW *d2 = s2->s_textW;
385 int d;
386
387 for(; n-- > 0; d1++, d2++)
388 if ( (d = (towlower(*d1) - towlower(*d2))) )
389 return d;
390
391 return s1->s_size - s2->s_size;
392 }
393 } else
394 { int i;
395
396 for(i=0; i<n; i++)
397 { wint_t c1 = towlower(str_fetch(s1, i));
398 wint_t c2 = towlower(str_fetch(s2, i));
399
400 if ( c1 != c2 )
401 return c1 -c2;
402 }
403
404 return s1->s_size - s2->s_size;
405 }
406 }
407
408
409 int
str_eq(PceString s1,PceString s2)410 str_eq(PceString s1, PceString s2)
411 { if ( s1->s_size == s2->s_size )
412 return str_cmp(s1, s2) == 0;
413
414 return FALSE;
415 }
416
417
418 int
str_icase_eq(PceString s1,PceString s2)419 str_icase_eq(PceString s1, PceString s2)
420 { if ( s1->s_size == s2->s_size )
421 return str_icase_cmp(s1, s2) == 0;
422
423 return FALSE;
424 }
425
426
427 int /* s2 is prefix of s1+offset */
str_prefix_offset(PceString s1,unsigned int offset,PceString s2)428 str_prefix_offset(PceString s1, unsigned int offset, PceString s2)
429 { if ( s2->s_size <= s1->s_size-offset )
430 { int n = s2->s_size;
431
432 if ( isstrA(s1) && isstrA(s2) )
433 { charA *d1 = s1->s_textA+offset;
434 charA *d2 = s2->s_textA;
435
436 while(n-- > 0)
437 if ( *d1++ != *d2++ )
438 return FALSE;
439
440 return TRUE;
441 } else
442 { int i;
443
444 for(i=0; i<n; i++)
445 if ( str_fetch(s1, i+offset) != str_fetch(s2, i) )
446 return FALSE;
447 }
448
449 return TRUE;
450 }
451
452 return FALSE;
453 }
454
455
456 int
str_prefix(PceString s1,PceString s2)457 str_prefix(PceString s1, PceString s2) /* s2 is prefix of s1 */
458 { return str_prefix_offset(s1, 0, s2);
459 }
460
461
462 int
str_icase_prefix(PceString s1,PceString s2)463 str_icase_prefix(PceString s1, PceString s2) /* s2 is prefix of s1 */
464 { if ( s2->s_size <= s1->s_size )
465 { int n = s2->s_size;
466
467 if ( isstrA(s1) && isstrA(s2) )
468 { charA *d1 = s1->s_textA;
469 charA *d2 = s2->s_textA;
470
471 for(; n-- > 0; d1++, d2++)
472 if ( tolower(*d1) != tolower(*d2) )
473 return FALSE;
474 } else
475 { int i = 0;
476
477 for(; n-- > 0; i++)
478 if ( towlower(str_fetch(s1, i)) != towlower(str_fetch(s2, i)) )
479 return FALSE;
480 }
481
482 return TRUE;
483 }
484
485 return FALSE;
486 }
487
488
489 int
str_suffix(PceString s1,PceString s2)490 str_suffix(PceString s1, PceString s2) /* s2 is suffix of s1 */
491 { if ( s2->s_size <= s1->s_size )
492 { int n = s2->s_size;
493 int offset = s1->s_size - s2->s_size;
494
495 if ( isstrA(s1) && isstrA(s2) )
496 { charA *d1 = &s1->s_textA[offset];
497 charA *d2 = s2->s_textA;
498
499 while(n-- > 0)
500 if ( *d1++ != *d2++ )
501 return FALSE;
502
503 return TRUE;
504 } else
505 { while(--n >= 0)
506 if ( str_fetch(s1, n+offset) != str_fetch(s2, n) )
507 return FALSE;
508
509 return TRUE;
510 }
511 }
512
513 return FALSE;
514 }
515
516
517 int
str_icase_suffix(PceString s1,PceString s2)518 str_icase_suffix(PceString s1, PceString s2) /* s2 is suffix of s1 */
519 { if ( s2->s_size <= s1->s_size )
520 { int n = s2->s_size;
521 int offset = s1->s_size - s2->s_size;
522
523 if ( isstrA(s1) && isstrA(s2) )
524 { charA *d1 = &s1->s_textA[offset];
525 charA *d2 = s2->s_textA;
526
527 for( ; n-- > 0; d1++, d2++)
528 { if ( tolower(*d1) != tolower(*d2) )
529 return FALSE;
530 }
531
532 return TRUE;
533 } else
534 { int i = 0;
535
536 for( ; n-- > 0; i++)
537 { if ( towlower(str_fetch(s1, i)) != towlower(str_fetch(s2, i)) )
538 return FALSE;
539 }
540 }
541
542 return TRUE;
543 }
544
545 return FALSE;
546 }
547
548
549 int
str_sub(PceString s1,PceString s2)550 str_sub(PceString s1, PceString s2) /* s2 is substring of s1 */
551 { if ( s2->s_size <= s1->s_size )
552 { int n = 0;
553 int m = s1->s_size - s2->s_size;
554
555 if ( s1->s_iswide == s2->s_iswide )
556 { if ( isstrA(s1) )
557 { for(; n <= m; n++)
558 { charA *d1 = &s1->s_textA[n];
559 charA *d2 = s2->s_textA;
560 int i = s2->s_size;
561
562 while( i-- > 0 )
563 if ( *d1++ != *d2++ )
564 goto next8;
565
566 return TRUE;
567 next8:;
568 }
569 } else
570 { for(; n <= m; n++)
571 { charW *d1 = &s1->s_textW[n];
572 charW *d2 = s2->s_textW;
573 int i = s2->s_size;
574
575 while( i-- > 0 )
576 if ( *d1++ != *d2++ )
577 goto next16;
578
579 return TRUE;
580 next16:;
581 }
582 }
583 } else
584 { for(; n <= m; n++)
585 { int i1 = n;
586 int i2 = 0;
587 int i = s2->s_size;
588
589 for( ; i-- > 0; i1++, i2++ )
590 if ( str_fetch(s1, i1) != str_fetch(s2, i2) )
591 goto nextmixed;
592
593 return TRUE;
594 nextmixed:;
595 }
596 }
597 }
598
599 return FALSE;
600 }
601
602
603 int
str_icasesub(PceString s1,PceString s2)604 str_icasesub(PceString s1, PceString s2) /* s2 is substring of s1 */
605 { if ( s2->s_size <= s1->s_size )
606 { int n = 0;
607 int m = s1->s_size - s2->s_size;
608
609 if ( s1->s_iswide == s2->s_iswide )
610 { if ( isstrA(s1) )
611 { for(; n <= m; n++)
612 { charA *d1 = &s1->s_textA[n];
613 charA *d2 = s2->s_textA;
614 int i;
615
616 for(i=s2->s_size; i-- > 0; d1++, d2++ )
617 { if ( tolower(*d1) != tolower(*d2) )
618 goto next8;
619 }
620
621 return TRUE;
622 next8:;
623 }
624 } else
625 { for(; n <= m; n++)
626 { charW *d1 = &s1->s_textW[n];
627 charW *d2 = s2->s_textW;
628 int i;
629
630 for(i=s2->s_size; i-- > 0; d1++, d2++ )
631 { if ( towlower(*d1) != towlower(*d2) )
632 goto next16;
633 }
634
635 return TRUE;
636 next16:;
637 }
638 }
639 } else
640 { for(; n <= m; n++)
641 { int i1 = n;
642 int i2 = 0;
643 int i = s2->s_size;
644
645 for( ; i-- > 0; i1++, i2++ )
646 if ( towlower(str_fetch(s1, i1)) != towlower(str_fetch(s2, i2)) )
647 goto nextmixed;
648
649 return TRUE;
650 nextmixed:;
651 }
652 }
653 }
654
655 return FALSE;
656 }
657
658
659 int
str_next_index(PceString s,int from,wint_t chr)660 str_next_index(PceString s, int from, wint_t chr)
661 { int i, n = s->s_size;
662
663 if ( isstrA(s) )
664 { charA *d = &s->s_textA[from];
665
666 for(i=from; i<n; i++, d++)
667 if ( *d == chr )
668 return i;
669 } else
670 { charW *d = &s->s_textW[from];
671
672 for(i=from; i<n; i++, d++)
673 if ( (wint_t)*d == chr )
674 return i;
675 }
676
677 return -1;
678 }
679
680
681 int
str_next_rindex(PceString s,int from,wint_t chr)682 str_next_rindex(PceString s, int from, wint_t chr)
683 { int i;
684
685 if ( isstrA(s) )
686 { charA *d = &s->s_textA[from];
687
688 for(i=from; i >= 0; i--, d--)
689 if ( *d == chr )
690 return i;
691 } else
692 { charW *d = &s->s_textW[from];
693
694 for(i=from; i >= 0; i--, d--)
695 if ( (wint_t)*d == chr )
696 return i;
697 }
698
699 return -1;
700 }
701
702
703 int
str_index(PceString s,wint_t chr)704 str_index(PceString s, wint_t chr)
705 { return str_next_index(s, 0, chr);
706 }
707
708
709 int
str_rindex(PceString s,wint_t chr)710 str_rindex(PceString s, wint_t chr)
711 { return str_next_rindex(s, s->s_size, chr);
712 }
713
714 /* count chr in [from,to) */
715
716 int
str_count_chr(PceString s,int from,int to,wint_t chr)717 str_count_chr(PceString s, int from, int to, wint_t chr)
718 { int i, count = 0;
719
720 if ( isstrA(s) )
721 { charA *d = &s->s_textA[from];
722
723 for(i=from; i<to; i++, d++)
724 if ( *d == chr )
725 count++;
726 } else
727 { charW *d = &s->s_textW[from];
728
729 for(i=from; i<to; i++, d++)
730 if ( (wint_t)*d == chr )
731 count++;
732 }
733
734 return count;
735 }
736
737
738 int
str_lineno(PceString s,int at)739 str_lineno(PceString s, int at)
740 { return str_count_chr(s, 0, at, '\n') + 1;
741 }
742
743
744 wint_t
str_fetch(PceString s,int idx)745 str_fetch(PceString s, int idx)
746 { return s->s_iswide ? str_fetchW(s, idx)
747 : str_fetchA(s, idx) & 0xff;
748 }
749
750
751 int
str_store(PceString s,int idx,unsigned int chr)752 str_store(PceString s, int idx, unsigned int chr)
753 { return s->s_iswide ? str_storeW(s, idx, chr)
754 : str_storeA(s, idx, chr);
755 }
756
757 /*******************************
758 * UTIL *
759 *******************************/
760
761 static void
str_from_char(PceString s,char c)762 str_from_char(PceString s, char c)
763 { unsigned char *text = alloc(sizeof(char)*2);
764 text[0] = c;
765 text[1] = '\0';
766
767 str_inithdr(s, FALSE);
768 s->s_textA = text;
769 s->s_size = 1;
770 }
771
772
773 static void
str_from_char16(PceString s,int c)774 str_from_char16(PceString s, int c)
775 { charW *text = alloc(sizeof(charW)*2);
776 text[0] = c;
777 text[1] = '\0';
778
779 str_inithdr(s, TRUE);
780 s->s_textW = text;
781 s->s_size = 1;
782 }
783
784
785 PceString
str_nl(PceString proto)786 str_nl(PceString proto)
787 { static string nl8;
788 static string nl16;
789
790 if ( !proto || !proto->s_iswide )
791 { if ( !nl8.s_size )
792 str_from_char(&nl8, '\n');
793
794 return &nl8;
795 } else
796 { if ( !nl16.s_size )
797 str_from_char16(&nl16, '\n');
798
799 return &nl16;
800 }
801 }
802
803
804 PceString
str_spc(PceString proto)805 str_spc(PceString proto)
806 { static string spc8;
807 static string spc16;
808
809 if ( !proto || !proto->s_iswide )
810 { if ( !spc8.s_size )
811 str_from_char(&spc8, ' ');
812
813 return &spc8;
814 } else
815 { if ( !spc16.s_size )
816 str_from_char16(&spc16, ' ');
817
818 return &spc16;
819 }
820 }
821
822
823 PceString
str_tab(PceString proto)824 str_tab(PceString proto)
825 { static string tab8;
826 static string tab16;
827
828 if ( !proto || !proto->s_iswide )
829 { if ( !tab8.s_size )
830 str_from_char(&tab8, '\t');
831
832 return &tab8;
833 } else
834 { if ( !tab16.s_size )
835 str_from_char16(&tab16, '\t');
836
837 return &tab16;
838 }
839 }
840
841
842 void
str_strip(PceString s)843 str_strip(PceString s)
844 { int size = s->s_size;
845
846 if ( isstrA(s) )
847 { charA *f = s->s_textA;
848 charA *t = s->s_textA;
849 charA *e = &s->s_textA[size];
850
851 while( f < e && iswspace(*f) ) /* ISO-Latin-1 */
852 f++;
853
854 do
855 { while( f < e && !iswspace(*f) )
856 *t++ = *f++;
857 while( f < e && iswspace(*f) )
858 f++;
859 if ( f < e )
860 *t++ = ' ';
861 } while( f < e );
862 s->s_size = t - s->s_textA;
863 } else
864 { charW *f = s->s_textW;
865 charW *t = s->s_textW;
866 charW *e = &s->s_textW[size];
867
868 while( f < e && iswspace(*f) )
869 f++;
870
871 do
872 { while( f < e && !iswspace(*f) )
873 *t++ = *f++;
874 while( f < e && iswspace(*f) )
875 f++;
876 if ( f < e )
877 *t++ = ' ';
878 } while( f < e );
879 s->s_size = t - s->s_textW;
880 }
881 }
882
883
884 int
str_common_length(PceString s1,PceString s2)885 str_common_length(PceString s1, PceString s2)
886 { int i = 0;
887 int size = min(s1->s_size, s2->s_size);
888
889 if ( s1->s_iswide == s2->s_iswide )
890 { if ( isstrA(s1) )
891 { charA *t1 = s1->s_textA;
892 charA *t2 = s2->s_textA;
893
894 while( i < size && *t1++ == *t2++ )
895 i++;
896 } else
897 { charW *t1 = s1->s_textW;
898 charW *t2 = s2->s_textW;
899
900 while( i < size && *t1++ == *t2++ )
901 i++;
902 }
903 }
904
905 return i;
906 }
907
908
909 int
str_icase_common_length(PceString s1,PceString s2)910 str_icase_common_length(PceString s1, PceString s2)
911 { int i = 0;
912 int size = min(s1->s_size, s2->s_size);
913
914 if ( s1->s_iswide == s2->s_iswide )
915 { if ( isstrA(s1) )
916 { charA *t1 = s1->s_textA;
917 charA *t2 = s2->s_textA;
918
919 while( i < size && tolower(*t1) == tolower(*t2) )
920 i++, t1++, t2++;
921 } else
922 { charW *t1 = s1->s_textW;
923 charW *t2 = s2->s_textW;
924
925 while( i < size && towlower(*t1) == towlower(*t2) )
926 i++, t1++, t2++;
927 }
928 }
929
930 return i;
931 }
932
933
934 /*******************************
935 * TEMPORARY STRINGS *
936 *******************************/
937
938 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
939 Temporary strings are designed to get character data code-by-code
940 without knowing the size in advance or wether or not the data fits in an
941 ISO Latin-1 string or not.
942 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
943
944 tmp_string *
str_tmp_init(tmp_string * tmp)945 str_tmp_init(tmp_string *tmp)
946 { str_inithdr(&tmp->s, FALSE);
947 tmp->s.s_textA = tmp->buffer;
948 tmp->allocated = sizeof(tmp->buffer);
949
950 return tmp;
951 }
952
953
954 wint_t
str_tmp_put(tmp_string * tmp,wint_t c)955 str_tmp_put(tmp_string *tmp, wint_t c)
956 { PceString s = &tmp->s;
957
958 if ( c > 0xff && !s->s_iswide )
959 { if ( s->s_textA == tmp->buffer &&
960 s->s_size*sizeof(charW) < sizeof(tmp->buffer) )
961 { charA b2[sizeof(tmp->buffer)];
962 const charA *f = b2;
963 const charA *e = &f[s->s_size];
964 charW *t = s->s_textW;
965
966 memcpy(b2, tmp->buffer, s->s_size);
967 while(f<e)
968 *t++ = *f++;
969 tmp->allocated /= sizeof(charW);
970 } else
971 { charW *new = pceMalloc(tmp->allocated * sizeof(charW));
972 const charA *f = tmp->buffer;
973 const charA *e = &f[s->s_size];
974 charW *t = new;
975
976 while(f<e)
977 *t++ = *f++;
978
979 if ( s->s_textA != tmp->buffer )
980 pceFree(s->s_textA);
981 s->s_textW = new;
982 }
983 s->s_iswide = TRUE;
984 }
985 if ( s->s_size >= tmp->allocated )
986 { if ( s->s_textA == tmp->buffer )
987 { long len = tmp->allocated*2;
988
989 if ( isstrA(s) )
990 { s->s_textA = pceMalloc(len);
991
992 memcpy(s->s_textA, tmp->buffer, sizeof(tmp->buffer));
993 } else
994 { s->s_textW = pceMalloc(len*sizeof(charW));
995
996 memcpy(s->s_textA, tmp->buffer, sizeof(tmp->buffer));
997 }
998
999 tmp->allocated = len;
1000 } else
1001 { tmp->allocated *= 2;
1002
1003 if ( isstrA(s) )
1004 s->s_textA = pceRealloc(s->s_textA, tmp->allocated);
1005 else
1006 s->s_textW = pceRealloc(s->s_textW, tmp->allocated*sizeof(charW));
1007 }
1008 }
1009
1010 if ( !s->s_iswide )
1011 s->s_textA[s->s_size++] = c;
1012 else
1013 s->s_textW[s->s_size++] = c;
1014
1015 return c;
1016 }
1017
1018
1019 void
str_tmp_done(tmp_string * tmp)1020 str_tmp_done(tmp_string *tmp)
1021 { if ( tmp->s.s_textA != tmp->buffer )
1022 pceFree(tmp->s.s_textA);
1023 }
1024