/fcs/hrio.hpp
C++ Header | 236 lines | 168 code | 20 blank | 48 comment | 53 complexity | 3542cb8f85373179885eaa876dbfc501 MD5 | raw file
1#ifndef ARBITRARY_GUARD_MACRO_CODE_OF_DOOM_WHICH_IS_CALLED_FCSHR_IO 2#define ARBITRARY_GUARD_MACRO_CODE_OF_DOOM_WHICH_IS_CALLED_FCSHR_IO 3 4#include<iostream> 5#include<sstream> 6#include<string> 7#include<exception> 8#include<fcs/util.hpp> 9 10namespace FCSTools 11{ 12 13 namespace HR 14 { 15 /* 16 FORMAT: 17 Overall it must be: 18 Sigil 19 Section Head 20 -- head information 21 Section Data 22 -- data information 23 Section Analysis 24 -- analysis information 25 26 FCS:H.R # this sigil tells us this is a Human-Readable FCS file 27 Section Head 28 # comments begin with `#' and go to the end of 29 # the line; they are ignored 30 31 # whitespace lines are also ignored 32 # <name> is any string beginning with a non-whitespace 33 # human-readable character, and terminating with return 34 # carriage '\n'; we note that '\r\n' is treated as 35 # two characters, but that '\r' is whitespace 36 37 # A <number> is in integral or double format 38 ColumnBegin 39 # indentation is ignored 40 Name: <name> 41 Range: <number> 42 Scale: <number>, <number> 43 ColumnEnd 44 Section Data 45 # Data must have K columns: 46 # one for each column-section as defined above 47 # each row represents one element in the list 48 # there may be comments in the data-section 49 # for instance, vendor specific information 50 # can be embedded in the data by using comments 51 <number> <number> ... <number> 52 # next element is special 53 <number> <number> ... <number> 54 ... ... ... 55 <number> <number> ... <number> 56 Section Analysis 57 # this section is vendor-specific (for now) 58 59 */ 60 61 struct FCSHR 62 { 63 struct ColumnDatum 64 { 65 std::string Name; 66 std::size_t Range; 67 std::pair<std::size_t,std::size_t> Scale; 68 }; 69 typedef std::vector<ColumnDatum> ColumnData; 70 struct Header 71 { 72 typedef ColumnData parameter_type; 73 ColumnData Parameter; 74 }; 75 76 typedef Header head_type; 77 typedef dataset data_type; 78 79 Header Head; 80 dataset Data; 81 void Reader (std::istream& file); 82 friend std::istream& operator >> (std::istream& file, FCSHR& hr) 83 { 84 hr.Reader (file); 85 return file; 86 } 87 void Writer (std::ostream& file) const; 88 friend std::ostream& operator << (std::ostream& file, FCSHR const& hr) 89 { 90 hr.Writer (file); 91 return file; 92 } 93 }; 94 95 void FCSHR::Writer (std::ostream& file) const 96 { 97 file << "FCS:H.R" << std::endl 98 << "Section Head" << std::endl; 99 for (std::size_t i=0; i<this->Head.Parameter.size (); ++i) 100 { 101 file << "ColumnBegin" << std::endl 102 << " Name: " << this->Head.Parameter[i].Name << std::endl 103 << " Range: " << this->Head.Parameter[i].Range << std::endl 104 << " Scale: " << this->Head.Parameter[i].Scale.first 105 << ", " << this->Head.Parameter[i].Scale.second << std::endl 106 << "ColumnEnd" << std::endl; 107 } 108 file << "Section Data" << std::endl; 109 for (std::size_t i=0; i<this->Data.size (); ++i) 110 for (std::size_t j=0; j<this->Data[i].size (); ++j) 111 file << (0==j?"\n":" ") << this->Data[i][j]; 112 } 113 114 void FCSHR::Reader (std::istream& file) 115 { 116 117 this->Head.Parameter.clear (); 118 this->Data.clear (); 119 120 // rolling interpretation 121 const std::size_t Uninitialized = 0; 122 const std::size_t Sigil = 1; 123 const std::size_t Head = 2; 124 const std::size_t Data = 3; 125 const std::size_t Analysis = 4; 126 127 std::size_t State = Uninitialized; 128 129 std::string line; 130 131 bool Column = false; 132 133 while (std::getline (file, line)) 134 { 135 // strip off any comments 136 std::size_t comment = line.find_first_of ('#'); 137 if (std::string::npos != comment) 138 line = line.substr (0, comment); 139 std::stringstream ssLine (line); 140 std::string nonWs; 141 ssLine >> nonWs; 142 std::string lnonWs = lower (nonWs); 143 if (Column) 144 { 145 if ("name:" == lnonWs) 146 { 147 std::string Name; 148 std::size_t pos = line.find_first_of (':'); 149 pos = line.find_first_not_of (" \t\v", pos+1); 150 if (std::string::npos != pos) 151 Name = line.substr (pos, line.size ()); 152 153 this->Head.Parameter.back ().Name = Name; 154 } 155 else if ("range:" == lnonWs) 156 { 157 std::size_t Range; 158 ssLine >> Range; 159 160 this->Head.Parameter.back ().Range = Range; 161 } 162 else if ("scale:" == lnonWs) 163 { 164 std::string comma; 165 std::size_t Scale1, Scale2; 166 ssLine >> Scale1 >> comma >> Scale2; 167 168 this->Head.Parameter.back ().Scale 169 = std::make_pair (Scale1, Scale2); 170 } 171 else if ("columnend" == lnonWs) 172 { 173 Column = false; 174 } 175 } 176 else if ('#' == lnonWs[0]) 177 { 178 continue; 179 } 180 else if ("fcs:h.r" == lnonWs) 181 { 182 State = Sigil; 183 continue; 184 } 185 else if ("section" == lnonWs) 186 { 187 std::string WhichSection; 188 ssLine >> WhichSection; 189 std::string lWS = lower (WhichSection); 190 if ("head" == lWS) 191 { 192 if (Sigil == State) 193 State = Head; 194 else 195 throw improper_state_in_file (); 196 } 197 else if ("data" == lWS) 198 { 199 if (Head == State) 200 State = Data; 201 else 202 throw improper_state_in_file (); 203 } 204 else if ("analysis" == lWS) 205 { 206 if (Data == State) 207 State = Analysis; 208 else 209 throw improper_state_in_file (); 210 } 211 } 212 else if ("columnbegin" == lnonWs) 213 { 214 if (Head == State) 215 Column = true; 216 else 217 throw improper_state_in_file (); 218 this->Head.Parameter.push_back (ColumnDatum ()); 219 } 220 else if (Data == State && lnonWs.size () > 0) 221 { 222 std::stringstream ssData (line); 223 // get data 224 element Element (this->Head.Parameter.size ()); 225 for (std::size_t i=0; i<Element.size (); ++i) 226 ssData >> Element[i]; 227 this->Data.push_back (Element); 228 } 229 } 230 } 231 232 } 233 234} 235 236#endif//ARBITRARY_GUARD_MACRO_CODE_OF_DOOM_WHICH_IS_CALLED_FCSHR_IO