diff options
| -rw-r--r-- | src/csvreader.cpp | 100 | ||||
| -rw-r--r-- | src/csvreader.h | 38 | ||||
| -rw-r--r-- | src/csvwriter.cpp | 39 | ||||
| -rw-r--r-- | src/csvwriter.h | 36 | ||||
| -rw-r--r-- | src/fbasicstring.h | 9 | ||||
| -rw-r--r-- | src/newline.cpp | 56 | ||||
| -rw-r--r-- | src/newline.h | 34 | ||||
| -rw-r--r-- | src/tests/csv.cpp | 41 |
8 files changed, 352 insertions, 1 deletions
diff --git a/src/csvreader.cpp b/src/csvreader.cpp new file mode 100644 index 0000000..a28c2c3 --- /dev/null +++ b/src/csvreader.cpp | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | #include "bu/csvreader.h" | ||
| 2 | #include "bu/stream.h" | ||
| 3 | |||
| 4 | #include "bu/sio.h" | ||
| 5 | using namespace Bu; | ||
| 6 | |||
| 7 | Bu::CsvReader::CsvReader( Bu::Stream &sIn, Bu::CsvReader::Style eStyle ) : | ||
| 8 | sIn( sIn ) | ||
| 9 | { | ||
| 10 | switch( eStyle ) | ||
| 11 | { | ||
| 12 | case styleExcel: | ||
| 13 | sDecode = Bu::slot( &decodeExcel ); | ||
| 14 | break; | ||
| 15 | |||
| 16 | case styleC: | ||
| 17 | sDecode = Bu::slot( &decodeExcel ); | ||
| 18 | break; | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | Bu::CsvReader::CsvReader( Bu::Stream &sIn, | ||
| 23 | Bu::CsvReader::DecodeSignal sDecode ) : | ||
| 24 | sIn( sIn ), | ||
| 25 | sDecode( sDecode ) | ||
| 26 | { | ||
| 27 | } | ||
| 28 | |||
| 29 | Bu::CsvReader::~CsvReader() | ||
| 30 | { | ||
| 31 | } | ||
| 32 | |||
| 33 | Bu::StrArray Bu::CsvReader::readLine() | ||
| 34 | { | ||
| 35 | Bu::StrArray aVals; | ||
| 36 | |||
| 37 | Bu::FString sLine = sIn.readLine(); | ||
| 38 | |||
| 39 | for( Bu::FString::iterator i = sLine.begin(); i; i++ ) | ||
| 40 | { | ||
| 41 | if( *i == ',' ) | ||
| 42 | { | ||
| 43 | } | ||
| 44 | else | ||
| 45 | { | ||
| 46 | aVals.append( sDecode( i ) ); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | return aVals; | ||
| 51 | } | ||
| 52 | |||
| 53 | Bu::FString Bu::CsvReader::decodeExcel( Bu::FString::iterator &i ) | ||
| 54 | { | ||
| 55 | Bu::FString sRet; | ||
| 56 | |||
| 57 | for(; i && (*i == ' ' || *i == '\t'); i++ ) { } | ||
| 58 | |||
| 59 | if( *i == '\"' ) | ||
| 60 | { | ||
| 61 | for( i++ ; i; i++ ) | ||
| 62 | { | ||
| 63 | if( *i == '\"' ) | ||
| 64 | { | ||
| 65 | i++; | ||
| 66 | if( *i == '\"' ) | ||
| 67 | { | ||
| 68 | sRet += *i; | ||
| 69 | } | ||
| 70 | else | ||
| 71 | { | ||
| 72 | return sRet; | ||
| 73 | } | ||
| 74 | } | ||
| 75 | else | ||
| 76 | { | ||
| 77 | sRet += *i; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | } | ||
| 81 | else | ||
| 82 | { | ||
| 83 | for( ; i; i++ ) | ||
| 84 | { | ||
| 85 | if( *i == ',' ) | ||
| 86 | { | ||
| 87 | return sRet; | ||
| 88 | } | ||
| 89 | sRet += *i; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | return sRet; | ||
| 94 | } | ||
| 95 | |||
| 96 | Bu::FString Bu::CsvReader::decodeC( Bu::FString::iterator &i ) | ||
| 97 | { | ||
| 98 | return ""; | ||
| 99 | } | ||
| 100 | |||
diff --git a/src/csvreader.h b/src/csvreader.h new file mode 100644 index 0000000..d89fabe --- /dev/null +++ b/src/csvreader.h | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | #ifndef BU_CSV_READER_H | ||
| 2 | #define BU_CSV_READER_H | ||
| 3 | |||
| 4 | #include "bu/fstring.h" | ||
| 5 | #include "bu/array.h" | ||
| 6 | #include "bu/signals.h" | ||
| 7 | |||
| 8 | namespace Bu | ||
| 9 | { | ||
| 10 | class Stream; | ||
| 11 | typedef Bu::Array<Bu::FString> StrArray; | ||
| 12 | |||
| 13 | class CsvReader | ||
| 14 | { | ||
| 15 | public: | ||
| 16 | typedef Bu::Signal1<Bu::FString, Bu::FString::iterator &> DecodeSignal; | ||
| 17 | enum Style | ||
| 18 | { | ||
| 19 | styleExcel, ///< Excel style quotes around things that need em | ||
| 20 | styleC ///< Escape things that need it C-style | ||
| 21 | }; | ||
| 22 | |||
| 23 | CsvReader( Stream &sIn, Style eStyle=styleExcel ); | ||
| 24 | CsvReader( Stream &sIn, DecodeSignal sDecode ); | ||
| 25 | virtual ~CsvReader(); | ||
| 26 | |||
| 27 | StrArray readLine(); | ||
| 28 | |||
| 29 | private: | ||
| 30 | Stream &sIn; | ||
| 31 | DecodeSignal sDecode; | ||
| 32 | |||
| 33 | static Bu::FString decodeExcel( Bu::FString::iterator &i ); | ||
| 34 | static Bu::FString decodeC( Bu::FString::iterator &i ); | ||
| 35 | }; | ||
| 36 | }; | ||
| 37 | |||
| 38 | #endif | ||
diff --git a/src/csvwriter.cpp b/src/csvwriter.cpp new file mode 100644 index 0000000..b66dca8 --- /dev/null +++ b/src/csvwriter.cpp | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | #include "bu/csvwriter.h" | ||
| 2 | #include "bu/stream.h" | ||
| 3 | |||
| 4 | Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, Bu::CsvWriter::Style eStyle ) : | ||
| 5 | sOut( sOut ) | ||
| 6 | { | ||
| 7 | switch( eStyle ) | ||
| 8 | { | ||
| 9 | case styleExcel: | ||
| 10 | sEncode = Bu::slot( &encodeExcel ); | ||
| 11 | break; | ||
| 12 | |||
| 13 | case styleC: | ||
| 14 | sEncode = Bu::slot( &encodeExcel ); | ||
| 15 | break; | ||
| 16 | } | ||
| 17 | } | ||
| 18 | |||
| 19 | Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, | ||
| 20 | Bu::CsvWriter::EncodeSignal sEncode ) : | ||
| 21 | sOut( sOut ), | ||
| 22 | sEncode( sEncode ) | ||
| 23 | { | ||
| 24 | } | ||
| 25 | |||
| 26 | Bu::CsvWriter::~CsvWriter() | ||
| 27 | { | ||
| 28 | } | ||
| 29 | |||
| 30 | Bu::FString Bu::CsvWriter::encodeExcel( const Bu::FString &sIn ) | ||
| 31 | { | ||
| 32 | return ""; | ||
| 33 | } | ||
| 34 | |||
| 35 | Bu::FString Bu::CsvWriter::encodeC( const Bu::FString &sIn ) | ||
| 36 | { | ||
| 37 | return ""; | ||
| 38 | } | ||
| 39 | |||
diff --git a/src/csvwriter.h b/src/csvwriter.h new file mode 100644 index 0000000..82f36d7 --- /dev/null +++ b/src/csvwriter.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | #ifndef BU_CSV_WRITER_H | ||
| 2 | #define BU_CSV_WRITER_H | ||
| 3 | |||
| 4 | #include "bu/fstring.h" | ||
| 5 | #include "bu/array.h" | ||
| 6 | #include "bu/signals.h" | ||
| 7 | |||
| 8 | namespace Bu | ||
| 9 | { | ||
| 10 | class Stream; | ||
| 11 | typedef Bu::Array<Bu::FString> StrArray; | ||
| 12 | |||
| 13 | class CsvWriter | ||
| 14 | { | ||
| 15 | public: | ||
| 16 | typedef Bu::Signal1<Bu::FString, const Bu::FString &> EncodeSignal; | ||
| 17 | enum Style | ||
| 18 | { | ||
| 19 | styleExcel, ///< Excel style quotes around things that need em | ||
| 20 | styleC ///< Escape things that need it C-style | ||
| 21 | }; | ||
| 22 | |||
| 23 | CsvWriter( Stream &sOut, Style eStyle=styleExcel ); | ||
| 24 | CsvWriter( Stream &sOut, EncodeSignal sEncode ); | ||
| 25 | virtual ~CsvWriter(); | ||
| 26 | |||
| 27 | private: | ||
| 28 | Stream &sOut; | ||
| 29 | EncodeSignal sEncode; | ||
| 30 | |||
| 31 | static Bu::FString encodeExcel( const Bu::FString &sIn ); | ||
| 32 | static Bu::FString encodeC( const Bu::FString &sIn ); | ||
| 33 | }; | ||
| 34 | }; | ||
| 35 | |||
| 36 | #endif | ||
diff --git a/src/fbasicstring.h b/src/fbasicstring.h index 838fbc2..535df55 100644 --- a/src/fbasicstring.h +++ b/src/fbasicstring.h | |||
| @@ -796,7 +796,7 @@ namespace Bu | |||
| 796 | append( &cData, 1 ); | 796 | append( &cData, 1 ); |
| 797 | } | 797 | } |
| 798 | } | 798 | } |
| 799 | 799 | ||
| 800 | /** | 800 | /** |
| 801 | * Append another FString to this one. | 801 | * Append another FString to this one. |
| 802 | *@param sData (MyType &) The FString to append. | 802 | *@param sData (MyType &) The FString to append. |
| @@ -1280,6 +1280,13 @@ namespace Bu | |||
| 1280 | return (*this); | 1280 | return (*this); |
| 1281 | } | 1281 | } |
| 1282 | 1282 | ||
| 1283 | MyType &operator+=( const MyType::const_iterator &i ) | ||
| 1284 | { | ||
| 1285 | append( i, i+1 ); | ||
| 1286 | |||
| 1287 | return (*this); | ||
| 1288 | } | ||
| 1289 | |||
| 1283 | /** | 1290 | /** |
| 1284 | * Plus equals operator for FString. | 1291 | * Plus equals operator for FString. |
| 1285 | *@param cData (const chr) The character to append to your FString. | 1292 | *@param cData (const chr) The character to append to your FString. |
diff --git a/src/newline.cpp b/src/newline.cpp new file mode 100644 index 0000000..0dbbae5 --- /dev/null +++ b/src/newline.cpp | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | #include "bu/newline.h" | ||
| 2 | |||
| 3 | Bu::NewLine::NewLine( Bu::Stream &rNext ) : | ||
| 4 | Bu::Filter( rNext ), | ||
| 5 | bExChar( false ) | ||
| 6 | { | ||
| 7 | } | ||
| 8 | |||
| 9 | Bu::NewLine::~NewLine() | ||
| 10 | { | ||
| 11 | } | ||
| 12 | |||
| 13 | void Bu::NewLine::start() | ||
| 14 | { | ||
| 15 | } | ||
| 16 | |||
| 17 | size_t Bu::NewLine::stop() | ||
| 18 | { | ||
| 19 | return 0; | ||
| 20 | } | ||
| 21 | |||
| 22 | size_t Bu::NewLine::read( void *pBuf, size_t iAmnt ) | ||
| 23 | { | ||
| 24 | size_t iRead = rNext.read( pBuf, iAmnt ); | ||
| 25 | size_t iOffset = 0; | ||
| 26 | |||
| 27 | for( size_t i = 0; i < iRead; i++ ) | ||
| 28 | { | ||
| 29 | if( pBuf[i] == '\r' ) | ||
| 30 | { | ||
| 31 | pBuf[i+iOffset] = '\n'; | ||
| 32 | if( pBuf[j+1] == '\n' ) | ||
| 33 | { | ||
| 34 | iOffset--; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | else if( pBuf[i] == '\n' ) | ||
| 38 | { | ||
| 39 | if( pBuf[j+1] == '\r' ) | ||
| 40 | { | ||
| 41 | iOffset--; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | else if( iOffset ) | ||
| 45 | { | ||
| 46 | pBuf[i+iOffset] = pBuf[i]; | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | iRead += iOffset; | ||
| 51 | } | ||
| 52 | |||
| 53 | size_t Bu::NewLine::write( const void *pBuf, size_t iAmnt ) | ||
| 54 | { | ||
| 55 | } | ||
| 56 | |||
diff --git a/src/newline.h b/src/newline.h new file mode 100644 index 0000000..8ee5779 --- /dev/null +++ b/src/newline.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #ifndef BU_NEW_LINE_H | ||
| 2 | #define BU_NEW_LINE_H | ||
| 3 | |||
| 4 | #include "bu/filter.h" | ||
| 5 | |||
| 6 | namespace Bu | ||
| 7 | { | ||
| 8 | /** | ||
| 9 | * Converts new-line characters from any standard convention into linefeeds | ||
| 10 | * (\n) on reading, and converts them to either your OS's standard or a | ||
| 11 | * specified standard, depending on how you construct the class. | ||
| 12 | * | ||
| 13 | * If you're reading in a text file, then this filter is practically | ||
| 14 | * required. | ||
| 15 | */ | ||
| 16 | class NewLine : public Bu::Filter | ||
| 17 | { | ||
| 18 | public: | ||
| 19 | NewLine( Bu::Stream &rNext ); | ||
| 20 | virtual ~NewLine(); | ||
| 21 | |||
| 22 | virtual void start(); | ||
| 23 | virtual size_t stop(); | ||
| 24 | |||
| 25 | virtual size_t read( void *pBuf, size_t iAmnt ); | ||
| 26 | virtual size_t write( const void *pBuf, size_t iAmnt ); | ||
| 27 | |||
| 28 | private: | ||
| 29 | bool bExChar; | ||
| 30 | char cExChar; | ||
| 31 | }; | ||
| 32 | }; | ||
| 33 | |||
| 34 | #endif | ||
diff --git a/src/tests/csv.cpp b/src/tests/csv.cpp new file mode 100644 index 0000000..03e1df8 --- /dev/null +++ b/src/tests/csv.cpp | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | #include "bu/optparser.h" | ||
| 2 | #include "bu/file.h" | ||
| 3 | #include "bu/newline.h" | ||
| 4 | #include "bu/csvreader.h" | ||
| 5 | #include "bu/sio.h" | ||
| 6 | |||
| 7 | using namespace Bu; | ||
| 8 | |||
| 9 | class Options : public OptParser | ||
| 10 | { | ||
| 11 | public: | ||
| 12 | Options( int argc, char *argv[] ) | ||
| 13 | { | ||
| 14 | addOption( slot( this, &Options::onRead ), 'r', "read", | ||
| 15 | "Read and display a csv file." ); | ||
| 16 | |||
| 17 | addHelpOption(); | ||
| 18 | |||
| 19 | parse( argc, argv ); | ||
| 20 | } | ||
| 21 | |||
| 22 | int onRead( StrArray aArgs ) | ||
| 23 | { | ||
| 24 | File fIn( aArgs[1], File::Read ); | ||
| 25 | NewLine nlIn( fIn ); | ||
| 26 | CsvReader rCsv( nlIn ); | ||
| 27 | while( !fIn.isEos() ) | ||
| 28 | { | ||
| 29 | sio << rCsv.readLine() << sio.nl; | ||
| 30 | } | ||
| 31 | sio << sio.nl; | ||
| 32 | return 1; | ||
| 33 | } | ||
| 34 | }; | ||
| 35 | |||
| 36 | int main( int argc, char *argv[] ) | ||
| 37 | { | ||
| 38 | Options opts( argc, argv ); | ||
| 39 | return 0; | ||
| 40 | } | ||
| 41 | |||
