// // 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 18:07:38 2026 // Update Count : 367 // #pragma once #include #include static struct __cfa_string_preference_boost_t {} __cfa_string_preference_boost; #define PBOOST forall ( | { __cfa_string_preference_boost_t __cfa_string_preference_boost; } ) struct string { string_res * inner; }; // RAII, assignment void ^?{}( string & s ); void ?{}( string & s ); // empty string void ?{}( string & s, string s2, size_t maxlen ); PBOOST void ?{}( string & s, string s2 ); void ?{}( string & s, char ); void ?{}( string & s, const char cs[] ); // copy from string literal (NULL-terminated) void ?{}( string & s, const char cs[], size_t size ); // copy specific length from buffer void ?{}( string & s, size_t rhs ); void ?{}( string & s, ssize_t rhs ); void ?{}( string & s, double rhs ); void ?{}( string & s, long double rhs ); void ?{}( string & s, double _Complex rhs ); void ?{}( string & s, long double _Complex rhs ); PBOOST string & ?=?( string & s, string rhs ); string & ?=?( string & s, char rhs ); // copy from 'l' string & ?=?( string & s, const char rhs[] ); // copy from "literal" string & assign( string & s, const string & rhs, size_t n ); string & assign( string & s, const char rhs[], size_t n ); string & ?=?( string & s, size_t rhs ); string & ?=?( string & s, ssize_t rhs ); string & ?=?( string & s, double rhs ); string & ?=?( string & s, long double rhs ); string & ?=?( string & s, double _Complex rhs ); string & ?=?( string & s, long double _Complex rhs ); // Conversion static inline string tostr( char c ) { string s = c; return s; } static inline string tostr( const char cs[] ) { string s = cs; return s; } static inline string tostr( size_t v ) { string s = v; return s; } static inline string tostr( ssize_t v ) { string s = v; return s; } static inline string tostr( double v ) { string s = v; return s; } static inline string tostr( long double v ) { string s = v; return s; } static inline string tostr( long double _Complex v ) { string s = v; return s; } // C compatibility static inline string & strcpy( string & s, const char cs[] ) { s = cs; return s; } static inline string & strncpy( string & s, const char cs[], size_t n ) { assign( s, cs, n ); return s; } static inline string & strcpy( string & s1, const string & s2 ) { s1 = s2; return s1; } static inline string & strncpy( string & s, const string & cs, size_t n ) { assign( s, cs, n ); return s; } char * strncpy( char dst[], string & src, size_t n ); char * ?=?( char *& dst, string & src ); void ?{}( char *& dst, string & src ); // Alternate construction: request shared edits struct string_Share { string * s; }; string_Share ?`share( string & s ); void ?{}( string & s, string_Share src ); // Getters static inline size_t len( const string & s ) { return len( *s.inner ); } static inline size_t len( const char cs[] ) { return strlen( cs ); }; static inline size_t strlen( const string & s ) { return len( s ); } size_t strnlen( const string & s, size_t maxlen ); // IO Operator forall( ostype & | basic_ostream( ostype ) ) { ostype & ?|?( ostype & out, string s ); void ?|?( ostype & out, string s ); } forall( istype & | basic_istream( istype ) ) istype & ?|?( istype & in, string & s ); static inline { _Ostream_Manip(string) bin( string s ) { return (_Ostream_Manip(string))@{ .val = s, .wd = 1, .pc = 0, .base = 'b', { .all = 0 } }; } _Ostream_Manip(string) oct( string s ) { return (_Ostream_Manip(string))@{ .val = s, .wd = 1, .pc = 0, .base = 'o', { .all = 0 } }; } _Ostream_Manip(string) hex( string s ) { return (_Ostream_Manip(string))@{ .val = s, .wd = 1, .pc = 0, .base = 'x', { .all = 0 } }; } _Ostream_Manip(string) quote( string s, const char qleft = '"', const char qright = '\0' ) { return (_Ostream_Manip(string))@{ .val = s, .wd = 1, .pc = 0, .base = 's', { .flags.quote = true }, .qleft = qleft, .qright = qright }; } _Ostream_Manip(string) wd( unsigned int wd, string s ) { return (_Ostream_Manip(string))@{ .val = s, .wd = wd, .pc = 0, .base = 's', { .all = 0 } }; } _Ostream_Manip(string) wd( unsigned int wd, unsigned int pc, string s ) { return (_Ostream_Manip(string))@{ .val = s, .wd = wd, .pc = pc, .base = 's', { .flags.pc = true } }; } _Ostream_Manip(string) & wd( unsigned int wd, _Ostream_Manip(string) & fmt ) { fmt.wd = wd; return fmt; } _Ostream_Manip(string) & wd( unsigned int wd, unsigned int pc, _Ostream_Manip(string) & fmt ) { fmt.wd = wd; fmt.pc = pc; fmt.flags.pc = true; return fmt; } _Ostream_Manip(string) & left( _Ostream_Manip(string) & fmt ) { fmt.flags.left = true; return fmt; } _Ostream_Manip(string) & nobase( _Ostream_Manip(string) & fmt ) { fmt.flags.nobsdp = true; return fmt; } _Ostream_Manip(string) & upcase( _Ostream_Manip(string) & fmt ) { if ( fmt.base == 'x' || fmt.base == 'b' ) fmt.base -= 32; /* upper case */ return fmt; } _Ostream_Manip(string) & quote( _Ostream_Manip(string) & fmt, const char qleft = '"', const char qright = '\0' ) { fmt.flags.quote = true; fmt.qleft = qleft, fmt.qright = qright; return fmt; } } // distribution forall( ostype & | basic_ostream( ostype ) ) { ostype & ?|?( ostype & os, _Ostream_Manip(string) f ); void ?|?( ostype & os, _Ostream_Manip(string) ); } struct _Istream_Swidth { string & s; inline _Istream_str_base; }; // _Istream_Swidth // Restrict nesting of input manipulators to those combinations that make sense. struct _Istream_Squote { _Istream_Swidth sstr; }; // _Istream_Squote struct _Istream_Sstr { string & s; inline _Istream_str_base; // _Istream_Swidth sstr; }; // _Istream_Sstr static inline { // read width does not include null terminator _Istream_Swidth wdi( unsigned int rwd, string & s ) { return (_Istream_Swidth)@{ .s = s, { {.scanset = 0p}, .wd = rwd, {.flags.rwd = true} } }; } _Istream_Sstr getline( string & s, const char delimiter = '\n' ) { return (_Istream_Sstr)@{ .s = s, { {.delimiters = { delimiter, '\0' } }, .wd = -1, {.flags.delimiter = true} } }; } _Istream_Sstr & getline( _Istream_Swidth & f, const char delimiter = '\n' ) { f.delimiters[0] = delimiter; f.delimiters[1] = '\0'; f.flags.delimiter = true; return (_Istream_Sstr &)f; } _Istream_Squote quote( string & s, const char Ldelimiter = '\"', const char Rdelimiter = '\0' ) { return (_Istream_Squote)@{ { .s = s, { {.delimiters = { Ldelimiter, Rdelimiter, '\0' }}, .wd = -1, {.flags.rwd = true} } } }; } _Istream_Squote & quote( _Istream_Swidth & f, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) { f.delimiters[0] = Ldelimiter; f.delimiters[1] = Rdelimiter; f.delimiters[2] = '\0'; return (_Istream_Squote &)f; } _Istream_Sstr incl( const char scanset[], string & s ) { return (_Istream_Sstr)@{ .s = s, { {.scanset = scanset}, .wd = -1, {.flags.inex = false} } }; } _Istream_Sstr & incl( const char scanset[], _Istream_Swidth & f ) { f.scanset = scanset; f.flags.inex = false; return (_Istream_Sstr &)f; } _Istream_Sstr excl( const char scanset[], string & s ) { return (_Istream_Sstr)@{ .s = s, { {.scanset = scanset}, .wd = -1, {.flags.inex = true} } }; } _Istream_Sstr & excl( const char scanset[], _Istream_Swidth & f ) { f.scanset = scanset; f.flags.inex = true; return (_Istream_Sstr &)f; } _Istream_Sstr ignore( string & s ) { return (_Istream_Sstr)@{ .s = s, { {.scanset = 0p}, .wd = -1, {.flags.ignore = true} } }; } _Istream_Sstr & ignore( _Istream_Swidth & f ) { f.flags.ignore = true; return (_Istream_Sstr &)f; } _Istream_Squote & ignore( _Istream_Squote & f ) { f.sstr.flags.ignore = true; return (_Istream_Squote &)f; } _Istream_Sstr & ignore( _Istream_Sstr & f ) { f.flags.ignore = true; return (_Istream_Sstr &)f; } } // distribution forall( istype & | basic_istream( istype ) ) { istype & ?|?( istype & is, _Istream_Squote f ); istype & ?|?( istype & is, _Istream_Sstr f ); static inline istype & ?|?( istype & is, _Istream_Swidth f ) { return is | *(_Istream_Sstr *)&f; } } // Concatenation void ?+=?( string & s, char c ); PBOOST void ?+=?( string & s, string ); void append( string & s, const string & s2, size_t maxlen ); void ?+=?( string & s, const char cs[] ); void append( string & s, const char buffer[], size_t bsize ); string ?+?( string s, char c ); string ?+?( char c, string s ); PBOOST string ?+?( string s, string s2 ); string ?+?( const char cs[], char c ); // not backwards compatible string ?+?( char c, const char cs[] ); string ?+?( const char cs1[] , const char cs2[] ); string ?+?( const char cs[] , string s ); string ?+?( string s, const char cs[] ); string ?+?( char, char ); // not being called 8-( static inline string & strcat( string & s1, const string & s2 ) { s1 += s2; return s1; } static inline string & strcat( string & s, const char cs[] ) { s += cs; return s; } static inline string & strncat( string & s1, const string & s2, size_t maxlen ) { append( s1, s2, maxlen ); return s1; } static inline string & strncat( string & s, const char buffer[], size_t bsize ) { append( s, buffer, bsize ); return s; } // Repetition // Type `signed long long int` chosen for `factor` argument to achieve cost detente. // This way, the call `'a' * 3` gets the same safe conversion cost calling here as for // the built-in definition `int * int`. typedef signed long long int strmul_factor_t; void ?*=?( string & s, strmul_factor_t factor ); string ?*?( char c, strmul_factor_t factor ); // not backwards compatible PBOOST string ?*?( string s, strmul_factor_t factor ); string ?*?( const char cs[], strmul_factor_t factor ); static inline string ?*?( strmul_factor_t factor, char c ) { return c * factor; } PBOOST static inline string ?*?( strmul_factor_t factor, string s ) { return s * factor; } static inline string ?*?( strmul_factor_t factor, const char cs[] ) { return cs * factor; } // Character access char ?[?]( const string & s, size_t index ); string ?[?]( string & s, size_t index ); // mutable length-1 slice of original //char codePointAt(const string & s, size_t index ); // to revisit under Unicode // Comparisons static inline int strcmp( const string & s1, const string & s2 ) { return strcmp( *s1.inner, *s2.inner ); } int strncmp( const string & s1, const string & s2, size_t maxlen ); static inline bool ?==?( const string & s1, const string & s2 ) { return *s1.inner == *s2.inner; } static inline bool ?!=?( const string & s1, const string & s2 ) { return *s1.inner != *s2.inner; } static inline bool ?>? ( const string & s1, const string & s2 ) { return *s1.inner > *s2.inner; } static inline bool ?>=?( const string & s1, const string & s2 ) { return *s1.inner >= *s2.inner; } static inline bool ?<=?( const string & s1, const string & s2 ) { return *s1.inner <= *s2.inner; } static inline bool ?? ( const string & s, const char cs[] ) { return *s.inner > cs; } static inline bool ?>=?( const string & s, const char cs[] ) { return *s.inner >= cs; } static inline bool ?<=?( const string & s, const char cs[] ) { return *s.inner <= cs; } static inline bool ?? ( const char cs[], const string & s ) { return cs > *s.inner; } static inline bool ?>=?( const char cs[], const string & s ) { return cs >= *s.inner; } static inline bool ?<=?( const char cs[], const string & s ) { return cs <= *s.inner; } static inline bool ?