// // 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 : Wed Apr 9 22:27:40 2025 // Update Count : 368 // #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 ); } void ?{}( string & s, const string & c ) { (s.inner) { malloc() }; ?{}( *s.inner, *c.inner, COPY_VALUE ); } void ?{}( string & s, const string & s2, size_t maxlen ) { (s.inner) { malloc() }; ?{}( *s.inner, *s2.inner, COPY_VALUE, maxlen ); } void ?{}( string & s, string & c ) { ?{}( s, (const string &) c ); } void ?{}( string & s, const 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, ssize_t 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 string & ?=?( string & s, const string & c ) { (*s.inner) = (*c.inner); return s; } 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, ssize_t 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; } //////////////////////////////////////////////////////// // 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 ) { (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 ) { (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_Squoted f ) { _Istream_Rquoted 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; } //////////////////////////////////////////////////////// // Comparison int strcmp( const string & s1, const string & s2 ) { return strcmp( *s1.inner, *s2.inner ); } bool ?==?( const string & s1, const string & s2 ) { return *s1.inner == *s2.inner; } bool ?!=?( const string & s1, const string & s2 ) { return *s1.inner != *s2.inner; } bool ?>? ( const string & s1, const string & s2 ) { return *s1.inner > *s2.inner; } bool ?>=?( const string & s1, const string & s2 ) { return *s1.inner >= *s2.inner; } bool ?<=?( const string & s1, const string & s2 ) { return *s1.inner <= *s2.inner; } bool ?? ( const string & s1, const char * s2 ) { return *s1.inner > s2; } bool ?>=?( const string & s1, const char * s2 ) { return *s1.inner >= s2; } bool ?<=?( const string & s1, const char * s2 ) { return *s1.inner <= s2; } bool ?? ( const char * s1, const string & s2 ) { return s1 > *s2.inner; } bool ?>=?( const char * s1, const string & s2 ) { return s1 >= *s2.inner; } bool ?<=?( const char * s1, const string & s2 ) { return s1 <= *s2.inner; } bool ?= 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 test( 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( 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 ); string front = s( 0, pos ); string back = s( pos + (ssize_t)len( from ) ); r = front + to + replace( back, 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; }