// // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // string -- variable-length, mutable run of text, with value semantics // // Author : Michael L. Brooks // Created On : Fri Sep 03 11:00:00 2021 // Last Modified By : Peter A. Buhr // Last Modified On : Fri May 8 08:38:51 2026 // Update Count : 413 // #define _COMPILING_STRING_CFA_ #include "string.hfa" #include "string_res.hfa" #include #pragma GCC visibility push(default) /* Implementation Principle: typical operation translates to the equivalent operation on `inner`. Exceptions are implementing new RAII pattern for value semantics and some const-hell handling. */ //////////////////////////////////////////////////////// // string RAII // private (not in header) static void ?{}( string & s, string_res & src, size_t start, size_t len ) { (s.inner) { malloc() }; ?{}( *s.inner, src, SHARE_EDITS, start, len ); } void ?{}( string & s ) { (s.inner) { malloc() }; ?{}( *s.inner ); } PBOOST void ?{}( string & s, string c ) { // c is a memcpy of the real src string (s.inner) { malloc() }; ?{}( *s.inner, *c.inner, COPY_VALUE ); } void ?{}( string & s, string s2, size_t maxlen ) { (s.inner) { malloc() }; ?{}( *s.inner, *s2.inner, COPY_VALUE, maxlen ); } void ?{}( string & s, char c ) { (s.inner) { malloc() }; ?{}( *s.inner, c ); } void ?{}( string & s, const char cs[] ) { (s.inner) { malloc() }; ?{}( *s.inner, cs ); } void ?{}( string & s, const char cs[] , size_t size ) { (s.inner) { malloc() }; ?{}( *s.inner, cs, size ); } void ?{}( string & s, size_t rhs ) { (s.inner) { malloc() }; ?{}( *s.inner, rhs ); } void ?{}( string & s, ssize_t rhs ) { (s.inner) { malloc() }; ?{}( *s.inner, rhs ); } void ?{}( string & s, double rhs ) { (s.inner) { malloc() }; ?{}( *s.inner, rhs ); } void ?{}( string & s, long double rhs ) { (s.inner) { malloc() }; ?{}( *s.inner, rhs ); } void ?{}( string & s, double _Complex rhs ) { (s.inner) { malloc() }; ?{}( *s.inner, rhs ); } void ?{}( string & s, long double _Complex rhs ) { (s.inner) { malloc() }; ?{}( *s.inner, rhs ); } void ^?{}( string & s ) { ^(*s.inner){}; free( s.inner ); s.inner = 0p; } //////////////////////////////////////////////////////// // Alternate construction: request shared edits string_Share ?`share( string & s ) { string_Share ret = { &s }; return ret; } void ?{}( string & s, string_Share src ) { ?{}( s, *src.s->inner, 0, src.s->inner->Handle.lnth ); } //////////////////////////////////////////////////////// // Assignment PBOOST string & ?=?( string & s, string rhs ) { (*s.inner) = (*rhs.inner); return s; } string & ?=?( string & s, char rhs ) { (*s.inner) = rhs; return s; } string & ?=?( string & s, const char rhs[] ) { (*s.inner) = rhs; return s; } string & assign( string & s, const string & rhs, size_t n ) { assign( *s.inner, *rhs.inner, n ); return s; } string & assign( string & s, const char rhs[], size_t n ) { assign( *s.inner, rhs, n ); return s; } string & ?=?( string & s, size_t rhs ) { (*s.inner) = rhs; return s; } string & ?=?( string & s, ssize_t rhs ) { (*s.inner) = rhs; return s; } string & ?=?( string & s, double rhs ) { (*s.inner) = rhs; return s; } string & ?=?( string & s, long double rhs ) { (*s.inner) = rhs; return s; } string & ?=?( string & s, double _Complex rhs ) { (*s.inner) = rhs; return s; } string & ?=?( string & s, long double _Complex rhs ) { (*s.inner) = rhs; return s; } //////////////////////////////////////////////////////// // C-style // safe conversion from string to char * char * strncpy( char dst[], string & src, size_t n ) { size_t l = min( n - 1, len( src ) ); // ensure null terminated for ( i; l ) dst[i] = src[i]; dst[l] = '\0'; return dst; } char * ?=?( char *& dst, string & src ) { dst = aalloc( len( src ) + 1 ); // ensure null terminated for ( i; len( src ) ) dst[i] = src[i]; dst[len(src)] = '\0'; return dst; } void ?{}( char *& dst, string & src ) { dst = aalloc( len( src ) + 1 ); // ensure null terminated for ( i; len( src ) ) dst[i] = src[i]; dst[len(src)] = '\0'; } size_t strnlen( const string & s, size_t maxlen ) { return min( len( s ), maxlen ); } //////////////////////////////////////////////////////// // Input-Output forall( ostype & | basic_ostream( ostype ) ) { ostype & ?|?( ostype & out, string s ) { return out | (*s.inner); // print internal string_res } void ?|?( ostype & out, string s ) with ( basic_ostream_table ) { (ostype &)(out | (*s.inner)); ends( out ); } ostype & ?|?( ostype & os, _Ostream_Manip(string) f ) { size_t l = len( f.val ); char cstr[l + 1]; // room for null terminator for ( i; l ) cstr[i] = f.val[i]; // copy string cstr[l] = '\0'; // terminate _Ostream_Manip(const char *) cf @= { cstr, f.wd, f.pc, f.base, {f.all}, f.qleft, f.qright }; return os | cf | nonl; } // ?|? void ?|?( ostype & os, _Ostream_Manip(string) f ) with ( basic_ostream_table ) { (ostype &)(os | f); ends( os ); } } forall( istype & | basic_istream( istype ) ) { istype & ?|?( istype & in, string & s ) { return in | (*s.inner); // read to internal string_res } istype & ?|?( istype & is, _Istream_Squote f ) { _Istream_Rquote f2 = { { f.sstr.s.inner, (_Istream_str_base)f.sstr } }; return is | f2; } // ?|? istype & ?|?( istype & is, _Istream_Sstr f ) { // _Istream_Rstr f2 = {f.sstr.s.inner, (_Istream_str_base)f.sstr}; _Istream_Rstr f2 = {f.s.inner, (_Istream_str_base)f}; return is | f2; } // ?|? } //////////////////////////////////////////////////////// // Slicing string ?()( string & s, ssize_t start, ssize_t len ) { if ( start < 0 ) start += len( s ); if ( len < 0 ) { len = -len; start -= len - 1; } if ( start < 0 || start >= len( s ) ) return (string){ "" }; if ( start + len > len( s ) ) len = len( s ) - start; string ret = { *s.inner, start, len }; return ret`share; } string ?()( string & s, ssize_t start ) { if ( start < 0 ) { start += len( s ); } string ret = { *s.inner, start, len( s ) - start }; return ret`share; } //////////////////////////////////////////////////////// // Concatenation void ?+=?( string & s, char c ) { (*s.inner) += c; } PBOOST void ?+=?( string & s, string s2 ) { (*s.inner) += (*s2.inner); } void append( string & s, const string & s2, size_t maxlen ) { append( (*s.inner), (*s2.inner), maxlen ); } void ?+=?( string & s, const char cs[] ) { (*s.inner) += cs; } void append( string & s, const char buffer[], size_t bsize ) { append( (*s.inner), buffer, bsize ); } string ?+?( string s, char c ) { string ret = s; ret += c; return ret; } string ?+?( char c, string s ) { string ret = c; ret += s; return ret; } PBOOST string ?+?( string s, string s2 ) { string ret = s; ret += s2; return ret; } string ?+?( const char cs[], char c ) { string ret = cs; ret += c; return ret; } string ?+?( char c, const char cs[] ) { string ret = c; ret += cs; return ret; } string ?+?( const char cs1[], const char cs2[] ) { string ret = cs1; ret += cs2; return ret; } string ?+?( const char cs[], string s ) { string ret = cs; ret += s; return ret; } string ?+?( string s, const char cs[] ) { string ret = s; ret += cs; return ret; } string ?+?( char c1, char c2 ) { string ret = c1; ret += c2; return ret; } //////////////////////////////////////////////////////// // Repetition void ?*=?( string & s, strmul_factor_t factor ) { (*s.inner) *= factor; } PBOOST string ?*?( string s, strmul_factor_t factor ) { string ret = s; ret *= factor; return ret; } string ?*?( char c, strmul_factor_t factor ) { string ret = c; ret *= factor; return ret; } string ?*?( const char cs[], strmul_factor_t factor ) { string ret = cs; ret *= factor; return ret; } //////////////////////////////////////////////////////// // Character access char ?[?]( const string & s, size_t index ) { return (*s.inner)[index]; } string ?[?]( string & s, size_t index ) { string ret = { *s.inner, index, 1 }; return ret`share; } //////////////////////////////////////////////////////// // Comparison #define STRNCPY_FMT "**** Error **** strncpy: maximum length %zu is greater than string lengths %zd or %zd." int strncmp( const string & s, const string & s2, size_t maxlen ) { if ( maxlen > len( s ) || maxlen > len( s2 ) ) { abort( STRNCPY_FMT, maxlen, len( s ), len( s2 ) ); } // if return strcmp$( s.inner->Handle.s, maxlen, s2.inner->Handle.s, maxlen ); } int strncmp( const string & s, const char cs[], size_t maxlen ) { size_t cslen = len( cs ); if ( maxlen > len( s ) || maxlen > cslen ) { abort( STRNCPY_FMT, maxlen, len( s ), cslen ); } // if return strcmp$( s.inner->Handle.s, maxlen, cs, maxlen ); } int strncmp( const char cs[], const string & s, size_t maxlen ) { size_t slen = len( cs ); if ( maxlen > slen || maxlen > len( s ) ) { abort( STRNCPY_FMT, maxlen, slen, len( s ) ); } // if return strcmp$( cs, maxlen, s.inner->Handle.s, maxlen ); } //////////////////////////////////////////////////////// // Search size_t find( const string & s, size_t start, size_t len, const string & key, size_t kstart, size_t klen ) { if ( start < 0 ) { start += len( s ); } if ( len < 0 ) { len = -len; start -= len; } if ( start >= len( s ) ) return 0; if ( start + len > len( s ) ) len = len( s ) - start; if ( kstart < 0 ) { kstart += len( key ); } if ( klen < 0 ) { klen = -klen; kstart -= klen; } if ( kstart >= len( key ) ) return 0; if ( kstart + klen > len( key ) ) klen = len( key ) - kstart; return findFrom( *s.inner, start, *key.inner ); } size_t find( const string & s, char key ) { return find( *s.inner, key ); } size_t find( const string & s, const string & key ) { return find( *s.inner, *key.inner ); } size_t find( const string & s, const char key[] ) { return find( *s.inner, key ); } size_t find( const string & s, const char key[], size_t keysize ) { return find( *s.inner, key, keysize ); } size_t find( const string & s, size_t start, char key ) { return findFrom( *s.inner, start, key ); } size_t find( const string & s, size_t start, const char key[] ) { return findFrom( *s.inner, start, key ); } size_t find( const string & s, size_t start, const char key[], size_t keysize ) { return findFrom( *s.inner, start, key, keysize ); } // bool includes( const string & s, const string & search ) { // return includes( *s.inner, *search.inner ); // } // bool includes( const string & s, const char search[] ) { // return includes( *s.inner, search ); // } // bool includes( const string & s, const char search[], size_t searchsize ) { // return includes( *s.inner, search, searchsize ); // } bool startsWith( const string & s, const string & prefix ) { return startsWith( *s.inner, *prefix.inner ); } bool startsWith( const string & s, const char prefix[] ) { return startsWith( *s.inner, prefix ); } bool startsWith( const string & s, const char prefix[], size_t prefixsize ) { return startsWith( *s.inner, prefix, prefixsize ); } bool endsWith( const string & s, const string & suffix ) { return endsWith( *s.inner, *suffix.inner ); } bool endsWith( const string & s, const char suffix[] ) { return endsWith( *s.inner, suffix ); } bool endsWith( const string & s, const char suffix[], size_t suffixsize ) { return endsWith( *s.inner, suffix, suffixsize ); } /////////////////////////////////////////////////////////////////////////// // charclass, include, exclude void ?{}( charclass & s, const string & chars ) { (s.inner) { malloc() }; ?{}( *s.inner, *(const string_res *)chars.inner ); } void ?{}( charclass & s, const char chars[] ) { (s.inner) { malloc() }; ?{}( *s.inner, chars ); } void ?{}( charclass & s, const char chars[], size_t charssize ) { (s.inner) { malloc() }; ?{}( *s.inner, chars, charssize ); } void ^?{}( charclass & s ) { ^(*s.inner){}; free( s.inner ); s.inner = 0p; } size_t exclude( const string & s, const charclass & mask ) { return exclude( *s.inner, *mask.inner ); } size_t include( const string & s, const charclass & mask ) { return include( *s.inner, *mask.inner ); } size_t include( const string & s, int (*f)( int ) ) { size_t l = len( s ); for ( i; l ) { if ( ! f( s[i] ) ) return i; } // for return l; } size_t exclude( const string & s, int (*f)( int ) ) { size_t l = len( s ); for ( i; l ) { if ( f( s[i] ) ) return i; } // for return l; } string replace( const string & s, const string & from, const string & to ) { ssize_t pos; string r; pos = find( s, from ); if ( pos < len( s ) ) { r = s( 0, pos ) + to + replace( s( pos + (ssize_t)len( from ) ), from, to ); } else { r = s; } // if return r; } string translate( const string & s, int (*f)( int ) ) { string r = s; size_t l = len( r ); for ( i; l ) { r[i] = (char)f( r[i] ); } // for return r; }