Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

346 lines
9.7 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1997
  6. //
  7. // File: parmio.h
  8. //
  9. //--------------------------------------------------------------------------
  10. ////////////////////////////////////////////////////////////////////////////////////
  11. // PARMIO.H: Parameter file I/O routines
  12. //
  13. //////////////////////////////////////////////////////////////////////////////////
  14. #ifndef _PARMIO_H_
  15. #define _PARMIO_H_
  16. #include "stlstream.h"
  17. // Parameter defining a named, nestable and iteratable item in a
  18. // parameter file. There are currently two type: blocks and values.
  19. // A block is a grouping of values and other blocks. A value is
  20. // a name = value pair. Blocks are bounded by {}, values are terminated
  21. // by ';'.
  22. struct PARMBLK
  23. {
  24. enum EPBLK
  25. {
  26. EPB_NONE, // nothing
  27. EPB_VAL, // simple name = value syntax
  28. EPB_BLK, // named block
  29. EPB_MAX
  30. };
  31. ZSTR _zsName; // Name of value or block
  32. int _indx; // index (-1 for "not present")
  33. EPBLK _eBlk; // type of block
  34. PARMBLK ( EPBLK eBlk = EPB_NONE, SZC szc = NULL, int indx = -1 )
  35. : _eBlk( eBlk ),
  36. _indx(indx)
  37. {
  38. if ( szc )
  39. _zsName = szc;
  40. }
  41. bool operator == ( const PARMBLK & pblk ) const;
  42. bool operator != ( const PARMBLK & pblk ) const;
  43. bool operator > ( const PARMBLK & pblk ) const;
  44. bool operator < ( const PARMBLK & pblk ) const;
  45. };
  46. // Define a stack of PARMBLKs; used for output parameter file writing
  47. class STKPARMBLK : public vector<PARMBLK> {};
  48. // Extended descriptor for a block read in from a parameter file.
  49. // Contains starting and ending offsets within the positionable stream.
  50. struct PARMBLKIN : PARMBLK
  51. {
  52. int _iblkEnd; // index of last+1 item/block in scope of this block
  53. streamoff _offsBeg; // Starting offset in the stream
  54. streamoff _offsEnd; // Ending offset in the stream
  55. streamoff _offsData; // Starting offset of the data in the block
  56. PARMBLKIN ( EPBLK eBlk = EPB_NONE, SZC szc = NULL, int indx = -1 )
  57. : PARMBLK(eBlk,szc,indx),
  58. _iblkEnd(-1),
  59. _offsBeg(-1),
  60. _offsEnd(-1),
  61. _offsData(-1)
  62. {
  63. }
  64. bool operator == ( const PARMBLKIN & pblkin ) const;
  65. bool operator != ( const PARMBLKIN & pblkin ) const;
  66. bool operator > ( const PARMBLKIN & pblkin ) const;
  67. bool operator < ( const PARMBLKIN & pblkin ) const;
  68. };
  69. // Define a stack of input parameter blocks for parameter file reading
  70. class STKPARMBLKIN : public vector<PARMBLKIN> {};
  71. //////////////////////////////////////////////////////////////////////////////////
  72. //
  73. // Class PARMOUTSTREAM. An output stream of parameters.
  74. //
  75. // Blocks and values are written out in sequence. Blocks
  76. // are opened, filled and closed using member functions
  77. // and function templates. All unclosed blocks are are
  78. // closed automatically during close().
  79. //
  80. //////////////////////////////////////////////////////////////////////////////////
  81. class PARMOUTSTREAM : public ofstream
  82. {
  83. public:
  84. PARMOUTSTREAM ();
  85. ~ PARMOUTSTREAM ();
  86. void close ();
  87. void StartBlock ( SZC szc = NULL, int indx = -1 );
  88. void StartItem ( SZC szc = NULL, int indx = -1 );
  89. bool BEndBlock ();
  90. bool BEndItem () { return BEndBlock(); }
  91. void nl ();
  92. ofstream & Stream ()
  93. { return (ofstream&) self; }
  94. protected:
  95. STKPARMBLK _stkblk;
  96. void StartChunk ( PARMBLK::EPBLK eBlk, SZC szc = NULL, int indx = -1 );
  97. };
  98. //////////////////////////////////////////////////////////////////////////////////
  99. //
  100. // Class PARMINSTREAM. An input stream of parameters.
  101. //
  102. // The input text stream is read once during scan(), and a table of
  103. // all blocks and values is built. The scan creates an outermost block
  104. // defining the entire file. Then other blocks are added as discovered,
  105. // and their starting and ending points are recorded.
  106. //
  107. // To use, construct, open() and scan(). Then, find the named section
  108. // (or value) in question using ifind(), which returns the scoping level.
  109. // Then, either construct an Iterator (nested class) to walk through the
  110. // values at that level or use ifind() to locate specific items by name.
  111. //
  112. //////////////////////////////////////////////////////////////////////////////////
  113. enum EC_PARM_PARSE
  114. {
  115. ECPP_PARSE_ERROR = EC_ERR_MIN,
  116. ECPP_UNMATCHED_QUOTE,
  117. ECPP_UNEXPECTED_EOF,
  118. ECPP_INVALID_CLUMP,
  119. ECPP_INVALID_NAME,
  120. ECPP_INVALID_BODY,
  121. };
  122. class PARMINSTREAM : public ifstream
  123. {
  124. public:
  125. PARMINSTREAM ();
  126. ~ PARMINSTREAM ();
  127. void close();
  128. // Build the rapid-access table
  129. void Scan ();
  130. // Find a block or item at the given level; -1 means "current level",
  131. // zero means outermost level. Returns index of block or -1 if
  132. // not found.
  133. int IblkFind ( SZC szcName, int index = -1, int iblkOuter = -1 );
  134. // Return the next data block in the array or
  135. // false if there are no more items.
  136. const PARMBLKIN * Pparmblk ( int iblk, int iblkOuter = -1 );
  137. // position the stream to process the parameter
  138. bool BSeekBlk ( int iblk );
  139. // read the parameter into a string
  140. bool BSeekBlkString ( int iblk, ZSTR & zsParam );
  141. // Pretty-print the block stack with nesting information
  142. void Dump ();
  143. // Return true if the block index is legal
  144. bool BBlkOk ( int iblk ) const
  145. { return iblk >= 0 || iblk < _stkblk.size(); }
  146. int Cblk () const
  147. { return _stkblk.size() ; }
  148. ifstream & Stream ()
  149. { return (ifstream&) self; }
  150. class Iterator
  151. {
  152. public:
  153. Iterator( PARMINSTREAM & fprm,
  154. SZC szcBlock = NULL,
  155. int index = -1,
  156. int iblkOuter = -1 );
  157. const PARMBLKIN * PblkNext ();
  158. protected:
  159. PARMINSTREAM & _fprm;
  160. int _iblkOuter;
  161. int _iblk;
  162. };
  163. friend class Iterator;
  164. protected:
  165. STKPARMBLKIN _stkblk; // The block array
  166. int _iline; // The current line number (parsing)
  167. ZSTR _zsWhite; // White space character set
  168. void ThrowParseError ( SZC szcError,
  169. int iline = -1,
  170. EC_PARM_PARSE ecpp = ECPP_PARSE_ERROR );
  171. int IGetc ();
  172. bool BIswhite ( char ch );
  173. void ScanQuote ( char ch );
  174. void ScanClump ();
  175. void ScanBlock ( char ch );
  176. PARMBLK::EPBLK EpblkScanItemBody ( streamoff & offsData );
  177. int IScanUnwhite ( bool bEofOk = false );
  178. void ScanItemList ();
  179. void ScanItemUnit ();
  180. void ScanItemDesc ( ZSTR & zsName, int & indx ) ;
  181. void ScanName ( ZSTR & szName );
  182. };
  183. //////////////////////////////////////////////////////////////////////////////////
  184. // Inline functions
  185. //////////////////////////////////////////////////////////////////////////////////
  186. inline
  187. PARMINSTREAM & operator >> (PARMINSTREAM & is, ZSTR & zs)
  188. {
  189. ios_base::iostate _St = ios_base::goodbit;
  190. zs.erase();
  191. const ifstream::sentry _Ok(is);
  192. if (_Ok)
  193. {
  194. _TRY_IO_BEGIN
  195. size_t _N = 0 < is.width() && is.width() < zs.max_size()
  196. ? is.width()
  197. : zs.max_size();
  198. int _C = is.rdbuf()->sgetc();
  199. bool bmeta = false;
  200. bool bfirst = true;
  201. for (; 0 < --_N; _C = is.rdbuf()->snextc())
  202. {
  203. if(char_traits<char>::eq_int_type(char_traits<char>::eof(), _C))
  204. {
  205. _St |= ios_base::eofbit;
  206. break;
  207. }
  208. else
  209. if ( ! bmeta && _C == CH_DELM_STR )
  210. {
  211. if ( ! bfirst )
  212. {
  213. is.rdbuf()->snextc();
  214. break;
  215. }
  216. }
  217. else
  218. if ( _C == CH_META && ! bmeta )
  219. {
  220. bmeta = true;
  221. }
  222. else
  223. {
  224. bmeta = false;
  225. zs.append(1, char_traits<char>::to_char_type(_C));
  226. }
  227. bfirst = false;
  228. }
  229. _CATCH_IO_(is);
  230. }
  231. else
  232. {
  233. _THROW1(runtime_error("file exhausted extracting string"));
  234. }
  235. is.width(0);
  236. is.setstate(_St);
  237. return is;
  238. }
  239. //////////////////////////////////////////////////////////////////////////////////
  240. // Template functions for parameter streams
  241. //////////////////////////////////////////////////////////////////////////////////
  242. //////////////////////////////////////////////////////////////////////////////////
  243. // Write SZC: no corresponding read, since no buffer exists
  244. //////////////////////////////////////////////////////////////////////////////////
  245. inline
  246. PARMOUTSTREAM & operator << (PARMOUTSTREAM & ofs, SZC szc)
  247. {
  248. ofs << CH_DELM_STR;
  249. for ( ; *szc ; )
  250. {
  251. char ch = *szc++;
  252. if ( ch == CH_DELM_STR || ch == CH_META )
  253. {
  254. if (char_traits<char>::eq_int_type(char_traits<char>::eof(),
  255. ofs.rdbuf()->sputc(CH_META)))
  256. break;
  257. }
  258. if (char_traits<char>::eq_int_type(char_traits<char>::eof(),
  259. ofs.rdbuf()->sputc(ch)))
  260. break;
  261. }
  262. ofs << CH_DELM_STR;
  263. return ofs;
  264. }
  265. //////////////////////////////////////////////////////////////////////////////////
  266. // Read and write ZSTRs
  267. //////////////////////////////////////////////////////////////////////////////////
  268. inline
  269. PARMOUTSTREAM & operator << (PARMOUTSTREAM & ofs, const ZSTR & zs)
  270. {
  271. ofs << CH_DELM_STR;
  272. for ( int ich = 0; ich < zs.size(); ++ich)
  273. {
  274. char ch = zs.at(ich);
  275. if ( ch == CH_DELM_STR || ch == CH_META )
  276. {
  277. if (char_traits<char>::eq_int_type(char_traits<char>::eof(),
  278. ofs.rdbuf()->sputc(CH_META)))
  279. break;
  280. }
  281. if (char_traits<char>::eq_int_type(char_traits<char>::eof(),
  282. ofs.rdbuf()->sputc(ch)))
  283. break;
  284. }
  285. if ( ich < zs.size() )
  286. _THROW1(runtime_error("file exhausted inserting string"));
  287. ofs << CH_DELM_STR;
  288. return ofs;
  289. }
  290. //////////////////////////////////////////////////////////////////////////////////
  291. // Simple parameter output routines using insertion
  292. //////////////////////////////////////////////////////////////////////////////////
  293. template<class T> inline
  294. PARMOUTSTREAM & AddParamValue ( PARMOUTSTREAM & fprm, const T & t, SZC szc, int indx = -1 )
  295. {
  296. fprm.StartItem( szc, indx );
  297. fprm << (const T &) t;
  298. fprm.BEndItem();
  299. return fprm;
  300. }
  301. //////////////////////////////////////////////////////////////////////////////////
  302. // Simple parameter input routines using extraction
  303. //////////////////////////////////////////////////////////////////////////////////
  304. template<class T> inline
  305. bool BGetParamValue ( PARMINSTREAM & fprm, T & t, SZC szc, int index = -1, int iblkOuter = -1 )
  306. {
  307. int iblk = fprm.IblkFind(szc, index, iblkOuter);
  308. if ( iblk < 0 )
  309. return false;
  310. fprm.BSeekBlk(iblk);
  311. fprm >> t;
  312. return true;
  313. }
  314. #endif