source: libcfa/src/collections/string.cfa @ e891349

Last change on this file since e891349 was e891349, checked in by Michael Brooks <mlbrooks@…>, 9 months ago

Tweak string assignment-strcpy-strncpy and concatenate-strcat-strncat declarations.

Implement -n- versions correctly.

Refactor to include string_res layer.

Add missing tests.

  • Property mode set to 100644
File size: 10.3 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
[479fbe3]12// Last Modified On : Sun Jan 14 12:03:47 2024
13// Update Count     : 240
[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// private (not in header)
[681e12f]32static void ?{}( string & s, string_res & src, size_t start, size_t end ) {
33    (s.inner) { malloc() };
34    ?{}( *s.inner, src, SHARE_EDITS, start, end );
[f450f2f]35}
36
[479fbe3]37void ?{}( string & s ) {
38    (s.inner) { malloc() };
39    ?{}( *s.inner );
40}
41
[681e12f]42void ?{}( string & s, const string & c ) {
43    (s.inner) { malloc() };
44    ?{}( *s.inner, *c.inner, COPY_VALUE );
[f450f2f]45}
46
[681e12f]47void ?{}( string & s, string & c ) {
48    ?{}( s, (const string &) c );
[f450f2f]49}
50
[479fbe3]51void ?{}( string & s, const char c ) {
[681e12f]52    (s.inner) { malloc() };
[479fbe3]53        char cs[2] = { c, '\0' };
54    ?{}( *s.inner, cs );
[f450f2f]55}
56
[479fbe3]57void ?{}( string & s, const char * c ) {
[681e12f]58    (s.inner) { malloc() };
[479fbe3]59    ?{}( *s.inner, c );
60}
61
62void ?{}( string & s, const char * c, size_t size) {
63    (s.inner) { malloc() };
64    ?{}( *s.inner, c, size );
[f450f2f]65}
66
[681e12f]67void ^?{}( string & s ) {
68    ^(*s.inner){};
69    free( s.inner );
70    s.inner = 0p;
[f450f2f]71}
72
73////////////////////////////////////////////////////////
74// Alternate construction: request shared edits
75
[681e12f]76string_WithSharedEdits ?`shareEdits( string & s ) {
77    string_WithSharedEdits ret = { &s };
[f450f2f]78    return ret;
79}
80
[681e12f]81void ?{}( string & s, string_WithSharedEdits src ) {
82    ?{}( s, *src.s->inner, 0, src.s->inner->Handle.lnth);
[f450f2f]83}
84
85////////////////////////////////////////////////////////
86// Assignment
87
[681e12f]88void ?=?( string & s, const char * val ) {
89    (*s.inner) = val;
[f450f2f]90}
91
[681e12f]92void ?=?(string & s, const string & c) {
93    (*s.inner) = (*c.inner);
[f450f2f]94}
95
[681e12f]96void ?=?( string & s, char val ) {
97    (*s.inner) = val;
[f450f2f]98}
99
[681e12f]100string & ?=?(string & s, string & c) { //// <---- straw man change
101    (*s.inner) = (*c.inner);
102    return s;
[f450f2f]103}
104
[e891349]105void assign(string & s, const string & c, size_t n) {
106    assign(*s.inner, *c.inner, n);
107}
108void assign(string & s, const char * c, size_t n) {
109    assign(*s.inner, c, n);
110}
111
[f450f2f]112
113////////////////////////////////////////////////////////
[d32679d5]114// Input-Output
[f450f2f]115
[681e12f]116ofstream & ?|?( ofstream & out, const string & s ) {
117    return out | (*s.inner); // print internal string_res
[f450f2f]118}
119
[681e12f]120void ?|?( ofstream & out, const string & s ) {
121    (ofstream &)(out | (*s.inner)); ends( out );
[f450f2f]122}
123
[34c6e1e6]124ofstream & ?|?( ofstream & os, _Ostream_Manip(string) f ) {
125        size_t len = size( f.val );
126        char cstr[len + 1];                                                                     // room for null terminator
127        for ( i; len ) cstr[i] = f.val[i];                                      // copy string
128        cstr[len] = '\0';                                                                       // terminate
129        _Ostream_Manip(const char *) cf @= { cstr, f.wd, f.pc, f.base, {f.all} };
130        os | cf | nonl;
131        return os;
132} // ?|?
133
134void ?|?( ofstream & os, _Ostream_Manip(string) f ) {
135        (ofstream &)(os | f); ends( os );
136}
137
[681e12f]138ifstream & ?|?(ifstream & in, string & s) {
139    return in | (*s.inner); // read to internal string_res
[d32679d5]140}
141
[681e12f]142void ?|?( ifstream & in, string & s ) {
143    in | (*s.inner);
[6264087]144}
[d32679d5]145
[34c6e1e6]146ifstream & ?|?( ifstream & is, _Istream_Sstr f ) {
[737988b]147        _Istream_Rstr f2 = {f.s.inner, (_Istream_str_base)f};
148    return is | f2;
[7e1dbd7]149} // ?|?
150
[34c6e1e6]151void ?|?( ifstream & in, _Istream_Sstr f ) {
[f842032]152    (ifstream &)(in | f);
[7e1dbd7]153}
154
[f450f2f]155////////////////////////////////////////////////////////
156// Slicing
157
[681e12f]158string ?()( string & s, size_t start, size_t end ) {
159    string ret = { *s.inner, start, end };
[f450f2f]160    return ret`shareEdits;
161}
162
[681e12f]163string ?()( string & s, size_t start ) {
164    string ret = { *s.inner, start, size( s ) };
[bc9f84a]165    return ret`shareEdits;
166}
167
[f450f2f]168////////////////////////////////////////////////////////
169// Comparison
170
[681e12f]171int  strcmp(const string & s1, const string & s2) { return strcmp(*s1.inner, *s2.inner); }
172bool ?==?(const string & s1, const string & s2) { return *s1.inner == *s2.inner; }
173bool ?!=?(const string & s1, const string & s2) { return *s1.inner != *s2.inner; }
174bool ?>? (const string & s1, const string & s2) { return *s1.inner >  *s2.inner; }
175bool ?>=?(const string & s1, const string & s2) { return *s1.inner >= *s2.inner; }
176bool ?<=?(const string & s1, const string & s2) { return *s1.inner <= *s2.inner; }
177bool ?<? (const string & s1, const string & s2) { return *s1.inner <  *s2.inner; }
178
179int  strcmp(const string & s1, const char * s2) { return strcmp(*s1.inner, s2 ); }
180bool ?==?(const string & s1, const char * s2) { return *s1.inner == s2; }
181bool ?!=?(const string & s1, const char * s2) { return *s1.inner != s2; }
182bool ?>? (const string & s1, const char * s2) { return *s1.inner >  s2; }
183bool ?>=?(const string & s1, const char * s2) { return *s1.inner >= s2; }
184bool ?<=?(const string & s1, const char * s2) { return *s1.inner <= s2; }
185bool ?<? (const string & s1, const char * s2) { return *s1.inner <  s2; }
186
187int  strcmp(const char * s1, const string & s2) { return strcmp( s1, *s2.inner); }
188bool ?==?(const char * s1, const string & s2) { return s1 == *s2.inner; }
189bool ?!=?(const char * s1, const string & s2) { return s1 != *s2.inner; }
190bool ?>? (const char * s1, const string & s2) { return s1 >  *s2.inner; }
191bool ?>=?(const char * s1, const string & s2) { return s1 >= *s2.inner; }
192bool ?<=?(const char * s1, const string & s2) { return s1 <= *s2.inner; }
193bool ?<? (const char * s1, const string & s2) { return s1 <  *s2.inner; }
[f450f2f]194
195
196////////////////////////////////////////////////////////
197// Getter
198
[6264087]199size_t size(const string & s) {
[681e12f]200    return size( *s.inner );
[f450f2f]201}
202
203////////////////////////////////////////////////////////
204// Concatenation
205
[681e12f]206void ?+=?(string & s, char c) {
207    (*s.inner) += c;
[f450f2f]208}
209
[6264087]210void ?+=?(string & s, const string & s2) {
[f450f2f]211    (*s.inner) += (*s2.inner);
212}
213
[e891349]214void append(string & s, const string & s2, size_t maxlen) {
215    append( (*s.inner), (*s2.inner), maxlen );
216}
217
[681e12f]218void ?+=?(string & s, const char * c) {
219    (*s.inner) += c;
[f450f2f]220}
221
[e891349]222void append(string & s, const char * buffer, size_t bsize) {
223    append( (*s.inner), buffer, bsize );
224}
225
[681e12f]226string ?+?(const string & s, char c) {
[f450f2f]227    string ret = s;
[681e12f]228    ret += c;
[f450f2f]229    return ret;
230}
231
[6264087]232string ?+?(const string & s, const string & s2) {
[f450f2f]233    string ret = s;
234    ret += s2;
235    return ret;
236}
237
[6264087]238string ?+?(const char * s1, const char * s2) {
[f450f2f]239    string ret = s1;
240    ret += s2;
241    return ret;
242}
243
[681e12f]244string ?+?(const string & s, const char * c) {
[f450f2f]245    string ret = s;
[681e12f]246    ret += c;
[f450f2f]247    return ret;
248}
249
250////////////////////////////////////////////////////////
251// Repetition
252
[38951c31]253void ?*=?(string & s, size_t factor) {
254    (*s.inner) *= factor;
[f450f2f]255}
256
[38951c31]257string ?*?(const string & s, size_t factor) {
258    string ret = s;
259    ret *= factor;
260    return ret;
[479fbe3]261}
262
263string ?*?(char c, size_t factor) {
264    string ret = c;
[38951c31]265    ret *= factor;
266    return ret;
[f450f2f]267}
268
[479fbe3]269string ?*?(const char * s, size_t factor) {
270    string ret = s;
[38951c31]271    ret *= factor;
272    return ret;
[f450f2f]273}
274
275////////////////////////////////////////////////////////
276// Character access
277
[6264087]278char ?[?](const string & s, size_t index) {
[f450f2f]279    return (*s.inner)[index];
280}
281
[6264087]282string ?[?](string & s, size_t index) {
[f450f2f]283    string ret = { *s.inner, index, index + 1 };
284    return ret`shareEdits;
285}
286
287////////////////////////////////////////////////////////
288// Search
289
[6264087]290bool contains(const string & s, char ch) {
[f450f2f]291    return contains( *s.inner, ch );
292}
293
[6264087]294int find(const string & s, char search) {
[f450f2f]295    return find( *s.inner, search );
296}
297
[6264087]298int find(const string & s, const string & search) {
[f450f2f]299    return find( *s.inner, *search.inner );
300}
301
[6264087]302int find(const string & s, const char * search) {
[f450f2f]303    return find( *s.inner, search);
304}
305
[6264087]306int find(const string & s, const char * search, size_t searchsize) {
[f450f2f]307    return find( *s.inner, search, searchsize);
308}
309
[6264087]310int findFrom(const string & s, size_t fromPos, char search) {
[08ed947]311    return findFrom( *s.inner, fromPos, search );
312}
313
[6264087]314int findFrom(const string & s, size_t fromPos, const string & search) {
[08ed947]315    return findFrom( *s.inner, fromPos, *search.inner );
316}
317
[6264087]318int findFrom(const string & s, size_t fromPos, const char * search) {
[08ed947]319    return findFrom( *s.inner, fromPos, search );
320}
321
[6264087]322int findFrom(const string & s, size_t fromPos, const char * search, size_t searchsize) {
[08ed947]323    return findFrom( *s.inner, fromPos, search, searchsize );
324}
325
[6264087]326bool includes(const string & s, const string & search) {
[f450f2f]327    return includes( *s.inner, *search.inner );
328}
329
[6264087]330bool includes(const string & s, const char * search) {
[f450f2f]331    return includes( *s.inner, search );
332}
333
[6264087]334bool includes(const string & s, const char * search, size_t searchsize) {
[f450f2f]335    return includes( *s.inner, search, searchsize );
336}
337
[6264087]338bool startsWith(const string & s, const string & prefix) {
[f450f2f]339    return startsWith( *s.inner, *prefix.inner );
340}
341
[6264087]342bool startsWith(const string & s, const char * prefix) {
[f450f2f]343    return startsWith( *s.inner, prefix );
344}
345
[6264087]346bool startsWith(const string & s, const char * prefix, size_t prefixsize) {
[f450f2f]347    return startsWith( *s.inner, prefix, prefixsize );
348}
349
[6264087]350bool endsWith(const string & s, const string & suffix) {
[f450f2f]351    return endsWith( *s.inner, *suffix.inner );
352}
353
[6264087]354bool endsWith(const string & s, const char * suffix) {
[f450f2f]355    return endsWith( *s.inner, suffix );
356}
357
[6264087]358bool endsWith(const string & s, const char * suffix, size_t suffixsize) {
[f450f2f]359    return endsWith( *s.inner, suffix, suffixsize );
360}
361
362
363///////////////////////////////////////////////////////////////////////////
364// charclass, include, exclude
365
[681e12f]366void ?{}( charclass & s, const string & chars) {
367    (s.inner) { malloc() };
368    ?{}( *s.inner, *(const string_res *)chars.inner );
[f450f2f]369}
370
[681e12f]371void ?{}( charclass & s, const char * chars ) {
372    (s.inner) { malloc() };
373    ?{}( *s.inner, chars );
[f450f2f]374}
375
[681e12f]376void ?{}( charclass & s, const char * chars, size_t charssize ) {
377    (s.inner) { malloc() };
378    ?{}( *s.inner, chars, charssize );
[f450f2f]379}
380
[681e12f]381void ^?{}( charclass & s ) {
382    ^(*s.inner){};
383    free( s.inner );
384    s.inner = 0p;
[f450f2f]385}
386
387
[6264087]388int exclude(const string & s, const charclass & mask) {
[f450f2f]389    return exclude( *s.inner, *mask.inner );
390}
391/*
[6264087]392StrSlice exclude(string & s, const charclass & mask) {
[f450f2f]393}
394*/
395
[6264087]396int include(const string & s, const charclass & mask) {
[f450f2f]397    return include( *s.inner, *mask.inner );
398}
399
400/*
[6264087]401StrSlice include(string & s, const charclass & mask) {
[f450f2f]402}
403*/
404
Note: See TracBrowser for help on using the repository browser.