source: libcfa/src/containers/string.cfa@ 4269d1b

stuck-waitfor-destruct
Last change on this file since 4269d1b was 7e1dbd7, checked in by Peter A. Buhr <pabuhr@…>, 2 years ago

first attempt at input manipulators for strings

  • Property mode set to 100644
File size: 11.6 KB
RevLine 
[f450f2f]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
[bc9f84a]11// Last Modified By : Peter A. Buhr
[7e1dbd7]12// Last Modified On : Mon Aug 28 19:00:45 2023
13// Update Count : 146
[f450f2f]14//
15
16#include "string.hfa"
17#include "string_res.hfa"
18#include <stdlib.hfa>
19
[accc9df9]20#pragma GCC visibility push(default)
[f450f2f]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
[6264087]57void ?{}( string & this, const char * buffer, size_t bsize) {
[f450f2f]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
[4b3b352]95string & ?=?(string & this, string & other) { //// <---- straw man change
[f450f2f]96 (*this.inner) = (*other.inner);
97 return this;
98}
99
100
101////////////////////////////////////////////////////////
[d32679d5]102// Input-Output
[f450f2f]103
[9ca5e56]104ofstream & ?|?( ofstream & out, const string & this ) {
105 return out | (*this.inner); // print internal string_res
[f450f2f]106}
107
[9ca5e56]108void ?|?( ofstream & out, const string & this ) {
109 (ofstream &)(out | (*this.inner)); ends( out );
[f450f2f]110}
111
[6264087]112ifstream & ?|?(ifstream & in, string & this) {
[d32679d5]113 return in | (*this.inner); // read to internal string_res
114}
115
[6264087]116void ?|?( ifstream & in, string & this ) {
117 (ifstream &)(in | this); ends( in );
118}
[d32679d5]119
[7e1dbd7]120static void readstr( ifstream & is, _Istream_str f, char fmtstr[], char cstr[] ) {
121 int check = f.rwd - 1;
122
123 if ( ! f.flags.rwd ) cstr[check] = '\0'; // insert sentinel
124 int len = fmt( is, fmtstr, cstr );
125 // fprintf( stderr, "KK %s %zd %d %c %s\n", fmtstr, len, check, cstr[check], cstr );
126
127 if ( ! f.flags.rwd && cstr[check] != '\0' ) // sentinel overwritten ?
128 throw (cstring_length){ &cstring_length_vt };
129
130 if ( f.flags.delimit ) { // getline ?
131 if ( len == 0 ) cstr[0] = '\0'; // empty read => argument unchanged => set empty
132 if ( ! eof( is ) ) fmt( is, "%*c" ); // ignore delimiter
133 } //if
134} // readstr
135
136ifstream & ?|?( ifstream & is, _Istream_str f ) {
137 // skip, same as for char *
138 if ( ! &f.s ) {
139 // fprintf( stderr, "skip %s %d\n", f.scanset, f.wd );
140 if ( f.rwd == -1 ) fmt( is, f.scanset, "" ); // no input arguments
141 else for ( f.rwd ) fmt( is, "%*c" );
142 return is;
143 } // if
144
145 enum { gwd = 16 + 2, wd = gwd - 1 }; // guarded and unguarded width
[88001dd]146 char cstr[gwd]; // read in chunks
147 bool cont = false;;
148
[7e1dbd7]149 if ( f.rwd == -1 ) f.rwd = wd;
150 const char * scanset = f.scanset;;
151 if ( f.flags.delimit ) scanset = f.delimit; // getline ?
152
153 size_t len = 0;
154 if ( scanset ) len = strlen( scanset );
155 char fmtstr[len + 16];
156 int start = 1;
157 fmtstr[0] = '%';
158 if ( f.flags.ignore ) { fmtstr[1] = '*'; start += 1; }
159 if ( f.rwd != -1 ) { start += sprintf( &fmtstr[start], "%d", f.rwd ); }
160
161 if ( ! scanset ) {
162 // %s, %*s, %ws, %*ws
163 fmtstr[start] = 's'; fmtstr[start + 1] = '\0';
164 // printf( "cstr %s\n", fmtstr );
165 } else {
166 // incl %[xxx], %*[xxx], %w[xxx], %*w[xxx]
167 // excl %[^xxx], %*[^xxx], %w[^xxx], %*w[^xxx]
168 fmtstr[start] = '['; start += 1;
169 if ( f.flags.inex ) { fmtstr[start] = '^'; start += 1; }
170 strcpy( &fmtstr[start], scanset ); // copy includes '\0'
171 len += start;
172 fmtstr[len] = ']'; fmtstr[len + 1] = '\0';
173 // printf( "incl/excl %s\n", fmtstr );
174 } // if
175
[88001dd]176 cstr[wd] = '\0'; // guard null terminate string
177 try {
[7e1dbd7]178 readstr( is, f, fmtstr, cstr );
[88001dd]179 } catch( cstring_length * ) {
[7e1dbd7]180 cont = true;
[88001dd]181 } finally {
[7e1dbd7]182 f.s = cstr; // ok to initialize string
[88001dd]183 } // try
184 for ( ; cont; ) { // overflow read ?
185 cont = false;
186 try {
[7e1dbd7]187 readstr( is, f, fmtstr, cstr );
[88001dd]188 } catch( cstring_length * ) {
189 cont = true; // continue not allowed
190 } finally {
[7e1dbd7]191 f.s += cstr; // build string chunk at a time
[88001dd]192 } // try
193 } // for
[7e1dbd7]194 return is;
195} // ?|?
196
197void ?|?( ifstream & in, _Istream_str f ) {
198 (ifstream &)(in | f); ends( in );
199}
200
201// void getline( ifstream & in, string & str, const char delimit = '\n' ) {
202// // .---------------,
203// // | | | | |...|0|0| check and guard
204// // `---------------'
205// enum { gwd = 128 + 2, wd = gwd - 1 }; // guarded and unguarded width
206// char cstr[gwd]; // read in chunks
207// bool cont = false;;
208
209// cstr[wd] = '\0'; // guard null terminate string
210// try {
211// in | getline( wdi( wd, cstr ), delimit ); // must have room for string terminator
212// if ( eof( in ) ) return; // do not change argument
213// } catch( cstring_length * ) {
214// cont = true;
215// } finally {
216// str = cstr; // ok to initialize string
217// } // try
218// for ( ; cont; ) { // overflow read ?
219// cont = false;
220// try {
221// in | getline( wdi( wd, cstr ), delimit ); // must have room for string terminator
222// if ( eof( in ) ) return;
223// } catch( cstring_length * ) {
224// cont = true; // continue not allowed
225// } finally {
226// str += cstr; // build string chunk at a time
227// } // try
228// } // for
229// }
[88001dd]230
[f450f2f]231////////////////////////////////////////////////////////
232// Slicing
233
234string ?()( string & this, size_t start, size_t end ) {
235 string ret = { *this.inner, start, end };
236 return ret`shareEdits;
237}
238
[bc9f84a]239string ?()( string & this, size_t start ) {
240 string ret = { *this.inner, start, size( this ) };
241 return ret`shareEdits;
242}
243
[f450f2f]244////////////////////////////////////////////////////////
245// Comparison
246
[6264087]247bool ?==?(const string & s, const string & other) {
[f450f2f]248 return *s.inner == *other.inner;
249}
250
[6264087]251bool ?!=?(const string & s, const string & other) {
[f450f2f]252 return *s.inner != *other.inner;
253}
254
[6264087]255bool ?==?(const string & s, const char * other) {
[f450f2f]256 return *s.inner == other;
257}
258
[6264087]259bool ?!=?(const string & s, const char * other) {
[f450f2f]260 return *s.inner != other;
261}
262
263////////////////////////////////////////////////////////
264// Getter
265
[6264087]266size_t size(const string & s) {
[f450f2f]267 return size( * s.inner );
268}
269
270////////////////////////////////////////////////////////
271// Concatenation
272
[6264087]273void ?+=?(string & s, char other) {
[f450f2f]274 (*s.inner) += other;
275}
276
[6264087]277void ?+=?(string & s, const string & s2) {
[f450f2f]278 (*s.inner) += (*s2.inner);
279}
280
[6264087]281void ?+=?(string & s, const char * other) {
[f450f2f]282 (*s.inner) += other;
283}
284
[6264087]285string ?+?(const string & s, char other) {
[f450f2f]286 string ret = s;
287 ret += other;
288 return ret;
289}
290
[6264087]291string ?+?(const string & s, const string & s2) {
[f450f2f]292 string ret = s;
293 ret += s2;
294 return ret;
295}
296
[6264087]297string ?+?(const char * s1, const char * s2) {
[f450f2f]298 string ret = s1;
299 ret += s2;
300 return ret;
301}
302
[6264087]303string ?+?(const string & s, const char * other) {
[f450f2f]304 string ret = s;
305 ret += other;
306 return ret;
307}
308
309////////////////////////////////////////////////////////
310// Repetition
311
[6264087]312string ?*?(const string & s, size_t factor) {
[f450f2f]313 string ret = "";
314 for (factor) ret += s;
315 return ret;
316}
317
318string ?*?(char c, size_t size) {
319 string ret = "";
320 for ((size_t)size) ret += c;
321 return ret;
322}
323
324string ?*?(const char *s, size_t factor) {
325 string ss = s;
326 return ss * factor;
327}
328
329////////////////////////////////////////////////////////
330// Character access
331
[6264087]332char ?[?](const string & s, size_t index) {
[f450f2f]333 return (*s.inner)[index];
334}
335
[6264087]336string ?[?](string & s, size_t index) {
[f450f2f]337 string ret = { *s.inner, index, index + 1 };
338 return ret`shareEdits;
339}
340
341////////////////////////////////////////////////////////
342// Search
343
[6264087]344bool contains(const string & s, char ch) {
[f450f2f]345 return contains( *s.inner, ch );
346}
347
[6264087]348int find(const string & s, char search) {
[f450f2f]349 return find( *s.inner, search );
350}
351
[6264087]352int find(const string & s, const string & search) {
[f450f2f]353 return find( *s.inner, *search.inner );
354}
355
[6264087]356int find(const string & s, const char * search) {
[f450f2f]357 return find( *s.inner, search);
358}
359
[6264087]360int find(const string & s, const char * search, size_t searchsize) {
[f450f2f]361 return find( *s.inner, search, searchsize);
362}
363
[6264087]364int findFrom(const string & s, size_t fromPos, char search) {
[08ed947]365 return findFrom( *s.inner, fromPos, search );
366}
367
[6264087]368int findFrom(const string & s, size_t fromPos, const string & search) {
[08ed947]369 return findFrom( *s.inner, fromPos, *search.inner );
370}
371
[6264087]372int findFrom(const string & s, size_t fromPos, const char * search) {
[08ed947]373 return findFrom( *s.inner, fromPos, search );
374}
375
[6264087]376int findFrom(const string & s, size_t fromPos, const char * search, size_t searchsize) {
[08ed947]377 return findFrom( *s.inner, fromPos, search, searchsize );
378}
379
[6264087]380bool includes(const string & s, const string & search) {
[f450f2f]381 return includes( *s.inner, *search.inner );
382}
383
[6264087]384bool includes(const string & s, const char * search) {
[f450f2f]385 return includes( *s.inner, search );
386}
387
[6264087]388bool includes(const string & s, const char * search, size_t searchsize) {
[f450f2f]389 return includes( *s.inner, search, searchsize );
390}
391
[6264087]392bool startsWith(const string & s, const string & prefix) {
[f450f2f]393 return startsWith( *s.inner, *prefix.inner );
394}
395
[6264087]396bool startsWith(const string & s, const char * prefix) {
[f450f2f]397 return startsWith( *s.inner, prefix );
398}
399
[6264087]400bool startsWith(const string & s, const char * prefix, size_t prefixsize) {
[f450f2f]401 return startsWith( *s.inner, prefix, prefixsize );
402}
403
[6264087]404bool endsWith(const string & s, const string & suffix) {
[f450f2f]405 return endsWith( *s.inner, *suffix.inner );
406}
407
[6264087]408bool endsWith(const string & s, const char * suffix) {
[f450f2f]409 return endsWith( *s.inner, suffix );
410}
411
[6264087]412bool endsWith(const string & s, const char * suffix, size_t suffixsize) {
[f450f2f]413 return endsWith( *s.inner, suffix, suffixsize );
414}
415
416
417///////////////////////////////////////////////////////////////////////////
418// charclass, include, exclude
419
420void ?{}( charclass & this, const string & chars) {
421 (this.inner) { malloc() };
422 ?{}( *this.inner, *(const string_res *)chars.inner );
423}
424
425void ?{}( charclass & this, const char * chars ) {
426 (this.inner) { malloc() };
427 ?{}( *this.inner, chars );
428}
429
430void ?{}( charclass & this, const char * chars, size_t charssize ) {
431 (this.inner) { malloc() };
432 ?{}( *this.inner, chars, charssize );
433}
434
435void ^?{}( charclass & this ) {
436 ^(*this.inner){};
437 free( this.inner );
438 this.inner = 0p;
439}
440
441
[6264087]442int exclude(const string & s, const charclass & mask) {
[f450f2f]443 return exclude( *s.inner, *mask.inner );
444}
445/*
[6264087]446StrSlice exclude(string & s, const charclass & mask) {
[f450f2f]447}
448*/
449
[6264087]450int include(const string & s, const charclass & mask) {
[f450f2f]451 return include( *s.inner, *mask.inner );
452}
453
454/*
[6264087]455StrSlice include(string & s, const charclass & mask) {
[f450f2f]456}
457*/
458
Note: See TracBrowser for help on using the repository browser.