source: libcfa/src/collections/string.cfa@ 831b2ec

Last change on this file since 831b2ec was 9018dcf, checked in by Peter A. Buhr <pabuhr@…>, 10 months ago

updates to string type

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