diff options
author | Mike Buland <eichlan@xagasoft.com> | 2010-02-11 00:38:09 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2010-02-11 00:38:09 +0000 |
commit | d61161061bd5998ef4b1fc2aaad2cf4bbd78e90d (patch) | |
tree | f4ea64381d4f0b3b7a9610758c034183098c2e96 | |
parent | 79b7b631750b69cbe06daedb0453306595dea6ad (diff) | |
download | libbu++-d61161061bd5998ef4b1fc2aaad2cf4bbd78e90d.tar.gz libbu++-d61161061bd5998ef4b1fc2aaad2cf4bbd78e90d.tar.bz2 libbu++-d61161061bd5998ef4b1fc2aaad2cf4bbd78e90d.tar.xz libbu++-d61161061bd5998ef4b1fc2aaad2cf4bbd78e90d.zip |
Started working on a CSV reader, it's pretty much done, the CSV writer is just
a shell, but I may finish it soon, and started work on NewLine, a filter that
converts newlines in text streams between the different OS standards.
Also added some more helper operators to fbasicstring.
-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 | |||