source: libcfa/src/collections/string.cfa @ 0b8c951d

Last change on this file since 0b8c951d was 55b060d, checked in by Peter A. Buhr <pabuhr@…>, 10 months ago

rename directories containers to collections

  • Property mode set to 100644
File size: 10.9 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// string -- variable-length, mutable run of text, with value semantics
8//
9// Author           : Michael L. Brooks
10// Created On       : Fri Sep 03 11:00:00 2021
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Tue Aug 29 18:32:34 2023
13// Update Count     : 153
14//
15
16#include "string.hfa"
17#include "string_res.hfa"
18#include <stdlib.hfa>
19
20#pragma GCC visibility push(default)
21
22/*
23Implementation Principle: typical operation translates to the equivalent
24operation on `inner`.  Exceptions are implementing new RAII pattern for value
25semantics and some const-hell handling.
26*/
27
28////////////////////////////////////////////////////////
29// string RAII
30
31
32void ?{}( string & this ) {
33    (this.inner) { malloc() };
34    ?{}( *this.inner );
35}
36
37// private (not in header)
38static void ?{}( string & this, string_res & src, size_t start, size_t end ) {
39    (this.inner) { malloc() };
40    ?{}( *this.inner, src, SHARE_EDITS, start, end );
41}
42
43void ?{}( string & this, const string & other ) {
44    (this.inner) { malloc() };
45    ?{}( *this.inner, *other.inner, COPY_VALUE );
46}
47
48void ?{}( string & this, string & other ) {
49    ?{}( this, (const string &) other );
50}
51
52void ?{}( string & this, const char * val ) {
53    (this.inner) { malloc() };
54    ?{}( *this.inner, val );
55}
56
57void ?{}( string & this, const char * buffer, size_t bsize) {
58    (this.inner) { malloc() };
59    ?{}( *this.inner, buffer, bsize );
60}
61
62void ^?{}( string & this ) {
63    ^(*this.inner){};
64    free( this.inner );
65    this.inner = 0p;
66}
67
68////////////////////////////////////////////////////////
69// Alternate construction: request shared edits
70
71string_WithSharedEdits ?`shareEdits( string & this ) {
72    string_WithSharedEdits ret = { &this };
73    return ret;
74}
75
76void ?{}( string & this, string_WithSharedEdits src ) {
77    ?{}( this, *src.s->inner, 0, src.s->inner->Handle.lnth);
78}
79
80////////////////////////////////////////////////////////
81// Assignment
82
83void ?=?( string & this, const char * val ) {
84    (*this.inner) = val;
85}
86
87void ?=?(string & this, const string & other) {
88    (*this.inner) = (*other.inner);
89}
90
91void ?=?( string & this, char val ) {
92    (*this.inner) = val;
93}
94
95string & ?=?(string & this, string & other) { //// <---- straw man change
96    (*this.inner) = (*other.inner);
97    return this;
98}
99
100
101////////////////////////////////////////////////////////
102// Input-Output
103
104ofstream & ?|?( ofstream & out, const string & this ) {
105    return out | (*this.inner); // print internal string_res
106}
107
108void ?|?( ofstream & out, const string & this ) {
109    (ofstream &)(out | (*this.inner)); ends( out );
110}
111
112ifstream & ?|?(ifstream & in, string & this) {
113    return in | (*this.inner); // read to internal string_res
114}
115
116void ?|?( ifstream & in, string & this ) {
117    (ifstream &)(in | this); ends( in );
118}
119
120ifstream & ?|?( ifstream & is, _Istream_str f ) {
121        // skip, same as for char *
122        if ( ! &f.s ) {
123                // fprintf( stderr,  "skip %s %d\n", f.scanset, f.wd );
124                if ( f.wd == -1 ) fmt( is, f.scanset, "" ); // no input arguments
125                else for ( f.wd ) fmt( is, "%*c" );
126                return is;
127        } // if
128
129        enum { gwd = 128 + 2, wd = gwd - 1 };                           // guarded and unguarded width
130        char cstr[gwd];                                                                         // read in chunks
131        bool cont = false;;
132
133        if ( f.wd == -1 ) f.wd = wd;
134        const char * scanset = f.scanset;;
135        if ( f.flags.delimit ) scanset = f.delimit;                     // getline ?
136
137        size_t len = 0;
138        if ( scanset ) len = strlen( scanset );
139        char fmtstr[len + 16];
140        int start = 1;
141        fmtstr[0] = '%';
142        if ( f.flags.ignore ) { fmtstr[1] = '*'; start += 1; }
143        if ( f.wd != -1 ) { start += sprintf( &fmtstr[start], "%d", f.wd ); }
144
145        if ( ! scanset ) {
146                // %s, %*s, %ws, %*ws
147                fmtstr[start] = 's'; fmtstr[start + 1] = '\0';
148                // printf( "cstr %s\n", fmtstr );
149        } else {
150                // incl %[xxx],  %*[xxx],  %w[xxx],  %*w[xxx]
151                // excl %[^xxx], %*[^xxx], %w[^xxx], %*w[^xxx]
152                fmtstr[start] = '['; start += 1;
153                if ( f.flags.inex ) { fmtstr[start] = '^'; start += 1; }
154                strcpy( &fmtstr[start], scanset );                              // copy includes '\0'
155                len += start;
156                fmtstr[len] = ']'; fmtstr[len + 1] = '\0';
157                // printf( "incl/excl %s\n", fmtstr );
158        } // if
159
160        cstr[wd] = '\0';                                                                        // guard null terminate string
161        try {
162                readstr( is, f, fmtstr, cstr );
163        } catch( cstring_length * ) {
164                cont = true;
165        } finally {
166                f.s = cstr;                                                                             // ok to initialize string
167        } // try
168        for ( ; cont; )  {                                                                      // overflow read ?
169                cont = false;
170                try {
171                        readstr( is, f, fmtstr, cstr );
172                } catch( cstring_length * ) {
173                        cont = true;                                                            // continue not allowed
174                } finally {
175                        f.s += cstr;                                                            // build string chunk at a time
176                } // try
177        } // for
178        return is;
179} // ?|?
180
181void ?|?( ifstream & in, _Istream_str f ) {
182    (ifstream &)(in | f); ends( in );
183}
184
185// void getline( ifstream & in, string & str, const char delimit = '\n' ) {
186//      // .---------------,
187//      // | | | | |...|0|0| check and guard
188//      // `---------------'
189//      enum { gwd = 128 + 2, wd = gwd - 1 };                           // guarded and unguarded width
190//      char cstr[gwd];                                                                         // read in chunks
191//      bool cont = false;;
192
193//      cstr[wd] = '\0';                                                                        // guard null terminate string
194//      try {
195//              in | getline( wdi( wd, cstr ), delimit );               // must have room for string terminator
196//              if ( eof( in  ) ) return;                                               // do not change argument
197//      } catch( cstring_length * ) {
198//              cont = true;
199//      } finally {
200//              str = cstr;                                                                             // ok to initialize string
201//      } // try
202//      for ( ; cont; )  {                                                                      // overflow read ?
203//              cont = false;
204//              try {
205//                      in | getline( wdi( wd, cstr ), delimit );       // must have room for string terminator
206//                      if ( eof( in  ) ) return;
207//              } catch( cstring_length * ) {
208//                      cont = true;                                                            // continue not allowed
209//              } finally {
210//                      str += cstr;                                                            // build string chunk at a time
211//              } // try
212//      } // for
213// }
214
215////////////////////////////////////////////////////////
216// Slicing
217
218string ?()( string & this, size_t start, size_t end ) {
219    string ret = { *this.inner, start, end };
220    return ret`shareEdits;
221}
222
223string ?()( string & this, size_t start ) {
224    string ret = { *this.inner, start, size( this ) };
225    return ret`shareEdits;
226}
227
228////////////////////////////////////////////////////////
229// Comparison
230
231bool ?==?(const string & s, const string & other) {
232    return *s.inner == *other.inner;
233}
234
235bool ?!=?(const string & s, const string & other) {
236    return *s.inner != *other.inner;
237}
238
239bool ?==?(const string & s, const char * other) {
240    return *s.inner == other;
241}
242
243bool ?!=?(const string & s, const char * other) {
244    return *s.inner != other;
245}
246
247////////////////////////////////////////////////////////
248// Getter
249
250size_t size(const string & s) {
251    return size( * s.inner );
252}
253
254////////////////////////////////////////////////////////
255// Concatenation
256
257void ?+=?(string & s, char other) {
258    (*s.inner) += other;
259}
260
261void ?+=?(string & s, const string & s2) {
262    (*s.inner) += (*s2.inner);
263}
264
265void ?+=?(string & s, const char * other) {
266    (*s.inner) += other;
267}
268
269string ?+?(const string & s, char other) {
270    string ret = s;
271    ret += other;
272    return ret;
273}
274
275string ?+?(const string & s, const string & s2) {
276    string ret = s;
277    ret += s2;
278    return ret;
279}
280
281string ?+?(const char * s1, const char * s2) {
282    string ret = s1;
283    ret += s2;
284    return ret;
285}
286
287string ?+?(const string & s, const char * other) {
288    string ret = s;
289    ret += other;
290    return ret;
291}
292
293////////////////////////////////////////////////////////
294// Repetition
295
296string ?*?(const string & s, size_t factor) {
297    string ret = "";
298    for (factor) ret += s;
299    return ret;
300}
301
302string ?*?(char c, size_t size) {
303    string ret = "";
304    for ((size_t)size) ret += c;
305    return ret;
306}
307
308string ?*?(const char *s, size_t factor) {
309    string ss = s;
310    return ss * factor;
311}
312
313////////////////////////////////////////////////////////
314// Character access
315
316char ?[?](const string & s, size_t index) {
317    return (*s.inner)[index];
318}
319
320string ?[?](string & s, size_t index) {
321    string ret = { *s.inner, index, index + 1 };
322    return ret`shareEdits;
323}
324
325////////////////////////////////////////////////////////
326// Search
327
328bool contains(const string & s, char ch) {
329    return contains( *s.inner, ch );
330}
331
332int find(const string & s, char search) {
333    return find( *s.inner, search );
334}
335
336int find(const string & s, const string & search) {
337    return find( *s.inner, *search.inner );
338}
339
340int find(const string & s, const char * search) {
341    return find( *s.inner, search);
342}
343
344int find(const string & s, const char * search, size_t searchsize) {
345    return find( *s.inner, search, searchsize);
346}
347
348int findFrom(const string & s, size_t fromPos, char search) {
349    return findFrom( *s.inner, fromPos, search );
350}
351
352int findFrom(const string & s, size_t fromPos, const string & search) {
353    return findFrom( *s.inner, fromPos, *search.inner );
354}
355
356int findFrom(const string & s, size_t fromPos, const char * search) {
357    return findFrom( *s.inner, fromPos, search );
358}
359
360int findFrom(const string & s, size_t fromPos, const char * search, size_t searchsize) {
361    return findFrom( *s.inner, fromPos, search, searchsize );
362}
363
364bool includes(const string & s, const string & search) {
365    return includes( *s.inner, *search.inner );
366}
367
368bool includes(const string & s, const char * search) {
369    return includes( *s.inner, search );
370}
371
372bool includes(const string & s, const char * search, size_t searchsize) {
373    return includes( *s.inner, search, searchsize );
374}
375
376bool startsWith(const string & s, const string & prefix) {
377    return startsWith( *s.inner, *prefix.inner );
378}
379
380bool startsWith(const string & s, const char * prefix) {
381    return startsWith( *s.inner, prefix );
382}
383
384bool startsWith(const string & s, const char * prefix, size_t prefixsize) {
385    return startsWith( *s.inner, prefix, prefixsize );
386}
387
388bool endsWith(const string & s, const string & suffix) {
389    return endsWith( *s.inner, *suffix.inner );
390}
391
392bool endsWith(const string & s, const char * suffix) {
393    return endsWith( *s.inner, suffix );
394}
395
396bool endsWith(const string & s, const char * suffix, size_t suffixsize) {
397    return endsWith( *s.inner, suffix, suffixsize );
398}
399
400
401///////////////////////////////////////////////////////////////////////////
402// charclass, include, exclude
403
404void ?{}( charclass & this, const string & chars) {
405    (this.inner) { malloc() };
406    ?{}( *this.inner, *(const string_res *)chars.inner );
407}
408
409void ?{}( charclass & this, const char * chars ) {
410    (this.inner) { malloc() };
411    ?{}( *this.inner, chars );
412}
413
414void ?{}( charclass & this, const char * chars, size_t charssize ) {
415    (this.inner) { malloc() };
416    ?{}( *this.inner, chars, charssize );
417}
418
419void ^?{}( charclass & this ) {
420    ^(*this.inner){};
421    free( this.inner );
422    this.inner = 0p;
423}
424
425
426int exclude(const string & s, const charclass & mask) {
427    return exclude( *s.inner, *mask.inner );
428}
429/*
430StrSlice exclude(string & s, const charclass & mask) {
431}
432*/
433
434int include(const string & s, const charclass & mask) {
435    return include( *s.inner, *mask.inner );
436}
437
438/*
439StrSlice include(string & s, const charclass & mask) {
440}
441*/
442
Note: See TracBrowser for help on using the repository browser.