// // 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_res -- variable-length, mutable run of text, with resource 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:37 2025 // Update Count : 79 // #pragma once #include #include // e.g. strlen //######################### HandleNode ######################### //private struct VbyteHeap; struct HandleNode { HandleNode * flink; // forward link HandleNode * blink; // backward link VbyteHeap * ulink; // upward link char * s; // pointer to byte string unsigned int lnth; // length of byte string }; // HandleNode VbyteHeap * DEBUG_string_heap(); size_t DEBUG_string_bytes_in_heap( VbyteHeap * heap ); size_t DEBUG_string_bytes_avail_until_gc( VbyteHeap * heap ); const char * DEBUG_string_heap_start( VbyteHeap * heap ); void TUNING_set_string_heap_liveness_threshold( double val ); //######################### String ######################### // A dynamically-sized string struct string_res { HandleNode Handle; // chars, start, end, global neighbours bool shareSet_owns_ulink; string_res * shareSet_prev; string_res * shareSet_next; }; //######################### charclass_res ######################### struct charclass_res { string_res chars; }; void ?{}( charclass_res & ) = void; void ?{}( charclass_res &, charclass_res) = void; charclass_res ?=?( charclass_res &, charclass_res) = void; void ?{}( charclass_res &, const string_res & chars); void ?{}( charclass_res &, const char * chars ); void ?{}( charclass_res &, const char * chars, size_t charssize ); void ^?{}( charclass_res & ); //######################### String ######################### // Getters static inline size_t len( const string_res & s ) { return s.Handle.lnth; } // Constructors, Assignment Operators, Destructor void ?{}(string_res & s); // empty string void ?{}(string_res & s, const char * buffer, size_t bsize); // copy specific length from buffer static inline void ?{}(string_res & s, const char * rhs) { // copy from string literal (NULL-terminated) (s){ rhs, strlen(rhs) }; } static inline void ?{}(string_res & s, char c ) { ?{}( s, &c, 1); } // Deleting the copy constructors makes the compiler reject an attempt to call/return by value void ?{}(string_res & s, const string_res & s2) = void; void ?{}(string_res & s, string_res & s2) = void; enum StrResInitMode { COPY_VALUE, SHARE_EDITS }; void ?{}(string_res & s, const string_res & src, StrResInitMode, size_t start, size_t len ); static inline void ?{}(string_res & s, const string_res & src, StrResInitMode mode ) { ?{}( s, src, mode, 0, len(src)); } static inline void ?{}(string_res & s, const string_res & src, StrResInitMode mode, size_t maxlen ) { ?{}( s, src, mode, 0, (len(src) > maxlen)?maxlen:len(src) ); } void ?{}( string_res & s, ssize_t rhs ); void ?{}( string_res & s, size_t rhs ); void ?{}( string_res & s, double rhs ); void ?{}( string_res & s, long double rhs ); void ?{}( string_res & s, double _Complex rhs ); void ?{}( string_res & s, long double _Complex rhs ); string_res & assign(string_res & s, const string_res & src, size_t maxlen); // copy specific length from other string string_res & assign(string_res & s, const char * buffer, size_t bsize); // copy specific length from buffer static inline string_res & ?=?(string_res & s, const char * c) { // copy from string literal (NULL-terminated) return assign(s, c, strlen( c)); } string_res & ?=?(string_res & s, const string_res & c); string_res & ?=?(string_res & s, string_res & c); string_res & ?=?(string_res & s, char c); string_res & ?=?( string_res & s, ssize_t rhs ); string_res & ?=?( string_res & s, size_t rhs ); string_res & ?=?( string_res & s, double rhs ); string_res & ?=?( string_res & s, long double rhs ); string_res & ?=?( string_res & s, double _Complex rhs ); string_res & ?=?( string_res & s, long double _Complex rhs ); void ^?{}(string_res & s); // IO Operator forall( ostype & | basic_ostream( ostype ) ) { ostype & ?|?(ostype & out, const string_res & s); void ?|?(ostype & out, const string_res & s); } forall( istype & | basic_istream( istype ) ) istype & ?|?(istype & in, string_res & s); struct _Istream_Rwidth { string_res * s; inline _Istream_str_base; }; // _Istream_Rwidth struct _Istream_Rquote { // string_res * s; // inline _Istream_str_base; _Istream_Rwidth rstr; }; // _Istream_Rquote struct _Istream_Rstr { string_res * s; inline _Istream_str_base; // _Istream_Rwidth rstr; }; // _Istream_Rstr static inline { // read width does not include null terminator _Istream_Rwidth wdi( unsigned int rwd, string_res & s ) { return (_Istream_Rwidth)@{ .s = &s, { {.scanset = 0p}, .wd = rwd, {.flags.rwd = true} } }; } _Istream_Rstr getline( string_res & s, const char delimiter = '\n' ) { return (_Istream_Rstr)@{ .s = &s, { {.delimiters = { delimiter, '\0' } }, .wd = -1, {.flags.delimiter = true} } }; } _Istream_Rstr & getline( _Istream_Rwidth & f, const char delimiter = '\n' ) { f.delimiters[0] = delimiter; f.delimiters[1] = '\0'; f.flags.delimiter = true; return (_Istream_Rstr &)f; } _Istream_Rquote quote( string_res & s, const char Ldelimiter = '\"', const char Rdelimiter = '\0' ) { return (_Istream_Rquote)@{ { .s = &s, { {.delimiters = { Ldelimiter, Rdelimiter, '\0' }}, .wd = -1, {.flags.rwd = true} } } }; } _Istream_Rquote & quote( _Istream_Rwidth & f, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) { f.delimiters[0] = Ldelimiter; f.delimiters[1] = Rdelimiter; f.delimiters[2] = '\0'; return (_Istream_Rquote &)f; } _Istream_Rstr incl( const char scanset[], string_res & s ) { return (_Istream_Rstr)@{ .s = &s, { {.scanset = scanset}, .wd = -1, {.flags.inex = false} } }; } _Istream_Rstr & incl( const char scanset[], _Istream_Rwidth & f ) { f.scanset = scanset; f.flags.inex = false; return (_Istream_Rstr &)f; } _Istream_Rstr excl( const char scanset[], string_res & s ) { return (_Istream_Rstr)@{ .s = &s, { {.scanset = scanset}, .wd = -1, {.flags.inex = true} } }; } _Istream_Rstr & excl( const char scanset[], _Istream_Rwidth & f ) { f.scanset = scanset; f.flags.inex = true; return (_Istream_Rstr &)f; } _Istream_Rstr ignore( string_res & s ) { return (_Istream_Rstr)@{ .s = &s, { {.scanset = 0p}, .wd = -1, {.flags.ignore = true} } }; } _Istream_Rstr & ignore( _Istream_Rwidth & f ) { f.flags.ignore = true; return (_Istream_Rstr &)f; } _Istream_Rquote & ignore( _Istream_Rquote & f ) { f.rstr.flags.ignore = true; return (_Istream_Rquote &)f; } _Istream_Rstr & ignore( _Istream_Rstr & f ) { f.flags.ignore = true; return (_Istream_Rstr &)f; } } // distribution forall( istype & | basic_istream( istype ) ) { istype & ?|?( istype & is, _Istream_Rquote f ); istype & ?|?( istype & is, _Istream_Rstr f ); static inline istype & ?|?( istype & is, _Istream_Rwidth f ) { return is | *(_Istream_Rstr *)&f; } } // Concatenation void append( string_res & s, const char * buffer, size_t bsize ); void append( string_res & s, const string_res & s2, size_t maxlen ); static inline void ?+=?( string_res & s, const string_res & s2 ) { append( s, s2.Handle.s, s2.Handle.lnth ); } static inline void ?+=?( string_res & s, char c ) { append( s, & c, 1 ); } static inline void ?+=?( string_res & s, const char * c ) { append( s, c, strlen( c ) ); } static inline string_res & strcat( string_res & s, const string_res & s2 ) { s += s2; return s; } static inline string_res & strcat( string_res & s, const char * c ) { s += c; return s; } static inline string_res & strncat( string_res & s, const string_res & s2, size_t maxlen ) { append(s, s2, maxlen); return s; } static inline string_res & strncat( string_res & s, const char * buffer, size_t bsize ) { append(s, buffer, bsize); return s; } // Repetition void ?*=?(string_res & s, size_t factor); // Character access void assignAt( const string_res & s, size_t index, char val); char ?[?]( const string_res & s, size_t index); // Mike changed to ret by val from Sunjay's ref, to match Peter's //char codePointAt( const string_res & s, size_t index); // revisit under Unicode // Comparisons int strcmp$( const char * s1, size_t l1, const char * s2, size_t l2 ); static inline int strcmp( const string_res & s1, const string_res & s2 ) { return strcmp$( s1.Handle.s, s1.Handle.lnth, s2.Handle.s, s2.Handle.lnth ); } static inline bool ?==?( const string_res & s1, const string_res & s2 ) { return strcmp( s1, s2 ) == 0; } static inline bool ?!=?( const string_res & s1, const string_res & s2 ) { return strcmp( s1, s2 ) != 0; } static inline bool ?>? ( const string_res & s1, const string_res & s2 ) { return strcmp( s1, s2 ) > 0; } static inline bool ?>=?( const string_res & s1, const string_res & s2 ) { return strcmp( s1, s2 ) >= 0; } static inline bool ?<=?( const string_res & s1, const string_res & s2 ) { return strcmp( s1, s2 ) <= 0; } static inline bool ?? ( const string_res & s1, const char * s2 ) { return strcmp( s1, s2 ) > 0; } static inline bool ?>=?( const string_res & s1, const char * s2 ) { return strcmp( s1, s2 ) >= 0; } static inline bool ?<=?( const string_res & s1, const char * s2 ) { return strcmp( s1, s2 ) <= 0; } static inline bool ?? ( const char * s1, const string_res & s2 ) { return strcmp( s1, s2 ) > 0; } static inline bool ?>=?( const char * s1, const string_res & s2 ) { return strcmp( s1, s2 ) >= 0; } static inline bool ?<=?( const char * s1, const string_res & s2 ) { return strcmp( s1, s2 ) <= 0; } static inline bool ?