/* KLayout Layout Viewer Copyright (C) 2006-2017 Matthias Koefferlein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HDR_tlString #define HDR_tlString #include "tlCommon.h" #include #include #include #include #include "tlException.h" #include "tlVariant.h" class QImage; namespace tl { class Extractor; template void extractor_impl (tl::Extractor &, T &); template bool test_extractor_impl (tl::Extractor &, T &); /** * @brief Another string class * * The purpose of this class is to provide a different string implementation * that is optimized for special purposes. For example, the assign method * and operator does reuse memory allocated so far. This way this object is * better suited to string objects that frequently change. */ class TL_PUBLIC string { public: typedef std::allocator allocator_t; /** * @brief The default constructor */ string () : m_size (0), m_capacity (0), mp_rep (0) { // nothing yet .. } /** * @brief The constructor from a const char * */ string (const char *c); /** * @brief The constructor from a const char * taking just a substring */ string (const char *c, size_t from, size_t to); /** * @brief The copy constructor */ string (const tl::string &s); /** * @brief The copy constructor taking just a substring */ string (const tl::string &s, size_t from, size_t to); /** * @brief The constructor creating a string from a STL string */ string (const std::string &s); /** * @brief The constructor creating a string from a STL string taking just a substring */ string (const std::string &s, size_t from, size_t to); /** * @brief Destructor */ ~string (); /** * @brief The assignment from a const char * */ tl::string &operator= (const char *c); /** * @brief The assignment from a const char * taking just a substring */ void assign (const char *c, size_t from, size_t to); /** * @brief The assignment operator */ tl::string &operator= (const tl::string &s); /** * @brief The assignment taking just a substring */ void assign (const tl::string &s, size_t from, size_t to); /** * @brief The assignment from a STL string */ tl::string &operator= (const std::string &s); /** * @brief The assignment from a STL string taking just a substring */ void assign (const std::string &s, size_t from, size_t to); /** * @brief The length of the string */ size_t size () const { return m_size; } /** * @brief Reserve a certain number of characters */ void reserve (size_t n); /** * @brief The capacity of the string */ size_t capacity () const { return m_capacity; } /** * @brief Swap the string with another object */ void swap (tl::string &s) { std::swap (mp_rep, s.mp_rep); std::swap (m_size, s.m_size); } /** * @brief Equality */ bool operator== (const char *c) const; /** * @brief Equality */ bool operator== (const tl::string &s) const; /** * @brief Inequality */ bool operator!= (const char *c) const; /** * @brief Inequality */ bool operator!= (const tl::string &s) const; /** * @brief Comparison operator */ bool operator< (const char *c) const; /** * @brief Comparison operator */ bool operator< (const tl::string &s) const; /** * @brief Comparison operator */ bool operator<= (const char *c) const; /** * @brief Comparison operator */ bool operator<= (const tl::string &s) const; /** * @brief Comparison operator */ bool operator> (const char *c) const; /** * @brief Comparison operator */ bool operator> (const tl::string &s) const; /** * @brief Comparison operator */ bool operator>= (const char *c) const; /** * @brief Comparison operator */ bool operator>= (const tl::string &s) const; /** * @brief Access to "C" representation */ const char *c_str () const { return mp_rep == 0 ? "" : mp_rep; } /** * @brief Access to STL representation */ std::string std_str () const { if (mp_rep == 0) { return std::string (); } else { return std::string (mp_rep, 0, m_size); } } /** * @brief Clear the string * * Unlike assignment of an empty string, "clear" releases the memory allocated * by this object. */ void clear (); private: size_t m_size; size_t m_capacity; char *mp_rep; }; TL_PUBLIC std::string to_upper_case (const std::string &s); TL_PUBLIC std::string to_lower_case (const std::string &s); TL_PUBLIC std::string to_string (double d, int prec); TL_PUBLIC std::string to_string (float d, int prec); TL_PUBLIC std::string to_string (const unsigned char *cp, int length); TL_PUBLIC std::string to_string (const char *cp, int length); template inline std::string to_string (const T &o) { return o.to_string (); } template <> inline std::string to_string (const double &d) { return to_string (d, 12); } template <> inline std::string to_string (const float &d) { return to_string (d, 6); } template <> TL_PUBLIC std::string to_string (const int &d); template <> TL_PUBLIC std::string to_string (const unsigned int &d); template <> TL_PUBLIC std::string to_string (const long &d); template <> TL_PUBLIC std::string to_string (const unsigned long &d); template <> TL_PUBLIC std::string to_string (const long long &d); template <> TL_PUBLIC std::string to_string (const unsigned long long &d); template <> TL_PUBLIC std::string to_string (const char * const &cp); template <> TL_PUBLIC std::string to_string (char * const &cp); template <> TL_PUBLIC std::string to_string (const unsigned char * const &cp); template <> TL_PUBLIC std::string to_string (unsigned char * const &cp); template <> TL_PUBLIC std::string to_string (const bool &b); template <> inline std::string to_string (const std::string &s) { return s; } // variants utilize parsable strings because this way the string representation can be translated back // to a variant object template <> inline std::string to_string (const tl::Variant &v) { return v.to_parsable_string (); } // some dummy conversions provided for tl::Variant implementation template <> inline std::string to_string (const QImage &) { return std::string (); } /** * @brief Convert to a quoted string * * The string returned by this method can be read from a corresponding extractor with * the "read_quoted" method. */ TL_PUBLIC std::string to_quoted_string (const std::string &s); /** * @brief Escape special characters in a string * * Special characters are replaced by escape sequences with a backslash. * The format of the sequence is \xxx where x is the ocal number of the * character and \r, \n and \t representing the CR, LF and TAB character. */ TL_PUBLIC std::string escape_string (const std::string &value); /** * @brief Remove escape sequences from a string * * Special characters are replaced by escape sequences with a backslash. * The format of the sequence is \xxx where x is the ocal number of the * character and \r, \n and \t representing the CR, LF and TAB character. */ TL_PUBLIC std::string unescape_string (const std::string &value); /** * @brief Levenshtein distance * * This function computes the edit distance ("Levenshtein distance") between two strings. */ TL_PUBLIC int edit_distance (const std::string &a, const std::string &b); /** * @brief Convert to a word or quoted string * * The string returned by this method can be read from a corresponding extractor with * the "read_word_or_quoted" method with the given "non_term" characters. */ TL_PUBLIC std::string to_word_or_quoted_string (const std::string &s, const char *non_term = "_.$"); /** * @brief Escapes HTML (or XML) characters from in and adds the result to out * If "replace_newlines" is true, "\n" will be replaced by "
". */ TL_PUBLIC void escape_to_html (std::string &out, const std::string &in, bool replace_newlines = true); /** * @brief Escapes HTML (or XML) characters from in and returns the resulting string * If "replace_newlines" is true, "\n" will be replaced by "
". */ TL_PUBLIC std::string escaped_to_html (const std::string &in, bool replace_newlines = true); /** * @brief Set the number of digits resolution for a micron display */ TL_PUBLIC void set_micron_resolution (unsigned int ndigits); /** * @brief A standard method to convert a micron value into a string for display */ TL_PUBLIC std::string micron_to_string (double d); /** * @brief Set the number of digits resolution for a dbu display */ TL_PUBLIC void set_db_resolution (unsigned int ndigits); /** * @brief A standard method to convert a coordinate in database units (pixel) into a string for display */ TL_PUBLIC std::string db_to_string (double d); /** * @brief A standard method to convert a coordinate in database units (pixel) into a string for display */ inline std::string db_to_string (int32_t d) { return to_string (d); } /** * @brief A standard method to convert a coordinate in database units (pixel) into a string for display */ inline std::string db_to_string (int64_t d) { return to_string (d); } /** * @brief A generic extractor (parser) class * * This class acts like a stream of which elements can be extracted on * a character-by-character or element basis. The "stream" is initialized * with a character pointer. Then, element by element can be extracted * using the read or try_read methods. * The stream in general consumes white spaces. * It is possible to customize the extractor by overloading the error method for example. */ class TL_PUBLIC Extractor { public: struct end { }; /** * @brief Constructor * * This constructor constructs an extractor object from a const char *. * The ownership over this pointer is not passed, i.e. it must be valid * during the parsing. */ Extractor (const char *s = ""); /** * @brief Constructor * * This constructor constructs an extractor object from a string. * It will internally store a copy of the string for parsing, so it can be * passed a temporary object. */ Extractor (const std::string &str); /** * @brief Destructor */ virtual ~Extractor () { } /** * @brief Read an unsigned integer * * A helper method to implement parsers on the chararacter-by-character basis. * This method reads an unsigned integer and returns the value past the last * valid character. It skips blanks at the beginning but not at the end. * On error, an exception is thrown. * * @param cp The current pointer (is being moved) * @param value Where the value is stored */ Extractor &read (unsigned int &value); /** * @brief Read an unsigned long (see read of an unsigned int) */ Extractor &read (unsigned long &value); /** * @brief Read an unsigned long long (see read of an unsigned int) */ Extractor &read (unsigned long long &value); /** * @brief Read a double (see read of an unsigned int) */ Extractor &read (double &value); /** * @brief Read a signed int (see read of an unsigned int) */ Extractor &read (int &value); /** * @brief Read a signed long (see read of an unsigned int) */ Extractor &read (long &value); /** * @brief Read a signed long long (see read of an unsigned int) */ Extractor &read (long long &value); /** * @brief Read a boolean value (see read of an unsigned int) * * The value can be either 0 or 1 or "true" or "false". */ Extractor &read (bool &value); /** * @brief Generic extrator * * This extractor requires a adaptor to actually to the extraction. * The adaptor is a functor taking the extractor and delivering the * specified type (void tl::extractor_impl (tl::Extractor &, T &)). */ template Extractor &read (T &value) { tl::extractor_impl (*this, value); return *this; } /** * @brief Read a string (see read of an unsigned int) * * The termination character may be specified with the "term" * string: if one of the characters in this string is encountered * or the input ends, the reader stops reading. */ Extractor &read (std::string &value, const char *term = ""); /** * @brief Read a string consisting of "word" characters * * Beside letters and digits the characters given in the "non_term" array are * allowed in the word as well. */ Extractor &read_word (std::string &value, const char *non_term = "_.$"); /** * @brief Read a quoted string * * The string may be either quoted with single or double quotes. Quotes inside the string * may be escaped with a backslash character. */ Extractor &read_quoted (std::string &value); /** * @brief Read a string consisting of "word" characters or accept quoted strings * * The string may be either given in the form allowed by "read_word" (with the * non_term characters) or by "read_quoted". */ Extractor &read_word_or_quoted (std::string &value, const char *non_term = "_.$"); /** * @brief Try to read an unsigned integer * * Similar to "read" but does not throw an exception if the input is not * a valid unsigned integer. In this case, the function returns false. * * @param cp The current pointer (is being moved) * @param value Where the value is stored * @return true, if a value could be read */ bool try_read (unsigned int &value); /** * @brief Try to read a signed int (see try to read an unsigned int) */ bool try_read (int &value); /** * @brief Try to read an unsigned long (see try to read an unsigned int) */ bool try_read (unsigned long &value); /** * @brief Try to read an unsigned long long (see try to read an unsigned int) */ bool try_read (unsigned long long &value); /** * @brief Try to read a signed long (see try to read an unsigned int) */ bool try_read (long &value); /** * @brief Try to read a signed long long (see try to read an unsigned int) */ bool try_read (long long &value); /** * @brief Try to read a double (see try to read an unsigned int) */ bool try_read (double &value); /** * @brief Try to read a boolean value (see try to read an unsigned int) * * The value can be either 0 or 1 or "true" or "false". */ bool try_read (bool &value); /** * @brief Try to read a string (see try to read an unsigned int) * * The termination character may be specified with the "term" * string: if one of the characters in this string is encountered * or the input ends, the reader stops reading. */ bool try_read (std::string &string, const char *term = ""); /** * @brief Try to read a string consisting of "word" characters * * A word is a non-empty string consisting of letters, digits and the special * characters "_.$" by default. */ bool try_read_word (std::string &value, const char *non_term = "_.$"); /** * @brief Try to read a quoted string * * See "read_quoted" for details */ bool try_read_quoted (std::string &value); /** * @brief Try to read a word or a quoted string * * See "read_word_or_quoted" for details */ bool try_read_word_or_quoted (std::string &value, const char *non_term = "_.$"); /** * @brief Generic extrator * * This extractor requires a adaptor to actually to the extraction. * The adaptor is a functor taking the extractor and delivering the * specified type (void tl::test_extractor_impl (tl::Extractor &, T &)). */ template bool try_read (T &value) { return tl::test_extractor_impl (*this, value); } /** * @brief Expect a token (a certain string) * * If the token is not present, issue an error. */ Extractor &expect (const char *token); /** * @brief Expect end of the string */ Extractor &expect_end (); /** * @brief Expect more text */ Extractor &expect_more (); /** * @brief Test for a token (a certain string) * * If the token is not present, return false. */ bool test (const char *token); /** * @brief Skip blanks * * A helper method to implement parsers on the chararacter-by-character basis. * * @param cp The current pointer (is being moved) * @return The value of cp on return */ const char *skip (); /** * @brief Access to the current character */ char operator* () const { return *m_cp; } /** * @brief Access to the current position */ const char *get () const { return m_cp; } /** * @brief Increment: advance to the next character */ Extractor &operator++ () { ++m_cp; return *this; } /** * @brief Test for end of stream * * This is not really a const method since it does a "skip" to determine if we * are at the end already. */ bool at_end () { return *skip () == 0; } /** * @brief Throw an error with a context information */ virtual void error (const std::string &msg); /** * @brief Some syntactic sugar * * Allows to extract something this way: extractor >> x; */ template Extractor &operator>> (X &x) { return read (x); } /** * @brief Extract a token (constant string) */ Extractor &operator>> (const char *token) { return expect (token); } /** * @brief Expect the end of the string */ Extractor &operator>> (end) { return expect_end (); } private: const char *m_cp; std::string m_str; }; TL_PUBLIC void from_string (const std::string &s, const char * &result); TL_PUBLIC void from_string (const std::string &s, const unsigned char * &result); TL_PUBLIC void from_string (const std::string &s, double &v) throw (tl::Exception); TL_PUBLIC void from_string (const std::string &s, int &v) throw (tl::Exception); TL_PUBLIC void from_string (const std::string &s, long &v) throw (tl::Exception); TL_PUBLIC void from_string (const std::string &s, long long &v) throw (tl::Exception); TL_PUBLIC void from_string (const std::string &s, unsigned int &v) throw (tl::Exception); TL_PUBLIC void from_string (const std::string &s, unsigned long &v) throw (tl::Exception); TL_PUBLIC void from_string (const std::string &s, unsigned long long &v) throw (tl::Exception); TL_PUBLIC void from_string (const std::string &s, bool &b) throw (tl::Exception); inline void from_string (const std::string &s, std::string &v) { v = s; } template inline void from_string (const std::string &s, T &t) { tl::Extractor ex (s.c_str ()); ex.read (t); } TL_PUBLIC std::string sprintf (const char *fmt, const std::vector &a, unsigned int a0 = 0); TL_PUBLIC std::string sprintf (const std::string &fmt, const std::vector &a, unsigned int a0 = 0); inline std::string sprintf (const std::string &fmt) { std::vector a; return sprintf(fmt, a); } inline std::string sprintf (const std::string &fmt, const tl::Variant &a1) { std::vector a; a.push_back (a1); return sprintf(fmt, a); } inline std::string sprintf (const std::string &fmt, const tl::Variant &a1, const tl::Variant &a2) { std::vector a; a.push_back (a1); a.push_back (a2); return sprintf(fmt, a); } inline std::string sprintf (const std::string &fmt, const tl::Variant &a1, const tl::Variant &a2, const tl::Variant &a3) { std::vector a; a.push_back (a1); a.push_back (a2); a.push_back (a3); return sprintf(fmt, a); } inline std::string sprintf (const std::string &fmt, const tl::Variant &a1, const tl::Variant &a2, const tl::Variant &a3, const tl::Variant &a4) { std::vector a; a.push_back (a1); a.push_back (a2); a.push_back (a3); a.push_back (a4); return sprintf(fmt, a); } inline std::string sprintf (const std::string &fmt, const tl::Variant &a1, const tl::Variant &a2, const tl::Variant &a3, const tl::Variant &a4, const tl::Variant &a5) { std::vector a; a.push_back (a1); a.push_back (a2); a.push_back (a3); a.push_back (a4); a.push_back (a5); return sprintf(fmt, a); } inline std::string sprintf (const std::string &fmt, const tl::Variant &a1, const tl::Variant &a2, const tl::Variant &a3, const tl::Variant &a4, const tl::Variant &a5, const tl::Variant &a6) { std::vector a; a.push_back (a1); a.push_back (a2); a.push_back (a3); a.push_back (a4); a.push_back (a5); a.push_back (a6); return sprintf(fmt, a); } inline std::string sprintf (const std::string &fmt, const tl::Variant &a1, const tl::Variant &a2, const tl::Variant &a3, const tl::Variant &a4, const tl::Variant &a5, const tl::Variant &a6, const tl::Variant &a7) { std::vector a; a.push_back (a1); a.push_back (a2); a.push_back (a3); a.push_back (a4); a.push_back (a5); a.push_back (a6); a.push_back (a7); return sprintf(fmt, a); } TL_PUBLIC std::string trim (const std::string &s); TL_PUBLIC std::vector split (const std::string &s, const std::string &sep); TL_PUBLIC std::string join (const std::vector &strings, const std::string &sep); } // namespace tl #endif