source: libcfa/src/strstream.cfa

Last change on this file was 321a1b15, checked in by Peter A. Buhr <pabuhr@…>, 2 months ago

change getANL to getANL$ (private), change eof to return bool versus int, add hack to make istrstream.fmt work except with wdi manipulators

  • Property mode set to 100644
File size: 5.4 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 : Sun Oct 10 16:13:20 2021
13// Update Count     : 101
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
27// *********************************** strstream ***********************************
28
29
30#define IO_MSG "I/O error: "
31
32// private
33inline bool sepPrt$( ostrstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
34inline void sepReset$( ostrstream & os ) { os.sepOnOff$ = os.sepDefault$; }
35inline void sepReset$( ostrstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
36inline const char * sepGetCur$( ostrstream & os ) { return os.sepCur$; }
37inline void sepSetCur$( ostrstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
38inline bool getNL$( ostrstream & os ) { return os.sawNL$; }
39inline void setNL$( ostrstream & os, bool state ) { os.sawNL$ = state; }
40inline bool getANL$( ostrstream & os ) { return os.nlOnOff$; }
41inline bool getPrt$( ostrstream & os ) { return os.prt$; }
42inline void setPrt$( ostrstream & os, bool state ) { os.prt$ = state; }
43
44// public
45void ?{}( ostrstream & os, char buf[], size_t size ) {
46        os.buf$ = buf;
47        os.size$ = size;
48        os.cursor$ = 0;
49        os.sepDefault$ = true;
50        os.sepOnOff$ = false;
51        os.nlOnOff$ = true;
52        os.prt$ = false;
53        os.sawNL$ = false;
54        sepSetCur$( os, sepGet( os ) );
55        sepSet( os, " " );
56        sepSetTuple( os, ", " );
57} // ?{}
58
59void sepOn( ostrstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
60void sepOff( ostrstream & os ) { os.sepOnOff$ = false; }
61
62bool sepDisable( ostrstream & os ) {
63        bool temp = os.sepDefault$;
64        os.sepDefault$ = false;
65        sepReset$( os );
66        return temp;
67} // sepDisable
68
69bool sepEnable( ostrstream & os ) {
70        bool temp = os.sepDefault$;
71        os.sepDefault$ = true;
72        if ( os.sepOnOff$ ) sepReset$( os );                            // start of line ?
73        return temp;
74} // sepEnable
75
76void nlOn( ostrstream & os ) { os.nlOnOff$ = true; }
77void nlOff( ostrstream & os ) { os.nlOnOff$ = false; }
78
79const char * sepGet( ostrstream & os ) { return os.separator$; }
80void sepSet( ostrstream & os, const char s[] ) {
81        assert( s );
82        strncpy( os.separator$, s, ostrstream_sepSize - 1 );
83        os.separator$[ostrstream_sepSize - 1] = '\0';
84} // sepSet
85
86const char * sepGetTuple( ostrstream & os ) { return os.tupleSeparator$; }
87void sepSetTuple( ostrstream & os, const char s[] ) {
88        assert( s );
89        strncpy( os.tupleSeparator$, s, ostrstream_sepSize - 1 );
90        os.tupleSeparator$[ostrstream_sepSize - 1] = '\0';
91} // sepSet
92
93void ends( ostrstream & os ) {
94        if ( getANL$( os ) ) nl( os );
95        else setPrt$( os, false );                                                      // turn off
96} // ends
97
98int fmt( ostrstream & os, const char format[], ... ) {
99        va_list args;
100        va_start( args, format );
101        int len = vsnprintf( os.buf$ + os.cursor$, os.size$ - os.cursor$, format, args );
102        va_end( args );
103        os.cursor$ += len;
104        if ( os.cursor$ >= os.size$ ) {                                         // cursor exceeded buffer size?
105                #define fmtmsg IO_MSG "ostrstream truncated write, buffer too small.\n"
106                write( STDERR_FILENO, fmtmsg, sizeof(fmtmsg) - 1 );
107                abort();
108        } // if
109
110        setPrt$( os, true );                                                            // called in output cascade
111        sepReset$( os );                                                                        // reset separator
112        return len;
113} // fmt
114
115ostrstream & write( ostrstream & os, FILE * stream ) {
116        if ( fwrite( os.buf$, 1, os.cursor$, stream ) != os.cursor$ ) {
117                #define ostrwritemsg IO_MSG "ostrstream write error.\n"
118                write( STDERR_FILENO, ostrwritemsg, sizeof(ostrwritemsg) - 1 );
119                abort();
120        } // if
121        return os;
122} // write
123
124ostrstream & write( ostrstream & os ) {
125        return write( os, stdout );
126} // write
127
128
129// *********************************** istrstream ***********************************
130
131// private
132bool getANL$( istrstream & is ) { return is.nlOnOff$; }
133
134// public
135void ?{}( istrstream & is, char buf[] ) {
136        is.buf$ = buf;
137        is.cursor$ = 0;
138        is.nlOnOff$ = false;
139} // ?{}
140
141void nlOn( istrstream & is ) { is.nlOnOff$ = true; }
142void nlOff( istrstream & is ) { is.nlOnOff$ = false; }
143
144void ends( istrstream & is ) {}
145bool eof( istrstream & is ) { return false; }
146
147int fmt( istrstream & is, const char format[], ... ) with(is) {
148        va_list args;
149        va_start( args, format );
150        // THIS DOES NOT WORK BECAUSE VSSCANF RETURNS NUMBER OF VALUES READ VERSUS BUFFER POSITION SCANNED.
151        int len = vsscanf( buf$ + cursor$, format, args );
152        va_end( args );
153        if ( len == EOF ) {
154                abort | IO_MSG "invalid read";
155        } // if
156        // SKULLDUGGERY: This hack skips over characters read by vsscanf by moving to the next whitespace but it does not
157        // handle C reads with wdi manipulators that leave the cursor at a non-whitespace character.
158        for ( ; buf$[cursor$] != ' ' && buf$[cursor$] != '\t' && buf$[cursor$] != '\0'; cursor$ += 1 ) {
159                //printf( "X \'%c\'\n", buf$[cursor$] );
160        } // for
161        if ( buf$[cursor$] != '\0' ) cursor$ += 1;      // advance to whitespace
162        return len;
163} // fmt
164
165istrstream &ungetc( istrstream & is, char c ) {
166        // if ( ungetc( c, (FILE *)(is.file$) ) == EOF ) {
167        //      abort | IO_MSG "ungetc" | nl | strerror( errno );
168        // } // if
169        return is;
170} // ungetc
171
172// Local Variables: //
173// tab-width: 4 //
174// End: //
Note: See TracBrowser for help on using the repository browser.