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