/fcs/hrio.hpp

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