source: libcfa/src/collections/string.cfa@ c4f8c4bf

Last change on this file since c4f8c4bf was c4f8c4bf, checked in by Michael Brooks <mlbrooks@…>, 9 months ago

Fix string-operator handling on +=

  • Property mode set to 100644
File size: 12.9 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// string -- variable-length, mutable run of text, with value semantics
8//
9// Author : Michael L. Brooks
10// Created On : Fri Sep 03 11:00:00 2021
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri Apr 11 08:31:21 2025
13// Update Count : 369
14//
15
16#define _COMPILING_STRING_CFA_
17
18#include "string.hfa"
19#include "string_res.hfa"
20#include <stdlib.hfa>
21
22#pragma GCC visibility push(default)
23
24/*
25Implementation Principle: typical operation translates to the equivalent
26operation on `inner`. Exceptions are implementing new RAII pattern for value
27semantics and some const-hell handling.
28*/
29
30////////////////////////////////////////////////////////
31// string RAII
32
33// private (not in header)
34static void ?{}( string & s, string_res & src, size_t start, size_t len ) {
35 (s.inner) { malloc() };
36 ?{}( *s.inner, src, SHARE_EDITS, start, len );
37}
38
39void ?{}( string & s ) {
40 (s.inner) { malloc() };
41 ?{}( *s.inner );
42}
43
44PBOOST void ?{}( string & s, string c ) { // c is a memcpy of the real src string
45 (s.inner) { malloc() };
46 ?{}( *s.inner, *c.inner, COPY_VALUE );
47}
48
49void ?{}( string & s, string s2, size_t maxlen ) {
50 (s.inner) { malloc() };
51 ?{}( *s.inner, *s2.inner, COPY_VALUE, maxlen );
52}
53
54void ?{}( string & s, char c ) {
55 (s.inner) { malloc() };
56 ?{}( *s.inner, c );
57}
58
59void ?{}( string & s, const char * c ) {
60 (s.inner) { malloc() };
61 ?{}( *s.inner, c );
62}
63
64void ?{}( string & s, const char * c, size_t size ) {
65 (s.inner) { malloc() };
66 ?{}( *s.inner, c, size );
67}
68
69void ?{}( string & s, signed long int rhs ) {
70 (s.inner) { malloc() };
71 ?{}( *s.inner, rhs );
72}
73
74void ?{}( string & s, size_t rhs ) {
75 (s.inner) { malloc() };
76 ?{}( *s.inner, rhs );
77}
78
79void ?{}( string & s, double rhs ) {
80 (s.inner) { malloc() };
81 ?{}( *s.inner, rhs );
82}
83
84void ?{}( string & s, long double rhs ) {
85 (s.inner) { malloc() };
86 ?{}( *s.inner, rhs );
87}
88
89void ?{}( string & s, double _Complex rhs ) {
90 (s.inner) { malloc() };
91 ?{}( *s.inner, rhs );
92}
93
94void ?{}( string & s, long double _Complex rhs ) {
95 (s.inner) { malloc() };
96 ?{}( *s.inner, rhs );
97}
98
99string str( ssize_t rhs ) {
100 string s = rhs;
101 return s;
102}
103
104string str( size_t rhs ) {
105 string s = rhs;
106 return s;
107}
108
109string str( double rhs ) {
110 string s = rhs;
111 return s;
112}
113
114string str( long double rhs ) {
115 string s = rhs;
116 return s;
117}
118
119string str( double _Complex rhs ) {
120 string s = rhs;
121 return s;
122}
123
124string str( long double _Complex rhs ) {
125 string s = rhs;
126 return s;
127}
128
129void ^?{}( string & s ) {
130 ^(*s.inner){};
131 free( s.inner );
132 s.inner = 0p;
133}
134
135////////////////////////////////////////////////////////
136// Alternate construction: request shared edits
137
138string_Share ?`share( string & s ) {
139 string_Share ret = { &s };
140 return ret;
141}
142
143void ?{}( string & s, string_Share src ) {
144 ?{}( s, *src.s->inner, 0, src.s->inner->Handle.lnth );
145}
146
147////////////////////////////////////////////////////////
148// Assignment
149
150PBOOST string & ?=?( string & s, string c ) {
151 (*s.inner) = (*c.inner);
152 return s;
153}
154
155string & ?=?( string & s, const char * val ) {
156 (*s.inner) = val;
157 return s;
158}
159
160string & ?=?( string & s, char val ) {
161 (*s.inner) = val;
162 return s;
163}
164
165string & assign( string & s, const string & c, size_t n ) {
166 assign( *s.inner, *c.inner, n );
167 return s;
168}
169
170string & assign( string & s, const char * c, size_t n ) {
171 assign( *s.inner, c, n );
172 return s;
173}
174
175string & ?=?( string & s, signed long int rhs ) {
176 (*s.inner) = rhs;
177 return s;
178}
179
180string & ?=?( string & s, size_t rhs ) {
181 (*s.inner) = rhs;
182 return s;
183}
184
185string & ?=?( string & s, double rhs ) {
186 (*s.inner) = rhs;
187 return s;
188}
189
190string & ?=?( string & s, long double rhs ) {
191 (*s.inner) = rhs;
192 return s;
193}
194
195string & ?=?( string & s, double _Complex rhs ) {
196 (*s.inner) = rhs;
197 return s;
198}
199
200string & ?=?( string & s, long double _Complex rhs ) {
201 (*s.inner) = rhs;
202 return s;
203}
204
205////////////////////////////////////////////////////////
206// Input-Output
207
208forall( ostype & | basic_ostream( ostype ) ) {
209 ostype & ?|?( ostype & out, string s ) {
210 return out | (*s.inner); // print internal string_res
211 }
212
213 void ?|?( ostype & out, string s ) {
214 (ostype &)(out | (*s.inner)); ends( out );
215 }
216
217 ostype & ?|?( ostype & os, _Ostream_Manip(string) f ) {
218 size_t l = len( f.val );
219 char cstr[l + 1]; // room for null terminator
220 for ( i; l ) cstr[i] = f.val[i]; // copy string
221 cstr[l] = '\0'; // terminate
222 _Ostream_Manip(const char *) cf @= { cstr, f.wd, f.pc, f.base, {f.all} };
223 return os | cf | nonl;
224 } // ?|?
225
226 void ?|?( ostype & os, _Ostream_Manip(string) f ) {
227 (ostype &)(os | f); ends( os );
228 }
229}
230
231forall( istype & | basic_istream( istype ) ) {
232 istype & ?|?( istype & in, string & s ) {
233 return in | (*s.inner); // read to internal string_res
234 }
235
236 istype & ?|?( istype & is, _Istream_Squoted f ) {
237 _Istream_Rquoted f2 = { { f.sstr.s.inner, (_Istream_str_base)f.sstr } };
238 return is | f2;
239 } // ?|?
240
241 istype & ?|?( istype & is, _Istream_Sstr f ) {
242 // _Istream_Rstr f2 = {f.sstr.s.inner, (_Istream_str_base)f.sstr};
243 _Istream_Rstr f2 = {f.s.inner, (_Istream_str_base)f};
244 return is | f2;
245 } // ?|?
246}
247
248////////////////////////////////////////////////////////
249// Slicing
250
251string ?()( string & s, ssize_t start, ssize_t len ) {
252 if ( start < 0 ) { start += len( s ); }
253 if ( len < 0 ) { len = -len; start -= len; }
254 if ( start >= len( s ) ) return (string){ "" };
255 if ( start + len > len( s ) ) len = len( s ) - start;
256 string ret = { *s.inner, start, len };
257 return ret`share;
258}
259
260string ?()( string & s, ssize_t start ) {
261 if ( start < 0 ) { start += len( s ); }
262 string ret = { *s.inner, start, len( s ) - start };
263 return ret`share;
264}
265
266////////////////////////////////////////////////////////
267// Comparison
268
269int strcmp( const string & s1, const string & s2 ) { return strcmp( *s1.inner, *s2.inner ); }
270bool ?==?( const string & s1, const string & s2 ) { return *s1.inner == *s2.inner; }
271bool ?!=?( const string & s1, const string & s2 ) { return *s1.inner != *s2.inner; }
272bool ?>? ( const string & s1, const string & s2 ) { return *s1.inner > *s2.inner; }
273bool ?>=?( const string & s1, const string & s2 ) { return *s1.inner >= *s2.inner; }
274bool ?<=?( const string & s1, const string & s2 ) { return *s1.inner <= *s2.inner; }
275bool ?<? ( const string & s1, const string & s2 ) { return *s1.inner < *s2.inner; }
276
277int strcmp( const string & s1, const char * s2 ) { return strcmp( *s1.inner, s2 ); }
278bool ?==?( const string & s1, const char * s2 ) { return *s1.inner == s2; }
279bool ?!=?( const string & s1, const char * s2 ) { return *s1.inner != s2; }
280bool ?>? ( const string & s1, const char * s2 ) { return *s1.inner > s2; }
281bool ?>=?( const string & s1, const char * s2 ) { return *s1.inner >= s2; }
282bool ?<=?( const string & s1, const char * s2 ) { return *s1.inner <= s2; }
283bool ?<? ( const string & s1, const char * s2 ) { return *s1.inner < s2; }
284
285int strcmp( const char * s1, const string & s2 ) { return strcmp( s1, *s2.inner ); }
286bool ?==?( const char * s1, const string & s2 ) { return s1 == *s2.inner; }
287bool ?!=?( const char * s1, const string & s2 ) { return s1 != *s2.inner; }
288bool ?>? ( const char * s1, const string & s2 ) { return s1 > *s2.inner; }
289bool ?>=?( const char * s1, const string & s2 ) { return s1 >= *s2.inner; }
290bool ?<=?( const char * s1, const string & s2 ) { return s1 <= *s2.inner; }
291bool ?<? ( const char * s1, const string & s2 ) { return s1 < *s2.inner; }
292
293////////////////////////////////////////////////////////
294// Concatenation
295
296void ?+=?( string & s, char c ) {
297 (*s.inner) += c;
298}
299
300PBOOST void ?+=?( string & s, string s2 ) {
301 (*s.inner) += (*s2.inner);
302}
303
304void append( string & s, const string & s2, size_t maxlen ) {
305 append( (*s.inner), (*s2.inner), maxlen );
306}
307
308void ?+=?( string & s, const char * c ) {
309 (*s.inner) += c;
310}
311
312void append( string & s, const char * buffer, size_t bsize ) {
313 append( (*s.inner), buffer, bsize );
314}
315
316string ?+?( string s, char c ) {
317 string ret = s;
318 ret += c;
319 return ret;
320}
321
322string ?+?( char c, string s ) {
323 string ret = c;
324 ret += s;
325 return ret;
326}
327
328PBOOST string ?+?( string s, string s2 ) {
329 string ret = s;
330 ret += s2;
331 return ret;
332}
333
334string ?+?( const char * s, char c ) {
335 string ret = s;
336 ret += c;
337 return ret;
338}
339
340string ?+?( char c, const char * s ) {
341 string ret = c;
342 ret += s;
343 return ret;
344}
345
346string ?+?( const char * s1, const char * s2 ) {
347 string ret = s1;
348 ret += s2;
349 return ret;
350}
351
352string ?+?( const char * s1, string s2 ) {
353 string ret = s1;
354 ret += s2;
355 return ret;
356}
357
358string ?+?( string s, const char * c ) {
359 string ret = s;
360 ret += c;
361 return ret;
362}
363
364string ?+?( char c1, char c2 ) {
365 string ret = c1;
366 ret += c2;
367 return ret;
368}
369
370////////////////////////////////////////////////////////
371// Repetition
372
373void ?*=?( string & s, strmul_factor_t factor ) {
374 (*s.inner) *= factor;
375}
376
377PBOOST string ?*?( string s, strmul_factor_t factor ) {
378 string ret = s;
379 ret *= factor;
380 return ret;
381}
382
383string ?*?( char c, strmul_factor_t factor ) {
384 string ret = c;
385 ret *= factor;
386 return ret;
387}
388
389string ?*?( const char * s, strmul_factor_t factor ) {
390 string ret = s;
391 ret *= factor;
392 return ret;
393}
394
395////////////////////////////////////////////////////////
396// Character access
397
398char ?[?]( const string & s, size_t index ) {
399 return (*s.inner)[index];
400}
401
402string ?[?]( string & s, size_t index ) {
403 string ret = { *s.inner, index, 1 };
404 return ret`share;
405}
406
407////////////////////////////////////////////////////////
408// Search
409
410bool contains( const string & s, char ch ) {
411 return contains( *s.inner, ch );
412}
413
414size_t find( const string & s, size_t start, size_t len, const string & key, size_t kstart, size_t klen ) {
415 if ( start < 0 ) { start += len( s ); }
416 if ( len < 0 ) { len = -len; start -= len; }
417 if ( start >= len( s ) ) return 0;
418 if ( start + len > len( s ) ) len = len( s ) - start;
419
420 if ( kstart < 0 ) { kstart += len( key ); }
421 if ( klen < 0 ) { klen = -klen; kstart -= klen; }
422 if ( kstart >= len( key ) ) return 0;
423 if ( kstart + klen > len( key ) ) klen = len( key ) - kstart;
424
425 return findFrom( *s.inner, start, *key.inner );
426}
427
428size_t find( const string & s, char key ) {
429 return find( *s.inner, key );
430}
431
432size_t find( const string & s, const string & key ) {
433 return find( *s.inner, *key.inner );
434}
435
436size_t find( const string & s, const char * key ) {
437 return find( *s.inner, key );
438}
439
440size_t find( const string & s, const char * key, size_t keysize ) {
441 return find( *s.inner, key, keysize );
442}
443
444size_t find( const string & s, size_t start, char key ) {
445 return findFrom( *s.inner, start, key );
446}
447
448size_t find( const string & s, size_t start, const char * key ) {
449 return findFrom( *s.inner, start, key );
450}
451
452size_t find( const string & s, size_t start, const char * key, size_t keysize ) {
453 return findFrom( *s.inner, start, key, keysize );
454}
455
456bool includes( const string & s, const string & mask ) {
457 return includes( *s.inner, *mask.inner );
458}
459
460bool includes( const string & s, const char * mask ) {
461 return includes( *s.inner, mask );
462}
463
464bool includes( const string & s, const char * mask, size_t masksize ) {
465 return includes( *s.inner, mask, masksize );
466}
467
468bool startsWith( const string & s, const string & prefix ) {
469 return startsWith( *s.inner, *prefix.inner );
470}
471
472bool startsWith( const string & s, const char * prefix ) {
473 return startsWith( *s.inner, prefix );
474}
475
476bool startsWith( const string & s, const char * prefix, size_t prefixsize ) {
477 return startsWith( *s.inner, prefix, prefixsize );
478}
479
480bool endsWith( const string & s, const string & suffix ) {
481 return endsWith( *s.inner, *suffix.inner );
482}
483
484bool endsWith( const string & s, const char * suffix ) {
485 return endsWith( *s.inner, suffix );
486}
487
488bool endsWith( const string & s, const char * suffix, size_t suffixsize ) {
489 return endsWith( *s.inner, suffix, suffixsize );
490}
491
492
493///////////////////////////////////////////////////////////////////////////
494// charclass, include, exclude
495
496void ?{}( charclass & s, const string & chars ) {
497 (s.inner) { malloc() };
498 ?{}( *s.inner, *(const string_res *)chars.inner );
499}
500
501void ?{}( charclass & s, const char * chars ) {
502 (s.inner) { malloc() };
503 ?{}( *s.inner, chars );
504}
505
506void ?{}( charclass & s, const char * chars, size_t charssize ) {
507 (s.inner) { malloc() };
508 ?{}( *s.inner, chars, charssize );
509}
510
511void ^?{}( charclass & s ) {
512 ^(*s.inner){};
513 free( s.inner );
514 s.inner = 0p;
515}
516
517size_t exclude( const string & s, const charclass & mask ) {
518 return exclude( *s.inner, *mask.inner );
519}
520
521size_t include( const string & s, const charclass & mask ) {
522 return include( *s.inner, *mask.inner );
523}
524
525size_t test( const string & s, int (*f)( int ) ) {
526 size_t l = len( s );
527 for ( i; l ) {
528 if ( ! f( s[i] ) ) return i;
529 } // for
530 return l;
531}
532
533string replace( string & s, const string & from, const string & to ) {
534 ssize_t pos;
535 string r;
536
537 pos = find( s, from );
538 if ( pos < len( s ) ) {
539 r = s( 0, pos ) + to + replace( s( pos + (ssize_t)len( from ) ), from, to );
540 } else {
541 r = s;
542 } // if
543 return r;
544}
545
546string translate( const string & s, int (*f)( int ) ) {
547 string r = s;
548 size_t l = len( r );
549 for ( i; l ) {
550 r[i] = (char)f( r[i] );
551 } // for
552 return r;
553}
Note: See TracBrowser for help on using the repository browser.