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

stuck-waitfor-destruct
Last change on this file since cefaa2df was c4f8c4bf, checked in by Michael Brooks <mlbrooks@…>, 10 months ago

Fix string-operator handling on +=

  • Property mode set to 100644
File size: 12.9 KB
RevLine 
[f450f2f]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
[bc9f84a]11// Last Modified By : Peter A. Buhr
[dab6e39]12// Last Modified On : Fri Apr 11 08:31:21 2025
13// Update Count : 369
[f450f2f]14//
15
[d03a386]16#define _COMPILING_STRING_CFA_
17
[f450f2f]18#include "string.hfa"
19#include "string_res.hfa"
20#include <stdlib.hfa>
21
[accc9df9]22#pragma GCC visibility push(default)
[f450f2f]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)
[e8b3717]34static void ?{}( string & s, string_res & src, size_t start, size_t len ) {
[4223317]35 (s.inner) { malloc() };
36 ?{}( *s.inner, src, SHARE_EDITS, start, len );
[f450f2f]37}
38
[479fbe3]39void ?{}( string & s ) {
[4223317]40 (s.inner) { malloc() };
41 ?{}( *s.inner );
[479fbe3]42}
43
[d03a386]44PBOOST void ?{}( string & s, string c ) { // c is a memcpy of the real src string
[4223317]45 (s.inner) { malloc() };
46 ?{}( *s.inner, *c.inner, COPY_VALUE );
[f450f2f]47}
48
[570e7ad]49void ?{}( string & s, string s2, size_t maxlen ) {
[4223317]50 (s.inner) { malloc() };
51 ?{}( *s.inner, *s2.inner, COPY_VALUE, maxlen );
[7abc3de]52}
53
[570e7ad]54void ?{}( string & s, char c ) {
[4223317]55 (s.inner) { malloc() };
56 ?{}( *s.inner, c );
[f450f2f]57}
58
[479fbe3]59void ?{}( string & s, const char * c ) {
[4223317]60 (s.inner) { malloc() };
61 ?{}( *s.inner, c );
[479fbe3]62}
63
[4dab7e8]64void ?{}( string & s, const char * c, size_t size ) {
[4223317]65 (s.inner) { malloc() };
66 ?{}( *s.inner, c, size );
[f450f2f]67}
68
[570e7ad]69void ?{}( string & s, signed long int rhs ) {
[4223317]70 (s.inner) { malloc() };
71 ?{}( *s.inner, rhs );
[f2898df]72}
73
74void ?{}( string & s, size_t rhs ) {
[4223317]75 (s.inner) { malloc() };
76 ?{}( *s.inner, rhs );
[f2898df]77}
78
79void ?{}( string & s, double rhs ) {
[4223317]80 (s.inner) { malloc() };
81 ?{}( *s.inner, rhs );
[f2898df]82}
83
84void ?{}( string & s, long double rhs ) {
[4223317]85 (s.inner) { malloc() };
86 ?{}( *s.inner, rhs );
[f2898df]87}
88
89void ?{}( string & s, double _Complex rhs ) {
[4223317]90 (s.inner) { malloc() };
91 ?{}( *s.inner, rhs );
[f2898df]92}
93
94void ?{}( string & s, long double _Complex rhs ) {
[4223317]95 (s.inner) { malloc() };
96 ?{}( *s.inner, rhs );
[f2898df]97}
98
[4dab7e8]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
[681e12f]129void ^?{}( string & s ) {
[4223317]130 ^(*s.inner){};
131 free( s.inner );
132 s.inner = 0p;
[f450f2f]133}
134
135////////////////////////////////////////////////////////
136// Alternate construction: request shared edits
137
[8c2723f]138string_Share ?`share( string & s ) {
[4223317]139 string_Share ret = { &s };
140 return ret;
[f450f2f]141}
142
[8c2723f]143void ?{}( string & s, string_Share src ) {
[4223317]144 ?{}( s, *src.s->inner, 0, src.s->inner->Handle.lnth );
[f450f2f]145}
146
147////////////////////////////////////////////////////////
148// Assignment
149
[d03a386]150PBOOST string & ?=?( string & s, string c ) {
[4223317]151 (*s.inner) = (*c.inner);
152 return s;
[906d8fa]153}
[f450f2f]154
[b1eefe50]155string & ?=?( string & s, const char * val ) {
[4223317]156 (*s.inner) = val;
157 return s;
[f450f2f]158}
159
[b1eefe50]160string & ?=?( string & s, char val ) {
[4223317]161 (*s.inner) = val;
162 return s;
[b1eefe50]163}
164
[4dab7e8]165string & assign( string & s, const string & c, size_t n ) {
[4223317]166 assign( *s.inner, *c.inner, n );
167 return s;
[e891349]168}
[b1eefe50]169
[4dab7e8]170string & assign( string & s, const char * c, size_t n ) {
[4223317]171 assign( *s.inner, c, n );
172 return s;
[e891349]173}
174
[570e7ad]175string & ?=?( string & s, signed long int rhs ) {
[4223317]176 (*s.inner) = rhs;
177 return s;
[f2898df]178}
179
180string & ?=?( string & s, size_t rhs ) {
[4223317]181 (*s.inner) = rhs;
182 return s;
[f2898df]183}
184
185string & ?=?( string & s, double rhs ) {
[4223317]186 (*s.inner) = rhs;
187 return s;
[f2898df]188}
189
190string & ?=?( string & s, long double rhs ) {
[4223317]191 (*s.inner) = rhs;
192 return s;
[f2898df]193}
194
195string & ?=?( string & s, double _Complex rhs ) {
[4223317]196 (*s.inner) = rhs;
197 return s;
[f2898df]198}
199
200string & ?=?( string & s, long double _Complex rhs ) {
[4223317]201 (*s.inner) = rhs;
202 return s;
[f2898df]203}
[f450f2f]204
205////////////////////////////////////////////////////////
[d32679d5]206// Input-Output
[f450f2f]207
[3f631d6]208forall( ostype & | basic_ostream( ostype ) ) {
209 ostype & ?|?( ostype & out, string s ) {
210 return out | (*s.inner); // print internal string_res
211 }
[f450f2f]212
[3f631d6]213 void ?|?( ostype & out, string s ) {
214 (ostype &)(out | (*s.inner)); ends( out );
215 }
[34c6e1e6]216
[3f631d6]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 } // ?|?
[34c6e1e6]225
[3f631d6]226 void ?|?( ostype & os, _Ostream_Manip(string) f ) {
227 (ostype &)(os | f); ends( os );
228 }
[d32679d5]229}
230
[3f631d6]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}
[7e1dbd7]247
[f450f2f]248////////////////////////////////////////////////////////
249// Slicing
250
[4223317]251string ?()( string & s, ssize_t start, ssize_t len ) {
[ee70ff5]252 if ( start < 0 ) { start += len( s ); }
[4223317]253 if ( len < 0 ) { len = -len; start -= len; }
[ed5023d1]254 if ( start >= len( s ) ) return (string){ "" };
[ee70ff5]255 if ( start + len > len( s ) ) len = len( s ) - start;
[4223317]256 string ret = { *s.inner, start, len };
257 return ret`share;
[f450f2f]258}
259
[4223317]260string ?()( string & s, ssize_t start ) {
[ee70ff5]261 if ( start < 0 ) { start += len( s ); }
262 string ret = { *s.inner, start, len( s ) - start };
[4223317]263 return ret`share;
[bc9f84a]264}
265
[f450f2f]266////////////////////////////////////////////////////////
267// Comparison
268
[4dab7e8]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; }
[f450f2f]292
293////////////////////////////////////////////////////////
294// Concatenation
295
[4dab7e8]296void ?+=?( string & s, char c ) {
[4223317]297 (*s.inner) += c;
[f450f2f]298}
299
[c4f8c4bf]300PBOOST void ?+=?( string & s, string s2 ) {
[4223317]301 (*s.inner) += (*s2.inner);
[f450f2f]302}
303
[4dab7e8]304void append( string & s, const string & s2, size_t maxlen ) {
[4223317]305 append( (*s.inner), (*s2.inner), maxlen );
[e891349]306}
307
[4dab7e8]308void ?+=?( string & s, const char * c ) {
[4223317]309 (*s.inner) += c;
[f450f2f]310}
311
[4dab7e8]312void append( string & s, const char * buffer, size_t bsize ) {
[4223317]313 append( (*s.inner), buffer, bsize );
[e891349]314}
315
[570e7ad]316string ?+?( string s, char c ) {
[4223317]317 string ret = s;
318 ret += c;
319 return ret;
[4dab7e8]320}
321
[570e7ad]322string ?+?( char c, string s ) {
[96a11655]323 string ret = c;
324 ret += s;
[4223317]325 return ret;
[f450f2f]326}
327
[d03a386]328PBOOST string ?+?( string s, string s2 ) {
[4223317]329 string ret = s;
330 ret += s2;
331 return ret;
[f450f2f]332}
333
[4dab7e8]334string ?+?( const char * s, char c ) {
[4223317]335 string ret = s;
336 ret += c;
337 return ret;
[4dab7e8]338}
339
340string ?+?( char c, const char * s ) {
[4223317]341 string ret = c;
342 ret += s;
343 return ret;
[4dab7e8]344}
345
346string ?+?( const char * s1, const char * s2 ) {
[4223317]347 string ret = s1;
348 ret += s2;
349 return ret;
[4dab7e8]350}
351
[570e7ad]352string ?+?( const char * s1, string s2 ) {
[4223317]353 string ret = s1;
354 ret += s2;
355 return ret;
[f450f2f]356}
357
[570e7ad]358string ?+?( string s, const char * c ) {
[4223317]359 string ret = s;
360 ret += c;
361 return ret;
[f450f2f]362}
363
[ee70ff5]364string ?+?( char c1, char c2 ) {
365 string ret = c1;
366 ret += c2;
367 return ret;
368}
369
[f450f2f]370////////////////////////////////////////////////////////
371// Repetition
372
[570e7ad]373void ?*=?( string & s, strmul_factor_t factor ) {
[4223317]374 (*s.inner) *= factor;
[f450f2f]375}
376
[d03a386]377PBOOST string ?*?( string s, strmul_factor_t factor ) {
[4223317]378 string ret = s;
379 ret *= factor;
380 return ret;
[479fbe3]381}
382
[570e7ad]383string ?*?( char c, strmul_factor_t factor ) {
[4223317]384 string ret = c;
385 ret *= factor;
386 return ret;
[f450f2f]387}
388
[570e7ad]389string ?*?( const char * s, strmul_factor_t factor ) {
[4223317]390 string ret = s;
391 ret *= factor;
392 return ret;
[f450f2f]393}
394
395////////////////////////////////////////////////////////
396// Character access
397
[4dab7e8]398char ?[?]( const string & s, size_t index ) {
[4223317]399 return (*s.inner)[index];
[f450f2f]400}
401
[4dab7e8]402string ?[?]( string & s, size_t index ) {
[4223317]403 string ret = { *s.inner, index, 1 };
404 return ret`share;
[f450f2f]405}
406
407////////////////////////////////////////////////////////
408// Search
409
[4dab7e8]410bool contains( const string & s, char ch ) {
[4223317]411 return contains( *s.inner, ch );
[f450f2f]412}
413
[9018dcf]414size_t find( const string & s, size_t start, size_t len, const string & key, size_t kstart, size_t klen ) {
[ed5023d1]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;
[9018dcf]424
[ed5023d1]425 return findFrom( *s.inner, start, *key.inner );
[f450f2f]426}
427
[9018dcf]428size_t find( const string & s, char key ) {
[ed5023d1]429 return find( *s.inner, key );
[f450f2f]430}
431
[9018dcf]432size_t find( const string & s, const string & key ) {
[ed5023d1]433 return find( *s.inner, *key.inner );
[f450f2f]434}
435
[9018dcf]436size_t find( const string & s, const char * key ) {
[ed5023d1]437 return find( *s.inner, key );
[f450f2f]438}
439
[9018dcf]440size_t find( const string & s, const char * key, size_t keysize ) {
[ed5023d1]441 return find( *s.inner, key, keysize );
[08ed947]442}
443
[9018dcf]444size_t find( const string & s, size_t start, char key ) {
[ed5023d1]445 return findFrom( *s.inner, start, key );
[08ed947]446}
447
[9018dcf]448size_t find( const string & s, size_t start, const char * key ) {
[ed5023d1]449 return findFrom( *s.inner, start, key );
[08ed947]450}
451
[9018dcf]452size_t find( const string & s, size_t start, const char * key, size_t keysize ) {
[ed5023d1]453 return findFrom( *s.inner, start, key, keysize );
[08ed947]454}
455
[ed5023d1]456bool includes( const string & s, const string & mask ) {
457 return includes( *s.inner, *mask.inner );
[f450f2f]458}
459
[ed5023d1]460bool includes( const string & s, const char * mask ) {
461 return includes( *s.inner, mask );
[f450f2f]462}
463
[ed5023d1]464bool includes( const string & s, const char * mask, size_t masksize ) {
465 return includes( *s.inner, mask, masksize );
[f450f2f]466}
467
[4dab7e8]468bool startsWith( const string & s, const string & prefix ) {
[4223317]469 return startsWith( *s.inner, *prefix.inner );
[f450f2f]470}
471
[4dab7e8]472bool startsWith( const string & s, const char * prefix ) {
[4223317]473 return startsWith( *s.inner, prefix );
[f450f2f]474}
475
[4dab7e8]476bool startsWith( const string & s, const char * prefix, size_t prefixsize ) {
[4223317]477 return startsWith( *s.inner, prefix, prefixsize );
[f450f2f]478}
479
[4dab7e8]480bool endsWith( const string & s, const string & suffix ) {
[4223317]481 return endsWith( *s.inner, *suffix.inner );
[f450f2f]482}
483
[4dab7e8]484bool endsWith( const string & s, const char * suffix ) {
[4223317]485 return endsWith( *s.inner, suffix );
[f450f2f]486}
487
[4dab7e8]488bool endsWith( const string & s, const char * suffix, size_t suffixsize ) {
[4223317]489 return endsWith( *s.inner, suffix, suffixsize );
[f450f2f]490}
491
492
493///////////////////////////////////////////////////////////////////////////
494// charclass, include, exclude
495
[4dab7e8]496void ?{}( charclass & s, const string & chars ) {
[4223317]497 (s.inner) { malloc() };
498 ?{}( *s.inner, *(const string_res *)chars.inner );
[f450f2f]499}
500
[681e12f]501void ?{}( charclass & s, const char * chars ) {
[4223317]502 (s.inner) { malloc() };
503 ?{}( *s.inner, chars );
[f450f2f]504}
505
[681e12f]506void ?{}( charclass & s, const char * chars, size_t charssize ) {
[4223317]507 (s.inner) { malloc() };
508 ?{}( *s.inner, chars, charssize );
[f450f2f]509}
510
[681e12f]511void ^?{}( charclass & s ) {
[4223317]512 ^(*s.inner){};
513 free( s.inner );
514 s.inner = 0p;
[f450f2f]515}
516
[9018dcf]517size_t exclude( const string & s, const charclass & mask ) {
[4223317]518 return exclude( *s.inner, *mask.inner );
[f450f2f]519}
520
[9018dcf]521size_t include( const string & s, const charclass & mask ) {
[4223317]522 return include( *s.inner, *mask.inner );
[f450f2f]523}
524
[9018dcf]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;
[f450f2f]553}
Note: See TracBrowser for help on using the repository browser.