// // 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 : Sun Apr 13 07:58:55 2025 // Update Count : 390 // #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 * c ) { (s.inner) { malloc() }; ?{}( *s.inner, c ); } void ?{}( string & s, const char * c, size_t size ) { (s.inner) { malloc() }; ?{}( *s.inner, c, size ); } void ?{}( string & s, signed long int rhs ) { (s.inner) { malloc() }; ?{}( *s.inner, rhs ); } void ?{}( string & s, size_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 ); } string str( ssize_t rhs ) { string s = rhs; return s; } string str( size_t rhs ) { string s = rhs; return s; } string str( double rhs ) { string s = rhs; return s; } string str( long double rhs ) { string s = rhs; return s; } string str( double _Complex rhs ) { string s = rhs; return s; } string str( long double _Complex rhs ) { string s = rhs; return s; } 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 c ) { (*s.inner) = (*c.inner); return s; } string & ?=?( string & s, const char * val ) { (*s.inner) = val; return s; } string & ?=?( string & s, char val ) { (*s.inner) = val; return s; } string & assign( string & s, const string & c, size_t n ) { assign( *s.inner, *c.inner, n ); return s; } string & assign( string & s, const char * c, size_t n ) { assign( *s.inner, c, n ); return s; } string & ?=?( string & s, signed long int rhs ) { (*s.inner) = rhs; return s; } string & ?=?( string & s, size_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; } //////////////////////////////////////////////////////// // Getter 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} }; 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; } if ( 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 * c ) { (*s.inner) += c; } 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 * s, char c ) { string ret = s; ret += c; return ret; } string ?+?( char c, const char * s ) { string ret = c; ret += s; return ret; } string ?+?( const char * s1, const char * s2 ) { string ret = s1; ret += s2; return ret; } string ?+?( const char * s1, string s2 ) { string ret = s1; ret += s2; return ret; } string ?+?( string s, const char * c ) { string ret = s; ret += c; 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 * s, strmul_factor_t factor ) { string ret = s; 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 & s1, const string & s2, size_t maxlen ) { if ( maxlen > len( s1 ) || maxlen > len( s2 ) ) { abort( STRNCPY_FMT, maxlen, len( s1 ), len( s2 ) ); } // if return strcmp$( s1.inner->Handle.s, maxlen, s2.inner->Handle.s, maxlen ); } int strncmp( const string & s1, const char * s2, size_t maxlen ) { size_t s2len = len( s2 ); if ( maxlen > len( s1 ) || maxlen > s2len ) { abort( STRNCPY_FMT, maxlen, len( s1 ), s2len ); } // if return strcmp$( s1.inner->Handle.s, maxlen, s2, maxlen ); } int strncmp( const char * s1, const string & s2, size_t maxlen ) { size_t s1len = len( s1 ); if ( maxlen > s1len || maxlen > len( s2 ) ) { abort( STRNCPY_FMT, maxlen, s1len, len( s2 ) ); } // if return strcmp$( s1, maxlen, s2.inner->Handle.s, maxlen ); } //////////////////////////////////////////////////////// // Search bool contains( const string & s, char ch ) { return contains( *s.inner, ch ); } 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 & mask ) { return includes( *s.inner, *mask.inner ); } bool includes( const string & s, const char * mask ) { return includes( *s.inner, mask ); } bool includes( const string & s, const char * mask, size_t masksize ) { return includes( *s.inner, mask, masksize ); } 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; }