source: libcfa/src/iostream.hfa@ fa29dfc

Last change on this file since fa29dfc 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: 24.1 KB
RevLine 
[86bd7c1f]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 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//
[3c573e9]7// iostream.hfa --
[86bd7c1f]8//
[90c3b1c]9// Author : Peter A. Buhr
[86bd7c1f]10// Created On : Wed May 27 17:56:53 2015
11// Last Modified By : Peter A. Buhr
[768d091]12// Last Modified On : Mon Apr 14 20:42:53 2025
13// Update Count : 767
[86bd7c1f]14//
15
[53a6c2a]16#pragma once
[51b73452]17
[58b6d1b]18#include "iterator.hfa"
[2f34fde]19#include "Exception.hfa"
[e56cfdb0]20
[8d321f9]21// *********************************** ostream ***********************************
[3c573e9]22
[8a97248]23forall( ostype & )
[ae0c1c3]24struct basic_ostream_data {
[9ebd778]25 // private
[ae0c1c3]26 bool (*sepPrt$)( ostype & ); // get separator state (on/off)
27 void (*sepReset$)( ostype & ); // set separator state to default state
28 void (*sepReset$)( ostype &, bool ); // set separator and default state
29 const char * (*sepGetCur$)( ostype & ); // get current separator string
30 void (*sepSetCur$)( ostype &, const char [] ); // set current separator string
31 bool (*getNL$)( ostype & ); // get newline
32 bool (*setNL$)( ostype &, bool ); // set newline
33 bool (*getANL$)( ostype & ); // get auto newline (on/off)
34 bool (*setANL$)( ostype &, bool ); // set auto newline (on/off), and return previous state
35 bool (*getPrt$)( ostype & ); // get fmt called in output cascade
36 bool (*setPrt$)( ostype &, bool ); // set fmt called in output cascade
[9ebd778]37 // public
[ae0c1c3]38 void (*nlOn)( ostype & ); // turn auto-newline state on
39 void (*nlOff)( ostype & ); // turn auto-newline state off
40
41 void (*sep)( ostype & ); // turn separator state on
42 void (*nosep)( ostype & ); // turn separator state off
43 bool (*sepOn)( ostype & ); // set default state to on, and return previous state
44 bool (*sepOff)( ostype & ); // set default state to off, and return previous state
45 const char * (*sepGet)( ostype & ); // get separator string
46 void (*sepSet)( ostype &, const char [] ); // set separator to string (15 character maximum)
47 const char * (*sepGetTuple)( ostype & ); // get tuple separator string
48 void (*sepSetTuple)( ostype &, const char [] ); // set tuple separator to string (15 character maximum)
49
50 void (*ends)( ostype & ); // end of output statement
51 int (*fmt)( ostype &, const char format[], ... ) __attribute__(( format(printf, 2, 3) ));
[85d8153]52}; // basic_ostream
[a0bd9a2]53
[ae0c1c3]54forall( ostype & )
55struct ostream_data {
56 inline basic_ostream_data( ostype );
57 bool (*fail)( ostype & ); // operation failed?
58 void (*clearerr)( ostype & );
59 int (*flush)( ostype & );
60 void (*open)( ostype &, const char name[], const char mode[] );
61 void (*close)( ostype & );
62 ostype & (*write)( ostype &, const char [], size_t );
63}; // ostream
64
65forall( ostype & )
66trait basic_ostream {
67 basic_ostream_data(ostype) const & basic_ostream_table;
68};
69
[8a97248]70forall( ostype & | basic_ostream( ostype ) )
71trait ostream {
[ae0c1c3]72 ostream_data(ostype) const & ostream_table;
73};
[90c3b1c]74
[8a97248]75// forall( T )
76// trait writeable {
[fd54fef]77// forall( ostype & | ostream( ostype ) ) ostype & ?|?( ostype &, T );
[e1780a2]78// }; // writeable
79
[8a97248]80forall( T, ostype & | ostream( ostype ) )
[dc9dd94]81trait writeable {
[09687aa]82 ostype & ?|?( ostype &, T );
[86f384b]83}; // writeable
[51b73452]84
[4e06c1e]85// implement writable for intrinsic types
[51b73452]86
[94d2544]87#define OSTYPE_VOID( T ) void ?|?( ostype &, T )
[b12e4ad]88#define OSTYPE_VOID_IMPL( os, T ) \
[94d2544]89 void ?|?( ostype & os, T t ) { \
[ae0c1c3]90 (ostype &)(os | t); \
91 basic_ostream_table.ends( os ); \
[94d2544]92 } // ?|?
93
[85d8153]94forall( ostype & | basic_ostream( ostype ) ) {
[93c2e0a]95 ostype & ?|?( ostype &, bool );
[94d2544]96 OSTYPE_VOID( bool );
[1e6e08de]97
[3ce0d440]98 ostype & ?|?( ostype &, char );
[94d2544]99 OSTYPE_VOID( char );
[3ce0d440]100 ostype & ?|?( ostype &, signed char );
[94d2544]101 OSTYPE_VOID( signed char );
[3ce0d440]102 ostype & ?|?( ostype &, unsigned char );
[94d2544]103 OSTYPE_VOID( unsigned char );
[09687aa]104
[3ce0d440]105 ostype & ?|?( ostype &, short int );
[94d2544]106 OSTYPE_VOID( short int );
[3ce0d440]107 ostype & ?|?( ostype &, unsigned short int );
[94d2544]108 OSTYPE_VOID( unsigned short int );
[3ce0d440]109 ostype & ?|?( ostype &, int );
[94d2544]110 OSTYPE_VOID( int );
[3ce0d440]111 ostype & ?|?( ostype &, unsigned int );
[94d2544]112 OSTYPE_VOID( unsigned int );
[3ce0d440]113 ostype & ?|?( ostype &, long int );
[94d2544]114 OSTYPE_VOID( long int );
[3ce0d440]115 ostype & ?|?( ostype &, long long int );
[94d2544]116 OSTYPE_VOID( long long int );
[3ce0d440]117 ostype & ?|?( ostype &, unsigned long int );
[94d2544]118 OSTYPE_VOID( unsigned long int );
[3ce0d440]119 ostype & ?|?( ostype &, unsigned long long int );
[94d2544]120 OSTYPE_VOID( unsigned long long int );
[ef3ac46]121 #if defined( __SIZEOF_INT128__ )
[bd5b443]122 ostype & ?|?( ostype &, int128 );
[94d2544]123 OSTYPE_VOID( int128 );
[bd5b443]124 ostype & ?|?( ostype &, unsigned int128 );
[94d2544]125 OSTYPE_VOID( unsigned int128 );
[ef3ac46]126 #endif // __SIZEOF_INT128__
[09687aa]127
[65240bb]128 ostype & ?|?( ostype &, float );
[94d2544]129 OSTYPE_VOID( float );
[3ce0d440]130 ostype & ?|?( ostype &, double );
[94d2544]131 OSTYPE_VOID( double );
[3ce0d440]132 ostype & ?|?( ostype &, long double );
[94d2544]133 OSTYPE_VOID( long double );
[09687aa]134
[3ce0d440]135 ostype & ?|?( ostype &, float _Complex );
[94d2544]136 OSTYPE_VOID( float _Complex );
[3ce0d440]137 ostype & ?|?( ostype &, double _Complex );
[94d2544]138 OSTYPE_VOID( double _Complex );
[3ce0d440]139 ostype & ?|?( ostype &, long double _Complex );
[94d2544]140 OSTYPE_VOID( long double _Complex );
[09687aa]141
[e3fea42]142 ostype & ?|?( ostype &, const char [] );
[94d2544]143 OSTYPE_VOID( const char [] );
[e7a8f65]144 // ostype & ?|?( ostype &, const char16_t [] );
[ef3ac46]145 #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
[e7a8f65]146 // ostype & ?|?( ostype &, const char32_t [] );
[ef3ac46]147 #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
[e7a8f65]148 // ostype & ?|?( ostype &, const wchar_t [] );
[3ce0d440]149 ostype & ?|?( ostype &, const void * );
[94d2544]150 OSTYPE_VOID( const void * );
[3ce0d440]151
[0a2e0e21]152 // FIX-ME: does not work so using macros
[c635047]153 // forall( T | { ostype & ?|?( ostype &, T ); } )
154 // void ?|?( ostype & os, T );
155
[3ce0d440]156 // manipulators
157 ostype & ?|?( ostype &, ostype & (*)( ostype & ) );
[94d2544]158 OSTYPE_VOID( ostype & (*)( ostype & ) );
[f5d9c37]159
[200fcb3]160 ostype & nl( ostype & );
161 ostype & nonl( ostype & );
[f5d9c37]162 ostype & nlOn( ostype & );
163 ostype & nlOff( ostype & );
164
165 ostype & sepVal( ostype & );
166 ostype & sepTupleVal( ostype & );
[3ce0d440]167 ostype & sep( ostype & );
[f5d9c37]168 ostype & nosep( ostype & );
[3ce0d440]169 ostype & sepOn( ostype & );
170 ostype & sepOff( ostype & );
[85d8153]171} // distribution
172
[c443d1d]173// tuples
[c0363be]174forall( ostype &, T, List ... | writeable( T, ostype ) | { ostype & ?|?( ostype &, List ); } ) {
175 ostype & ?|?( ostype & os, T arg, List rest );
176 void ?|?( ostype & os, T arg, List rest );
[200fcb3]177} // distribution
[c443d1d]178
[e56cfdb0]179// writes the range [begin, end) to the given stream
[fd54fef]180forall( ostype &, elt_type | writeable( elt_type, ostype ), iterator_type | iterator( iterator_type, elt_type ) ) {
[200fcb3]181 void write( iterator_type begin, iterator_type end, ostype & os );
182 void write_reverse( iterator_type begin, iterator_type end, ostype & os );
183} // distribution
[51b73452]184
[8d321f9]185// *********************************** manipulators ***********************************
[3c573e9]186
[a0bd9a2]187struct _Ostream_Flags {
[dc9dd94]188 unsigned char eng:1; // engineering notation
189 unsigned char neg:1; // val is negative
190 unsigned char pc:1; // precision specified
191 unsigned char left:1; // left justify
192 unsigned char nobsdp:1; // base prefix / decimal point
193 unsigned char sign:1; // plus / minus sign
194 unsigned char pad0:1; // zero pad
[a0bd9a2]195};
196
[96ef156]197// FIXME: Should be an anonymous inner union of _Ostream_Manip.
198// Hoisting manually to work around warning of #294.
199union _Ostream_Manip_Mode {
200 unsigned char all;
201 _Ostream_Flags flags;
202};
203
[fd54fef]204forall( T )
[3c573e9]205struct _Ostream_Manip {
206 T val; // polymorphic base-type
[424dfc4]207 int wd, pc; // width, precision: signed for computations
[3c573e9]208 char base; // numeric base / floating-point style
[96ef156]209 inline _Ostream_Manip_Mode;
[3c573e9]210}; // _Ostream_Manip
211
[8d321f9]212// *********************************** integral ***********************************
[3c573e9]213
[94d2544]214#define INTEGRAL_FMT_DECL( T, CODE ) \
[3c573e9]215static inline { \
[1a7203d]216 _Ostream_Manip(T) bin( T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = 1, .pc = 0, .base = 'b', { .all = 0 } }; } \
217 _Ostream_Manip(T) oct( T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = 1, .pc = 0, .base = 'o', { .all = 0 } }; } \
218 _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = 1, .pc = 0, .base = 'x', { .all = 0 } }; } \
219 _Ostream_Manip(T) wd( unsigned int wd, T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = wd, .pc = 0, .base = CODE, { .all = 0 } }; } \
220 _Ostream_Manip(T) wd( unsigned int wd, unsigned int pc, T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = wd, .pc = pc, .base = CODE, { .flags.pc = true } }; } \
[8abe4090]221 _Ostream_Manip(T) & wd( unsigned int wd, _Ostream_Manip(T) & fmt ) { fmt.wd = wd; return fmt; } \
222 _Ostream_Manip(T) & wd( unsigned int wd, unsigned int pc, _Ostream_Manip(T) & fmt ) { fmt.wd = wd; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \
[3c573e9]223 _Ostream_Manip(T) & left( _Ostream_Manip(T) & fmt ) { fmt.flags.left = true; return fmt; } \
224 _Ostream_Manip(T) & upcase( _Ostream_Manip(T) & fmt ) { if ( fmt.base == 'x' || fmt.base == 'b' ) fmt.base -= 32; /* upper case */ return fmt; } \
225 _Ostream_Manip(T) & nobase( _Ostream_Manip(T) & fmt ) { fmt.flags.nobsdp = true; return fmt; } \
226 _Ostream_Manip(T) & pad0( _Ostream_Manip(T) & fmt ) { fmt.flags.pad0 = true; return fmt; } \
[1a7203d]227 _Ostream_Manip(T) sign( T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = 1, .pc = 0, .base = CODE, { .flags.sign = true } }; } \
[3c573e9]228 _Ostream_Manip(T) & sign( _Ostream_Manip(T) & fmt ) { fmt.flags.sign = true; return fmt; } \
[04396aa]229} /* distribution */ \
[85d8153]230forall( ostype & | basic_ostream( ostype ) ) { \
[3c573e9]231 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \
[c635047]232 OSTYPE_VOID( _Ostream_Manip(T) ); \
[61c7239]233} // ?|?
[3c573e9]234
[94d2544]235INTEGRAL_FMT_DECL( signed char, 'd' )
236INTEGRAL_FMT_DECL( unsigned char, 'u' )
237INTEGRAL_FMT_DECL( signed short int, 'd' )
238INTEGRAL_FMT_DECL( unsigned short int, 'u' )
239INTEGRAL_FMT_DECL( signed int, 'd' )
240INTEGRAL_FMT_DECL( unsigned int, 'u' )
241INTEGRAL_FMT_DECL( signed long int, 'd' )
242INTEGRAL_FMT_DECL( unsigned long int, 'u' )
243INTEGRAL_FMT_DECL( signed long long int, 'd' )
244INTEGRAL_FMT_DECL( unsigned long long int, 'u' )
[bd5b443]245#if defined( __SIZEOF_INT128__ )
[94d2544]246INTEGRAL_FMT_DECL( int128, 'd' )
247INTEGRAL_FMT_DECL( unsigned int128, 'u' )
[2b22b5c4]248#endif // __SIZEOF_INT128__
[3c573e9]249
[8d321f9]250// *********************************** floating point ***********************************
[3c573e9]251
252// Default suffix for values with no fraction is "."
[94d2544]253#define FLOATING_POINT_FMT_DECL( T ) \
[3c573e9]254static inline { \
[1a7203d]255 _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = 1, .pc = 0, .base = 'a', { .all = 0 } }; } \
256 _Ostream_Manip(T) sci( T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = 1, .pc = 0, .base = 'e', { .all = 0 } }; } \
257 _Ostream_Manip(T) eng( T val ) { return (_Ostream_Manip(T))@{ .val = val, 1, -1, .base = 'g', { .flags.eng = true } }; } \
258 _Ostream_Manip(T) wd( unsigned int wd, T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = wd, .pc = 0, .base = 'g', { .all = 0 } }; } \
259 _Ostream_Manip(T) wd( unsigned int wd, unsigned int pc, T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = wd, .pc = pc, .base = 'f', { .flags.pc = true } }; } \
260 _Ostream_Manip(T) ws( unsigned int wd, unsigned int pc, T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = wd, .pc = pc, .base = 'g', { .flags.pc = true } }; } \
[8abe4090]261 _Ostream_Manip(T) & wd( unsigned int wd, _Ostream_Manip(T) & fmt ) { if ( fmt.flags.eng ) fmt.base = 'f'; fmt.wd = wd; return fmt; } \
262 _Ostream_Manip(T) & wd( unsigned int wd, unsigned int pc, _Ostream_Manip(T) & fmt ) { \
263 if ( fmt.flags.eng ) fmt.base = 'f'; fmt.wd = wd; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \
264 _Ostream_Manip(T) & ws( unsigned int wd, unsigned int pc, _Ostream_Manip(T) & fmt ) { fmt.wd = wd; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \
[3c573e9]265 _Ostream_Manip(T) & left( _Ostream_Manip(T) & fmt ) { fmt.flags.left = true; return fmt; } \
[1a7203d]266 _Ostream_Manip(T) upcase( T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = 1, .pc = 0, .base = 'G', { .all = 0 } }; } \
[3c573e9]267 _Ostream_Manip(T) & upcase( _Ostream_Manip(T) & fmt ) { fmt.base -= 32; /* upper case */ return fmt; } \
268 _Ostream_Manip(T) & pad0( _Ostream_Manip(T) & fmt ) { fmt.flags.pad0 = true; return fmt; } \
[1a7203d]269 _Ostream_Manip(T) sign( T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = 1, .pc = 0, .base = 'g', { .flags.sign = true } }; } \
[3c573e9]270 _Ostream_Manip(T) & sign( _Ostream_Manip(T) & fmt ) { fmt.flags.sign = true; return fmt; } \
[1a7203d]271 _Ostream_Manip(T) nodp( T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = 1, .pc = 0, .base = 'g', { .flags.nobsdp = true } }; } \
[3c573e9]272 _Ostream_Manip(T) & nodp( _Ostream_Manip(T) & fmt ) { fmt.flags.nobsdp = true; return fmt; } \
[1a7203d]273 _Ostream_Manip(T) unit( T val ) { return (_Ostream_Manip(T))@{ .val = val, .wd = 1, .pc = 0, .base = 'g', { .flags.nobsdp = true } }; } \
[fd4c009]274 _Ostream_Manip(T) & unit( _Ostream_Manip(T) & fmt ) { fmt.flags.nobsdp = true; return fmt; } \
[04396aa]275} /* distribution */ \
[85d8153]276forall( ostype & | basic_ostream( ostype ) ) { \
[3c573e9]277 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \
[c635047]278 OSTYPE_VOID( _Ostream_Manip(T) ); \
[61c7239]279} // ?|?
[3c573e9]280
[94d2544]281FLOATING_POINT_FMT_DECL( double )
282FLOATING_POINT_FMT_DECL( long double )
[3c573e9]283
[8d321f9]284// *********************************** character ***********************************
[3c573e9]285
286static inline {
[1a7203d]287 _Ostream_Manip(char) bin( char c ) { return (_Ostream_Manip(char))@{ .val = c, .wd = 1, .pc = 0, .base = 'b', { .all = 0 } }; }
288 _Ostream_Manip(char) oct( char c ) { return (_Ostream_Manip(char))@{ .val = c, .wd = 1, .pc = 0, .base = 'o', { .all = 0 } }; }
289 _Ostream_Manip(char) hex( char c ) { return (_Ostream_Manip(char))@{ .val = c, .wd = 1, .pc = 0, .base = 'x', { .all = 0 } }; }
290 _Ostream_Manip(char) wd( unsigned int wd, char c ) { return (_Ostream_Manip(char))@{ c, wd, 0, .base = 'c', { .all = 0 } }; }
[8abe4090]291 _Ostream_Manip(char) & wd( unsigned int wd, _Ostream_Manip(char) & fmt ) { fmt.wd = wd; return fmt; }
[3c573e9]292 _Ostream_Manip(char) & left( _Ostream_Manip(char) & fmt ) { fmt.flags.left = true; return fmt; }
293 _Ostream_Manip(char) & upcase( _Ostream_Manip(char) & fmt ) { if ( fmt.base == 'x' || fmt.base == 'b' ) fmt.base -= 32; /* upper case */ return fmt; }
294 _Ostream_Manip(char) & nobase( _Ostream_Manip(char) & fmt ) { fmt.flags.nobsdp = true; return fmt; }
295} // distribution
[85d8153]296forall( ostype & | basic_ostream( ostype ) ) {
[3c573e9]297 ostype & ?|?( ostype & os, _Ostream_Manip(char) f );
[c635047]298 OSTYPE_VOID( _Ostream_Manip(char) ); \
[61c7239]299} // ?|?
[3c573e9]300
[8d321f9]301// *********************************** C string ***********************************
[3c573e9]302
303static inline {
[1a7203d]304 _Ostream_Manip(const char *) bin( const char s[] ) { return (_Ostream_Manip(const char *))@{ .val = s, .wd = 1, .pc = 0, .base = 'b', { .all = 0 } }; }
305 _Ostream_Manip(const char *) oct( const char s[] ) { return (_Ostream_Manip(const char *))@{ .val = s, .wd = 1, .pc = 0, .base = 'o', { .all = 0 } }; }
306 _Ostream_Manip(const char *) hex( const char s[] ) { return (_Ostream_Manip(const char *))@{ .val = s, .wd = 1, .pc = 0, .base = 'x', { .all = 0 } }; }
307 _Ostream_Manip(const char *) wd( unsigned int wd, const char s[] ) { return (_Ostream_Manip(const char *))@{ s, wd, 0, .base = 's', { .all = 0 } }; }
308 _Ostream_Manip(const char *) wd( unsigned int wd, unsigned int pc, const char s[] ) { return (_Ostream_Manip(const char *))@{ s, .wd = wd, .pc = pc, .base = 's', { .flags.pc = true } }; }
[8abe4090]309 _Ostream_Manip(const char *) & wd( unsigned int wd, _Ostream_Manip(const char *) & fmt ) { fmt.wd = wd; return fmt; }
310 _Ostream_Manip(const char *) & wd( unsigned int wd, unsigned int pc, _Ostream_Manip(const char *) & fmt ) { fmt.wd = wd; fmt.pc = pc; fmt.flags.pc = true; return fmt; }
[3c573e9]311 _Ostream_Manip(const char *) & left( _Ostream_Manip(const char *) & fmt ) { fmt.flags.left = true; return fmt; }
312 _Ostream_Manip(const char *) & nobase( _Ostream_Manip(const char *) & fmt ) { fmt.flags.nobsdp = true; return fmt; }
313} // distribution
[85d8153]314forall( ostype & | basic_ostream( ostype ) ) {
[3c573e9]315 ostype & ?|?( ostype & os, _Ostream_Manip(const char *) f );
[c635047]316 OSTYPE_VOID( _Ostream_Manip(const char *) ); \
[61c7239]317} // ?|?
[3c573e9]318
[8d321f9]319// *********************************** istream ***********************************
[3c573e9]320
[8a97248]321forall( istype & )
[ae0c1c3]322struct basic_istream_data {
[c8371b5]323 // private
[ae0c1c3]324 bool (*getANL$)( istype & ); // get scan newline (on/off)
325 bool (*setANL$)( istype &, bool ); // set scan newline (on/off)
[c8371b5]326 // public
[ae0c1c3]327 void (*nlOn)( istype & ); // read newline
328 void (*nlOff)( istype & ); // scan newline
329 int (*fmt)( istype &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
330 istype & (*ungetc)( char, istype & );
331 bool (*eof)( istype & );
332 void (*clearerr)( istype & );
[ef3ac46]333}; // basic_istream
334
[ae0c1c3]335forall( istype & )
336struct istream_data {
337 inline basic_istream_data( istype );
338 bool (*fail)( istype & );
339 void (*open)( istype & is, const char name[], const char mode[] );
340 void (*open)( istype & is, const char name[] );
341 void (*close)( istype & is );
342 istype & (*read)( istype &, char [], size_t );
343}; // istream
344
345forall( istype & )
346trait basic_istream {
347 basic_istream_data(istype) const & basic_istream_table;
348};
349
[8a97248]350forall( istype & | basic_istream( istype ) )
351trait istream {
[ae0c1c3]352 istream_data(istype) const & istream_table;
353};
[51b73452]354
[8a97248]355forall( T )
356trait readable {
[fd54fef]357 forall( istype & | istream( istype ) ) istype & ?|?( istype &, T );
[86f384b]358}; // readable
[51b73452]359
[ef3ac46]360forall( istype & | basic_istream( istype ) ) {
[93c2e0a]361 istype & ?|?( istype &, bool & );
[3ce0d440]362
363 istype & ?|?( istype &, char & );
364 istype & ?|?( istype &, signed char & );
365 istype & ?|?( istype &, unsigned char & );
366
367 istype & ?|?( istype &, short int & );
368 istype & ?|?( istype &, unsigned short int & );
369 istype & ?|?( istype &, int & );
370 istype & ?|?( istype &, unsigned int & );
371 istype & ?|?( istype &, long int & );
372 istype & ?|?( istype &, unsigned long int & );
[21baa40]373 istype & ?|?( istype &, long long int & );
[3ce0d440]374 istype & ?|?( istype &, unsigned long long int & );
[ef3ac46]375 #if defined( __SIZEOF_INT128__ )
[21baa40]376 istype & ?|?( istype &, int128 & );
377 istype & ?|?( istype &, unsigned int128 & );
[ef3ac46]378 #endif // __SIZEOF_INT128__
[3ce0d440]379
380 istype & ?|?( istype &, float & );
381 istype & ?|?( istype &, double & );
382 istype & ?|?( istype &, long double & );
383
384 istype & ?|?( istype &, float _Complex & );
385 istype & ?|?( istype &, double _Complex & );
386 istype & ?|?( istype &, long double _Complex & );
387
[c015e2d]388 // This is too restrictive as it prevents building a format in a string and using that format.
389 // inline istype & ?|?( istype &, char [] ) { // possible error, too restrictive to change
390 // _Static_assert( false, "reading a character array without a maximum length is unsafe. Use input manipulator \"wdi( N, s )\", where \"char s[N]\" or fmt( s )." );
391 // }
392 istype & ?|?( istype &, const char [] ); // match text
[61c7239]393
[3ce0d440]394 // manipulators
395 istype & ?|?( istype &, istype & (*)( istype & ) );
[200fcb3]396 istype & nl( istype & is );
[3c5dee4]397 istype & nlOn( istype & );
398 istype & nlOff( istype & );
[ef3ac46]399} // distribution
400
[2f34fde]401// *********************************** exceptions ***********************************
402
[3ac5fd8]403ExceptionDecl( end_of_file ); // read encounters end of file
[211def2]404ExceptionDecl( missing_data ); // read finds no appropriate data
405ExceptionDecl( cstring_length ); // character string size exceeded
406ExceptionDecl( data_range ); // value too large for numerical type
[2f34fde]407
[8d321f9]408// *********************************** manipulators ***********************************
[51b73452]409
[e0dc038]410// skip does not compose with other C string manipulators.
[0f107e4]411struct _Istream_Cskip {
412 const char * scanset;
413 unsigned wd; // scan width
414}; // _Istream_Cskip
415
416static inline {
[1a7203d]417 _Istream_Cskip skip( const char scanset[] ) { return (_Istream_Cskip)@{ .scanset = scanset, .wd = 0 }; }
418 _Istream_Cskip skip( unsigned int wd ) { return (_Istream_Cskip)@{ .scanset = 0p, .wd = wd }; }
[0f107e4]419} // distribution
420
[38de914]421struct _Istream_str_base {
[e7a8f65]422 union {
423 const char * scanset;
[4aae2bd]424 char delimiters[3]; // [0] => left, [1] => right
[e7a8f65]425 };
[3c573e9]426 int wd; // width
[61c7239]427 union {
428 unsigned char all;
429 struct {
430 unsigned char ignore:1; // do not change input argument
431 unsigned char inex:1; // include/exclude characters in scanset
[baa1d5d]432 unsigned char delimiter:1; // delimit character(s)
[2f34fde]433 unsigned char rwd:1; // read width
[61c7239]434 } flags;
435 };
[38de914]436}; // _Istream_str_base
437
[5764204]438struct _Istream_Cwidth {
[38de914]439 char * s;
440 inline _Istream_str_base;
[211def2]441}; // _Istream_Cwidth
[61c7239]442
[5764204]443// Restrict nesting of input manipulators to those combinations that make sense.
444
[30548de]445struct _Istream_Cquote {
[5764204]446 _Istream_Cwidth cstr;
[30548de]447}; // _Istream_Cquote
[8c13ca8]448
[211def2]449struct _Istream_Cstr {
450 _Istream_Cwidth cstr;
451}; // _Istream_Cstr
452
[04396aa]453static inline {
[5764204]454 // width must include room for null terminator, (gcc) scanf does not allow a 0 width => wd > 1 (1 char and null) and rd > 0 (1 char);
455 _Istream_Cwidth wdi( unsigned int wd, char s[] ) {
[211def2]456 if ( wd <= 1 ) throwResume ExceptionInst( cstring_length ); // minimum 1 character and null terminator
[1a7203d]457 return (_Istream_Cwidth)@{ .s = s, { {.scanset = 0p}, .wd = wd, {.all = 0} } };
[5764204]458 }
459 _Istream_Cwidth wdi( unsigned int wd, unsigned int rwd, char s[] ) {
[211def2]460 if ( wd <= 1 || wd <= rwd ) throwResume ExceptionInst( cstring_length ); // minimum 1 character, null terminator, plus subset
[1a7203d]461 return (_Istream_Cwidth)@{ .s = s, { {.scanset = 0p}, .wd = rwd, {.flags.rwd = true} } };
[5ad2c6c7]462 }
[211def2]463 _Istream_Cstr & getline( _Istream_Cwidth & f, const char delimiter = '\n' ) {
464 f.delimiters[0] = delimiter; f.delimiters[1] = '\0'; f.flags.delimiter = true; return (_Istream_Cstr &)f;
465 }
[30548de]466 _Istream_Cquote quote( char & ch, const char Ldelimiter = '\'', const char Rdelimiter = '\0' ) {
467 return (_Istream_Cquote)@{ { .s = &ch, { {.delimiters = { Ldelimiter, Rdelimiter, '\1' }}, .wd = 1, {.flags.rwd = true} } } };
[baa1d5d]468 }
[30548de]469 _Istream_Cquote & quote( _Istream_Cwidth & f, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) {
[5764204]470 f.delimiters[0] = Ldelimiter; f.delimiters[1] = Rdelimiter; f.delimiters[2] = '\0';
[30548de]471 return (_Istream_Cquote &)f;
[8c13ca8]472 }
[5764204]473 _Istream_Cstr & incl( const char scanset[], _Istream_Cwidth & f ) { f.scanset = scanset; f.flags.inex = false; return (_Istream_Cstr &)f; }
474 _Istream_Cstr & excl( const char scanset[], _Istream_Cwidth & f ) { f.scanset = scanset; f.flags.inex = true; return (_Istream_Cstr &)f; }
[1a7203d]475 _Istream_Cstr ignore( const char s[] ) { return (_Istream_Cstr)@{ { .s = (char *)s, { {.scanset = 0p}, .wd = -1, {.flags.ignore = true} } } }; }
[5764204]476 _Istream_Cstr & ignore( _Istream_Cwidth & f ) { f.flags.ignore = true; return (_Istream_Cstr &)f; }
[30548de]477 _Istream_Cquote & ignore( _Istream_Cquote & f ) { f.cstr.flags.ignore = true; return (_Istream_Cquote &)f; }
[5764204]478 _Istream_Cstr & ignore( _Istream_Cstr & f ) { f.cstr.flags.ignore = true; return (_Istream_Cstr &)f; }
[04396aa]479} // distribution
[8c13ca8]480
[ef3ac46]481forall( istype & | basic_istream( istype ) ) {
[8c13ca8]482 istype & ?|?( istype & is, _Istream_Cskip f );
[30548de]483 istype & ?|?( istype & is, _Istream_Cquote f );
[5764204]484 istype & ?|?( istype & is, _Istream_Cstr f );
[211def2]485 static inline istype & ?|?( istype & is, _Istream_Cwidth f ) { return is | *(_Istream_Cstr *)&f; }
[8c13ca8]486} // distribution
[86a8be5]487
[96ef156]488// FIXME: `| sized(T)` seems to be working around a bug, but it is logically unnecessary.
489// Including sized(T) causes a warning that is telling us to get rid of it.
490#pragma GCC diagnostic push
491#pragma GCC diagnostic ignored "-Wunused-parameter"
492forall( T & | sized(T) )
[3c573e9]493struct _Istream_Manip {
494 T & val; // polymorphic base-type
495 int wd; // width
[61c7239]496 bool ignore; // do not change input argument
[3c573e9]497}; // _Istream_Manip
[96ef156]498#pragma GCC diagnostic pop
[3c573e9]499
[94d2544]500#define INPUT_FMT_DECL( T ) \
[04396aa]501static inline { \
[1a7203d]502 _Istream_Manip(T) wdi( unsigned int wd, T & val ) { return (_Istream_Manip(T))@{ .val = val, .wd = wd, .ignore = false }; } \
503 _Istream_Manip(T) ignore( const T & val ) { return (_Istream_Manip(T))@{ .val = (T &)val, .wd = -1, .ignore = true }; } \
[04396aa]504 _Istream_Manip(T) & ignore( _Istream_Manip(T) & fmt ) { fmt.ignore = true; return fmt; } \
505} /* distribution */ \
[ef3ac46]506forall( istype & | basic_istream( istype ) ) { \
[3c573e9]507 istype & ?|?( istype & is, _Istream_Manip(T) f ); \
[61c7239]508} // ?|?
[3c573e9]509
[baa1d5d]510INPUT_FMT_DECL( char )
[94d2544]511INPUT_FMT_DECL( signed char )
512INPUT_FMT_DECL( unsigned char )
513INPUT_FMT_DECL( signed short int )
514INPUT_FMT_DECL( unsigned short int )
515INPUT_FMT_DECL( signed int )
516INPUT_FMT_DECL( unsigned int )
517INPUT_FMT_DECL( signed long int )
518INPUT_FMT_DECL( unsigned long int )
519INPUT_FMT_DECL( signed long long int )
520INPUT_FMT_DECL( unsigned long long int )
521
522INPUT_FMT_DECL( float )
523INPUT_FMT_DECL( double )
524INPUT_FMT_DECL( long double )
525
526INPUT_FMT_DECL( float _Complex )
527INPUT_FMT_DECL( double _Complex )
528INPUT_FMT_DECL( long double _Complex )
[3c573e9]529
[8d321f9]530// *********************************** time ***********************************
[3c573e9]531
[200fcb3]532#include <time_t.hfa> // Duration (constructors) / Time (constructors)
[10a97adb]533
[fd54fef]534forall( ostype & | ostream( ostype ) ) {
[200fcb3]535 ostype & ?|?( ostype & os, Duration dur );
[c635047]536 OSTYPE_VOID( Duration );
[200fcb3]537 ostype & ?|?( ostype & os, Time time );
[c635047]538 OSTYPE_VOID( Time );
[200fcb3]539} // distribution
[10a97adb]540
[eae8b37]541forall( istype & | istream( istype ), E | CfaEnum( E ) | Serial(E) )
542istype & ?|?( istype &, E & );
543
544forall( ostype & | ostream( ostype ), E | CfaEnum( E ) ) {
545 ostype & ?|?( ostype &, E );
546 OSTYPE_VOID( E );
547}
548
[86bd7c1f]549// Local Variables: //
550// tab-width: 4 //
551// End: //
Note: See TracBrowser for help on using the repository browser.