source: libcfa/src/strstream.cfa @ 17cb385

ADTast-experimentalenumforall-pointer-decaypthread-emulationqualifiedEnum
Last change on this file since 17cb385 was 321a1b15, checked in by Peter A. Buhr <pabuhr@…>, 3 years 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
RevLine 
[fec63b2]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
[321a1b15]12// Last Modified On : Sun Oct 10 16:13:20 2021
13// Update Count     : 101
[fec63b2]14//
15
16#include "strstream.hfa"
[321a1b15]17#include "fstream.hfa"                                                                  // abort
[fec63b2]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
[666483d]26
[fec63b2]27// *********************************** strstream ***********************************
28
29
30#define IO_MSG "I/O error: "
31
32// private
[321a1b15]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; }
[fec63b2]43
44// public
[666483d]45void ?{}( ostrstream & os, char buf[], size_t size ) {
[fec63b2]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
[666483d]59void sepOn( ostrstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
60void sepOff( ostrstream & os ) { os.sepOnOff$ = false; }
[fec63b2]61
[666483d]62bool sepDisable( ostrstream & os ) {
[fec63b2]63        bool temp = os.sepDefault$;
64        os.sepDefault$ = false;
65        sepReset$( os );
66        return temp;
67} // sepDisable
68
[666483d]69bool sepEnable( ostrstream & os ) {
[fec63b2]70        bool temp = os.sepDefault$;
71        os.sepDefault$ = true;
72        if ( os.sepOnOff$ ) sepReset$( os );                            // start of line ?
73        return temp;
74} // sepEnable
75
[666483d]76void nlOn( ostrstream & os ) { os.nlOnOff$ = true; }
77void nlOff( ostrstream & os ) { os.nlOnOff$ = false; }
[fec63b2]78
[666483d]79const char * sepGet( ostrstream & os ) { return os.separator$; }
80void sepSet( ostrstream & os, const char s[] ) {
[fec63b2]81        assert( s );
[666483d]82        strncpy( os.separator$, s, ostrstream_sepSize - 1 );
83        os.separator$[ostrstream_sepSize - 1] = '\0';
[fec63b2]84} // sepSet
85
[666483d]86const char * sepGetTuple( ostrstream & os ) { return os.tupleSeparator$; }
87void sepSetTuple( ostrstream & os, const char s[] ) {
[fec63b2]88        assert( s );
[666483d]89        strncpy( os.tupleSeparator$, s, ostrstream_sepSize - 1 );
90        os.tupleSeparator$[ostrstream_sepSize - 1] = '\0';
[fec63b2]91} // sepSet
92
[666483d]93void ends( ostrstream & os ) {
[fec63b2]94        if ( getANL$( os ) ) nl( os );
95        else setPrt$( os, false );                                                      // turn off
96} // ends
97
[666483d]98int fmt( ostrstream & os, const char format[], ... ) {
[fec63b2]99        va_list args;
100        va_start( args, format );
101        int len = vsnprintf( os.buf$ + os.cursor$, os.size$ - os.cursor$, format, args );
[666483d]102        va_end( args );
[fec63b2]103        os.cursor$ += len;
104        if ( os.cursor$ >= os.size$ ) {                                         // cursor exceeded buffer size?
[666483d]105                #define fmtmsg IO_MSG "ostrstream truncated write, buffer too small.\n"
[fec63b2]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
[666483d]115ostrstream & write( ostrstream & os, FILE * stream ) {
[fec63b2]116        if ( fwrite( os.buf$, 1, os.cursor$, stream ) != os.cursor$ ) {
[666483d]117                #define ostrwritemsg IO_MSG "ostrstream write error.\n"
118                write( STDERR_FILENO, ostrwritemsg, sizeof(ostrwritemsg) - 1 );
[fec63b2]119                abort();
120        } // if
121        return os;
122} // write
123
[666483d]124ostrstream & write( ostrstream & os ) {
125        return write( os, stdout );
126} // write
127
128
129// *********************************** istrstream ***********************************
130
[321a1b15]131// private
132bool getANL$( istrstream & is ) { return is.nlOnOff$; }
[666483d]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
[321a1b15]144void ends( istrstream & is ) {}
145bool eof( istrstream & is ) { return false; }
[666483d]146
[321a1b15]147int fmt( istrstream & is, const char format[], ... ) with(is) {
[666483d]148        va_list args;
149        va_start( args, format );
[321a1b15]150        // THIS DOES NOT WORK BECAUSE VSSCANF RETURNS NUMBER OF VALUES READ VERSUS BUFFER POSITION SCANNED.
151        int len = vsscanf( buf$ + cursor$, format, args );
[666483d]152        va_end( args );
153        if ( len == EOF ) {
[321a1b15]154                abort | IO_MSG "invalid read";
[666483d]155        } // if
[321a1b15]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
[666483d]162        return len;
163} // fmt
[fec63b2]164
[321a1b15]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
[fec63b2]172// Local Variables: //
173// tab-width: 4 //
174// End: //
Note: See TracBrowser for help on using the repository browser.