TextFile.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * Copyright (c) 2001 Jani Kajala
  3. *
  4. * Permission to use, copy, modify, distribute and sell this
  5. * software and its documentation for any purpose is hereby
  6. * granted without fee, provided that the above copyright notice
  7. * appear in all copies and that both that copyright notice and
  8. * this permission notice appear in supporting documentation.
  9. * Jani Kajala makes no representations about the suitability
  10. * of this software for any purpose. It is provided "as is"
  11. * without express or implied warranty.
  12. */
  13. #include "TextFile.h"
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. //-----------------------------------------------------------------------------
  17. namespace dev
  18. {
  19. class TextFile::TextFileImpl
  20. {
  21. public:
  22. TextFile::ErrorType err;
  23. int line;
  24. explicit TextFileImpl( const char* filename )
  25. {
  26. err = TextFile::ERROR_NONE;
  27. line = 1;
  28. m_peeked = false;
  29. m_peekedChar = 0;
  30. m_file = fopen( filename, "rt" );
  31. if ( !m_file )
  32. err = TextFile::ERROR_OPEN;
  33. }
  34. ~TextFileImpl()
  35. {
  36. if ( m_file )
  37. {
  38. fclose( m_file );
  39. m_file = 0;
  40. }
  41. }
  42. bool eof() const
  43. {
  44. if ( err )
  45. return true;
  46. return 0 != feof(m_file);
  47. }
  48. bool peekChar( char* ch )
  49. {
  50. if ( err )
  51. return false;
  52. if ( !m_peeked )
  53. {
  54. int c = getc( m_file );
  55. if ( EOF != c )
  56. {
  57. m_peeked = true;
  58. m_peekedChar = (char)c;
  59. }
  60. else
  61. {
  62. if ( ferror(m_file) )
  63. err = TextFile::ERROR_READ;
  64. }
  65. }
  66. if ( m_peeked )
  67. *ch = m_peekedChar;
  68. return m_peeked;
  69. }
  70. bool readChar( char* ch )
  71. {
  72. if ( err )
  73. return false;
  74. bool more = peekChar( ch );
  75. m_peeked = false;
  76. if ( more && *ch == '\n' )
  77. ++line;
  78. return more;
  79. }
  80. bool skipWhitespace()
  81. {
  82. if ( err )
  83. return false;
  84. char ch;
  85. while ( peekChar(&ch) )
  86. {
  87. if ( !isspace(ch) )
  88. break;
  89. readChar( &ch );
  90. }
  91. return !eof();
  92. }
  93. bool readString( char* buf, int size )
  94. {
  95. if ( err )
  96. return false;
  97. skipWhitespace();
  98. int count = 0;
  99. char ch;
  100. while ( peekChar(&ch) )
  101. {
  102. if ( isspace(ch) )
  103. break;
  104. if ( count+1 < size )
  105. buf[count++] = ch;
  106. readChar( &ch );
  107. }
  108. if ( size > 0 )
  109. buf[count] = 0;
  110. return count > 0;
  111. }
  112. void skipLine()
  113. {
  114. if ( err )
  115. return;
  116. char ch;
  117. while ( readChar(&ch) )
  118. {
  119. if ( ch == '\n' )
  120. break;
  121. }
  122. }
  123. long readHex()
  124. {
  125. if ( err )
  126. return 0;
  127. skipWhitespace();
  128. // hex must start with alphanumeric character
  129. char ch;
  130. if ( !peekChar(&ch) || !isalnum(ch) )
  131. {
  132. err = TextFile::ERROR_PARSE;
  133. return 0;
  134. }
  135. long x = 0;
  136. while ( peekChar(&ch) )
  137. {
  138. switch ( ch )
  139. {
  140. case '0': x <<= 4; x += 0; break;
  141. case '1': x <<= 4; x += 1; break;
  142. case '2': x <<= 4; x += 2; break;
  143. case '3': x <<= 4; x += 3; break;
  144. case '4': x <<= 4; x += 4; break;
  145. case '5': x <<= 4; x += 5; break;
  146. case '6': x <<= 4; x += 6; break;
  147. case '7': x <<= 4; x += 7; break;
  148. case '8': x <<= 4; x += 8; break;
  149. case '9': x <<= 4; x += 9; break;
  150. case 'a':
  151. case 'A': x <<= 4; x += 0xA; break;
  152. case 'b':
  153. case 'B': x <<= 4; x += 0xB; break;
  154. case 'c':
  155. case 'C': x <<= 4; x += 0xC; break;
  156. case 'd':
  157. case 'D': x <<= 4; x += 0xD; break;
  158. case 'e':
  159. case 'E': x <<= 4; x += 0xE; break;
  160. case 'f':
  161. case 'F': x <<= 4; x += 0xF; break;
  162. default: return x;
  163. }
  164. readChar( &ch );
  165. }
  166. return x;
  167. }
  168. private:
  169. bool m_peeked;
  170. char m_peekedChar;
  171. FILE* m_file;
  172. TextFileImpl( const TextFileImpl& );
  173. TextFileImpl& operator=( const TextFileImpl& );
  174. };
  175. //-----------------------------------------------------------------------------
  176. TextFile::TextFile( const char* filename )
  177. {
  178. m_this = new TextFileImpl( filename );
  179. }
  180. TextFile::~TextFile()
  181. {
  182. delete m_this;
  183. }
  184. bool TextFile::readString( char* buf, int size )
  185. {
  186. return m_this->readString( buf, size );
  187. }
  188. void TextFile::skipLine()
  189. {
  190. m_this->skipLine();
  191. }
  192. long TextFile::readHex()
  193. {
  194. return m_this->readHex();
  195. }
  196. bool TextFile::skipWhitespace()
  197. {
  198. return m_this->skipWhitespace();
  199. }
  200. TextFile::ErrorType TextFile::error() const
  201. {
  202. return m_this->err;
  203. }
  204. bool TextFile::readChar( char* ch )
  205. {
  206. return m_this->readChar( ch );
  207. }
  208. bool TextFile::peekChar( char* ch )
  209. {
  210. return m_this->peekChar( ch );
  211. }
  212. bool TextFile::eof() const
  213. {
  214. return m_this->eof();
  215. }
  216. int TextFile::line() const
  217. {
  218. return m_this->line;
  219. }
  220. } // dev