// // 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 21:03:35 2025 // Update Count : 284 // #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 * c ); // copy from string literal (NULL-terminated) void ?{}( string & s, const char * c, size_t size ); // copy specific length from buffer void ?{}( string & s, signed long int rhs ); void ?{}( string & s, size_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 ); static inline void ?{}( string & s, int rhs ) { (s){(signed long int) rhs}; } // string str( ssize_t rhs ); // string str( size_t rhs ); // string str( double rhs ); // string str( long double rhs ); // string str( double _Complex rhs ); // string str( long double _Complex rhs ); PBOOST string & ?=?( string & s, string c ); string & ?=?( string & s, const char * c ); // copy from "literal" string & ?=?( string & s, char c ); // copy from 'l' string & assign( string & s, const string & c, size_t n ); string & assign( string & s, const char * c, size_t n ); string & ?=?( string & s, signed long int rhs ); string & ?=?( string & s, size_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 ); static inline string & ?=?( string & s, int rhs ) { return s = ((signed long int) rhs); } // to match cost of (char * int): int static inline string & strcpy( string & s, const char * c ) { s = c; return s; } static inline string & strncpy( string & s, const char * c, size_t n ) { assign( s, c, n ); return s; } static inline string & strcpy( string & s, const string & c ) { s = c; return s; } static inline string & strncpy( string & s, const string & c, size_t n ) { assign( s, c, n ); return s; } // 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))@{ s, 1, 0, 'b', { .all = 0 } }; } _Ostream_Manip(string) oct( string s ) { return (_Ostream_Manip(string))@{ s, 1, 0, 'o', { .all = 0 } }; } _Ostream_Manip(string) hex( string s ) { return (_Ostream_Manip(string))@{ s, 1, 0, 'x', { .all = 0 } }; } _Ostream_Manip(string) wd( unsigned int w, string s ) { return (_Ostream_Manip(string))@{ s, w, 0, 's', { .all = 0 } }; } _Ostream_Manip(string) wd( unsigned int w, unsigned int pc, string s ) { return (_Ostream_Manip(string))@{ s, w, pc, 's', { .flags.pc = true } }; } _Ostream_Manip(string) & wd( unsigned int w, _Ostream_Manip(string) & fmt ) { fmt.wd = w; return fmt; } _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; } _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; } } // 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 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 * s2 ); 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 * s, char c ); // not backwards compatible string ?+?( char c, const char * s ); string ?+?( const char * c, const char * s ); string ?+?( const char * c, string s ); string ?+?( string s, const char * c ); string ?+?( char, char ); // not being called 8-( static inline string & strcat( string & s, const string & s2 ) { s += s2; return s; } static inline string & strcat( string & s, const char * c ) { s += c; return s; } static inline string & strncat( string & s, const string & s2, size_t maxlen ) { append( s, s2, maxlen ); return s; } 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 * s, strmul_factor_t factor ); static inline string ?*?( strmul_factor_t factor, char s ) { return s * factor; } PBOOST static inline string ?*?( strmul_factor_t factor, string s ) { return s * factor; } static inline string ?*?( strmul_factor_t factor, const char * s ) { return s * 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 & s1, const char * s2 ) { return *s1.inner > s2; } static inline bool ?>=?( const string & s1, const char * s2 ) { return *s1.inner >= s2; } static inline bool ?<=?( const string & s1, const char * s2 ) { return *s1.inner <= s2; } static inline bool ?? ( const char * s1, const string & s2 ) { return s1 > *s2.inner; } static inline bool ?>=?( const char * s1, const string & s2 ) { return s1 >= *s2.inner; } static inline bool ?<=?( const char * s1, const string & s2 ) { return s1 <= *s2.inner; } static inline bool ?