diff options
Diffstat (limited to 'source/core')
| -rw-r--r-- | source/core/slang-list.h | 2 | ||||
| -rw-r--r-- | source/core/slang-string-escape-util.cpp | 43 | ||||
| -rw-r--r-- | source/core/slang-string-escape-util.h | 16 | ||||
| -rw-r--r-- | source/core/slang-string-util.cpp | 100 | ||||
| -rw-r--r-- | source/core/slang-string-util.h | 6 |
5 files changed, 162 insertions, 5 deletions
diff --git a/source/core/slang-list.h b/source/core/slang-list.h index 08d9aa773..4420cc084 100644 --- a/source/core/slang-list.h +++ b/source/core/slang-list.h @@ -351,7 +351,7 @@ namespace Slang void growToCount(Index count) { - Index newBufferCount = Index(1) << Math::Log2Ceil(count); + Index newBufferCount = Index(1) << Math::Log2Ceil((unsigned int)count); if (m_capacity < newBufferCount) { reserve(newBufferCount); diff --git a/source/core/slang-string-escape-util.cpp b/source/core/slang-string-escape-util.cpp index a91d88e05..ffc43a7cb 100644 --- a/source/core/slang-string-escape-util.cpp +++ b/source/core/slang-string-escape-util.cpp @@ -18,6 +18,8 @@ public: virtual bool isQuotingNeeded(const UnownedStringSlice& slice) SLANG_OVERRIDE { return isEscapingNeeded(slice); } virtual bool isEscapingNeeded(const UnownedStringSlice& slice) SLANG_OVERRIDE; + virtual bool isUnescapingNeeeded(const UnownedStringSlice& slice) SLANG_OVERRIDE; + virtual SlangResult appendEscaped(const UnownedStringSlice& slice, StringBuilder& out) SLANG_OVERRIDE; virtual SlangResult appendUnescaped(const UnownedStringSlice& slice, StringBuilder& out) SLANG_OVERRIDE; virtual SlangResult lexQuoted(const char* cursor, const char** outCursor) SLANG_OVERRIDE; @@ -30,6 +32,13 @@ bool SpaceStringEscapeHandler::isEscapingNeeded(const UnownedStringSlice& slice) return slice.indexOf(' ') >= 0; } +bool SpaceStringEscapeHandler::isUnescapingNeeeded(const UnownedStringSlice& slice) +{ + SLANG_UNUSED(slice); + // As it stands we never have to unescape + return false; +} + SlangResult SpaceStringEscapeHandler::appendUnescaped(const UnownedStringSlice& slice, StringBuilder& out) { if (slice.indexOf('"') >= 0) @@ -98,6 +107,7 @@ public: virtual bool isQuotingNeeded(const UnownedStringSlice& slice) SLANG_OVERRIDE { SLANG_UNUSED(slice); return true; } virtual bool isEscapingNeeded(const UnownedStringSlice& slice) SLANG_OVERRIDE; + virtual bool isUnescapingNeeeded(const UnownedStringSlice& slice) SLANG_OVERRIDE; virtual SlangResult appendEscaped(const UnownedStringSlice& slice, StringBuilder& out) SLANG_OVERRIDE; virtual SlangResult appendUnescaped(const UnownedStringSlice& slice, StringBuilder& out) SLANG_OVERRIDE; virtual SlangResult lexQuoted(const char* cursor, const char** outCursor) SLANG_OVERRIDE; @@ -167,6 +177,12 @@ static char _getCppUnescapedChar(char c) } } + +bool CppStringEscapeHandler::isUnescapingNeeeded(const UnownedStringSlice& slice) +{ + return slice.indexOf('\\') >= 0; +} + /* static */bool CppStringEscapeHandler::isEscapingNeeded(const UnownedStringSlice& slice) { const char* cur = slice.begin(); @@ -456,6 +472,7 @@ public: virtual bool isQuotingNeeded(const UnownedStringSlice& slice) SLANG_OVERRIDE { SLANG_UNUSED(slice); return true; } virtual bool isEscapingNeeded(const UnownedStringSlice& slice) SLANG_OVERRIDE; + virtual bool isUnescapingNeeeded(const UnownedStringSlice& slice) SLANG_OVERRIDE; virtual SlangResult appendEscaped(const UnownedStringSlice& slice, StringBuilder& out) SLANG_OVERRIDE; virtual SlangResult appendUnescaped(const UnownedStringSlice& slice, StringBuilder& out) SLANG_OVERRIDE; virtual SlangResult lexQuoted(const char* cursor, const char** outCursor) SLANG_OVERRIDE; @@ -463,6 +480,11 @@ public: JSONStringEscapeHandler() : Super('"') {} }; +bool JSONStringEscapeHandler::isUnescapingNeeeded(const UnownedStringSlice& slice) +{ + return slice.indexOf('\\') >= 0; +} + bool JSONStringEscapeHandler::isEscapingNeeded(const UnownedStringSlice& slice) { const char* cur = slice.begin(); @@ -868,6 +890,23 @@ StringEscapeUtil::Handler* StringEscapeUtil::getHandler(Style style) } } +/* static */bool StringEscapeUtil::isQuoted(char quoteChar, UnownedStringSlice& slice) +{ + const Index len = slice.getLength(); + return len >= 2 && slice[0] == quoteChar && slice[len - 1] == quoteChar; +} + +/* static */UnownedStringSlice StringEscapeUtil::unquote(char quoteChar, const UnownedStringSlice& slice) +{ + const Index len = slice.getLength(); + if (len >= 2 && slice[0] == quoteChar && slice[len - 1] == quoteChar) + { + return UnownedStringSlice(slice.begin() + 1, len - 2); + } + SLANG_ASSERT(!"Not quoted!"); + return UnownedStringSlice(); +} + /* static */SlangResult StringEscapeUtil::appendMaybeUnquoted(Handler* handler, const UnownedStringSlice& slice, StringBuilder& out) { const char quoteChar = handler->getQuoteChar(); @@ -885,6 +924,10 @@ StringEscapeUtil::Handler* StringEscapeUtil::getHandler(Style style) } } +/* static */SlangResult StringEscapeUtil::isUnescapeShellLikeNeeded(Handler* handler, const UnownedStringSlice& slice) +{ + return slice.indexOf(handler->getQuoteChar()) >= 0; +} /* static */SlangResult StringEscapeUtil::unescapeShellLike(Handler* handler, const UnownedStringSlice& slice, StringBuilder& out) { diff --git a/source/core/slang-string-escape-util.h b/source/core/slang-string-escape-util.h index c3039eb47..5f749c423 100644 --- a/source/core/slang-string-escape-util.h +++ b/source/core/slang-string-escape-util.h @@ -14,6 +14,9 @@ public: 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; @@ -57,6 +60,14 @@ struct StringEscapeUtil /// 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); } + /// If quoting is needed appends to out quoted static SlangResult appendMaybeQuoted(Handler* handler, const UnownedStringSlice& slice, StringBuilder& out); @@ -69,6 +80,11 @@ struct StringEscapeUtil /// 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); }; diff --git a/source/core/slang-string-util.cpp b/source/core/slang-string-util.cpp index 7a142f643..b2886c413 100644 --- a/source/core/slang-string-util.cpp +++ b/source/core/slang-string-util.cpp @@ -458,9 +458,31 @@ ComPtr<ISlangBlob> StringUtil::createStringBlob(const String& string) } } -SLANG_FORCE_INLINE static bool _isDigit(char c) +/* static */SlangResult StringUtil::parseDouble(const UnownedStringSlice& text, double& out) { - return (c >= '0' && c <= '9'); + const Index bufSize = 32; + + const auto len = text.getLength(); + + if (len > bufSize - 1) + { + List<char> work; + work.setCount(len + 1); + char* dst = work.getBuffer(); + + ::memcpy(dst, text.begin(), len * sizeof(char)); + dst[len] = 0; + + out = atof(dst); + } + else + { + char buf[bufSize]; + ::memcpy(buf, text.begin(), len * sizeof(char)); + buf[len] = 0; + out = atof(buf); + } + return SLANG_OK; } /* static */SlangResult StringUtil::parseInt(const UnownedStringSlice& in, Int& outValue) @@ -476,7 +498,7 @@ SLANG_FORCE_INLINE static bool _isDigit(char c) } // We need at least one digit - if (cur >= end || !_isDigit(*cur)) + if (cur >= end || !CharUtil::isDigit(*cur)) { return SLANG_FAIL; } @@ -486,7 +508,7 @@ SLANG_FORCE_INLINE static bool _isDigit(char c) for (; cur < end; ++cur) { const char c = *cur; - if (!_isDigit(c)) + if (!CharUtil::isDigit(c)) { return SLANG_FAIL; } @@ -499,4 +521,74 @@ SLANG_FORCE_INLINE static bool _isDigit(char c) return SLANG_OK; } +/* static */SlangResult StringUtil::parseInt64(const UnownedStringSlice& text, int64_t& out) +{ + bool negate = false; + + const char* cur = text.begin(); + const char* end = text.end(); + + if (cur < end) + { + if (*cur == '-') + { + negate = true; + cur++; + } + else if (*cur == '+') + { + cur++; + } + } + + // Must have at least one digit + if (cur >= end || !CharUtil::isDigit(*cur)) + { + return SLANG_FAIL; + } + + uint64_t value = 0; + // We can have 20 digits, but the last digit can cause overflow. + // Lets do the easy first digits first + Index numSimple = 19; + for (; cur < end && CharUtil::isDigit(*cur) && numSimple > 0; ++cur, --numSimple) + { + value = value * 10 + (*cur - '0'); + } + + if (cur < end && CharUtil::isDigit(*cur)) + { + const auto prevValue = value; + value = value * 10 + (*cur - '0'); + cur++; + + if (value < prevValue) + { + // We have overflow + return SLANG_FAIL; + } + } + + if (negate) + { + if (value > ~((~uint64_t(0)) >> 1)) + { + // Overflow + return SLANG_FAIL; + } + out = -int64_t(value); + } + else + { + if (value > ((~uint64_t(0)) >> 1)) + { + // Overflow + return SLANG_FAIL; + } + out = value; + } + + return (cur == end) ? SLANG_OK : SLANG_FAIL; +} + } // namespace Slang diff --git a/source/core/slang-string-util.h b/source/core/slang-string-util.h index 2b30120b7..6a0794082 100644 --- a/source/core/slang-string-util.h +++ b/source/core/slang-string-util.h @@ -100,6 +100,12 @@ struct StringUtil /// Convert in to int. Returns SLANG_FAIL on error static SlangResult parseInt(const UnownedStringSlice& in, Int& outValue); + + /// Convert ioText into double. Returns SLANG_OK on success. + static SlangResult parseDouble(const UnownedStringSlice& text, double& out); + + /// Convert into int64_t. Returns SLANG_OK on success. + static SlangResult parseInt64(const UnownedStringSlice& text, int64_t& out); }; /* A helper class that allows parsing of lines from text with iteration. Uses StringUtil::extractLine for the actual underlying implementation. */ |
