source: libcfa/src/collections/string.cfa@ 2f16569

Last change on this file since 2f16569 was 2f16569, checked in by Peter A. Buhr <pabuhr@…>, 21 hours ago

remove string 'contains' function and replace with 'includes', make string 'includes' inline

  • Property mode set to 100644
File size: 12.7 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
[2f16569]12// Last Modified On : Fri May 8 07:41:00 2026
13// Update Count : 409
[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
[d8a2f98]59void ?{}( string & s, const char * cs ) {
[4223317]60 (s.inner) { malloc() };
[d8a2f98]61 ?{}( *s.inner, cs );
[479fbe3]62}
63
[d8a2f98]64void ?{}( string & s, const char * cs , size_t size ) {
[4223317]65 (s.inner) { malloc() };
[d8a2f98]66 ?{}( *s.inner, cs, size );
[f450f2f]67}
68
[2f16569]69void ?{}( string & s, size_t rhs ) {
[4223317]70 (s.inner) { malloc() };
71 ?{}( *s.inner, rhs );
[f2898df]72}
73
[2f16569]74void ?{}( string & s, ssize_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
[681e12f]99void ^?{}( string & s ) {
[4223317]100 ^(*s.inner){};
101 free( s.inner );
102 s.inner = 0p;
[f450f2f]103}
104
105////////////////////////////////////////////////////////
106// Alternate construction: request shared edits
107
[8c2723f]108string_Share ?`share( string & s ) {
[4223317]109 string_Share ret = { &s };
110 return ret;
[f450f2f]111}
112
[8c2723f]113void ?{}( string & s, string_Share src ) {
[4223317]114 ?{}( s, *src.s->inner, 0, src.s->inner->Handle.lnth );
[f450f2f]115}
116
117////////////////////////////////////////////////////////
118// Assignment
119
[2f16569]120PBOOST string & ?=?( string & s, string rhs ) {
121 (*s.inner) = (*rhs.inner);
[4223317]122 return s;
[906d8fa]123}
[f450f2f]124
[2f16569]125string & ?=?( string & s, char rhs ) {
126 (*s.inner) = rhs;
[4223317]127 return s;
[f450f2f]128}
129
[2f16569]130string & ?=?( string & s, const char * rhs ) {
131 (*s.inner) = rhs;
[4223317]132 return s;
[b1eefe50]133}
134
[2f16569]135string & assign( string & s, const string & rhs, size_t n ) {
136 assign( *s.inner, *rhs.inner, n );
[4223317]137 return s;
[e891349]138}
[b1eefe50]139
[2f16569]140string & assign( string & s, const char * rhs, size_t n ) {
141 assign( *s.inner, rhs, n );
[4223317]142 return s;
[e891349]143}
144
[2f16569]145string & ?=?( string & s, size_t rhs ) {
[4223317]146 (*s.inner) = rhs;
147 return s;
[f2898df]148}
149
[2f16569]150string & ?=?( string & s, ssize_t rhs ) {
[4223317]151 (*s.inner) = rhs;
152 return s;
[f2898df]153}
154
155string & ?=?( string & s, double rhs ) {
[4223317]156 (*s.inner) = rhs;
157 return s;
[f2898df]158}
159
160string & ?=?( string & s, long double rhs ) {
[4223317]161 (*s.inner) = rhs;
162 return s;
[f2898df]163}
164
165string & ?=?( string & s, double _Complex rhs ) {
[4223317]166 (*s.inner) = rhs;
167 return s;
[f2898df]168}
169
170string & ?=?( string & s, long double _Complex rhs ) {
[4223317]171 (*s.inner) = rhs;
172 return s;
[f2898df]173}
[f450f2f]174
[5ad6f0d]175////////////////////////////////////////////////////////
[829a955]176// C-style
177
178// safe conversion from string to char *
179char * strncpy( char * dst, string & src, size_t n ) {
180 size_t l = min( n - 1, len( src ) ); // ensure null terminated
181 for ( i; l ) dst[i] = src[i];
182 dst[l] = '\0';
183 return dst;
184}
185char * ?=?( char *& dst, string & src ) {
186 dst = aalloc( len( src ) + 1 ); // ensure null terminated
187 for ( i; len( src ) ) dst[i] = src[i];
188 dst[len(src)] = '\0';
189 return dst;
190}
191void ?{}( char *& dst, string & src ) {
192 dst = aalloc( len( src ) + 1 ); // ensure null terminated
193 for ( i; len( src ) ) dst[i] = src[i];
194 dst[len(src)] = '\0';
195}
[5ad6f0d]196
197size_t strnlen( const string & s, size_t maxlen ) { return min( len( s ), maxlen ); }
198
[f450f2f]199////////////////////////////////////////////////////////
[d32679d5]200// Input-Output
[f450f2f]201
[3f631d6]202forall( ostype & | basic_ostream( ostype ) ) {
203 ostype & ?|?( ostype & out, string s ) {
204 return out | (*s.inner); // print internal string_res
205 }
[f450f2f]206
[ae0c1c3]207 void ?|?( ostype & out, string s ) with ( basic_ostream_table ) {
[3f631d6]208 (ostype &)(out | (*s.inner)); ends( out );
209 }
[34c6e1e6]210
[3f631d6]211 ostype & ?|?( ostype & os, _Ostream_Manip(string) f ) {
212 size_t l = len( f.val );
213 char cstr[l + 1]; // room for null terminator
214 for ( i; l ) cstr[i] = f.val[i]; // copy string
215 cstr[l] = '\0'; // terminate
[bb1eabc]216 _Ostream_Manip(const char *) cf @= { cstr, f.wd, f.pc, f.base, {f.all}, f.qleft, f.qright };
[3f631d6]217 return os | cf | nonl;
218 } // ?|?
[34c6e1e6]219
[ae0c1c3]220 void ?|?( ostype & os, _Ostream_Manip(string) f ) with ( basic_ostream_table ) {
[3f631d6]221 (ostype &)(os | f); ends( os );
222 }
[d32679d5]223}
224
[3f631d6]225forall( istype & | basic_istream( istype ) ) {
226 istype & ?|?( istype & in, string & s ) {
227 return in | (*s.inner); // read to internal string_res
228 }
229
[30548de]230 istype & ?|?( istype & is, _Istream_Squote f ) {
231 _Istream_Rquote f2 = { { f.sstr.s.inner, (_Istream_str_base)f.sstr } };
[3f631d6]232 return is | f2;
233 } // ?|?
234
235 istype & ?|?( istype & is, _Istream_Sstr f ) {
236 // _Istream_Rstr f2 = {f.sstr.s.inner, (_Istream_str_base)f.sstr};
237 _Istream_Rstr f2 = {f.s.inner, (_Istream_str_base)f};
238 return is | f2;
239 } // ?|?
240}
[7e1dbd7]241
[f450f2f]242////////////////////////////////////////////////////////
243// Slicing
244
[4223317]245string ?()( string & s, ssize_t start, ssize_t len ) {
[5b21636b]246 if ( start < 0 ) start += len( s );
247 if ( len < 0 ) { len = -len; start -= len - 1; }
248 if ( start < 0 || start >= len( s ) ) return (string){ "" };
249 if ( start + len > len( s ) ) len = len( s ) - start;
[4223317]250 string ret = { *s.inner, start, len };
251 return ret`share;
[f450f2f]252}
253
[4223317]254string ?()( string & s, ssize_t start ) {
[ee70ff5]255 if ( start < 0 ) { start += len( s ); }
256 string ret = { *s.inner, start, len( s ) - start };
[4223317]257 return ret`share;
[bc9f84a]258}
259
[f450f2f]260////////////////////////////////////////////////////////
261// Concatenation
262
[4dab7e8]263void ?+=?( string & s, char c ) {
[4223317]264 (*s.inner) += c;
[f450f2f]265}
266
[c4f8c4bf]267PBOOST void ?+=?( string & s, string s2 ) {
[4223317]268 (*s.inner) += (*s2.inner);
[f450f2f]269}
270
[4dab7e8]271void append( string & s, const string & s2, size_t maxlen ) {
[4223317]272 append( (*s.inner), (*s2.inner), maxlen );
[e891349]273}
274
[d8a2f98]275void ?+=?( string & s, const char * cs ) {
276 (*s.inner) += cs;
[f450f2f]277}
278
[4dab7e8]279void append( string & s, const char * buffer, size_t bsize ) {
[4223317]280 append( (*s.inner), buffer, bsize );
[e891349]281}
282
[570e7ad]283string ?+?( string s, char c ) {
[4223317]284 string ret = s;
285 ret += c;
286 return ret;
[4dab7e8]287}
288
[570e7ad]289string ?+?( char c, string s ) {
[96a11655]290 string ret = c;
291 ret += s;
[4223317]292 return ret;
[f450f2f]293}
294
[d03a386]295PBOOST string ?+?( string s, string s2 ) {
[4223317]296 string ret = s;
297 ret += s2;
298 return ret;
[f450f2f]299}
300
[d8a2f98]301string ?+?( const char * cs, char c ) {
302 string ret = cs;
[4223317]303 ret += c;
304 return ret;
[4dab7e8]305}
306
[d8a2f98]307string ?+?( char c, const char * cs ) {
[4223317]308 string ret = c;
[d8a2f98]309 ret += cs;
[4223317]310 return ret;
[4dab7e8]311}
312
[d8a2f98]313string ?+?( const char * cs1, const char * cs2 ) {
314 string ret = cs1;
315 ret += cs2;
[4223317]316 return ret;
[4dab7e8]317}
318
[d8a2f98]319string ?+?( const char * cs, string s ) {
320 string ret = cs;
321 ret += s;
[4223317]322 return ret;
[f450f2f]323}
324
[d8a2f98]325string ?+?( string s, const char * cs ) {
[4223317]326 string ret = s;
[d8a2f98]327 ret += cs;
[4223317]328 return ret;
[f450f2f]329}
330
[ee70ff5]331string ?+?( char c1, char c2 ) {
332 string ret = c1;
333 ret += c2;
334 return ret;
335}
336
[f450f2f]337////////////////////////////////////////////////////////
338// Repetition
339
[570e7ad]340void ?*=?( string & s, strmul_factor_t factor ) {
[4223317]341 (*s.inner) *= factor;
[f450f2f]342}
343
[d03a386]344PBOOST string ?*?( string s, strmul_factor_t factor ) {
[4223317]345 string ret = s;
346 ret *= factor;
347 return ret;
[479fbe3]348}
349
[570e7ad]350string ?*?( char c, strmul_factor_t factor ) {
[4223317]351 string ret = c;
352 ret *= factor;
353 return ret;
[f450f2f]354}
355
[d8a2f98]356string ?*?( const char * cs, strmul_factor_t factor ) {
357 string ret = cs;
[4223317]358 ret *= factor;
359 return ret;
[f450f2f]360}
361
362////////////////////////////////////////////////////////
363// Character access
364
[4dab7e8]365char ?[?]( const string & s, size_t index ) {
[4223317]366 return (*s.inner)[index];
[f450f2f]367}
368
[4dab7e8]369string ?[?]( string & s, size_t index ) {
[4223317]370 string ret = { *s.inner, index, 1 };
371 return ret`share;
[f450f2f]372}
373
[5ad6f0d]374////////////////////////////////////////////////////////
375// Comparison
376
377#define STRNCPY_FMT "**** Error **** strncpy: maximum length %zu is greater than string lengths %zd or %zd."
378
[d8a2f98]379int strncmp( const string & s, const string & s2, size_t maxlen ) {
380 if ( maxlen > len( s ) || maxlen > len( s2 ) ) {
381 abort( STRNCPY_FMT, maxlen, len( s ), len( s2 ) );
[5ad6f0d]382 } // if
[d8a2f98]383 return strcmp$( s.inner->Handle.s, maxlen, s2.inner->Handle.s, maxlen );
[5ad6f0d]384}
385
[d8a2f98]386int strncmp( const string & s, const char * cs, size_t maxlen ) {
387 size_t cslen = len( cs );
388 if ( maxlen > len( s ) || maxlen > cslen ) {
389 abort( STRNCPY_FMT, maxlen, len( s ), cslen );
[5ad6f0d]390 } // if
[d8a2f98]391 return strcmp$( s.inner->Handle.s, maxlen, cs, maxlen );
[5ad6f0d]392}
393
[d8a2f98]394int strncmp( const char * s, const string & cs, size_t maxlen ) {
395 size_t slen = len( s );
396 if ( maxlen > slen || maxlen > len( cs ) ) {
397 abort( STRNCPY_FMT, maxlen, slen, len( cs ) );
[5ad6f0d]398 } // if
[d8a2f98]399 return strcmp$( s, maxlen, cs.inner->Handle.s, maxlen );
[5ad6f0d]400}
401
[f450f2f]402////////////////////////////////////////////////////////
403// Search
404
[9018dcf]405size_t find( const string & s, size_t start, size_t len, const string & key, size_t kstart, size_t klen ) {
[ed5023d1]406 if ( start < 0 ) { start += len( s ); }
407 if ( len < 0 ) { len = -len; start -= len; }
408 if ( start >= len( s ) ) return 0;
409 if ( start + len > len( s ) ) len = len( s ) - start;
410
411 if ( kstart < 0 ) { kstart += len( key ); }
412 if ( klen < 0 ) { klen = -klen; kstart -= klen; }
413 if ( kstart >= len( key ) ) return 0;
414 if ( kstart + klen > len( key ) ) klen = len( key ) - kstart;
[9018dcf]415
[ed5023d1]416 return findFrom( *s.inner, start, *key.inner );
[f450f2f]417}
418
[9018dcf]419size_t find( const string & s, char key ) {
[ed5023d1]420 return find( *s.inner, key );
[f450f2f]421}
422
[9018dcf]423size_t find( const string & s, const string & key ) {
[ed5023d1]424 return find( *s.inner, *key.inner );
[f450f2f]425}
426
[9018dcf]427size_t find( const string & s, const char * key ) {
[ed5023d1]428 return find( *s.inner, key );
[f450f2f]429}
430
[9018dcf]431size_t find( const string & s, const char * key, size_t keysize ) {
[ed5023d1]432 return find( *s.inner, key, keysize );
[08ed947]433}
434
[9018dcf]435size_t find( const string & s, size_t start, char key ) {
[ed5023d1]436 return findFrom( *s.inner, start, key );
[08ed947]437}
438
[9018dcf]439size_t find( const string & s, size_t start, const char * key ) {
[ed5023d1]440 return findFrom( *s.inner, start, key );
[08ed947]441}
442
[9018dcf]443size_t find( const string & s, size_t start, const char * key, size_t keysize ) {
[ed5023d1]444 return findFrom( *s.inner, start, key, keysize );
[08ed947]445}
446
[2f16569]447// bool includes( const string & s, const string & search ) {
448// return includes( *s.inner, *search.inner );
449// }
[f450f2f]450
[2f16569]451// bool includes( const string & s, const char * search ) {
452// return includes( *s.inner, search );
453// }
[f450f2f]454
[2f16569]455// bool includes( const string & s, const char * search, size_t searchsize ) {
456// return includes( *s.inner, search, searchsize );
457// }
[f450f2f]458
[4dab7e8]459bool startsWith( const string & s, const string & prefix ) {
[4223317]460 return startsWith( *s.inner, *prefix.inner );
[f450f2f]461}
462
[4dab7e8]463bool startsWith( const string & s, const char * prefix ) {
[4223317]464 return startsWith( *s.inner, prefix );
[f450f2f]465}
466
[4dab7e8]467bool startsWith( const string & s, const char * prefix, size_t prefixsize ) {
[4223317]468 return startsWith( *s.inner, prefix, prefixsize );
[f450f2f]469}
470
[4dab7e8]471bool endsWith( const string & s, const string & suffix ) {
[4223317]472 return endsWith( *s.inner, *suffix.inner );
[f450f2f]473}
474
[4dab7e8]475bool endsWith( const string & s, const char * suffix ) {
[4223317]476 return endsWith( *s.inner, suffix );
[f450f2f]477}
478
[4dab7e8]479bool endsWith( const string & s, const char * suffix, size_t suffixsize ) {
[4223317]480 return endsWith( *s.inner, suffix, suffixsize );
[f450f2f]481}
482
483
484///////////////////////////////////////////////////////////////////////////
485// charclass, include, exclude
486
[4dab7e8]487void ?{}( charclass & s, const string & chars ) {
[4223317]488 (s.inner) { malloc() };
489 ?{}( *s.inner, *(const string_res *)chars.inner );
[f450f2f]490}
491
[681e12f]492void ?{}( charclass & s, const char * chars ) {
[4223317]493 (s.inner) { malloc() };
494 ?{}( *s.inner, chars );
[f450f2f]495}
496
[681e12f]497void ?{}( charclass & s, const char * chars, size_t charssize ) {
[4223317]498 (s.inner) { malloc() };
499 ?{}( *s.inner, chars, charssize );
[f450f2f]500}
501
[681e12f]502void ^?{}( charclass & s ) {
[4223317]503 ^(*s.inner){};
504 free( s.inner );
505 s.inner = 0p;
[f450f2f]506}
507
[9018dcf]508size_t exclude( const string & s, const charclass & mask ) {
[4223317]509 return exclude( *s.inner, *mask.inner );
[f450f2f]510}
511
[9018dcf]512size_t include( const string & s, const charclass & mask ) {
[4223317]513 return include( *s.inner, *mask.inner );
[f450f2f]514}
515
[5ad6f0d]516size_t include( const string & s, int (*f)( int ) ) {
[9018dcf]517 size_t l = len( s );
518 for ( i; l ) {
519 if ( ! f( s[i] ) ) return i;
520 } // for
521 return l;
522}
523
[5ad6f0d]524size_t exclude( const string & s, int (*f)( int ) ) {
525 size_t l = len( s );
526 for ( i; l ) {
527 if ( f( s[i] ) ) return i;
528 } // for
529 return l;
530}
531
532string replace( const string & s, const string & from, const string & to ) {
[9018dcf]533 ssize_t pos;
534 string r;
535
536 pos = find( s, from );
537 if ( pos < len( s ) ) {
538 r = s( 0, pos ) + to + replace( s( pos + (ssize_t)len( from ) ), from, to );
539 } else {
540 r = s;
541 } // if
542 return r;
543}
544
545string translate( const string & s, int (*f)( int ) ) {
546 string r = s;
547 size_t l = len( r );
548 for ( i; l ) {
549 r[i] = (char)f( r[i] );
550 } // for
551 return r;
[f450f2f]552}
Note: See TracBrowser for help on using the repository browser.