#ifndef SLANG_CORE_STRING_ESCAPE_UTIL_H #define SLANG_CORE_STRING_ESCAPE_UTIL_H #include "slang-list.h" #include "slang-string.h" namespace Slang { class StringEscapeHandler { public: /// True if quoting is needed virtual bool isQuotingNeeded(const UnownedStringSlice& slice) = 0; /// True if any escaping is needed. If not slice can be used (assuming appropriate quoting) as /// is virtual bool isEscapingNeeded(const UnownedStringSlice& slice) = 0; /// True if we need to unescape virtual bool isUnescapingNeeeded(const UnownedStringSlice& slice) = 0; /// Takes slice and adds any appropriate escaping (for example C++/C type escaping for special /// characters like '\', '"' and if not ascii will write out as hex sequence) Does not append /// quotes virtual SlangResult appendEscaped(const UnownedStringSlice& slice, StringBuilder& out) = 0; /// Given a slice append it unescaped /// Does not consume surrounding quotes virtual SlangResult appendUnescaped(const UnownedStringSlice& slice, StringBuilder& out) = 0; /// Lex quoted text. /// The first character of cursor should be the quoteCharacter. /// cursor points to the string to be lexed - must typically be 0 terminated. /// outCursor on successful lex will be at the next character after was processed. virtual SlangResult lexQuoted(const char* cursor, const char** outCursor) = 0; SLANG_FORCE_INLINE char getQuoteChar() const { return m_quoteChar; } StringEscapeHandler(char quoteChar) : m_quoteChar(quoteChar) { } protected: const char m_quoteChar; }; /* A set of function that can be used for escaping/unescaping quoting/unquoting strings. The distinction between 'escaping' and 'quoting' here, is just that escaping is the 'payload' of quotes. In *principal* the Style can determine different styles of escaping that can be used. */ struct StringEscapeUtil { typedef StringEscapeHandler Handler; enum class Style { Cpp, ///< Cpp style quoting and escape handling Space, ///< Applies quotes if there are spaces. Does not escape. JSON, ///< Json encoding Slang, ///< Slang style string encoding (For now same as Cpp but that may change in the ///< future) CountOf, }; /// Given a style returns a handler static Handler* getHandler(Style style); /// Get without quotes. Will assert if not correctly quoted static UnownedStringSlice unquote(char quoteChar, const UnownedStringSlice& slice); static UnownedStringSlice unquote(Handler* handler, const UnownedStringSlice& slice) { return unquote(handler->getQuoteChar(), slice); } /// True is slice is quoted static bool isQuoted(char quoteChar, UnownedStringSlice& slice); static bool isQuoted(Handler* handler, UnownedStringSlice& slice) { return isQuoted(handler->getQuoteChar(), slice); } /// Given a command line arg slice, if it is quoted, unquotes it, else returns the slice as is. static UnownedStringSlice maybeUnquoteCommandLineArg(UnownedStringSlice slice); /// If quoting is needed appends to out quoted static SlangResult appendMaybeQuoted( Handler* handler, const UnownedStringSlice& slice, StringBuilder& out); /// If the slice appears to be quoted for the style, unquote it, else just append to out static SlangResult appendMaybeUnquoted( Handler* handler, const UnownedStringSlice& slice, StringBuilder& out); /// Appends to out slice without quotes static SlangResult appendUnquoted( Handler* handler, const UnownedStringSlice& slice, StringBuilder& out); /// Append with quotes (even if not needed) static SlangResult appendQuoted( Handler* handler, const UnownedStringSlice& slice, StringBuilder& out); /// True if requires 'shell-like' unescape. With shell-like, quoting does *not* have to start at /// the start of the slice. and there may be multiple quoted section static SlangResult isUnescapeShellLikeNeeded(Handler* handler, const UnownedStringSlice& slice); /// Shells can have multiple quoted sections. This function makes a string with out quoting static SlangResult unescapeShellLike( Handler* handler, const UnownedStringSlice& slice, StringBuilder& out); static String escapeString(UnownedStringSlice input, Style style = Style::Slang); static String unescapeString(UnownedStringSlice input, Style style = Style::Slang); }; } // namespace Slang #endif // SLANG_CORE_STRING_ESCAPE_UTIL_H