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.

652 lines
22 KiB

15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
16 years ago
16 years ago
16 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
  1. #ifndef RICHIO_H_
  2. #define RICHIO_H_
  3. /*
  4. * This program source code file is part of KiCad, a free EDA CAD application.
  5. *
  6. * Copyright (C) 2007-2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  7. * Copyright (C) 2007 KiCad Developers, see change_log.txt for contributors.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, you may find one here:
  21. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  22. * or you may search the http://www.gnu.org website for the version 2 license,
  23. * or you may write to the Free Software Foundation, Inc.,
  24. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  25. */
  26. // This file defines 3 classes useful for working with DSN text files and is named
  27. // "richio" after its author, Richard Hollenbeck, aka Dick Hollenbeck.
  28. #include <string>
  29. #include <vector>
  30. // I really did not want to be dependent on wxWidgets in richio
  31. // but the errorText needs to be wide char so wxString rules.
  32. #include <wx/wx.h>
  33. #include <stdio.h>
  34. /**
  35. * @ingroup exception_types
  36. * @{
  37. */
  38. #define IO_FORMAT _( "IO_ERROR: %s\nfrom %s : %s" )
  39. #define PARSE_FORMAT _( "PARSE_ERROR: %s in input/source \"%s\", line %d, offset %d\nfrom %s : %s" )
  40. // references:
  41. // http://stackoverflow.com/questions/2670816/how-can-i-use-the-compile-time-constant-line-in-a-string
  42. #define STRINGIFY(x) #x
  43. #define TOSTRING(x) STRINGIFY(x)
  44. // use one of the following __LOC__ defs, depending on whether your
  45. // compiler supports __func__ or not, and how it handles __LINE__
  46. #define __LOC__ ((std::string(__FUNCTION__) + "() : line ") + TOSTRING(__LINE__)).c_str()
  47. //#define __LOC__ TOSTRING(__LINE__)
  48. /// macro which captures the "call site" values of __FILE_ & __LOC__
  49. #define THROW_IO_ERROR( msg ) throw IO_ERROR( __FILE__, __LOC__, msg )
  50. /**
  51. * Struct IO_ERROR
  52. * is a class used to hold an error message and may be used to throw exceptions
  53. * containing meaningful error messages.
  54. * @author Dick Hollenbeck
  55. */
  56. struct IO_ERROR // : std::exception
  57. {
  58. wxString errorText;
  59. /**
  60. * Constructor
  61. *
  62. * @param aThrowersFile is the __FILE__ preprocessor macro but generated
  63. * at the source file of thrower.
  64. *
  65. * @param aThrowersLoc can be either a function name, such as __func__
  66. * or a stringified __LINE__ preprocessor macro but generated
  67. * at the source function of the thrower, or concatonation. Use macro
  68. * THROW_IO_ERROR() to wrap a call to this constructor at the call site.
  69. *
  70. * @param aMsg is error text that will be streamed through wxString.Printf()
  71. * using the format string IO_FORMAT above.
  72. */
  73. IO_ERROR( const char* aThrowersFile,
  74. const char* aThrowersLoc,
  75. const wxString& aMsg )
  76. {
  77. init( aThrowersFile, aThrowersLoc, aMsg );
  78. }
  79. #if !wxCHECK_VERSION(2, 9, 0)
  80. // 2.9.0 and greater provide a wxString() constructor taking "const char*" whereas
  81. // 2.8 did not. In 2.9.x this IO_ERROR() constructor uses that wxString( const char* )
  82. // constructor making this here constructor ambiguous with the IO_ERROR()
  83. // taking the wxString.
  84. IO_ERROR( const char* aThrowersFile,
  85. const char* aThrowersLoc,
  86. const std::string& aMsg )
  87. {
  88. init( aThrowersFile, aThrowersLoc, wxString::FromUTF8( aMsg.c_str() ) );
  89. }
  90. #endif
  91. /**
  92. * handles the case where _() is passed as aMsg.
  93. */
  94. IO_ERROR( const char* aThrowersFile,
  95. const char* aThrowersLoc,
  96. const wxChar* aMsg )
  97. {
  98. init( aThrowersFile, aThrowersLoc, wxString( aMsg ) );
  99. }
  100. void init( const char* aThrowersFile, const char* aThrowersLoc, const wxString& aMsg );
  101. IO_ERROR() {}
  102. ~IO_ERROR() throw ( /*none*/ ){}
  103. };
  104. /**
  105. * Class PARSE_ERROR
  106. * contains a filename or source description, a problem input line, a line number,
  107. * a byte offset, and an error message which contains the the caller's report and his
  108. * call site information: CPP source file, function, and line number.
  109. * @author Dick Hollenbeck
  110. */
  111. struct PARSE_ERROR : public IO_ERROR
  112. {
  113. // wxString errorText is still public from IO_ERROR
  114. int lineNumber; ///< at which line number, 1 based index.
  115. int byteIndex; ///< at which byte offset within the line, 1 based index
  116. /// problem line of input [say, from a LINE_READER].
  117. /// this is brought up in original byte format rather than wxString form, incase
  118. /// there was a problem with the encoding, in which case converting to wxString is
  119. /// not reliable in this context.
  120. std::string inputLine;
  121. /**
  122. * Constructor
  123. * which is normally called via the macro THROW_PARSE_ERROR so that
  124. * __FILE__ and __LOC__ can be captured from the call site.
  125. */
  126. PARSE_ERROR( const char* aThrowersFile, const char* aThrowersLoc,
  127. const wxString& aMsg, const wxString& aSource,
  128. const char* aInputLine,
  129. int aLineNumber, int aByteIndex ) :
  130. IO_ERROR()
  131. {
  132. init( aThrowersFile, aThrowersLoc, aMsg, aSource, aInputLine, aLineNumber, aByteIndex );
  133. }
  134. void init( const char* aThrowersFile, const char* aThrowersLoc,
  135. const wxString& aMsg, const wxString& aSource,
  136. const char* aInputLine,
  137. int aLineNumber, int aByteIndex );
  138. ~PARSE_ERROR() throw ( /*none*/ ){}
  139. };
  140. #define THROW_PARSE_ERROR( aMsg, aSource, aInputLine, aLineNumber, aByteIndex ) \
  141. throw PARSE_ERROR( __FILE__, __LOC__, aMsg, aSource, aInputLine, aLineNumber, aByteIndex )
  142. /** @} exception_types */
  143. #define LINE_READER_LINE_DEFAULT_MAX 100000
  144. #define LINE_READER_LINE_INITIAL_SIZE 5000
  145. /**
  146. * Class LINE_READER
  147. * is an abstract class from which implementation specific LINE_READERs may
  148. * be derived to read single lines of text and manage a line number counter.
  149. */
  150. class LINE_READER
  151. {
  152. protected:
  153. unsigned length; ///< no. bytes in line before trailing nul.
  154. unsigned lineNum;
  155. char* line; ///< the read line of UTF8 text
  156. unsigned capacity; ///< no. bytes allocated for line.
  157. unsigned maxLineLength; ///< maximum allowed capacity using resizing.
  158. wxString source; ///< origin of text lines, e.g. filename or "clipboard"
  159. /**
  160. * Function expandCapacity
  161. * will expand the capacity of @a line up to maxLineLength but not greater, so
  162. * be careful about making assumptions of @a capacity after calling this.
  163. */
  164. void expandCapacity( unsigned newsize );
  165. public:
  166. /**
  167. * Constructor LINE_READER
  168. * builds a line reader and fixes the length of the maximum supported
  169. * line length to @a aMaxLineLength.
  170. */
  171. LINE_READER( unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX );
  172. virtual ~LINE_READER();
  173. /**
  174. * Function ReadLine
  175. * reads a line of text into the buffer and increments the line number
  176. * counter. If the line is larger than aMaxLineLength passed to the
  177. * constructor, then an exception is thrown. The line is nul terminated.
  178. * @return char* - The beginning of the read line, or NULL if EOF.
  179. * @throw IO_ERROR when a line is too long.
  180. */
  181. virtual char* ReadLine() throw( IO_ERROR ) = 0;
  182. /**
  183. * Function GetSource
  184. * returns the name of the source of the lines in an abstract sense.
  185. * This may be a file or it may be the clipboard or any other source
  186. * of lines of text. The returned string is useful for reporting error
  187. * messages.
  188. */
  189. virtual const wxString& GetSource() const
  190. {
  191. return source;
  192. }
  193. /**
  194. * Function Line
  195. * returns a pointer to the last line that was read in.
  196. */
  197. char* Line() const
  198. {
  199. return line;
  200. }
  201. /**
  202. * Operator char*
  203. * is a casting operator that returns a char* pointer to the start of the
  204. * line buffer.
  205. */
  206. operator char* () const
  207. {
  208. return Line();
  209. }
  210. /**
  211. * Function Line Number
  212. * returns the line number of the last line read from this LINE_READER. Lines
  213. * start from 1.
  214. */
  215. virtual unsigned LineNumber() const
  216. {
  217. return lineNum;
  218. }
  219. /**
  220. * Function Length
  221. * returns the number of bytes in the last line read from this LINE_READER.
  222. */
  223. unsigned Length() const
  224. {
  225. return length;
  226. }
  227. };
  228. /**
  229. * Class FILE_LINE_READER
  230. * is a LINE_READER that reads from an open file. File must be already open
  231. * so that this class can exist without any UI policy.
  232. */
  233. class FILE_LINE_READER : public LINE_READER
  234. {
  235. protected:
  236. bool iOwn; ///< if I own the file, I'll promise to close it, else not.
  237. FILE* fp; ///< I may own this file, but might not.
  238. public:
  239. /**
  240. * Constructor FILE_LINE_READER
  241. * takes @a aFileName and the size of the desired line buffer and opens
  242. * the file and assumes the obligation to close it.
  243. *
  244. * @param aFileName is the name of the file to open and to use for error reporting purposes.
  245. *
  246. * @param aStartingLineNumber is the initial line number to report on error, and is
  247. * accessible here for the case where multiple DSNLEXERs are reading from the
  248. * same file in sequence, all from the same open file (with @a doOwn = false).
  249. * Internally it is incremented by one after each ReadLine(), so the first
  250. * reported line number will always be one greater than what is provided here.
  251. *
  252. * @param aMaxLineLength is the number of bytes to use in the line buffer.
  253. *
  254. * @throw IO_ERROR if @a aFileName cannot be opened.
  255. */
  256. FILE_LINE_READER( const wxString& aFileName,
  257. unsigned aStartingLineNumber = 0,
  258. unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX ) throw( IO_ERROR );
  259. /**
  260. * Constructor FILE_LINE_READER
  261. * takes an open FILE and the size of the desired line buffer and takes
  262. * ownership of the open file, i.e. assumes the obligation to close it.
  263. *
  264. * @param aFile is an open file.
  265. * @param aFileName is the name of the file for error reporting purposes.
  266. * @param doOwn if true, means I should close the open file, else not.
  267. * @param aStartingLineNumber is the initial line number to report on error, and is
  268. * accessible here for the case where multiple DSNLEXERs are reading from the
  269. * same file in sequence, all from the same open file (with @a doOwn = false).
  270. * Internally it is incremented by one after each ReadLine(), so the first
  271. * reported line number will always be one greater than what is provided here.
  272. * @param aMaxLineLength is the number of bytes to use in the line buffer.
  273. */
  274. FILE_LINE_READER( FILE* aFile, const wxString& aFileName, bool doOwn = true,
  275. unsigned aStartingLineNumber = 0,
  276. unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX );
  277. /**
  278. * Destructor
  279. * may or may not close the open file, depending on @a doOwn in constructor.
  280. */
  281. ~FILE_LINE_READER();
  282. char* ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description
  283. /**
  284. * Function Rewind
  285. * rewinds the file and resets the line number back to zero. Line number
  286. * will go to 1 on first ReadLine().
  287. */
  288. void Rewind()
  289. {
  290. rewind( fp );
  291. lineNum = 0;
  292. }
  293. };
  294. /**
  295. * Class STRING_LINE_READER
  296. * is a LINE_READER that reads from a multiline 8 bit wide std::string
  297. */
  298. class STRING_LINE_READER : public LINE_READER
  299. {
  300. protected:
  301. std::string lines;
  302. size_t ndx;
  303. public:
  304. /**
  305. * Constructor STRING_LINE_READER( const std::string&, const wxString& )
  306. *
  307. * @param aString is a source string consisting of one or more lines
  308. * of text, where multiple lines are separated with a '\n' character.
  309. * The last line does not necessarily need a trailing '\n'.
  310. *
  311. * @param aSource describes the source of aString for error reporting purposes
  312. * can be anything meaninful, such as wxT( "clipboard" ).
  313. */
  314. STRING_LINE_READER( const std::string& aString, const wxString& aSource );
  315. /**
  316. * Constructor STRING_LINE_READER( const STRING_LINE_READER& )
  317. * allows for a continuation of the reading of a stream started by another
  318. * STRING_LINE_READER. Any stream offset and source name are used from
  319. * @a aStartingPoint.
  320. */
  321. STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint );
  322. char* ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description
  323. };
  324. /**
  325. * Class INPUTSTREAM_LINE_READER
  326. * is a LINE_READER that reads from a wxInputStream object.
  327. */
  328. class INPUTSTREAM_LINE_READER : public LINE_READER
  329. {
  330. protected:
  331. wxInputStream* m_stream; //< The input stream to read. No ownership of this pointer.
  332. public:
  333. /**
  334. * Constructor WXINPUTSTREAM_LINE_READER
  335. *
  336. * @param aStream A pointer to a wxInputStream object to read.
  337. */
  338. INPUTSTREAM_LINE_READER( wxInputStream* aStream );
  339. char* ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description
  340. };
  341. #define OUTPUTFMTBUFZ 500 ///< default buffer size for any OUTPUT_FORMATTER
  342. /**
  343. * Class OUTPUTFORMATTER
  344. * is an important interface (abstract class) used to output 8 bit text in
  345. * a convenient way. The primary interface is "printf() - like" but
  346. * with support for indentation control. The destination of the 8 bit
  347. * wide text is up to the implementer.
  348. * <p>
  349. * The implementer only has to implement the write() function, but can
  350. * also optionally re-implement GetQuoteChar().
  351. * <p>
  352. * If you want to output a wxString, then use TO_UTF8() on it
  353. * before passing it as an argument to Print().
  354. * <p>
  355. * Since this is an abstract interface, only classes derived from
  356. * this one may actually be used.
  357. */
  358. class OUTPUTFORMATTER
  359. {
  360. std::vector<char> buffer;
  361. char quoteChar[2];
  362. int sprint( const char* fmt, ... ) throw( IO_ERROR );
  363. int vprint( const char* fmt, va_list ap ) throw( IO_ERROR );
  364. protected:
  365. OUTPUTFORMATTER( int aReserve = OUTPUTFMTBUFZ, char aQuoteChar = '"' ) :
  366. buffer( aReserve, '\0' )
  367. {
  368. quoteChar[0] = aQuoteChar;
  369. quoteChar[1] = '\0';
  370. }
  371. virtual ~OUTPUTFORMATTER() {}
  372. /**
  373. * Function GetQuoteChar
  374. * performs quote character need determination according to the Specctra DSN
  375. * specification.
  376. * @param wrapee A string that might need wrapping on each end.
  377. * @param quote_char A single character C string which provides the current
  378. * quote character, should it be needed by the wrapee.
  379. *
  380. * @return const char* - the quote_char as a single character string, or ""
  381. * if the wrapee does not need to be wrapped.
  382. */
  383. static const char* GetQuoteChar( const char* wrapee, const char* quote_char );
  384. /**
  385. * Function write
  386. * should be coded in the interface implementation (derived) classes.
  387. *
  388. * @param aOutBuf is the start of a byte buffer to write.
  389. * @param aCount tells how many bytes to write.
  390. * @throw IO_ERROR, if there is a problem outputting, such as a full disk.
  391. */
  392. virtual void write( const char* aOutBuf, int aCount ) throw( IO_ERROR ) = 0;
  393. #if defined(__GNUG__) // The GNU C++ compiler defines this
  394. // When used on a C++ function, we must account for the "this" pointer,
  395. // so increase the STRING-INDEX and FIRST-TO_CHECK by one.
  396. // See http://docs.freebsd.org/info/gcc/gcc.info.Function_Attributes.html
  397. // Then to get format checking during the compile, compile with -Wall or -Wformat
  398. #define PRINTF_FUNC __attribute__ ((format (printf, 3, 4)))
  399. #else
  400. #define PRINTF_FUNC // nothing
  401. #endif
  402. public:
  403. //-----<interface functions>------------------------------------------
  404. /**
  405. * Function Print
  406. * formats and writes text to the output stream.
  407. *
  408. * @param nestLevel The multiple of spaces to precede the output with.
  409. * @param fmt A printf() style format string.
  410. * @param ... a variable list of parameters that will get blended into
  411. * the output under control of the format string.
  412. * @return int - the number of characters output.
  413. * @throw IO_ERROR, if there is a problem outputting, such as a full disk.
  414. */
  415. int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IO_ERROR );
  416. /**
  417. * Function GetQuoteChar
  418. * performs quote character need determination.
  419. * It returns the quote character as a single character string for a given
  420. * input wrapee string. If the wrappee does not need to be quoted,
  421. * the return value is "" (the null string), such as when there are no
  422. * delimiters in the input wrapee string. If you want the quote_char
  423. * to be assuredly not "", then pass in "(" as the wrappee.
  424. * <p>
  425. * Implementations are free to override the default behavior, which is to
  426. * call the static function of the same name.
  427. * @param wrapee A string that might need wrapping on each end.
  428. * @return const char* - the quote_char as a single character string, or ""
  429. * if the wrapee does not need to be wrapped.
  430. */
  431. virtual const char* GetQuoteChar( const char* wrapee );
  432. /**
  433. * Function Quotes
  434. * checks \a aWrapee input string for a need to be quoted
  435. * (e.g. contains a ')' character or a space), and for \" double quotes
  436. * within the string that need to be escaped such that the DSNLEXER
  437. * will correctly parse the string from a file later.
  438. *
  439. * @param aWrapee is a string that might need wraping in double quotes,
  440. * and it might need to have its internal content escaped, or not.
  441. *
  442. * @return std::string - whose c_str() function can be called for passing
  443. * to printf() style functions that output UTF8 encoded s-expression streams.
  444. *
  445. * @throw IO_ERROR, if there is any kind of problem with the input string.
  446. */
  447. virtual std::string Quotes( const std::string& aWrapee ) throw( IO_ERROR );
  448. std::string Quotew( const wxString& aWrapee ) throw( IO_ERROR );
  449. //-----</interface functions>-----------------------------------------
  450. };
  451. /**
  452. * Class STRING_FORMATTER
  453. * implements OUTPUTFORMATTER to a memory buffer. After Print()ing the
  454. * string is available through GetString()
  455. */
  456. class STRING_FORMATTER : public OUTPUTFORMATTER
  457. {
  458. std::string mystring;
  459. public:
  460. /**
  461. * Constructor STRING_FORMATTER
  462. * reserves space in the buffer
  463. */
  464. STRING_FORMATTER( int aReserve = OUTPUTFMTBUFZ, char aQuoteChar = '"' ) :
  465. OUTPUTFORMATTER( aReserve, aQuoteChar )
  466. {
  467. }
  468. /**
  469. * Function Clear
  470. * clears the buffer and empties the internal string.
  471. */
  472. void Clear()
  473. {
  474. mystring.clear();
  475. }
  476. /**
  477. * Function StripUseless
  478. * removes whitespace, '(', and ')' from the mystring.
  479. */
  480. void StripUseless();
  481. std::string GetString()
  482. {
  483. return mystring;
  484. }
  485. protected:
  486. //-----<OUTPUTFORMATTER>------------------------------------------------
  487. void write( const char* aOutBuf, int aCount ) throw( IO_ERROR );
  488. //-----</OUTPUTFORMATTER>-----------------------------------------------
  489. };
  490. /**
  491. * Class FILE_OUTPUTFORMATTER
  492. * may be used for text file output. It is about 8 times faster than
  493. * STREAM_OUTPUTFORMATTER for file streams.
  494. */
  495. class FILE_OUTPUTFORMATTER : public OUTPUTFORMATTER
  496. {
  497. public:
  498. /**
  499. * Constructor
  500. * @param aFileName is the full filename to open and save to as a text file.
  501. * @param aMode is what you would pass to wxFopen()'s mode, defaults to wxT( "wt" )
  502. * for text files that are to be created here and now.
  503. * @param aQuoteChar is a char used for quoting problematic strings
  504. (with whitespace or special characters in them).
  505. * @throw IO_ERROR if the file cannot be opened.
  506. */
  507. FILE_OUTPUTFORMATTER( const wxString& aFileName,
  508. const wxChar* aMode = wxT( "wt" ),
  509. char aQuoteChar = '"' )
  510. throw( IO_ERROR );
  511. ~FILE_OUTPUTFORMATTER();
  512. protected:
  513. //-----<OUTPUTFORMATTER>------------------------------------------------
  514. void write( const char* aOutBuf, int aCount ) throw( IO_ERROR );
  515. //-----</OUTPUTFORMATTER>-----------------------------------------------
  516. FILE* m_fp; ///< takes ownership
  517. wxString m_filename;
  518. };
  519. /**
  520. * Class STREAM_OUTPUTFORMATTER
  521. * implements OUTPUTFORMATTER to a wxWidgets wxOutputStream. The stream is
  522. * neither opened nor closed by this class.
  523. */
  524. class STREAM_OUTPUTFORMATTER : public OUTPUTFORMATTER
  525. {
  526. wxOutputStream& os;
  527. public:
  528. /**
  529. * Constructor STREAM_OUTPUTFORMATTER
  530. * can take any number of wxOutputStream derivations, so it can write
  531. * to a file, socket, or zip file.
  532. */
  533. STREAM_OUTPUTFORMATTER( wxOutputStream& aStream, char aQuoteChar = '"' ) :
  534. OUTPUTFORMATTER( OUTPUTFMTBUFZ, aQuoteChar ),
  535. os( aStream )
  536. {
  537. }
  538. protected:
  539. //-----<OUTPUTFORMATTER>------------------------------------------------
  540. void write( const char* aOutBuf, int aCount ) throw( IO_ERROR );
  541. //-----</OUTPUTFORMATTER>-----------------------------------------------
  542. };
  543. #endif // RICHIO_H_