00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef CGATOOLS_UTIL_DELIMITEDLINEPARSER_HPP_
00016 #define CGATOOLS_UTIL_DELIMITEDLINEPARSER_HPP_ 1
00017
00021
00022 #include "cgatools/core.hpp"
00023 #include "cgatools/util/parse.hpp"
00024 #include "cgatools/util/Exception.hpp"
00025
00026 #include <string>
00027 #include <vector>
00028
00029 #include <boost/shared_ptr.hpp>
00030 #include <boost/array.hpp>
00031
00032 #include <cstring>
00033
00034 namespace cgatools { namespace util {
00035
00037 class DelimitedFieldParser
00038 {
00039 public:
00040 DelimitedFieldParser(const std::string& name)
00041 : name_(name)
00042 {
00043 }
00044
00045 virtual ~DelimitedFieldParser()
00046 {
00047 }
00048
00049 const std::string& getName() const
00050 {
00051 return name_;
00052 }
00053
00058 virtual void parse(const char* first, const char* last) = 0;
00059
00060 protected:
00062 std::string name_;
00063 };
00064
00066 class IgnoreField : public DelimitedFieldParser
00067 {
00068 public:
00069 IgnoreField(const std::string& name)
00070 : DelimitedFieldParser(name)
00071 {
00072 }
00073
00074 void parse(const char* first, const char* last)
00075 {
00076 }
00077 };
00078
00081 template <typename Value>
00082 class ValueField : public DelimitedFieldParser
00083 {
00084 public:
00085 ValueField(const std::string& name, Value* val)
00086 : DelimitedFieldParser(name),
00087 val_(val)
00088 {
00089 }
00090
00091 void parse(const char* first, const char* last)
00092 {
00093 for(size_t ii=0; ii<exceptions_.size(); ii++)
00094 {
00095 size_t strSize = exceptions_[ii].first.length();
00096 if (size_t(last-first) == strSize &&
00097 0 == std::strncmp(first, exceptions_[ii].first.c_str(), strSize))
00098 {
00099 *val_ = exceptions_[ii].second;
00100 return;
00101 }
00102 }
00103
00104 *val_ = parseValue<Value>(first, last);
00105 }
00106
00109 ValueField<Value>& exception(const std::string& key, const Value& val)
00110 {
00111 exceptions_.push_back(make_pair(key, val));
00112 return *this;
00113 }
00114
00115 private:
00116 Value* val_;
00117 std::vector< std::pair<std::string, Value> > exceptions_;
00118 };
00119
00124 template <typename Value>
00125 class ValueVectorField : public DelimitedFieldParser
00126 {
00127 public:
00128 ValueVectorField(const std::string& name, char delimiter, std::vector<Value>* val)
00129 : DelimitedFieldParser(name),
00130 delimiter_(delimiter),
00131 val_(val)
00132 {
00133 }
00134
00135 void parse(const char* first, const char* last)
00136 {
00137 val_->clear();
00138
00139 const char* ii = first;
00140 while (ii < last)
00141 {
00142 const char* jj;
00143 for (jj = ii; jj < last && *jj != delimiter_; ++jj) ;
00144
00145 Value v = parseValue<Value>(ii, jj);
00146 val_->push_back(v);
00147
00148 ii = jj + 1;
00149 }
00150 }
00151 private:
00152 char delimiter_;
00153 std::vector<Value>* val_;
00154 };
00155
00157 class StringField : public DelimitedFieldParser
00158 {
00159 public:
00160 StringField(const std::string& name, std::string* val)
00161 : DelimitedFieldParser(name),
00162 val_(val)
00163 {
00164 }
00165
00166 void parse(const char* first, const char* last);
00167
00168 private:
00169 std::string* val_;
00170 };
00171
00173 class CharField : public DelimitedFieldParser
00174 {
00175 public:
00176 CharField(const std::string& name, char* val)
00177 : DelimitedFieldParser(name),
00178 val_(val)
00179 {
00180 }
00181
00182 void parse(const char* first, const char* last);
00183
00184 private:
00185 char* val_;
00186 };
00187
00188 class StrandField : public DelimitedFieldParser
00189 {
00190 public:
00191 StrandField(const std::string& name, bool* val)
00192 : DelimitedFieldParser(name),
00193 val_(val)
00194 {
00195 }
00196
00197 void parse(const char* first, const char* last);
00198
00199 private:
00200 bool* val_;
00201 };
00202
00203 class SideField : public DelimitedFieldParser
00204 {
00205 public:
00206 SideField(const std::string& name, uint8_t* val)
00207 : DelimitedFieldParser(name),
00208 val_(val)
00209 {
00210 }
00211
00212 void parse(const char* first, const char* last);
00213
00214 private:
00215 uint8_t* val_;
00216 };
00217
00219 class DelimitedLineParser
00220 {
00221 friend class DelimitedFile;
00222 public:
00225 enum EmptyFieldHandling
00226 {
00229 PROCESS_EMPTY_FIELDS = 0,
00232 SKIP_EMPTY_FIELDS = 1
00233 };
00234
00237 enum StrictnessChecking
00238 {
00241 STRICT_CHECKING = 0,
00244 RELAXED_CHECKING = 1
00245 };
00246
00247 typedef std::vector< boost::shared_ptr<DelimitedFieldParser> > Fields;
00248
00250 DelimitedLineParser();
00251
00255 template <class Field>
00256 DelimitedLineParser& addField(const Field& field)
00257 {
00258 boost::shared_ptr<Field> ptr(new Field(field));
00259 fields_.push_back(ptr);
00260 return *this;
00261 }
00262
00264 template <class Field>
00265 DelimitedLineParser& setField(size_t offset, const Field& field)
00266 {
00267 CGA_ASSERT(offset < fields_.size());
00268 boost::shared_ptr<Field> ptr(new Field(field));
00269 fields_[offset] = ptr;
00270 return *this;
00271 }
00272
00274 void parseLine( const char* first, const char* last,
00275 char delimiter = '\t',
00276 EmptyFieldHandling emptyHandling = PROCESS_EMPTY_FIELDS,
00277 StrictnessChecking strictnessChecking = RELAXED_CHECKING);
00278
00279 void parseLine( const std::string& line,
00280 char delimiter = '\t',
00281 EmptyFieldHandling emptyHandling = PROCESS_EMPTY_FIELDS,
00282 StrictnessChecking strictnessChecking = RELAXED_CHECKING);
00283
00285 const Fields& getFields() const {return fields_;}
00286
00287 private:
00288 Fields fields_;
00289 };
00290
00291 class DelimitedField : public DelimitedFieldParser
00292 {
00293 public:
00294 DelimitedField(const std::string& name, char delimiter, const DelimitedLineParser& lineParser)
00295 : DelimitedFieldParser(name),
00296 delimiter_(delimiter),
00297 lineParser_(lineParser)
00298 {
00299 }
00300
00301 void parse(const char* first, const char* last);
00302
00303 private:
00304 char delimiter_;
00305 DelimitedLineParser lineParser_;
00306 };
00307
00308 } }
00309
00310 #endif // CGATOOLS_UTIL_DELIMITEDLINEPARSER_HPP_