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.

505 lines
16 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
16 years ago
16 years ago
16 years ago
15 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2007-2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  5. * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #ifndef RICHIO_H_
  25. #define RICHIO_H_
  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 <vector>
  29. #include <utf8.h>
  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 <cstdio>
  33. #include <wx/string.h>
  34. #include <wx/stream.h>
  35. #include <ki_exception.h>
  36. /**
  37. * This is like sprintf() but the output is appended to a std::string instead of to a
  38. * character array.
  39. *
  40. * @param aResult is the string to append to, previous text is not clear()ed.
  41. * @param aFormat is a printf() style format string.
  42. * @return the count of bytes appended to the result string, no terminating nul is included.
  43. */
  44. int
  45. #if defined(__GNUG__)
  46. __attribute__ ((format (printf, 2, 3)))
  47. #endif
  48. StrPrintf( std::string* aResult, const char* aFormat, ... );
  49. /**
  50. * This is like sprintf() but the output is returned in a std::string instead of to a
  51. * character array.
  52. *
  53. * @param format is a printf() style format string.
  54. * @return std::string - the result of the sprintf().
  55. */
  56. std::string
  57. #if defined(__GNUG__)
  58. __attribute__ ((format (printf, 1, 2)))
  59. #endif
  60. StrPrintf( const char* format, ... );
  61. #define LINE_READER_LINE_DEFAULT_MAX 1000000
  62. #define LINE_READER_LINE_INITIAL_SIZE 5000
  63. /**
  64. * An abstract class from which implementation specific LINE_READERs may be derived to
  65. * read single lines of text and manage a line number counter.
  66. */
  67. class LINE_READER
  68. {
  69. public:
  70. /**
  71. * Build a line reader and fixes the length of the maximum supported line length
  72. * to @a aMaxLineLength.
  73. */
  74. LINE_READER( unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX );
  75. virtual ~LINE_READER();
  76. /**
  77. * Read a line of text into the buffer and increments the line number counter.
  78. *
  79. * If the line is larger than the maximum length passed to the constructor, then an
  80. * exception is thrown. The line is nul terminated.
  81. *
  82. * @return The beginning of the read line, or NULL if EOF.
  83. * @throw IO_ERROR when a line is too long.
  84. */
  85. virtual char* ReadLine() = 0;
  86. /**
  87. * Returns the name of the source of the lines in an abstract sense.
  88. *
  89. * This may be a file or it may be the clipboard or any other source of lines of text.
  90. * The returned string is useful for reporting error messages.
  91. */
  92. virtual const wxString& GetSource() const
  93. {
  94. return m_source;
  95. }
  96. /**
  97. * Return a pointer to the last line that was read in.
  98. */
  99. char* Line() const
  100. {
  101. return m_line;
  102. }
  103. /**
  104. * A casting operator that returns a char* pointer to the start of the line buffer.
  105. */
  106. operator char* () const
  107. {
  108. return Line();
  109. }
  110. /**
  111. * Return the line number of the last line read from this LINE_READER.
  112. *
  113. * Lines start from 1.
  114. */
  115. virtual unsigned LineNumber() const
  116. {
  117. return m_lineNum;
  118. }
  119. /**
  120. * Return the number of bytes in the last line read from this LINE_READER.
  121. */
  122. unsigned Length() const
  123. {
  124. return m_length;
  125. }
  126. protected:
  127. /**
  128. * Will expand the capacity of @a line up to maxLineLength but not greater, so
  129. * be careful about making assumptions of @a capacity after calling this.
  130. */
  131. void expandCapacity( unsigned aNewsize );
  132. unsigned m_length; ///< no. bytes in line before trailing nul.
  133. unsigned m_lineNum;
  134. char* m_line; ///< the read line of UTF8 text
  135. unsigned m_capacity; ///< no. bytes allocated for line.
  136. unsigned m_maxLineLength; ///< maximum allowed capacity using resizing.
  137. wxString m_source; ///< origin of text lines, e.g. filename or "clipboard"
  138. };
  139. /**
  140. * A LINE_READER that reads from an open file.
  141. *
  142. * File must be already open so that this class can exist without any UI policy.
  143. */
  144. class FILE_LINE_READER : public LINE_READER
  145. {
  146. public:
  147. /**
  148. * Take @a aFileName and the size of the desired line buffer and opens the file and
  149. * assumes the obligation to close it.
  150. *
  151. * @param aFileName is the name of the file to open and to use for error reporting purposes.
  152. * @param aStartingLineNumber is the initial line number to report on error, and is
  153. * accessible here for the case where multiple DSNLEXERs are reading from the
  154. * same file in sequence, all from the same open file (with @a doOwn = false).
  155. * Internally it is incremented by one after each ReadLine(), so the first
  156. * reported line number will always be one greater than what is provided here.
  157. * @param aMaxLineLength is the number of bytes to use in the line buffer.
  158. *
  159. * @throw IO_ERROR if @a aFileName cannot be opened.
  160. */
  161. FILE_LINE_READER( const wxString& aFileName, unsigned aStartingLineNumber = 0,
  162. unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX );
  163. /**
  164. * Take an open FILE and the size of the desired line buffer and takes ownership of
  165. * the open file, i.e. assumes the obligation to close it.
  166. *
  167. * @param aFile is an open file.
  168. * @param aFileName is the name of the file for error reporting purposes.
  169. * @param doOwn if true, means I should close the open file, else not.
  170. * @param aStartingLineNumber is the initial line number to report on error, and is
  171. * accessible here for the case where multiple DSNLEXERs are reading from the
  172. * same file in sequence, all from the same open file (with @a doOwn = false).
  173. * Internally it is incremented by one after each ReadLine(), so the first
  174. * reported line number will always be one greater than what is provided here.
  175. * @param aMaxLineLength is the number of bytes to use in the line buffer.
  176. */
  177. FILE_LINE_READER( FILE* aFile, const wxString& aFileName, bool doOwn = true,
  178. unsigned aStartingLineNumber = 0,
  179. unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX );
  180. /**
  181. * May or may not close the open file, depending on @a doOwn in constructor.
  182. */
  183. ~FILE_LINE_READER();
  184. char* ReadLine() override;
  185. /**
  186. * Rewind the file and resets the line number back to zero.
  187. *
  188. * Line number will go to 1 on first ReadLine().
  189. */
  190. void Rewind()
  191. {
  192. rewind( m_fp );
  193. m_lineNum = 0;
  194. }
  195. long int FileLength();
  196. long int CurPos();
  197. protected:
  198. bool m_iOwn; ///< if I own the file, I'll promise to close it, else not.
  199. FILE* m_fp; ///< I may own this file, but might not.
  200. };
  201. /**
  202. * Is a #LINE_READER that reads from a multiline 8 bit wide std::string
  203. */
  204. class STRING_LINE_READER : public LINE_READER
  205. {
  206. protected:
  207. std::string m_lines;
  208. size_t m_ndx;
  209. public:
  210. /**
  211. * Construct a string line reader.
  212. *
  213. * @param aString is a source string consisting of one or more lines
  214. * of text, where multiple lines are separated with a '\n' character.
  215. * The last line does not necessarily need a trailing '\n'.
  216. * @param aSource describes the source of aString for error reporting purposes
  217. * can be anything meaningful, such as wxT( "clipboard" ).
  218. */
  219. STRING_LINE_READER( const std::string& aString, const wxString& aSource );
  220. /**
  221. * Construct a string line reader.
  222. *
  223. * Allows for a continuation of the reading of a stream started by another
  224. * STRING_LINE_READER. Any stream offset and source name are used from
  225. */
  226. STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint );
  227. char* ReadLine() override;
  228. };
  229. /**
  230. * A #LINE_READER that reads from a wxInputStream object.
  231. */
  232. class INPUTSTREAM_LINE_READER : public LINE_READER
  233. {
  234. public:
  235. /**
  236. * Construct a #LINE_READER from a wxInputStream object.
  237. *
  238. * @param aStream A pointer to a wxInputStream object to read.
  239. * @param aSource The name of the stream source, for error reporting purposes.
  240. */
  241. INPUTSTREAM_LINE_READER( wxInputStream* aStream, const wxString& aSource );
  242. char* ReadLine() override;
  243. protected:
  244. wxInputStream* m_stream; //< The input stream to read. No ownership of this pointer.
  245. };
  246. #define OUTPUTFMTBUFZ 500 ///< default buffer size for any OUTPUT_FORMATTER
  247. /**
  248. * An interface used to output 8 bit text in a convenient way.
  249. *
  250. * The primary interface is "printf() - like" but with support for indentation control. The
  251. * destination of the 8 bit wide text is up to the implementer.
  252. * <p>
  253. * The implementer only has to implement the write() function, but can also optionally
  254. * re-implement GetQuoteChar().
  255. * <p>
  256. * If you want to output a wxString, then use TO_UTF8() on it before passing it as an
  257. * argument to Print().
  258. * <p>
  259. * Since this is an abstract interface, only classes derived from this one may actually be
  260. * used.
  261. */
  262. class OUTPUTFORMATTER
  263. {
  264. protected:
  265. OUTPUTFORMATTER( int aReserve = OUTPUTFMTBUFZ, char aQuoteChar = '"' ) :
  266. m_buffer( aReserve, '\0' )
  267. {
  268. quoteChar[0] = aQuoteChar;
  269. quoteChar[1] = '\0';
  270. }
  271. virtual ~OUTPUTFORMATTER() {}
  272. /**
  273. * Perform quote character need determination according to the Specctra DSN specification.
  274. * @param wrapee A string that might need wrapping on each end.
  275. * @param quote_char A single character C string which provides the current
  276. * quote character, should it be needed by the wrapee.
  277. *
  278. * @return the quote_char as a single character string, or "" if the wrapee does not need
  279. * to be wrapped.
  280. */
  281. static const char* GetQuoteChar( const char* wrapee, const char* quote_char );
  282. /**
  283. * Should be coded in the interface implementation (derived) classes.
  284. *
  285. * @param aOutBuf is the start of a byte buffer to write.
  286. * @param aCount tells how many bytes to write.
  287. * @throw IO_ERROR, if there is a problem outputting, such as a full disk.
  288. */
  289. virtual void write( const char* aOutBuf, int aCount ) = 0;
  290. #if defined(__GNUG__) // The GNU C++ compiler defines this
  291. // When used on a C++ function, we must account for the "this" pointer,
  292. // so increase the STRING-INDEX and FIRST-TO_CHECK by one.
  293. // See http://docs.freebsd.org/info/gcc/gcc.info.Function_Attributes.html
  294. // Then to get format checking during the compile, compile with -Wall or -Wformat
  295. #define PRINTF_FUNC __attribute__( ( format( printf, 3, 4 ) ) )
  296. #else
  297. #define PRINTF_FUNC // nothing
  298. #endif
  299. public:
  300. /**
  301. * Format and write text to the output stream.
  302. *
  303. * @param nestLevel The multiple of spaces to precede the output with.
  304. * @param fmt A printf() style format string.
  305. * @param ... a variable list of parameters that will get blended into
  306. * the output under control of the format string.
  307. * @return int - the number of characters output.
  308. * @throw IO_ERROR, if there is a problem outputting, such as a full disk.
  309. */
  310. int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... );
  311. /**
  312. * Perform quote character need determination.
  313. *
  314. * It returns the quote character as a single character string for a given input wrapee
  315. * string. If the wrappee does not need to be quoted, the return value is "" (the null
  316. * string), such as when there are no delimiters in the input wrapee string. If you want
  317. * the quote_char to be assuredly not "", then pass in "(" as the wrappee.
  318. * <p>
  319. * Implementations are free to override the default behavior, which is to call the static
  320. * function of the same name.
  321. *
  322. * @param wrapee A string that might need wrapping on each end.
  323. * @return the quote_char as a single character string, or "" if the wrapee does not need
  324. * to be wrapped.
  325. */
  326. virtual const char* GetQuoteChar( const char* wrapee ) const;
  327. /**
  328. * Check \a aWrapee input string for a need to be quoted (e.g. contains a ')' character
  329. * or a space), and for \" double quotes within the string that need to be escaped such
  330. * that the DSNLEXER will correctly parse the string from a file later.
  331. *
  332. * @param aWrapee is a string that might need wrapping in double quotes, and it might need
  333. * to have its internal content escaped, or not.
  334. * @return a std::string- whose c_str() function can be called for passing to printf()
  335. * style functions that output UTF8 encoded s-expression streams.
  336. *
  337. * @throw IO_ERROR, if there is any kind of problem with the input string.
  338. */
  339. virtual std::string Quotes( const std::string& aWrapee ) const;
  340. std::string Quotew( const wxString& aWrapee ) const;
  341. private:
  342. std::vector<char> m_buffer;
  343. char quoteChar[2];
  344. int sprint( const char* fmt, ... );
  345. int vprint( const char* fmt, va_list ap );
  346. };
  347. /**
  348. * Implement an #OUTPUTFORMATTER to a memory buffer.
  349. *
  350. * After Print()ing the string is available through GetString()
  351. */
  352. class STRING_FORMATTER : public OUTPUTFORMATTER
  353. {
  354. public:
  355. /**
  356. * Reserve space in the buffer.
  357. */
  358. STRING_FORMATTER( int aReserve = OUTPUTFMTBUFZ, char aQuoteChar = '"' ) :
  359. OUTPUTFORMATTER( aReserve, aQuoteChar )
  360. {
  361. }
  362. /**
  363. * Clear the buffer and empties the internal string.
  364. */
  365. void Clear()
  366. {
  367. m_mystring.clear();
  368. }
  369. /**
  370. * Removes whitespace, '(', and ')' from the string.
  371. */
  372. void StripUseless();
  373. const std::string& GetString()
  374. {
  375. return m_mystring;
  376. }
  377. protected:
  378. void write( const char* aOutBuf, int aCount ) override;
  379. private:
  380. std::string m_mystring;
  381. };
  382. /**
  383. * Used for text file output.
  384. *
  385. * It is about 8 times faster than STREAM_OUTPUTFORMATTER for file streams.
  386. */
  387. class FILE_OUTPUTFORMATTER : public OUTPUTFORMATTER
  388. {
  389. public:
  390. /**
  391. * @param aFileName is the full filename to open and save to as a text file.
  392. * @param aMode is what you would pass to wxFopen()'s mode, defaults to wxT( "wt" )
  393. * for text files that are to be created here and now.
  394. * @param aQuoteChar is a char used for quoting problematic strings (with whitespace or
  395. * special characters in them).
  396. * @throw IO_ERROR if the file cannot be opened.
  397. */
  398. FILE_OUTPUTFORMATTER( const wxString& aFileName, const wxChar* aMode = wxT( "wt" ),
  399. char aQuoteChar = '"' );
  400. ~FILE_OUTPUTFORMATTER();
  401. protected:
  402. void write( const char* aOutBuf, int aCount ) override;
  403. FILE* m_fp; ///< takes ownership
  404. wxString m_filename;
  405. };
  406. /**
  407. * Implement an #OUTPUTFORMATTER to a wxWidgets wxOutputStream.
  408. *
  409. * The stream is neither opened nor closed by this class.
  410. */
  411. class STREAM_OUTPUTFORMATTER : public OUTPUTFORMATTER
  412. {
  413. wxOutputStream& m_os;
  414. public:
  415. /**
  416. * This can take any number of wxOutputStream derivations, so it can write to a file,
  417. * socket, or zip file.
  418. */
  419. STREAM_OUTPUTFORMATTER( wxOutputStream& aStream, char aQuoteChar = '"' ) :
  420. OUTPUTFORMATTER( OUTPUTFMTBUFZ, aQuoteChar ),
  421. m_os( aStream )
  422. {
  423. }
  424. protected:
  425. void write( const char* aOutBuf, int aCount ) override;
  426. };
  427. #endif // RICHIO_H_