source: libcfa/src/collections/string.cfa@ 950c58e

stuck-waitfor-destruct
Last change on this file since 950c58e was 686912c, checked in by Peter A. Buhr <pabuhr@…>, 2 years ago

third attempt at input manipulators for strings

  • Property mode set to 100644
File size: 9.2 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
[686912c]12// Last Modified On : Thu Aug 31 13:20:41 2023
13// Update Count : 161
[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]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 );
[38de914]124 if ( f.wd == -1 ) fmt( is, f.scanset, "" ); // no input arguments
125 else for ( f.wd ) fmt( is, "%*c" );
[7e1dbd7]126 return is;
127 } // if
128
[686912c]129 // .---------------,
130 // | | | | |...|0|0| check and guard
131 // `---------------'
[38de914]132 enum { gwd = 128 + 2, wd = gwd - 1 }; // guarded and unguarded width
[88001dd]133 char cstr[gwd]; // read in chunks
[686912c]134 bool cont = false;
[88001dd]135
[38de914]136 if ( f.wd == -1 ) f.wd = wd;
[686912c]137 _Istream_Cstr cfmt = { cstr, (_Istream_str_base)f };
[7e1dbd7]138
[88001dd]139 cstr[wd] = '\0'; // guard null terminate string
140 try {
[686912c]141 is | cfmt;
[88001dd]142 } catch( cstring_length * ) {
[7e1dbd7]143 cont = true;
[88001dd]144 } finally {
[7e1dbd7]145 f.s = cstr; // ok to initialize string
[88001dd]146 } // try
147 for ( ; cont; ) { // overflow read ?
148 cont = false;
149 try {
[686912c]150 is | cfmt;
[88001dd]151 } catch( cstring_length * ) {
152 cont = true; // continue not allowed
153 } finally {
[7e1dbd7]154 f.s += cstr; // build string chunk at a time
[88001dd]155 } // try
156 } // for
[7e1dbd7]157 return is;
158} // ?|?
159
160void ?|?( ifstream & in, _Istream_str f ) {
161 (ifstream &)(in | f); ends( in );
162}
163
[f450f2f]164////////////////////////////////////////////////////////
165// Slicing
166
167string ?()( string & this, size_t start, size_t end ) {
168 string ret = { *this.inner, start, end };
169 return ret`shareEdits;
170}
171
[bc9f84a]172string ?()( string & this, size_t start ) {
173 string ret = { *this.inner, start, size( this ) };
174 return ret`shareEdits;
175}
176
[f450f2f]177////////////////////////////////////////////////////////
178// Comparison
179
[6264087]180bool ?==?(const string & s, const string & other) {
[f450f2f]181 return *s.inner == *other.inner;
182}
183
[6264087]184bool ?!=?(const string & s, const string & other) {
[f450f2f]185 return *s.inner != *other.inner;
186}
187
[6264087]188bool ?==?(const string & s, const char * other) {
[f450f2f]189 return *s.inner == other;
190}
191
[6264087]192bool ?!=?(const string & s, const char * other) {
[f450f2f]193 return *s.inner != other;
194}
195
196////////////////////////////////////////////////////////
197// Getter
198
[6264087]199size_t size(const string & s) {
[f450f2f]200 return size( * s.inner );
201}
202
203////////////////////////////////////////////////////////
204// Concatenation
205
[6264087]206void ?+=?(string & s, char other) {
[f450f2f]207 (*s.inner) += other;
208}
209
[6264087]210void ?+=?(string & s, const string & s2) {
[f450f2f]211 (*s.inner) += (*s2.inner);
212}
213
[6264087]214void ?+=?(string & s, const char * other) {
[f450f2f]215 (*s.inner) += other;
216}
217
[6264087]218string ?+?(const string & s, char other) {
[f450f2f]219 string ret = s;
220 ret += other;
221 return ret;
222}
223
[6264087]224string ?+?(const string & s, const string & s2) {
[f450f2f]225 string ret = s;
226 ret += s2;
227 return ret;
228}
229
[6264087]230string ?+?(const char * s1, const char * s2) {
[f450f2f]231 string ret = s1;
232 ret += s2;
233 return ret;
234}
235
[6264087]236string ?+?(const string & s, const char * other) {
[f450f2f]237 string ret = s;
238 ret += other;
239 return ret;
240}
241
242////////////////////////////////////////////////////////
243// Repetition
244
[6264087]245string ?*?(const string & s, size_t factor) {
[f450f2f]246 string ret = "";
247 for (factor) ret += s;
248 return ret;
249}
250
251string ?*?(char c, size_t size) {
252 string ret = "";
253 for ((size_t)size) ret += c;
254 return ret;
255}
256
257string ?*?(const char *s, size_t factor) {
258 string ss = s;
259 return ss * factor;
260}
261
262////////////////////////////////////////////////////////
263// Character access
264
[6264087]265char ?[?](const string & s, size_t index) {
[f450f2f]266 return (*s.inner)[index];
267}
268
[6264087]269string ?[?](string & s, size_t index) {
[f450f2f]270 string ret = { *s.inner, index, index + 1 };
271 return ret`shareEdits;
272}
273
274////////////////////////////////////////////////////////
275// Search
276
[6264087]277bool contains(const string & s, char ch) {
[f450f2f]278 return contains( *s.inner, ch );
279}
280
[6264087]281int find(const string & s, char search) {
[f450f2f]282 return find( *s.inner, search );
283}
284
[6264087]285int find(const string & s, const string & search) {
[f450f2f]286 return find( *s.inner, *search.inner );
287}
288
[6264087]289int find(const string & s, const char * search) {
[f450f2f]290 return find( *s.inner, search);
291}
292
[6264087]293int find(const string & s, const char * search, size_t searchsize) {
[f450f2f]294 return find( *s.inner, search, searchsize);
295}
296
[6264087]297int findFrom(const string & s, size_t fromPos, char search) {
[08ed947]298 return findFrom( *s.inner, fromPos, search );
299}
300
[6264087]301int findFrom(const string & s, size_t fromPos, const string & search) {
[08ed947]302 return findFrom( *s.inner, fromPos, *search.inner );
303}
304
[6264087]305int findFrom(const string & s, size_t fromPos, const char * search) {
[08ed947]306 return findFrom( *s.inner, fromPos, search );
307}
308
[6264087]309int findFrom(const string & s, size_t fromPos, const char * search, size_t searchsize) {
[08ed947]310 return findFrom( *s.inner, fromPos, search, searchsize );
311}
312
[6264087]313bool includes(const string & s, const string & search) {
[f450f2f]314 return includes( *s.inner, *search.inner );
315}
316
[6264087]317bool includes(const string & s, const char * search) {
[f450f2f]318 return includes( *s.inner, search );
319}
320
[6264087]321bool includes(const string & s, const char * search, size_t searchsize) {
[f450f2f]322 return includes( *s.inner, search, searchsize );
323}
324
[6264087]325bool startsWith(const string & s, const string & prefix) {
[f450f2f]326 return startsWith( *s.inner, *prefix.inner );
327}
328
[6264087]329bool startsWith(const string & s, const char * prefix) {
[f450f2f]330 return startsWith( *s.inner, prefix );
331}
332
[6264087]333bool startsWith(const string & s, const char * prefix, size_t prefixsize) {
[f450f2f]334 return startsWith( *s.inner, prefix, prefixsize );
335}
336
[6264087]337bool endsWith(const string & s, const string & suffix) {
[f450f2f]338 return endsWith( *s.inner, *suffix.inner );
339}
340
[6264087]341bool endsWith(const string & s, const char * suffix) {
[f450f2f]342 return endsWith( *s.inner, suffix );
343}
344
[6264087]345bool endsWith(const string & s, const char * suffix, size_t suffixsize) {
[f450f2f]346 return endsWith( *s.inner, suffix, suffixsize );
347}
348
349
350///////////////////////////////////////////////////////////////////////////
351// charclass, include, exclude
352
353void ?{}( charclass & this, const string & chars) {
354 (this.inner) { malloc() };
355 ?{}( *this.inner, *(const string_res *)chars.inner );
356}
357
358void ?{}( charclass & this, const char * chars ) {
359 (this.inner) { malloc() };
360 ?{}( *this.inner, chars );
361}
362
363void ?{}( charclass & this, const char * chars, size_t charssize ) {
364 (this.inner) { malloc() };
365 ?{}( *this.inner, chars, charssize );
366}
367
368void ^?{}( charclass & this ) {
369 ^(*this.inner){};
370 free( this.inner );
371 this.inner = 0p;
372}
373
374
[6264087]375int exclude(const string & s, const charclass & mask) {
[f450f2f]376 return exclude( *s.inner, *mask.inner );
377}
378/*
[6264087]379StrSlice exclude(string & s, const charclass & mask) {
[f450f2f]380}
381*/
382
[6264087]383int include(const string & s, const charclass & mask) {
[f450f2f]384 return include( *s.inner, *mask.inner );
385}
386
387/*
[6264087]388StrSlice include(string & s, const charclass & mask) {
[f450f2f]389}
390*/
391
Note: See TracBrowser for help on using the repository browser.