source: libcfa/src/collections/string.cfa@ 7592f42

Last change on this file since 7592f42 was ae0c1c3, checked in by Andrew Beach <ajbeach@…>, 6 months ago

Rewrote the iostream traits to have a single assertion each, a table containing function pointers. This is just an experiment right now. It seems that it does cause significant speed up of assertion resolution, but for some reason also seems to add a flat overhead that mostly eats up that saving.

  • Property mode set to 100644
File size: 12.5 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 : Sun Apr 13 07:58:55 2025
13// Update Count : 390
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// Getter
207
208size_t strnlen( const string & s, size_t maxlen ) { return min( len( s ), maxlen ); }
209
210////////////////////////////////////////////////////////
211// Input-Output
212
213forall( ostype & | basic_ostream( ostype ) ) {
214 ostype & ?|?( ostype & out, string s ) {
215 return out | (*s.inner); // print internal string_res
216 }
217
218 void ?|?( ostype & out, string s ) with ( basic_ostream_table ) {
219 (ostype &)(out | (*s.inner)); ends( out );
220 }
221
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 } // ?|?
230
231 void ?|?( ostype & os, _Ostream_Manip(string) f ) with ( basic_ostream_table ) {
232 (ostype &)(os | f); ends( os );
233 }
234}
235
236forall( istype & | basic_istream( istype ) ) {
237 istype & ?|?( istype & in, string & s ) {
238 return in | (*s.inner); // read to internal string_res
239 }
240
241 istype & ?|?( istype & is, _Istream_Squote f ) {
242 _Istream_Rquote f2 = { { f.sstr.s.inner, (_Istream_str_base)f.sstr } };
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}
252
253////////////////////////////////////////////////////////
254// Slicing
255
256string ?()( string & s, ssize_t start, ssize_t len ) {
257 if ( start < 0 ) { start += len( s ); }
258 if ( len < 0 ) { len = -len; start -= len; }
259 if ( start >= len( s ) ) return (string){ "" };
260 if ( start + len > len( s ) ) len = len( s ) - start;
261 string ret = { *s.inner, start, len };
262 return ret`share;
263}
264
265string ?()( string & s, ssize_t start ) {
266 if ( start < 0 ) { start += len( s ); }
267 string ret = { *s.inner, start, len( s ) - start };
268 return ret`share;
269}
270
271////////////////////////////////////////////////////////
272// Concatenation
273
274void ?+=?( string & s, char c ) {
275 (*s.inner) += c;
276}
277
278PBOOST void ?+=?( string & s, string s2 ) {
279 (*s.inner) += (*s2.inner);
280}
281
282void append( string & s, const string & s2, size_t maxlen ) {
283 append( (*s.inner), (*s2.inner), maxlen );
284}
285
286void ?+=?( string & s, const char * c ) {
287 (*s.inner) += c;
288}
289
290void append( string & s, const char * buffer, size_t bsize ) {
291 append( (*s.inner), buffer, bsize );
292}
293
294string ?+?( string s, char c ) {
295 string ret = s;
296 ret += c;
297 return ret;
298}
299
300string ?+?( char c, string s ) {
301 string ret = c;
302 ret += s;
303 return ret;
304}
305
306PBOOST string ?+?( string s, string s2 ) {
307 string ret = s;
308 ret += s2;
309 return ret;
310}
311
312string ?+?( const char * s, char c ) {
313 string ret = s;
314 ret += c;
315 return ret;
316}
317
318string ?+?( char c, const char * s ) {
319 string ret = c;
320 ret += s;
321 return ret;
322}
323
324string ?+?( const char * s1, const char * s2 ) {
325 string ret = s1;
326 ret += s2;
327 return ret;
328}
329
330string ?+?( const char * s1, string s2 ) {
331 string ret = s1;
332 ret += s2;
333 return ret;
334}
335
336string ?+?( string s, const char * c ) {
337 string ret = s;
338 ret += c;
339 return ret;
340}
341
342string ?+?( char c1, char c2 ) {
343 string ret = c1;
344 ret += c2;
345 return ret;
346}
347
348////////////////////////////////////////////////////////
349// Repetition
350
351void ?*=?( string & s, strmul_factor_t factor ) {
352 (*s.inner) *= factor;
353}
354
355PBOOST string ?*?( string s, strmul_factor_t factor ) {
356 string ret = s;
357 ret *= factor;
358 return ret;
359}
360
361string ?*?( char c, strmul_factor_t factor ) {
362 string ret = c;
363 ret *= factor;
364 return ret;
365}
366
367string ?*?( const char * s, strmul_factor_t factor ) {
368 string ret = s;
369 ret *= factor;
370 return ret;
371}
372
373////////////////////////////////////////////////////////
374// Character access
375
376char ?[?]( const string & s, size_t index ) {
377 return (*s.inner)[index];
378}
379
380string ?[?]( string & s, size_t index ) {
381 string ret = { *s.inner, index, 1 };
382 return ret`share;
383}
384
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
413////////////////////////////////////////////////////////
414// Search
415
416bool contains( const string & s, char ch ) {
417 return contains( *s.inner, ch );
418}
419
420size_t find( const string & s, size_t start, size_t len, const string & key, size_t kstart, size_t klen ) {
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;
430
431 return findFrom( *s.inner, start, *key.inner );
432}
433
434size_t find( const string & s, char key ) {
435 return find( *s.inner, key );
436}
437
438size_t find( const string & s, const string & key ) {
439 return find( *s.inner, *key.inner );
440}
441
442size_t find( const string & s, const char * key ) {
443 return find( *s.inner, key );
444}
445
446size_t find( const string & s, const char * key, size_t keysize ) {
447 return find( *s.inner, key, keysize );
448}
449
450size_t find( const string & s, size_t start, char key ) {
451 return findFrom( *s.inner, start, key );
452}
453
454size_t find( const string & s, size_t start, const char * key ) {
455 return findFrom( *s.inner, start, key );
456}
457
458size_t find( const string & s, size_t start, const char * key, size_t keysize ) {
459 return findFrom( *s.inner, start, key, keysize );
460}
461
462bool includes( const string & s, const string & mask ) {
463 return includes( *s.inner, *mask.inner );
464}
465
466bool includes( const string & s, const char * mask ) {
467 return includes( *s.inner, mask );
468}
469
470bool includes( const string & s, const char * mask, size_t masksize ) {
471 return includes( *s.inner, mask, masksize );
472}
473
474bool startsWith( const string & s, const string & prefix ) {
475 return startsWith( *s.inner, *prefix.inner );
476}
477
478bool startsWith( const string & s, const char * prefix ) {
479 return startsWith( *s.inner, prefix );
480}
481
482bool startsWith( const string & s, const char * prefix, size_t prefixsize ) {
483 return startsWith( *s.inner, prefix, prefixsize );
484}
485
486bool endsWith( const string & s, const string & suffix ) {
487 return endsWith( *s.inner, *suffix.inner );
488}
489
490bool endsWith( const string & s, const char * suffix ) {
491 return endsWith( *s.inner, suffix );
492}
493
494bool endsWith( const string & s, const char * suffix, size_t suffixsize ) {
495 return endsWith( *s.inner, suffix, suffixsize );
496}
497
498
499///////////////////////////////////////////////////////////////////////////
500// charclass, include, exclude
501
502void ?{}( charclass & s, const string & chars ) {
503 (s.inner) { malloc() };
504 ?{}( *s.inner, *(const string_res *)chars.inner );
505}
506
507void ?{}( charclass & s, const char * chars ) {
508 (s.inner) { malloc() };
509 ?{}( *s.inner, chars );
510}
511
512void ?{}( charclass & s, const char * chars, size_t charssize ) {
513 (s.inner) { malloc() };
514 ?{}( *s.inner, chars, charssize );
515}
516
517void ^?{}( charclass & s ) {
518 ^(*s.inner){};
519 free( s.inner );
520 s.inner = 0p;
521}
522
523size_t exclude( const string & s, const charclass & mask ) {
524 return exclude( *s.inner, *mask.inner );
525}
526
527size_t include( const string & s, const charclass & mask ) {
528 return include( *s.inner, *mask.inner );
529}
530
531size_t include( const string & s, int (*f)( int ) ) {
532 size_t l = len( s );
533 for ( i; l ) {
534 if ( ! f( s[i] ) ) return i;
535 } // for
536 return l;
537}
538
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 ) {
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;
567}
Note: See TracBrowser for help on using the repository browser.