PageRenderTime 63ms CodeModel.GetById 50ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  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