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

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

more inlining, add strnlen and strncmp for string type

  • 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 ) {
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 ) {
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.