2018-05-25 20:07:45 -05:00
// 21 may 2018
# include <vector>
class Error {
public :
2018-05-26 15:56:53 -05:00
virtual ~ Error ( void ) = default ;
2018-05-25 20:07:45 -05:00
virtual const char * String ( void ) const = 0 ;
} ;
extern Error * NewEOF ( void ) ;
extern Error * NewErrShortWrite ( void ) ;
extern bool IsEOF ( Error * e ) ;
2018-05-27 14:50:00 -05:00
// super lightweight (can be passed by value without any data being copied) wrapper around an array of bytes that can be sliced further without copying (std::vector can't do that easily)
// this is modelled after Go's slices
2018-05-27 14:36:16 -05:00
class ByteSlice {
char * data ;
size_t len ;
size_t cap ;
public :
ByteSlice ( void ) ; // default constructor; equivalent to Go's nil slice
ByteSlice ( const ByteSlice & b ) ; // copy constructor
ByteSlice ( ByteSlice & & b ) ; // move constructor; sets b to ByteSlice()
ByteSlice ( const char * b , size_t n ) ;
ByteSlice ( size_t len , size_t cap ) ;
2018-05-27 18:48:39 -05:00
ByteSlice ( int len , size_t cap ) ; // deal with stupid rule about 0 (see https://stackoverflow.com/a/4610586/3408572)
2018-05-27 14:36:16 -05:00
~ ByteSlice ( void ) ;
// note: copy assignment does not use copy-and-swap because I get neither copy-and-swap nor ADL public friend swap functions (https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom, https://stackoverflow.com/questions/5695548/public-friend-swap-member-function)
// (and also [14:55:04] <discord> <devin> i don't see why you'd need swap-on-copy semantics for anything if you're really just trying to make copy assignments create two references to the same memory)
ByteSlice & operator = ( const ByteSlice & b ) ; // copy assignment
ByteSlice & operator = ( ByteSlice & & b ) ; // move assignment; sets b to ByteSlice()
char * Data ( void ) ;
const char * Data ( void ) const ;
size_t Len ( void ) const ;
size_t Cap ( void ) const ;
ByteSlice Slice ( size_t start , size_t end ) ;
ByteSlice Append ( const char * b , size_t n ) ;
ByteSlice Append ( const ByteSlice & b ) ;
2018-05-27 14:50:00 -05:00
ByteSlice AppendString ( const char * str ) ;
2018-05-27 14:36:16 -05:00
void CopyFrom ( const char * b , size_t n ) ;
void CopyFrom ( const ByteSlice & b ) ;
} ;
2018-05-25 20:07:45 -05:00
class ReadCloser {
public :
2018-05-26 15:56:53 -05:00
virtual ~ ReadCloser ( void ) = default ;
2018-05-25 20:07:45 -05:00
2018-05-27 14:50:00 -05:00
virtual Error * Read ( ByteSlice b , size_t * n ) = 0 ;
2018-05-25 20:07:45 -05:00
} ;
class WriteCloser {
public :
2018-05-26 15:56:53 -05:00
virtual ~ WriteCloser ( void ) = default ;
2018-05-25 20:07:45 -05:00
2018-05-27 14:50:00 -05:00
virtual Error * Write ( const ByteSlice b ) = 0 ;
2018-05-25 20:07:45 -05:00
} ;
extern Error * OpenRead ( const char * filename , ReadCloser * * r ) ;
2018-05-26 16:42:11 -05:00
extern Error * CreateWrite ( const char * filename , WriteCloser * * w ) ;
2018-05-25 20:07:45 -05:00
class Scanner {
ReadCloser * r ;
2018-05-27 18:48:39 -05:00
ByteSlice buf ;
ByteSlice p ;
2018-05-27 14:50:00 -05:00
ByteSlice line ;
2018-05-25 20:07:45 -05:00
Error * err ;
public :
Scanner ( ReadCloser * r ) ;
~ Scanner ( void ) ;
bool Scan ( void ) ;
2018-05-27 14:50:00 -05:00
ByteSlice Bytes ( void ) const ;
2018-05-25 20:07:45 -05:00
Error * Err ( void ) const ;
} ;
2018-05-26 16:42:11 -05:00
2018-05-27 14:50:00 -05:00
extern std : : vector < ByteSlice > ByteSliceFields ( ByteSlice s ) ;