source: libcfa/src/collections/string.cfa@ 15eebd4

Last change on this file since 15eebd4 was 5ad6f0d, checked in by Peter A. Buhr <pabuhr@…>, 10 months ago

more inlining, add strnlen and strncmp for string type

  • Property mode set to 100644
File size: 12.5 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
[5ad6f0d]12// Last Modified On : Sun Apr 13 07:58:55 2025
13// Update Count : 390
[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
[5ad6f0d]205////////////////////////////////////////////////////////
206// Getter
207
208size_t strnlen( const string & s, size_t maxlen ) { return min( len( s ), maxlen ); }
209
[f450f2f]210////////////////////////////////////////////////////////
[d32679d5]211// Input-Output
[f450f2f]212
[3f631d6]213forall( ostype & | basic_ostream( ostype ) ) {
214 ostype & ?|?( ostype & out, string s ) {
215 return out | (*s.inner); // print internal string_res
216 }
[f450f2f]217
[3f631d6]218 void ?|?( ostype & out, string s ) {
219 (ostype &)(out | (*s.inner)); ends( out );
220 }
[34c6e1e6]221
[3f631d6]222 ostype & ?|?( ostype & os, _Ostream_Manip(string) f ) {
223 size_t l = len( f.val );
224 char cstr[l + 1]; // room for null terminator
225 for ( i; l ) cstr[i] = f.val[i]; // copy string
226 cstr[l] = '\0'; // terminate
227 _Ostream_Manip(const char *) cf @= { cstr, f.wd, f.pc, f.base, {f.all} };
228 return os | cf | nonl;
229 } // ?|?
[34c6e1e6]230
[3f631d6]231 void ?|?( ostype & os, _Ostream_Manip(string) f ) {
232 (ostype &)(os | f); ends( os );
233 }
[d32679d5]234}
235
[3f631d6]236forall( istype & | basic_istream( istype ) ) {
237 istype & ?|?( istype & in, string & s ) {
238 return in | (*s.inner); // read to internal string_res
239 }
240
[30548de]241 istype & ?|?( istype & is, _Istream_Squote f ) {
242 _Istream_Rquote f2 = { { f.sstr.s.inner, (_Istream_str_base)f.sstr } };
[3f631d6]243 return is | f2;
244 } // ?|?
245
246 istype & ?|?( istype & is, _Istream_Sstr f ) {
247 // _Istream_Rstr f2 = {f.sstr.s.inner, (_Istream_str_base)f.sstr};
248 _Istream_Rstr f2 = {f.s.inner, (_Istream_str_base)f};
249 return is | f2;
250 } // ?|?
251}
[7e1dbd7]252
[f450f2f]253////////////////////////////////////////////////////////
254// Slicing
255
[4223317]256string ?()( string & s, ssize_t start, ssize_t len ) {
[ee70ff5]257 if ( start < 0 ) { start += len( s ); }
[4223317]258 if ( len < 0 ) { len = -len; start -= len; }
[ed5023d1]259 if ( start >= len( s ) ) return (string){ "" };
[ee70ff5]260 if ( start + len > len( s ) ) len = len( s ) - start;
[4223317]261 string ret = { *s.inner, start, len };
262 return ret`share;
[f450f2f]263}
264
[4223317]265string ?()( string & s, ssize_t start ) {
[ee70ff5]266 if ( start < 0 ) { start += len( s ); }
267 string ret = { *s.inner, start, len( s ) - start };
[4223317]268 return ret`share;
[bc9f84a]269}
270
[f450f2f]271////////////////////////////////////////////////////////
272// Concatenation
273
[4dab7e8]274void ?+=?( string & s, char c ) {
[4223317]275 (*s.inner) += c;
[f450f2f]276}
277
[c4f8c4bf]278PBOOST void ?+=?( string & s, string s2 ) {
[4223317]279 (*s.inner) += (*s2.inner);
[f450f2f]280}
281
[4dab7e8]282void append( string & s, const string & s2, size_t maxlen ) {
[4223317]283 append( (*s.inner), (*s2.inner), maxlen );
[e891349]284}
285
[4dab7e8]286void ?+=?( string & s, const char * c ) {
[4223317]287 (*s.inner) += c;
[f450f2f]288}
289
[4dab7e8]290void append( string & s, const char * buffer, size_t bsize ) {
[4223317]291 append( (*s.inner), buffer, bsize );
[e891349]292}
293
[570e7ad]294string ?+?( string s, char c ) {
[4223317]295 string ret = s;
296 ret += c;
297 return ret;
[4dab7e8]298}
299
[570e7ad]300string ?+?( char c, string s ) {
[96a11655]301 string ret = c;
302 ret += s;
[4223317]303 return ret;
[f450f2f]304}
305
[d03a386]306PBOOST string ?+?( string s, string s2 ) {
[4223317]307 string ret = s;
308 ret += s2;
309 return ret;
[f450f2f]310}
311
[4dab7e8]312string ?+?( const char * s, char c ) {
[4223317]313 string ret = s;
314 ret += c;
315 return ret;
[4dab7e8]316}
317
318string ?+?( char c, const char * s ) {
[4223317]319 string ret = c;
320 ret += s;
321 return ret;
[4dab7e8]322}
323
324string ?+?( const char * s1, const char * s2 ) {
[4223317]325 string ret = s1;
326 ret += s2;
327 return ret;
[4dab7e8]328}
329
[570e7ad]330string ?+?( const char * s1, string s2 ) {
[4223317]331 string ret = s1;
332 ret += s2;
333 return ret;
[f450f2f]334}
335
[570e7ad]336string ?+?( string s, const char * c ) {
[4223317]337 string ret = s;
338 ret += c;
339 return ret;
[f450f2f]340}
341
[ee70ff5]342string ?+?( char c1, char c2 ) {
343 string ret = c1;
344 ret += c2;
345 return ret;
346}
347
[f450f2f]348////////////////////////////////////////////////////////
349// Repetition
350
[570e7ad]351void ?*=?( string & s, strmul_factor_t factor ) {
[4223317]352 (*s.inner) *= factor;
[f450f2f]353}
354
[d03a386]355PBOOST string ?*?( string s, strmul_factor_t factor ) {
[4223317]356 string ret = s;
357 ret *= factor;
358 return ret;
[479fbe3]359}
360
[570e7ad]361string ?*?( char c, strmul_factor_t factor ) {
[4223317]362 string ret = c;
363 ret *= factor;
364 return ret;
[f450f2f]365}
366
[570e7ad]367string ?*?( const char * s, strmul_factor_t factor ) {
[4223317]368 string ret = s;
369 ret *= factor;
370 return ret;
[f450f2f]371}
372
373////////////////////////////////////////////////////////
374// Character access
375
[4dab7e8]376char ?[?]( const string & s, size_t index ) {
[4223317]377 return (*s.inner)[index];
[f450f2f]378}
379
[4dab7e8]380string ?[?]( string & s, size_t index ) {
[4223317]381 string ret = { *s.inner, index, 1 };
382 return ret`share;
[f450f2f]383}
384
[5ad6f0d]385////////////////////////////////////////////////////////
386// Comparison
387
388#define STRNCPY_FMT "**** Error **** strncpy: maximum length %zu is greater than string lengths %zd or %zd."
389
390int strncmp( const string & s1, const string & s2, size_t maxlen ) {
391 if ( maxlen > len( s1 ) || maxlen > len( s2 ) ) {
392 abort( STRNCPY_FMT, maxlen, len( s1 ), len( s2 ) );
393 } // if
394 return strcmp$( s1.inner->Handle.s, maxlen, s2.inner->Handle.s, maxlen );
395}
396
397int strncmp( const string & s1, const char * s2, size_t maxlen ) {
398 size_t s2len = len( s2 );
399 if ( maxlen > len( s1 ) || maxlen > s2len ) {
400 abort( STRNCPY_FMT, maxlen, len( s1 ), s2len );
401 } // if
402 return strcmp$( s1.inner->Handle.s, maxlen, s2, maxlen );
403}
404
405int strncmp( const char * s1, const string & s2, size_t maxlen ) {
406 size_t s1len = len( s1 );
407 if ( maxlen > s1len || maxlen > len( s2 ) ) {
408 abort( STRNCPY_FMT, maxlen, s1len, len( s2 ) );
409 } // if
410 return strcmp$( s1, maxlen, s2.inner->Handle.s, maxlen );
411}
412
[f450f2f]413////////////////////////////////////////////////////////
414// Search
415
[4dab7e8]416bool contains( const string & s, char ch ) {
[4223317]417 return contains( *s.inner, ch );
[f450f2f]418}
419
[9018dcf]420size_t find( const string & s, size_t start, size_t len, const string & key, size_t kstart, size_t klen ) {
[ed5023d1]421 if ( start < 0 ) { start += len( s ); }
422 if ( len < 0 ) { len = -len; start -= len; }
423 if ( start >= len( s ) ) return 0;
424 if ( start + len > len( s ) ) len = len( s ) - start;
425
426 if ( kstart < 0 ) { kstart += len( key ); }
427 if ( klen < 0 ) { klen = -klen; kstart -= klen; }
428 if ( kstart >= len( key ) ) return 0;
429 if ( kstart + klen > len( key ) ) klen = len( key ) - kstart;
[9018dcf]430
[ed5023d1]431 return findFrom( *s.inner, start, *key.inner );
[f450f2f]432}
433
[9018dcf]434size_t find( const string & s, char key ) {
[ed5023d1]435 return find( *s.inner, key );
[f450f2f]436}
437
[9018dcf]438size_t find( const string & s, const string & key ) {
[ed5023d1]439 return find( *s.inner, *key.inner );
[f450f2f]440}
441
[9018dcf]442size_t find( const string & s, const char * key ) {
[ed5023d1]443 return find( *s.inner, key );
[f450f2f]444}
445
[9018dcf]446size_t find( const string & s, const char * key, size_t keysize ) {
[ed5023d1]447 return find( *s.inner, key, keysize );
[08ed947]448}
449
[9018dcf]450size_t find( const string & s, size_t start, char key ) {
[ed5023d1]451 return findFrom( *s.inner, start, key );
[08ed947]452}
453
[9018dcf]454size_t find( const string & s, size_t start, const char * key ) {
[ed5023d1]455 return findFrom( *s.inner, start, key );
[08ed947]456}
457
[9018dcf]458size_t find( const string & s, size_t start, const char * key, size_t keysize ) {
[ed5023d1]459 return findFrom( *s.inner, start, key, keysize );
[08ed947]460}
461
[ed5023d1]462bool includes( const string & s, const string & mask ) {
463 return includes( *s.inner, *mask.inner );
[f450f2f]464}
465
[ed5023d1]466bool includes( const string & s, const char * mask ) {
467 return includes( *s.inner, mask );
[f450f2f]468}
469
[ed5023d1]470bool includes( const string & s, const char * mask, size_t masksize ) {
471 return includes( *s.inner, mask, masksize );
[f450f2f]472}
473
[4dab7e8]474bool startsWith( const string & s, const string & prefix ) {
[4223317]475 return startsWith( *s.inner, *prefix.inner );
[f450f2f]476}
477
[4dab7e8]478bool startsWith( const string & s, const char * prefix ) {
[4223317]479 return startsWith( *s.inner, prefix );
[f450f2f]480}
481
[4dab7e8]482bool startsWith( const string & s, const char * prefix, size_t prefixsize ) {
[4223317]483 return startsWith( *s.inner, prefix, prefixsize );
[f450f2f]484}
485
[4dab7e8]486bool endsWith( const string & s, const string & suffix ) {
[4223317]487 return endsWith( *s.inner, *suffix.inner );
[f450f2f]488}
489
[4dab7e8]490bool endsWith( const string & s, const char * suffix ) {
[4223317]491 return endsWith( *s.inner, suffix );
[f450f2f]492}
493
[4dab7e8]494bool endsWith( const string & s, const char * suffix, size_t suffixsize ) {
[4223317]495 return endsWith( *s.inner, suffix, suffixsize );
[f450f2f]496}
497
498
499///////////////////////////////////////////////////////////////////////////
500// charclass, include, exclude
501
[4dab7e8]502void ?{}( charclass & s, const string & chars ) {
[4223317]503 (s.inner) { malloc() };
504 ?{}( *s.inner, *(const string_res *)chars.inner );
[f450f2f]505}
506
[681e12f]507void ?{}( charclass & s, const char * chars ) {
[4223317]508 (s.inner) { malloc() };
509 ?{}( *s.inner, chars );
[f450f2f]510}
511
[681e12f]512void ?{}( charclass & s, const char * chars, size_t charssize ) {
[4223317]513 (s.inner) { malloc() };
514 ?{}( *s.inner, chars, charssize );
[f450f2f]515}
516
[681e12f]517void ^?{}( charclass & s ) {
[4223317]518 ^(*s.inner){};
519 free( s.inner );
520 s.inner = 0p;
[f450f2f]521}
522
[9018dcf]523size_t exclude( const string & s, const charclass & mask ) {
[4223317]524 return exclude( *s.inner, *mask.inner );
[f450f2f]525}
526
[9018dcf]527size_t include( const string & s, const charclass & mask ) {
[4223317]528 return include( *s.inner, *mask.inner );
[f450f2f]529}
530
[5ad6f0d]531size_t include( const string & s, int (*f)( int ) ) {
[9018dcf]532 size_t l = len( s );
533 for ( i; l ) {
534 if ( ! f( s[i] ) ) return i;
535 } // for
536 return l;
537}
538
[5ad6f0d]539size_t exclude( const string & s, int (*f)( int ) ) {
540 size_t l = len( s );
541 for ( i; l ) {
542 if ( f( s[i] ) ) return i;
543 } // for
544 return l;
545}
546
547string replace( const string & s, const string & from, const string & to ) {
[9018dcf]548 ssize_t pos;
549 string r;
550
551 pos = find( s, from );
552 if ( pos < len( s ) ) {
553 r = s( 0, pos ) + to + replace( s( pos + (ssize_t)len( from ) ), from, to );
554 } else {
555 r = s;
556 } // if
557 return r;
558}
559
560string translate( const string & s, int (*f)( int ) ) {
561 string r = s;
562 size_t l = len( r );
563 for ( i; l ) {
564 r[i] = (char)f( r[i] );
565 } // for
566 return r;
[f450f2f]567}
Note: See TracBrowser for help on using the repository browser.