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/unix.h> /* storeStringFile() prototype */
37
38 static CharArray stringToCharArray(PceString s);
39
40 /********************************
41 * CREATE/CONVERT *
42 ********************************/
43
44
45 status
initialiseCharArray(CharArray n,CharArray value)46 initialiseCharArray(CharArray n, CharArray value)
47 { str_cphdr(&n->data, &value->data);
48 str_alloc(&n->data);
49 if ( value->data.s_readonly )
50 n->data.s_textA = value->data.s_textA;
51 else
52 memcpy(n->data.s_textA, value->data.s_textA, str_datasize(&n->data));
53
54 succeed;
55 }
56
57
58 static status
unlinkCharArray(CharArray n)59 unlinkCharArray(CharArray n)
60 { str_unalloc(&n->data);
61
62 succeed;
63 }
64
65
66 static status
cloneCharArray(CharArray str,CharArray clone)67 cloneCharArray(CharArray str, CharArray clone)
68 { clonePceSlots(str, clone);
69 clone->data = str->data;
70 str_alloc(&clone->data);
71 memcpy(clone->data.s_textA, str->data.s_textA, str_datasize(&str->data));
72
73 succeed;
74 }
75
76
77 static status
storeCharArray(CharArray s,FileObj file)78 storeCharArray(CharArray s, FileObj file)
79 { TRY(storeSlotsObject(s, file));
80
81 return storeStringFile(file, &s->data);
82 }
83
84
85 static status
loadCharArray(CharArray s,IOSTREAM * fd,ClassDef def)86 loadCharArray(CharArray s, IOSTREAM *fd, ClassDef def)
87 { TRY(loadSlotsObject(s, fd, def));
88
89 return loadStringFile(fd, &s->data);
90 }
91
92
93 static CharArray
getConvertCharArray(Any ctx,Any val)94 getConvertCharArray(Any ctx, Any val)
95 { string s;
96
97 TRY(toString(val, &s));
98 answer(stringToCharArray(&s));
99 }
100
101
102 Name
getValueCharArray(CharArray n)103 getValueCharArray(CharArray n)
104 { answer(StringToName(&n->data));
105 }
106
107
108 /********************************
109 * TESTS *
110 ********************************/
111
112 status
equalCharArray(CharArray n1,CharArray n2,BoolObj ign_case)113 equalCharArray(CharArray n1, CharArray n2, BoolObj ign_case)
114 { if ( ign_case == ON )
115 return str_icase_eq(&n1->data, &n2->data);
116 else
117 return str_eq(&n1->data, &n2->data);
118 }
119
120
121 /* n2 is prefix of n1 */
122
123 status
prefixCharArray(CharArray n1,CharArray n2,BoolObj ign_case)124 prefixCharArray(CharArray n1, CharArray n2, BoolObj ign_case)
125 { if ( ign_case == ON )
126 return str_icase_prefix(&n1->data, &n2->data);
127 else
128 return str_prefix(&n1->data, &n2->data);
129 }
130
131
132 status
suffixCharArray(CharArray n,CharArray s,BoolObj ign_case)133 suffixCharArray(CharArray n, CharArray s, BoolObj ign_case)
134 { if ( ign_case == ON )
135 return str_icase_suffix(&n->data, &s->data);
136 else
137 return str_suffix(&n->data, &s->data);
138 }
139
140
141 static status
largerCharArray(CharArray n1,CharArray n2)142 largerCharArray(CharArray n1, CharArray n2)
143 { if ( str_cmp(&n1->data, &n2->data) > 0 )
144 succeed;
145 fail;
146 }
147
148
149 static status
smallerCharArray(CharArray n1,CharArray n2)150 smallerCharArray(CharArray n1, CharArray n2)
151 { if ( str_cmp(&n1->data, &n2->data) < 0 )
152 succeed;
153 fail;
154 }
155
156
157 static status
subCharArray(CharArray n1,CharArray n2,BoolObj ign_case)158 subCharArray(CharArray n1, CharArray n2, BoolObj ign_case)
159 { if ( ign_case != ON )
160 { if ( str_sub(&n1->data, &n2->data) )
161 succeed;
162 } else
163 { if ( str_icasesub(&n1->data, &n2->data) )
164 succeed;
165 }
166
167 fail;
168 }
169
170
171 status
isWideCharArray(Any s)172 isWideCharArray(Any s)
173 { CharArray ca = s;
174
175 return str_iswide(&ca->data);
176 }
177
178
179 /********************************
180 * MODIFICATIONS *
181 ********************************/
182
183 static CharArray
getModifyCharArray(CharArray n,CharArray n2)184 getModifyCharArray(CharArray n, CharArray n2)
185 { answer(answerObject(classOfObject(n), n2, EAV));
186 }
187
188
189 static CharArray
ModifiedCharArray(CharArray n,PceString buf)190 ModifiedCharArray(CharArray n, PceString buf)
191 {
192 Class class = classOfObject(n);
193
194 if ( class == ClassName )
195 return (CharArray) StringToName(buf);
196 else if ( class == ClassString)
197 return (CharArray) StringToString(buf); /* ??? */
198 else
199 { CharArray scratch = StringToScratchCharArray(buf);
200 CharArray rval = get(n, NAME_modify, scratch, EAV);
201
202 doneScratchCharArray(scratch);
203 answer(rval);
204 }
205 }
206
207
208 CharArray
getCopyCharArray(CharArray n)209 getCopyCharArray(CharArray n)
210 { answer(ModifiedCharArray(n, &n->data));
211 }
212
213
214 /* This assumes the capitalised version of an ISO Latin-1 string always
215 fits in an ISO Latin-1 string. Is this true for all accented characters?
216 */
217
218 CharArray
getCapitaliseCharArray(CharArray n)219 getCapitaliseCharArray(CharArray n)
220 { if ( n->data.s_size == 0 )
221 answer(n);
222 else
223 { PceString d = &n->data;
224 int size = d->s_size;
225 LocalString(buf, d->s_iswide, size);
226 int i=1, o=1;
227
228 str_store(buf, 0, towupper(str_fetch(d, 0)));
229
230 for(; i < size; i++, o++)
231 { wint_t c = str_fetch(d, i);
232
233 if ( iswordsep(c) )
234 { if ( ++i < size )
235 str_store(buf, o, towupper(str_fetch(d, i)));
236 else
237 break;
238 } else
239 str_store(buf, o, towlower(c));
240 }
241
242 buf->s_size = o;
243 answer(ModifiedCharArray(n, buf));
244 }
245 }
246
247
248 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
249 Upcase first letter, downcase the rest and replace word separators (-_)
250 by spaces.
251 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
252
253 CharArray
getLabelNameCharArray(CharArray n)254 getLabelNameCharArray(CharArray n)
255 { PceString s = &n->data;
256 int size = s->s_size;
257 int i;
258
259 if ( size == 0 )
260 return n;
261
262 { LocalString(buf, s->s_iswide, size);
263 int o = 0;
264 wint_t c = str_fetch(s, 0);
265
266 i = 0;
267 str_store(buf, o, towupper(c));
268 i++, o++;
269
270 for( ; i < size; i++, o++ )
271 { c = str_fetch(s, i);
272
273 if ( iswordsep(c) )
274 str_store(buf, o, ' ');
275 else
276 str_store(buf, o, c);
277 }
278 buf->s_size = o;
279
280 answer(ModifiedCharArray(n, buf));
281 }
282 }
283
284
285 CharArray
getDowncaseCharArray(CharArray n)286 getDowncaseCharArray(CharArray n)
287 { PceString s = &n->data;
288 int size = s->s_size;
289 LocalString(buf, s->s_iswide, size);
290 int i;
291
292 for(i=0; i<size; i++)
293 str_store(buf, i, tolower(str_fetch(s, i)));
294 buf->s_size = size;
295
296 answer(ModifiedCharArray(n, buf));
297 }
298
299
300 static CharArray
getUpcaseCharArray(CharArray n)301 getUpcaseCharArray(CharArray n)
302 { PceString s = &n->data;
303 int size = s->s_size;
304 LocalString(buf, s->s_iswide, size);
305 int i;
306
307 for(i=0; i<size; i++)
308 str_store(buf, i, towupper(str_fetch(s, i)));
309 buf->s_size = size;
310
311 answer(ModifiedCharArray(n, buf));
312 }
313
314
315 static CharArray
getStripCharArray(CharArray n,Name how)316 getStripCharArray(CharArray n, Name how)
317 { PceString s = &n->data;
318 int size = s->s_size;
319 LocalString(buf, s->s_iswide, size);
320 int i=0, o=0, lnb=0;
321
322 if ( isDefault(how) )
323 how = NAME_canonicalise;
324
325 if ( how == NAME_canonicalise || how == NAME_leading || how == NAME_both )
326 { for(; i<size && iswspace(str_fetch(s, i)); i++)
327 ;
328 }
329 for( ; i<size; i++)
330 { wint_t c = str_fetch(s, i);
331
332 str_store(buf, o++, c);
333 if ( !iswspace(c) )
334 lnb = o;
335 else if ( how == NAME_canonicalise )
336 { for( ; i+1<size && iswspace(str_fetch(s, i+1)); i++)
337 ;
338 }
339 }
340 if ( how == NAME_canonicalise || how == NAME_trailing || how == NAME_both )
341 buf->s_size = lnb;
342 else
343 buf->s_size = o;
344
345 answer(ModifiedCharArray(n, buf));
346 }
347
348
349 static Chain
getSplitCharArray(CharArray in,CharArray br)350 getSplitCharArray(CharArray in, CharArray br)
351 { PceString s1 = &in->data;
352 int size = s1->s_size;
353 int i=0, last=0;
354 Chain ch = answerObject(ClassChain, EAV);
355 string buf;
356
357 str_cphdr(&buf, s1);
358
359 if ( notDefault(br) ) /* given pattern */
360 { PceString b = &br->data;
361
362 while( i<=size-b->s_size )
363 { if ( str_prefix_offset(s1, i, b) )
364 { if ( isstrA(s1) )
365 buf.s_textA = s1->s_textA+last;
366 else
367 buf.s_textW = s1->s_textW+last;
368
369 buf.s_size = i-last;
370 appendChain(ch, ModifiedCharArray(in, &buf));
371
372 i = last = i+b->s_size;
373 } else
374 i++;
375 }
376 } else
377 { for(; i<size && iswspace(str_fetch(s1, i)); i++) /* strip leading */
378 ;
379 last = i;
380
381 while( i<size )
382 { if ( iswspace(str_fetch(s1, i)) )
383 { if ( isstrA(s1) )
384 buf.s_textA = s1->s_textA+last;
385 else
386 buf.s_textW = s1->s_textW+last;
387
388 buf.s_size = i-last;
389 appendChain(ch, ModifiedCharArray(in, &buf));
390
391 while(i < size && iswspace(str_fetch(s1, i)))
392 i++;
393 last = i;
394 if ( i == size ) /* trailing blanks */
395 answer(ch);
396 } else
397 i++;
398 }
399 }
400
401 if ( isstrA(s1) )
402 buf.s_textA = s1->s_textA+last;
403 else
404 buf.s_textW = s1->s_textW+last;
405
406 buf.s_size = size-last;
407 appendChain(ch, ModifiedCharArray(in, &buf));
408
409 answer(ch);
410 }
411
412
413 CharArray
getAppendCharArray(CharArray n1,CharArray n2)414 getAppendCharArray(CharArray n1, CharArray n2)
415 { PceString s1 = &n1->data;
416 PceString s2 = &n2->data;
417 int iswide = (s1->s_iswide || s2->s_iswide);
418 LocalString(buf, iswide, s1->s_size + s2->s_size);
419
420 buf->s_size = s1->s_size + s2->s_size;
421 str_ncpy(buf, 0, s1, 0, s1->s_size);
422 str_ncpy(buf, s1->s_size, s2, 0, s2->s_size);
423
424 answer(ModifiedCharArray(n1, buf));
425 }
426
427
428 static CharArray
getAppendCharArrayv(CharArray ca,int argc,CharArray * argv)429 getAppendCharArrayv(CharArray ca, int argc, CharArray *argv)
430 { int l = ca->data.s_size;
431 int iswide = ca->data.s_iswide;
432 int i;
433
434 for( i=0; i<argc; i++ )
435 { l += argv[i]->data.s_size;
436 if ( argv[i]->data.s_iswide )
437 iswide = TRUE;
438 }
439
440 { LocalString(buf, iswide, l);
441 int d;
442
443 str_ncpy(buf, 0, &ca->data, 0, ca->data.s_size);
444 d = ca->data.s_size;
445
446 for( i=0; i<argc; i++ )
447 { str_ncpy(buf, d, &argv[i]->data, 0, argv[i]->data.s_size);
448 d += argv[i]->data.s_size;
449 }
450
451 buf->s_size = l;
452 answer(ModifiedCharArray(ca, buf));
453 }
454 }
455
456
457 CharArray
getDeleteSuffixCharArray(CharArray n,CharArray s)458 getDeleteSuffixCharArray(CharArray n, CharArray s)
459 { if ( suffixCharArray(n, s, OFF) )
460 { string buf;
461
462 str_cphdr(&buf, &n->data);
463 buf.s_text = n->data.s_text;
464 buf.s_size = n->data.s_size - s->data.s_size;
465
466 answer(ModifiedCharArray(n, &buf));
467 }
468
469 fail;
470 }
471
472
473 CharArray
getEnsureSuffixCharArray(CharArray n,CharArray s)474 getEnsureSuffixCharArray(CharArray n, CharArray s)
475 { if ( suffixCharArray(n, s, OFF) )
476 answer(n);
477
478 answer(getAppendCharArray(n, s));
479 }
480
481
482 static CharArray
getDeletePrefixCharArray(CharArray n,CharArray s)483 getDeletePrefixCharArray(CharArray n, CharArray s)
484 { if ( prefixCharArray(n, s, OFF) )
485 { string buf;
486
487 str_cphdr(&buf, &n->data);
488 buf.s_size = n->data.s_size - s->data.s_size;
489 if ( isstrA(&buf) )
490 buf.s_textA = &n->data.s_textA[s->data.s_size];
491 else
492 buf.s_textW = &n->data.s_textW[s->data.s_size];
493
494 answer(ModifiedCharArray(n, &buf));
495 }
496
497 fail;
498 }
499
500
501 CharArray
getSubCharArray(CharArray n,Int start,Int end)502 getSubCharArray(CharArray n, Int start, Int end)
503 { string s;
504 int x, y;
505 int len = n->data.s_size;
506
507 x = valInt(start);
508 y = (isDefault(end) ? len : valInt(end));
509 if ( x < 0 || y > len || x > y )
510 fail;
511
512 str_cphdr(&s, &n->data);
513 s.s_size = y-x;
514 if ( isstrA(&n->data) )
515 s.s_textA = &n->data.s_textA[x];
516 else
517 s.s_textW = &n->data.s_textW[x];
518
519 answer(ModifiedCharArray(n, &s));
520 }
521
522
523 /*******************************
524 * BASE-64 ENCODING *
525 *******************************/
526
527 static int
base64_char(unsigned int in)528 base64_char(unsigned int in)
529 { if ( in < 26 ) return 'A'+in;
530 if ( in < 52 ) return 'a'+in-26;
531 if ( in < 62 ) return '0'+in-52;
532 if ( in == 62 ) return '+';
533 assert(in == 63);
534 return '/';
535 }
536
537
538 static unsigned long
base64_code(unsigned int in)539 base64_code(unsigned int in)
540 { if ( in == '+' ) return 62;
541 if ( in == '/' ) return 63;
542 if ( in < '0' ) return ~0L;
543 if ( in <= '9' ) return in - '0' + 52;
544 if ( in < 'A' ) return ~0L;
545 if ( in <= 'Z' ) return in - 'A';
546 if ( in < 'a' ) return ~0L;
547 if ( in <= 'z' ) return in - 'a' + 26;
548 return ~0L;
549 }
550
551
552 static CharArray
getBase64EncodeCharArray(CharArray in)553 getBase64EncodeCharArray(CharArray in)
554 { PceString s = &in->data;
555 int size = s->s_size;
556 int triples = (size+2)/3;
557 LocalString(buf, FALSE, triples*4);
558 int i, o=0;
559 unsigned long v;
560
561 for(i=0; i+2<size;)
562 { v = (str_fetch(s, i)<<16) + (str_fetch(s, i+1)<<8) + str_fetch(s, i+2);
563 i += 3;
564 str_store(buf, o++, base64_char((v>>18)&0x3f));
565 str_store(buf, o++, base64_char((v>>12)&0x3f));
566 str_store(buf, o++, base64_char((v>> 6)&0x3f));
567 str_store(buf, o++, base64_char((v>> 0)&0x3f));
568 }
569
570 if ( size - i == 2 )
571 { v = (str_fetch(s, i)<<16) + (str_fetch(s, i+1)<<8);
572 str_store(buf, o++, base64_char((v>>18)&0x3f));
573 str_store(buf, o++, base64_char((v>>12)&0x3f));
574 str_store(buf, o++, base64_char((v>> 6)&0x3f));
575 str_store(buf, o++, '=');
576 } else if ( size - i == 1)
577 { v = (str_fetch(s, i)<<16);
578 str_store(buf, o++, base64_char((v>>18)&0x3f));
579 str_store(buf, o++, base64_char((v>>12)&0x3f));
580 str_store(buf, o++, '=');
581 str_store(buf, o++, '=');
582 }
583
584 buf->s_size = o;
585 answer(ModifiedCharArray(in, buf));
586 }
587
588
589 static CharArray
getBase64DecodeCharArray(CharArray in)590 getBase64DecodeCharArray(CharArray in)
591 { PceString s = &in->data;
592 int size = s->s_size;
593 LocalString(buf, FALSE, (size/4)*3);
594 int i, o = 0;
595 unsigned long v = 0L;
596
597 for(i=0; i+3<size; )
598 { int c;
599
600 v = (base64_code(str_fetch(s, i)) << 18) |
601 (base64_code(str_fetch(s, i+1)) << 12);
602 i += 2;
603 c = str_fetch(s, i++);
604 if ( c == '=' )
605 { i++; /* skip last (must be =) */
606 str_store(buf, o++, (v>>16) & 0xff);
607 break;
608 }
609 v |= base64_code(c) << 6;
610 c = str_fetch(s, i++);
611 if ( c == '=' )
612 { str_store(buf, o++, (v>>16) & 0xff);
613 str_store(buf, o++, (v>>8) & 0xff);
614 break;
615 }
616 v |= base64_code(c);
617 if ( v == ~(unsigned long)0 )
618 fail;
619 str_store(buf, o++, (v>>16) & 0xff);
620 str_store(buf, o++, (v>>8) & 0xff);
621 str_store(buf, o++, (v>>0) & 0xff);
622 }
623
624 if ( i != size || v == ~(unsigned long)0 )
625 fail;
626
627 buf->s_size = o;
628 answer(ModifiedCharArray(in, buf));
629 }
630
631
632 /*******************************
633 * AS-FILE *
634 *******************************/
635
636 static CharArray
getReadAsFileCharArray(CharArray n,Int from,Int size)637 getReadAsFileCharArray(CharArray n, Int from, Int size)
638 { int f = valInt(from);
639 int s = valInt(size);
640
641 if ( f < 0 || s < 0 || f > n->data.s_size )
642 fail;
643
644 if ( f == 0 && s >= n->data.s_size )
645 answer(n);
646 else
647 { string str;
648
649 if ( f+s > n->data.s_size )
650 s = n->data.s_size - f;
651
652 str_cphdr(&str, &n->data);
653 str.s_size = s;
654 if ( isstrA(&n->data) )
655 str.s_textA = &n->data.s_textA[f];
656 else
657 str.s_textW = &n->data.s_textW[f];
658
659 answer((CharArray)StringToString(&str));
660 }
661 }
662
663
664 /********************************
665 * READING GETS *
666 ********************************/
667
668 Int
getSizeCharArray(Any n)669 getSizeCharArray(Any n)
670 { CharArray c = n;
671
672 answer(toInt(c->data.s_size));
673 }
674
675
676 static Int
getCharacterCharArray(CharArray n,Int idx)677 getCharacterCharArray(CharArray n, Int idx)
678 { int i = valInt(idx);
679
680 if ( i < 0 || i >= n->data.s_size )
681 fail;
682
683 answer(toInt(str_fetch(&n->data, i)));
684 }
685
686
687 static Int
getIndexCharArray(CharArray n,Int chr,Int here)688 getIndexCharArray(CharArray n, Int chr, Int here)
689 { wint_t c = valInt(chr);
690 int h;
691
692 h = (isDefault(here) ? 0 : valInt(here));
693 if ( (h = str_next_index(&n->data, h, c)) >= 0 )
694 answer(toInt(h));
695
696 fail;
697 }
698
699
700 static Int
getRindexCharArray(CharArray n,Int chr,Int here)701 getRindexCharArray(CharArray n, Int chr, Int here)
702 { wint_t c = valInt(chr);
703 int h, len = n->data.s_size;
704
705 h = (isDefault(here) ? (len - 1) : valInt(here));
706 if ( (h = str_next_rindex(&n->data, h, c)) >= 0 )
707 answer(toInt(h));
708
709 fail;
710 }
711
712
713 static Int
getLineNoCharArray(CharArray name,Int caret)714 getLineNoCharArray(CharArray name, Int caret)
715 { int here = (isDefault(caret) ? name->data.s_size : valInt(caret));
716
717 answer(toInt(str_lineno(&name->data, here)));
718 }
719
720
721 static Vector
getScanCharArray(CharArray n,CharArray fmt)722 getScanCharArray(CharArray n, CharArray fmt)
723 { if ( isstrA(&n->data) && isstrA(&fmt->data) )
724 { Any argv[SCAN_MAX_ARGS];
725 Int argc;
726
727 TRY(argc = scanstr((char *)n->data.s_textA,
728 (char *)fmt->data.s_textA,
729 argv));
730
731 answer(answerObjectv(ClassVector, valInt(argc), argv));
732 } else
733 { errorPce(n, NAME_notSupportedForChar16);
734 fail;
735 }
736 }
737
738
739 static Name
getCompareCharArray(CharArray n1,CharArray n2,BoolObj ignore_case)740 getCompareCharArray(CharArray n1, CharArray n2, BoolObj ignore_case)
741 { int rval;
742
743 if ( ignore_case == ON )
744 rval = str_icase_cmp(&n1->data, &n2->data);
745 else
746 rval = str_cmp(&n1->data, &n2->data);
747
748 if ( rval < 0 )
749 answer(NAME_smaller);
750 else if ( rval == 0 )
751 answer(NAME_equal);
752 else
753 answer(NAME_larger);
754
755 assert(0); /* should not get here! */
756 fail;
757 }
758
759
760 /********************************
761 * C-CONVERSIONS *
762 ********************************/
763
764 #define SCRATCH_CHAR_ARRAYS (10)
765
766 static CharArray scratch_char_arrays;
767
768 void
initCharArrays(void)769 initCharArrays(void)
770 { CharArray ca;
771 int n;
772 int size = sizeof(struct char_array) * SCRATCH_CHAR_ARRAYS;
773
774 scratch_char_arrays = alloc(size);
775 memset(scratch_char_arrays, 0, size);
776
777 for(ca=scratch_char_arrays, n = 0; n < SCRATCH_CHAR_ARRAYS; ca++, n++)
778 { initHeaderObj(ca, ClassCharArray);
779 setProtectedObj(ca);
780 createdObject(ca, NAME_new);
781 }
782 }
783
784
785 CharArray
CtoScratchCharArray(const char * s)786 CtoScratchCharArray(const char *s)
787 { CharArray name = scratch_char_arrays;
788 size_t len = strlen(s);
789 int n;
790
791 for(n = 0; n < SCRATCH_CHAR_ARRAYS; n++, name++)
792 { if ( name->data.s_textA == NULL )
793 { str_set_n_ascii(&name->data, len, (char *)s);
794
795 return name;
796 }
797 }
798
799 initCharArrays(); /* handle the crash better */
800 NOTREACHED;
801 fail;
802 }
803
804
805 CharArray
StringToScratchCharArray(const PceString s)806 StringToScratchCharArray(const PceString s)
807 { CharArray name = scratch_char_arrays;
808 int n;
809
810 for(n = 0; n < SCRATCH_CHAR_ARRAYS; n++, name++)
811 { if ( name->data.s_textA == NULL )
812 { str_cphdr(&name->data, s);
813 name->data.s_text = s->s_text;
814 return name;
815 }
816 }
817
818 initCharArrays(); /* handle the crash better */
819 NOTREACHED;
820 fail;
821 }
822
823
824 void
doneScratchCharArray(CharArray n)825 doneScratchCharArray(CharArray n)
826 { n->data.s_text = NULL;
827 }
828
829
830 CharArray
CtoCharArray(char * s)831 CtoCharArray(char *s)
832 { CharArray name = CtoScratchCharArray(s);
833 CharArray rval = answerObject(ClassCharArray, name, EAV);
834
835 doneScratchCharArray(name);
836 return rval;
837 }
838
839
840 static CharArray
stringToCharArray(PceString s)841 stringToCharArray(PceString s)
842 { CharArray name = StringToScratchCharArray(s);
843 CharArray rval = answerObject(ClassCharArray, name, EAV);
844
845 doneScratchCharArray(name);
846 return rval;
847 }
848
849
850 /*******************************
851 * CLASS DECLARATION *
852 *******************************/
853
854 /* Type declarations */
855
856 static char *T_ofAchar_fromADintD[] =
857 { "of=char", "from=[int]" };
858 static char *T_gsub[] =
859 { "start=int", "end=[int]" };
860 static char *T_match[] =
861 { "text=char_array", "ignore_case=[bool]" };
862 static char *T_readAsFile[] =
863 { "from=int", "size=int" };
864
865 /* Instance Variables */
866
867 static vardecl var_charArray[] =
868 { IV(NAME_header, "alien:str_h", IV_NONE,
869 NAME_internal, "Header info (packed)"),
870 IV(NAME_text, "alien:wint_t *", IV_NONE,
871 NAME_internal, "Text represented (8- or 16-bits chars)")
872 };
873
874 /* Send Methods */
875
876 static senddecl send_charArray[] =
877 { SM(NAME_initialise, 1, "text=char_array", initialiseCharArray,
878 DEFAULT, "Create from other char_array"),
879 SM(NAME_unlink, 0, NULL, unlinkCharArray,
880 DEFAULT, "Free the char *"),
881 SM(NAME_equal, 2, T_match, equalCharArray,
882 NAME_compare, "Test if names represent same text"),
883 SM(NAME_larger, 1, "than=char_array", largerCharArray,
884 NAME_compare, "Test if I'm alphabetically after arg"),
885 SM(NAME_smaller, 1, "than=char_array", smallerCharArray,
886 NAME_compare, "Test if I'm alphabetically before arg"),
887 SM(NAME_prefix, 2, T_match, prefixCharArray,
888 NAME_test, "Test if receiver has prefix argument"),
889 SM(NAME_sub, 2, T_match, subCharArray,
890 NAME_test, "Test if argument is a substring"),
891 SM(NAME_suffix, 2, T_match, suffixCharArray,
892 NAME_test, "Test if receiver has suffix argument"),
893 SM(NAME_isWide, 0, NULL, isWideCharArray,
894 NAME_encoding, "Test if text contains non ISO-Latin-1 characters")
895 };
896
897 /* Get Methods */
898
899 static getdecl get_charArray[] =
900 { GM(NAME_printName, 0, "char_array", NULL, getSelfObject,
901 DEFAULT, "Equivalent to <-self"),
902 GM(NAME_size, 0, "int", NULL, getSizeCharArray,
903 NAME_cardinality, "Number of characters in the text"),
904 GM(NAME_capitalise, 0, "char_array", NULL, getCapitaliseCharArray,
905 NAME_case, "Capitalised version of name"),
906 GM(NAME_downcase, 0, "char_array", NULL, getDowncaseCharArray,
907 NAME_case, "Map all uppercase letters to lowercase"),
908 GM(NAME_labelName, 0, "char_array", NULL, getLabelNameCharArray,
909 NAME_case, "Default name used for labels"),
910 GM(NAME_upcase, 0, "char_array", NULL, getUpcaseCharArray,
911 NAME_case, "Map all lowercase letters to uppercase"),
912 GM(NAME_strip, 1, "char_array", "[{canonicalise,leading,trailing,both}]", getStripCharArray,
913 NAME_content, "Strip leading/trailing blanks"),
914 GM(NAME_compare, 2, "{smaller,equal,larger}", T_match, getCompareCharArray,
915 NAME_compare, "Alphabetical comparison"),
916 GM(NAME_append, 1, "char_array", "char_array ...", getAppendCharArrayv,
917 NAME_content, "Concatenation of me and the argument(s)"),
918 GM(NAME_character, 1, "char", "int", getCharacterCharArray,
919 NAME_content, "Character code of 0-based nth character"),
920 GM(NAME_deletePrefix, 1, "char_array", "prefix=char_array", getDeletePrefixCharArray,
921 NAME_content, "Delete specified prefix"),
922 GM(NAME_deleteSuffix, 1, "char_array", "suffix=char_array", getDeleteSuffixCharArray,
923 NAME_content, "Delete specified suffix"),
924 GM(NAME_ensureSuffix, 1, "char_array", "suffix=char_array", getEnsureSuffixCharArray,
925 NAME_content, "Append suffix if not already there"),
926 GM(NAME_sub, 2, "char_array", T_gsub, getSubCharArray,
927 NAME_content, "Get substring from 0-based start and end"),
928 GM(NAME_convert, 1, "char_array", "any", getConvertCharArray,
929 NAME_conversion, "Convert `text-convertible'"),
930 GM(NAME_value, 0, "name", NULL, getValueCharArray,
931 NAME_conversion, "Value as a name"),
932 GM(NAME_copy, 0, "char_array", NULL, getCopyCharArray,
933 NAME_copy, "Copy representing the same text"),
934 GM(NAME_split, 1, "chain", "separator=[char_array]", getSplitCharArray,
935 NAME_content, "Split text using separator"),
936 GM(NAME_modify, 1, "char_array", "char_array", getModifyCharArray,
937 NAME_internal, "New instance of my class"),
938 GM(NAME_lineNo, 1, "line=int", "index=[int]", getLineNoCharArray,
939 NAME_line, "Get 1-based line number at which index is"),
940 GM(NAME_index, 2, "int", T_ofAchar_fromADintD, getIndexCharArray,
941 NAME_parse, "Get 0-based index starting at pos (forwards)"),
942 GM(NAME_rindex, 2, "int", T_ofAchar_fromADintD, getRindexCharArray,
943 NAME_parse, "Get 0-based index starting at pos (backwards)"),
944 GM(NAME_scan, 1, "vector", "format=char_array", getScanCharArray,
945 NAME_parse, "C-scanf like parsing of string"),
946 GM(NAME_base64Encode, 0, "char_array", NULL, getBase64EncodeCharArray,
947 NAME_mime, "Perform base-64 encoding on the argument"),
948 GM(NAME_base64Decode, 0, "char_array", NULL, getBase64DecodeCharArray,
949 NAME_mime, "Perform base-64 decoding on the argument"),
950 GM(NAME_readAsFile, 2, "char_array", T_readAsFile, getReadAsFileCharArray,
951 NAME_stream, "Read data from object using pce_open/3"),
952 GM(NAME_sizeAsFile, 0, "characters=int", NULL, getSizeCharArray,
953 NAME_stream, "Support pce_open/3")
954 };
955
956 /* Resources */
957
958 #define rc_charArray NULL
959 /*
960 static classvardecl rc_charArray[] =
961 {
962 };
963 */
964
965 /* Class Declaration */
966
967 static Name charArray_termnames[] = { NAME_value };
968
969 ClassDecl(charArray_decls,
970 var_charArray, send_charArray, get_charArray, rc_charArray,
971 1, charArray_termnames,
972 "$Rev$");
973
974 status
makeClassCharArray(Class class)975 makeClassCharArray(Class class)
976 { declareClass(class, &charArray_decls);
977
978 setCloneFunctionClass(class, cloneCharArray);
979 setLoadStoreFunctionClass(class, loadCharArray, storeCharArray);
980
981 initCharArrays();
982
983 succeed;
984 }
985