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

stuck-waitfor-destruct
Last change on this file since d03a386 was d03a386, checked in by Michael Brooks <mlbrooks@…>, 10 months ago

Give a few string operator overloads a preference boost.

Intent is to approximate: When selecting +/* candidates, treat it ambiguous until finding a user-given arithmetic-vs-string constraint, such as assigning the result to a string. Once a string interpretation is imposed, prefer an alternative that converts to string as soon as possible.

This description is not directly achievable with the CFA type system. The approximation has the known flaw shown in the string-operator test, where a fairly built-up expression that should be ambiguous is actually defaulting to the string version.

This change is the last of the string-overload reorganizations that the string-operator test was originally meant to illustrate. In Mike's opinion, the resulting state is ideal, except for the just-mentioned flaw.

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