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

Last change on this file since d03a386 was d03a386, checked in by Michael Brooks <mlbrooks@…>, 5 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: 15.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 : Wed Apr 9 22:27:41 2025
13// Update Count : 259
14//
15
16#pragma once
17
18#include <iostream.hfa>
19#include <string_res.hfa>
20
21static struct __cfa_string_preference_boost_t {} __cfa_string_preference_boost;
22#define PBOOST forall ( | { __cfa_string_preference_boost_t __cfa_string_preference_boost; } )
23
24struct string {
25 string_res * inner;
26};
27
28// RAII, assignment
29void ^?{}( string & s );
30
31void ?{}( string & s ); // empty string
32void ?{}( string & s, string s2, size_t maxlen );
33PBOOST void ?{}( string & s, string s2 );
34void ?{}( string & s, char );
35void ?{}( string & s, const char * c ); // copy from string literal (NULL-terminated)
36void ?{}( string & s, const char * c, size_t size ); // copy specific length from buffer
37
38void ?{}( string & s, signed long int rhs );
39void ?{}( string & s, size_t rhs );
40void ?{}( string & s, double rhs );
41void ?{}( string & s, long double rhs );
42void ?{}( string & s, double _Complex rhs );
43void ?{}( string & s, long double _Complex rhs );
44static inline void ?{}( string & s, int rhs ) { (s){(signed long int) rhs}; }
45
46// string str( ssize_t rhs );
47// string str( size_t rhs );
48// string str( double rhs );
49// string str( long double rhs );
50// string str( double _Complex rhs );
51// string str( long double _Complex rhs );
52
53PBOOST string & ?=?( string & s, string c );
54string & ?=?( string & s, const char * c ); // copy from "literal"
55string & ?=?( string & s, char c ); // copy from 'l'
56string & assign( string & s, const string & c, size_t n );
57string & assign( string & s, const char * c, size_t n );
58string & ?=?( string & s, signed long int rhs );
59string & ?=?( string & s, size_t rhs );
60string & ?=?( string & s, double rhs );
61string & ?=?( string & s, long double rhs );
62string & ?=?( string & s, double _Complex rhs );
63string & ?=?( string & s, long double _Complex rhs );
64static inline string & ?=?( string & s, int rhs ) { return s = ((signed long int) rhs); } // to match cost of (char * int): int
65
66static inline string & strcpy( string & s, const char * c ) { s = c; return s; }
67static inline string & strncpy( string & s, const char * c, size_t n ) { assign( s, c, n ); return s; }
68static inline string & strcpy( string & s, const string & c ) { s = c; return s; }
69static inline string & strncpy( string & s, const string & c, size_t n ) { assign( s, c, n ); return s; }
70
71// Alternate construction: request shared edits
72struct string_Share {
73 string * s;
74};
75string_Share ?`share( string & s );
76void ?{}( string & s, string_Share src );
77
78// Getters
79static inline size_t len( const string & s ) { return len( *s.inner ); }
80static inline size_t len( const char * cs ) { return strlen( cs ); };
81static inline size_t strlen( const string & s ) { return len( s ); }
82
83// IO Operator
84forall( ostype & | basic_ostream( ostype ) ) {
85 ostype & ?|?( ostype & out, string s );
86 void ?|?( ostype & out, string s );
87}
88forall( istype & | basic_istream( istype ) )
89istype & ?|?( istype & in, string & s );
90
91static inline {
92 _Ostream_Manip(string) bin( string s ) { return (_Ostream_Manip(string))@{ s, 1, 0, 'b', { .all = 0 } }; }
93 _Ostream_Manip(string) oct( string s ) { return (_Ostream_Manip(string))@{ s, 1, 0, 'o', { .all = 0 } }; }
94 _Ostream_Manip(string) hex( string s ) { return (_Ostream_Manip(string))@{ s, 1, 0, 'x', { .all = 0 } }; }
95 _Ostream_Manip(string) wd( unsigned int w, string s ) { return (_Ostream_Manip(string))@{ s, w, 0, 's', { .all = 0 } }; }
96 _Ostream_Manip(string) wd( unsigned int w, unsigned int pc, string s ) { return (_Ostream_Manip(string))@{ s, w, pc, 's', { .flags.pc = true } }; }
97 _Ostream_Manip(string) & wd( unsigned int w, _Ostream_Manip(string) & fmt ) { fmt.wd = w; return fmt; }
98 _Ostream_Manip(string) & wd( unsigned int w, unsigned int pc, _Ostream_Manip(string) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; }
99 _Ostream_Manip(string) & left( _Ostream_Manip(string) & fmt ) { fmt.flags.left = true; return fmt; }
100 _Ostream_Manip(string) & nobase( _Ostream_Manip(string) & fmt ) { fmt.flags.nobsdp = true; return fmt; }
101} // distribution
102forall( ostype & | basic_ostream( ostype ) ) {
103 ostype & ?|?( ostype & os, _Ostream_Manip(string) f );
104 void ?|?( ostype & os, _Ostream_Manip(string) );
105}
106
107struct _Istream_Swidth {
108 string & s;
109 inline _Istream_str_base;
110}; // _Istream_Swidth
111
112struct _Istream_Squoted {
113 _Istream_Swidth sstr;
114}; // _Istream_Squoted
115
116struct _Istream_Sstr {
117 string & s;
118 inline _Istream_str_base;
119// _Istream_Swidth sstr;
120}; // _Istream_Sstr
121
122static inline {
123 // read width does not include null terminator
124 _Istream_Swidth wdi( unsigned int rwd, string & s ) { return (_Istream_Swidth)@{ .s = s, { {.scanset = 0p}, .wd = rwd, {.flags.rwd = true} } }; }
125 _Istream_Sstr getline( string & s, const char delimiter = '\n' ) {
126// return (_Istream_Sstr)@{ { .s = s, { {.delimiters = { delimiter, '\0' } }, .wd = -1, {.flags.delimiter = true} } } };
127 return (_Istream_Sstr)@{ .s = s, { {.delimiters = { delimiter, '\0' } }, .wd = -1, {.flags.delimiter = true} } };
128 }
129 _Istream_Sstr & getline( _Istream_Swidth & f, const char delimiter = '\n' ) {
130 f.delimiters[0] = delimiter; f.delimiters[1] = '\0'; f.flags.delimiter = true; return (_Istream_Sstr &)f;
131 }
132 _Istream_Squoted quoted( string & s, const char Ldelimiter = '\"', const char Rdelimiter = '\0' ) {
133 return (_Istream_Squoted)@{ { .s = s, { {.delimiters = { Ldelimiter, Rdelimiter, '\0' }}, .wd = -1, {.flags.rwd = true} } } };
134 }
135 _Istream_Squoted & quoted( _Istream_Swidth & f, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) {
136 f.delimiters[0] = Ldelimiter; f.delimiters[1] = Rdelimiter; f.delimiters[2] = '\0';
137 return (_Istream_Squoted &)f;
138 }
139// _Istream_Sstr incl( const char scanset[], string & s ) { return (_Istream_Sstr)@{ { .s = s, { {.scanset = scanset}, .wd = -1, {.flags.inex = false} } } }; }
140 _Istream_Sstr incl( const char scanset[], string & s ) { return (_Istream_Sstr)@{ .s = s, { {.scanset = scanset}, .wd = -1, {.flags.inex = false} } }; }
141 _Istream_Sstr & incl( const char scanset[], _Istream_Swidth & f ) { f.scanset = scanset; f.flags.inex = false; return (_Istream_Sstr &)f; }
142// _Istream_Sstr excl( const char scanset[], string & s ) { return (_Istream_Sstr)@{ { .s = s, { {.scanset = scanset}, .wd = -1, {.flags.inex = true} } } }; }
143 _Istream_Sstr excl( const char scanset[], string & s ) { return (_Istream_Sstr)@{ .s = s, { {.scanset = scanset}, .wd = -1, {.flags.inex = true} } }; }
144 _Istream_Sstr & excl( const char scanset[], _Istream_Swidth & f ) { f.scanset = scanset; f.flags.inex = true; return (_Istream_Sstr &)f; }
145// _Istream_Sstr ignore( string & s ) { return (_Istream_Sstr)@{ { .s = s, { {.scanset = 0p}, .wd = -1, {.flags.ignore = true} } } }; }
146 _Istream_Sstr ignore( string & s ) { return (_Istream_Sstr)@{ .s = s, { {.scanset = 0p}, .wd = -1, {.flags.ignore = true} } }; }
147 _Istream_Sstr & ignore( _Istream_Swidth & f ) { f.flags.ignore = true; return (_Istream_Sstr &)f; }
148 _Istream_Squoted & ignore( _Istream_Squoted & f ) { f.sstr.flags.ignore = true; return (_Istream_Squoted &)f; }
149// _Istream_Sstr & ignore( _Istream_Sstr & f ) { f.sstr.flags.ignore = true; return (_Istream_Sstr &)f; }
150 _Istream_Sstr & ignore( _Istream_Sstr & f ) { f.flags.ignore = true; return (_Istream_Sstr &)f; }
151} // distribution
152forall( istype & | basic_istream( istype ) ) {
153 istype & ?|?( istype & is, _Istream_Squoted f );
154 istype & ?|?( istype & is, _Istream_Sstr f );
155 static inline istype & ?|?( istype & is, _Istream_Swidth f ) { return is | *(_Istream_Sstr *)&f; }
156}
157
158// Concatenation
159void ?+=?( string & s, char c );
160void ?+=?( string & s, const string & s2 );
161void append( string & s, const string & s2, size_t maxlen );
162void ?+=?( string & s, const char * s2 );
163void append( string & s, const char * buffer, size_t bsize );
164
165string ?+?( string s, char c );
166string ?+?( char c, string s );
167PBOOST string ?+?( string s, string s2 );
168string ?+?( const char * s, char c ); // not backwards compatible
169string ?+?( char c, const char * s );
170string ?+?( const char * c, const char * s );
171string ?+?( const char * c, string s );
172string ?+?( string s, const char * c );
173string ?+?( char, char ); // not being called 8-(
174
175static inline string & strcat( string & s, const string & s2 ) { s += s2; return s; }
176static inline string & strcat( string & s, const char * c ) { s += c; return s; }
177static inline string & strncat( string & s, const string & s2, size_t maxlen ) { append( s, s2, maxlen ); return s; }
178static inline string & strncat( string & s, const char * buffer, size_t bsize ) { append( s, buffer, bsize ); return s; }
179
180// Repetition
181
182// Type `signed long long int` chosen for `factor` argument to achieve cost detente.
183// This way, the call `'a' * 3` gets the same safe conversion cost calling here as for
184// the built-in definition `int * int`.
185typedef signed long long int strmul_factor_t;
186
187void ?*=?( string & s, strmul_factor_t factor );
188string ?*?( char c, strmul_factor_t factor ); // not backwards compatible
189PBOOST string ?*?( string s, strmul_factor_t factor );
190string ?*?( const char * s, strmul_factor_t factor );
191static inline string ?*?( strmul_factor_t factor, char s ) { return s * factor; }
192PBOOST static inline string ?*?( strmul_factor_t factor, string s ) { return s * factor; }
193static inline string ?*?( strmul_factor_t factor, const char * s ) { return s * factor; }
194
195// Character access
196char ?[?]( const string & s, size_t index );
197string ?[?]( string & s, size_t index ); // mutable length-1 slice of original
198//char codePointAt(const string & s, size_t index ); // to revisit under Unicode
199
200// Comparisons
201int strcmp ( const string &, const string & );
202bool ?==?( const string &, const string & );
203bool ?!=?( const string &, const string & );
204bool ?>? ( const string &, const string & );
205bool ?>=?( const string &, const string & );
206bool ?<=?( const string &, const string & );
207bool ?<? ( const string &, const string & );
208
209int strcmp( const string &, const char * );
210bool ?==?( const string &, const char * );
211bool ?!=?( const string &, const char * );
212bool ?>? ( const string &, const char * );
213bool ?>=?( const string &, const char * );
214bool ?<=?( const string &, const char * );
215bool ?<? ( const string &, const char * );
216
217int strcmp( const char *, const string & );
218bool ?==?( const char *, const string & );
219bool ?!=?( const char *, const string & );
220bool ?>? ( const char *, const string & );
221bool ?>=?( const char *, const string & );
222bool ?<=?( const char *, const string & );
223bool ?<? ( const char *, const string & );
224
225// String search
226bool contains( const string & s, char ch ); // single character
227
228//int find( const string & s, size_t start, size_t len, const string & key, size_t kstart, size_t klen );
229size_t find$( const string_res & s, size_t start, size_t len, const string & key_res, size_t kstart, size_t klen );
230
231size_t find( const string & s, char key );
232size_t find( const string & s, const char * key );
233size_t find( const string & s, const string & key );
234size_t find( const string & s, const char * key, size_t keysize );
235
236size_t find( const string & s, size_t start, char key );
237size_t find( const string & s, size_t start, const string & key );
238size_t find( const string & s, size_t start, const char * key );
239size_t find( const string & s, size_t start, const char * key, size_t keysize );
240static inline ?^?( const string & key, const string & s ) { return find( s, key ); }
241static inline ?^?( const char * key, const string & s ) { return find( s, key ); }
242
243bool includes( const string & s, const string & mask );
244bool includes( const string & s, const char * mask );
245bool includes( const string & s, const char * mask, size_t masksize );
246
247bool startsWith( const string & s, const string & prefix );
248bool startsWith( const string & s, const char * prefix );
249bool startsWith( const string & s, const char * prefix, size_t prefixsize );
250
251bool endsWith( const string & s, const string & suffix );
252bool endsWith( const string & s, const char * suffix );
253bool endsWith( const string & s, const char * suffix, size_t suffixsize );
254
255// Slicing
256string ?()( string & s, ssize_t start, ssize_t len );
257static inline string ?()( const string & s, ssize_t start, ssize_t len ) { string & w = (string &)s; return w( start, len ); } // FIX ME
258string ?()( string & s, ssize_t start );
259static inline string ?()( const string & s, ssize_t start ) { string & w = (string &)s; return w( start ); } // FIX ME
260static inline string ?()( string & s, char m ) { return s( find( s, m ), 1 )`share; }
261static inline string ?()( const string & s, char m ) { string & w = (string &)s; return w( find( s, m ), 1 )`share; } // FIX ME
262static inline string ?()( string & s, const char * m ) { return s( find( s, m ), len( m ) )`share; }
263static inline string ?()( const string & s, const char * m ) { string & w = (string &)s; return w( find( s, m ), len( m ) )`share; } // FIX ME
264static inline string ?()( string & s, const string & m ) { return s( find( s, m ), len( m ) )`share; }
265static inline string ?()( const string & s, const string & m ) { string & w = (string &)s; return w( find( s, m ), len( m ) )`share; } // FIX ME
266
267struct charclass {
268 charclass_res * inner;
269};
270
271void ?{}( charclass & ) = void;
272void ?{}( charclass &, charclass ) = void;
273charclass ?=?( charclass &, charclass ) = void;
274
275void ?{}( charclass &, const string & chars );
276void ?{}( charclass &, const char * chars );
277void ?{}( charclass &, const char * chars, size_t charssize );
278void ^?{}( charclass & );
279
280size_t include( const string & s, const charclass & mask );
281static inline size_t include( const char * s, const charclass & mask ) { string temp = s; return include( temp, mask ); }
282static inline string include( const string & s, const charclass & mask ) { ssize_t i = include( s, mask ); return s( 0, i )`share; }
283static inline string include( const char * s, const charclass & mask ) { string temp = s; ssize_t i = include( temp, mask ); return temp( 0, i ); }
284
285size_t exclude( const string & s, const charclass & mask );
286static inline size_t exclude( const char * s, const charclass & mask ) { string temp = s; return exclude( temp, mask ); }
287static inline string exclude( const string & s, const charclass & mask ) { ssize_t i = exclude( s, mask ); return s( 0, i )`share; }
288static inline string exclude( const char * s, const charclass & mask ) { string temp = s; ssize_t i = exclude( temp, mask ); return temp( 0, i ); }
289
290size_t test( const string & s, int (*f)( int ) );
291static inline size_t test( const char * c, int (*f)( int ) ) {
292 const string S = c;
293 return test( S, f );
294}
295
296string replace( string & s, const string & from, const string & to );
297static inline string replace( const char * s, const char * from, const char * to ) {
298 string S = s, From = from, To = to;
299 return replace( S, From, To );
300}
301static inline string replace( string & s, const char * from, const char * to ) {
302 string From = from, To = to;
303 return replace( s, From, To );
304}
305static inline string replace( string & s, const char * from, const string & to ) {
306 string From = from;
307 return replace( s, From, to );
308}
309static inline string replace( string & s, string & from, const char * to ) {
310 string To = to;
311 return replace( s, from, To );
312}
313
314string translate( const string & s, int (*f)( int ) );
315static inline string translate( const char * c, int (*f)( int ) ) {
316 const string S = c;
317 return translate( S, f );
318}
319
320#ifndef _COMPILING_STRING_CFA_
321#undef PBOOST
322#endif
Note: See TracBrowser for help on using the repository browser.