source: libcfa/src/strstream.cfa@ b28ce93

Last change on this file since b28ce93 was ae0c1c3, checked in by Andrew Beach <ajbeach@…>, 5 months ago

Rewrote the iostream traits to have a single assertion each, a table containing function pointers. This is just an experiment right now. It seems that it does cause significant speed up of assertion resolution, but for some reason also seems to add a flat overhead that mostly eats up that saving.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2021 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// strstream.cfa --
8//
9// Author : Peter A. Buhr
10// Created On : Thu Apr 22 22:24:35 2021
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Mon Apr 14 20:45:00 2025
13// Update Count : 116
14//
15
16#include "strstream.hfa"
17#include "fstream.hfa" // abort
18
19#include <stdio.h> // vsnprintf
20#include <stdarg.h> // varargs
21#include <string.h> // strncpy, strerror
22#include <assert.h>
23#include <errno.h> // errno
24#include <unistd.h> // sbrk, sysconf
25
26#pragma GCC visibility push(default)
27
28// *********************************** strstream ***********************************
29
30static basic_ostream_data(ostrstream) ostrstream_basic_data = {
31 sepPrt$,
32 sepReset$,
33 sepReset$,
34 sepGetCur$,
35 sepSetCur$,
36 getNL$,
37 setNL$,
38 getANL$,
39 setANL$,
40 getPrt$,
41 setPrt$,
42 nlOn,
43 nlOff,
44 sep,
45 nosep,
46 sepOn,
47 sepOff,
48 sepGet,
49 sepSet,
50 sepGetTuple,
51 sepSetTuple,
52 ends,
53 fmt,
54};
55
56basic_ostream_data(ostrstream) const & basic_ostream_table = ostrstream_basic_data;
57
58#define IO_MSG "I/O error: "
59
60// private
61inline bool getNL$( ostrstream & os ) { return os.sawNL$; }
62inline bool setNL$( ostrstream & os, bool state ) { bool temp = os.sawNL$; os.sawNL$ = state; return temp; }
63inline bool getANL$( ostrstream & os ) { return os.nlOnOff$; }
64inline bool setANL$( ostrstream & os, bool state ) { bool temp = os.nlOnOff$; os.nlOnOff$ = state; return temp; }
65inline bool sepPrt$( ostrstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
66inline void sepReset$( ostrstream & os ) { os.sepOnOff$ = os.sepDefault$; }
67inline void sepReset$( ostrstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
68inline const char * sepGetCur$( ostrstream & os ) { return os.sepCur$; }
69inline void sepSetCur$( ostrstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
70inline bool getPrt$( ostrstream & os ) { return os.prt$; }
71inline bool setPrt$( ostrstream & os, bool state ) { bool temp = os.prt$; os.prt$ = state; return temp; }
72
73// public
74void nlOn( ostrstream & os ) { os.nlOnOff$ = true; }
75void nlOff( ostrstream & os ) { os.nlOnOff$ = false; }
76
77void ?{}( ostrstream & os, char buf[], size_t size ) {
78 os.buf$ = buf;
79 os.size$ = size;
80 os.cursor$ = 0;
81 os.sepDefault$ = true;
82 os.sepOnOff$ = false;
83 os.nlOnOff$ = true;
84 os.prt$ = false;
85 os.sawNL$ = false;
86 sepSetCur$( os, sepGet( os ) );
87 sepSet( os, " " );
88 sepSetTuple( os, ", " );
89} // ?{}
90
91void sep( ostrstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
92void nosep( ostrstream & os ) { os.sepOnOff$ = false; }
93
94bool sepOn( ostrstream & os ) {
95 bool temp = os.sepDefault$;
96 os.sepDefault$ = true;
97 if ( os.sepOnOff$ ) sepReset$( os ); // start of line ?
98 return temp;
99} // sepOn
100
101bool sepOff( ostrstream & os ) {
102 bool temp = os.sepDefault$;
103 os.sepDefault$ = false;
104 sepReset$( os );
105 return temp;
106} // sepOff
107
108const char * sepGet( ostrstream & os ) { return os.separator$; }
109void sepSet( ostrstream & os, const char s[] ) {
110 assert( s );
111 strncpy( os.separator$, s, ostrstream_sepSize - 1 );
112 os.separator$[ostrstream_sepSize - 1] = '\0';
113} // sepSet
114
115const char * sepGetTuple( ostrstream & os ) { return os.tupleSeparator$; }
116void sepSetTuple( ostrstream & os, const char s[] ) {
117 assert( s );
118 strncpy( os.tupleSeparator$, s, ostrstream_sepSize - 1 );
119 os.tupleSeparator$[ostrstream_sepSize - 1] = '\0';
120} // sepSet
121
122void ends( ostrstream & os ) {
123 if ( getANL$( os ) ) nl( os );
124 else setPrt$( os, false ); // turn off
125} // ends
126
127int fmt( ostrstream & os, const char format[], ... ) {
128 va_list args;
129 va_start( args, format );
130 int len = vsnprintf( os.buf$ + os.cursor$, os.size$ - os.cursor$, format, args );
131 va_end( args );
132 os.cursor$ += len;
133 if ( os.cursor$ >= os.size$ ) { // cursor exceeded buffer size?
134 #define fmtmsg IO_MSG "ostrstream truncated write, buffer too small.\n"
135 write( STDERR_FILENO, fmtmsg, sizeof(fmtmsg) - 1 );
136 abort();
137 } // if
138
139 setPrt$( os, true ); // called in output cascade
140 sepReset$( os ); // reset separator
141 return len;
142} // fmt
143
144ostrstream & write( ostrstream & os, FILE * stream ) {
145 if ( fwrite( os.buf$, 1, os.cursor$, stream ) != os.cursor$ ) {
146 #define ostrwritemsg IO_MSG "ostrstream write error.\n"
147 write( STDERR_FILENO, ostrwritemsg, sizeof(ostrwritemsg) - 1 );
148 abort();
149 } // if
150 return os;
151} // write
152
153ostrstream & write( ostrstream & os ) {
154 return write( os, stdout );
155} // write
156
157
158// *********************************** istrstream ***********************************
159
160static basic_istream_data(istrstream) istrstream_basic_data = {
161 getANL$,
162 setANL$,
163 nlOn,
164 nlOff,
165 fmt,
166 ungetc,
167 eof,
168 clearerr,
169};
170
171basic_istream_data(istrstream) const & basic_istream_data = istrstream_basic_data;
172
173// private
174bool getANL$( istrstream & is ) { return is.nlOnOff$; }
175bool setANL$( istrstream & is, bool state ) { bool temp = is.nlOnOff$; is.nlOnOff$ = state; return temp; }
176
177// public
178void ?{}( istrstream & is, char buf[] ) {
179 is.buf$ = buf;
180 is.cursor$ = 0;
181 is.nlOnOff$ = false;
182} // ?{}
183
184void nlOn( istrstream & is ) { is.nlOnOff$ = true; }
185void nlOff( istrstream & is ) { is.nlOnOff$ = false; }
186
187int fmt( istrstream & is, const char format[], ... ) with(is) {
188 va_list args;
189 va_start( args, format );
190 // THIS DOES NOT WORK BECAUSE VSSCANF RETURNS NUMBER OF VALUES READ VERSUS BUFFER POSITION SCANNED.
191 int len = vsscanf( buf$ + cursor$, format, args );
192 va_end( args );
193 if ( len == EOF ) {
194 abort | IO_MSG "invalid read";
195 } // if
196 // SKULLDUGGERY: This hack skips over characters read by vsscanf by moving to the next whitespace but it does not
197 // handle C reads with wdi manipulators that leave the cursor at a non-whitespace character.
198 for ( ; buf$[cursor$] != ' ' && buf$[cursor$] != '\t' && buf$[cursor$] != '\0'; cursor$ += 1 ) {
199 //printf( "X \'%c\'\n", buf$[cursor$] );
200 } // for
201 if ( buf$[cursor$] != '\0' ) cursor$ += 1; // advance to whitespace
202 return len;
203} // fmt
204
205istrstream &ungetc( char c, istrstream & is ) {
206 // if ( ungetc( c, (FILE *)(is.file$) ) == EOF ) {
207 // abort | IO_MSG "ungetc" | nl | strerror( errno );
208 // } // if
209 return is;
210} // ungetc
211
212bool eof( istrstream & is ) { return false; }
213void clearerr( istrstream & ) {} // no error flags to clear
214void ends( istrstream & is ) {}
215
216// Local Variables: //
217// tab-width: 4 //
218// End: //
Note: See TracBrowser for help on using the repository browser.