Edit

kc3-lang/angle/src/common/string_utils.cpp

Branch :

  • Show log

    Commit

  • Author : John Plate
    Date : 2021-06-11 19:12:11
    Hash : 69562546
    Message : CL: Refactor info structs and fix conformance bug - Remove variable name prefix from Info structs to be more consistent with other ANGLE structs. - Fix CL object validation check with magics, since the Mesa solution doesn't work without RTTI. - Add support for some extensions required by OpenCL 1.1 and for some optional extensions. - Fix more conformance bugs. Bug: angleproject:6015 Change-Id: I41b1c45d95059a9994f5dc78bf9b74476cc6f2d4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2956349 Commit-Queue: John Plate <jplate@google.com> Reviewed-by: Cody Northrop <cnorthrop@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/common/string_utils.cpp
  • //
    // Copyright 2015 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // string_utils:
    //   String helper functions.
    //
    
    #include "common/string_utils.h"
    
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    #include <fstream>
    #include <sstream>
    
    #include "common/platform.h"
    #include "common/system_utils.h"
    
    namespace
    {
    
    bool EndsWithSuffix(const char *str,
                        const size_t strLen,
                        const char *suffix,
                        const size_t suffixLen)
    {
        return suffixLen <= strLen && strncmp(str + strLen - suffixLen, suffix, suffixLen) == 0;
    }
    
    }  // anonymous namespace
    
    namespace angle
    {
    
    const char kWhitespaceASCII[] = " \f\n\r\t\v";
    
    std::vector<std::string> SplitString(const std::string &input,
                                         const std::string &delimiters,
                                         WhitespaceHandling whitespace,
                                         SplitResult resultType)
    {
        std::vector<std::string> result;
        if (input.empty())
        {
            return result;
        }
    
        std::string::size_type start = 0;
        while (start != std::string::npos)
        {
            auto end = input.find_first_of(delimiters, start);
    
            std::string piece;
            if (end == std::string::npos)
            {
                piece = input.substr(start);
                start = std::string::npos;
            }
            else
            {
                piece = input.substr(start, end - start);
                start = end + 1;
            }
    
            if (whitespace == TRIM_WHITESPACE)
            {
                piece = TrimString(piece, kWhitespaceASCII);
            }
    
            if (resultType == SPLIT_WANT_ALL || !piece.empty())
            {
                result.push_back(std::move(piece));
            }
        }
    
        return result;
    }
    
    void SplitStringAlongWhitespace(const std::string &input, std::vector<std::string> *tokensOut)
    {
    
        std::istringstream stream(input);
        std::string line;
    
        while (std::getline(stream, line))
        {
            size_t prev = 0, pos;
            while ((pos = line.find_first_of(kWhitespaceASCII, prev)) != std::string::npos)
            {
                if (pos > prev)
                    tokensOut->push_back(line.substr(prev, pos - prev));
                prev = pos + 1;
            }
            if (prev < line.length())
                tokensOut->push_back(line.substr(prev, std::string::npos));
        }
    }
    
    std::string TrimString(const std::string &input, const std::string &trimChars)
    {
        auto begin = input.find_first_not_of(trimChars);
        if (begin == std::string::npos)
        {
            return "";
        }
    
        std::string::size_type end = input.find_last_not_of(trimChars);
        if (end == std::string::npos)
        {
            return input.substr(begin);
        }
    
        return input.substr(begin, end - begin + 1);
    }
    
    std::string GetPrefix(const std::string &input, size_t offset, const char *delimiter)
    {
        size_t match = input.find(delimiter, offset);
        if (match == std::string::npos)
        {
            return input.substr(offset);
        }
        return input.substr(offset, match - offset);
    }
    
    std::string GetPrefix(const std::string &input, size_t offset, char delimiter)
    {
        size_t match = input.find(delimiter, offset);
        if (match == std::string::npos)
        {
            return input.substr(offset);
        }
        return input.substr(offset, match - offset);
    }
    
    bool HexStringToUInt(const std::string &input, unsigned int *uintOut)
    {
        unsigned int offset = 0;
    
        if (input.size() >= 2 && input[0] == '0' && input[1] == 'x')
        {
            offset = 2u;
        }
    
        // Simple validity check
        if (input.find_first_not_of("0123456789ABCDEFabcdef", offset) != std::string::npos)
        {
            return false;
        }
    
        std::stringstream inStream(input);
        inStream >> std::hex >> *uintOut;
        return !inStream.fail();
    }
    
    bool ReadFileToString(const std::string &path, std::string *stringOut)
    {
        std::ifstream inFile(path.c_str());
        if (inFile.fail())
        {
            return false;
        }
    
        inFile.seekg(0, std::ios::end);
        stringOut->reserve(static_cast<std::string::size_type>(inFile.tellg()));
        inFile.seekg(0, std::ios::beg);
    
        stringOut->assign(std::istreambuf_iterator<char>(inFile), std::istreambuf_iterator<char>());
        return !inFile.fail();
    }
    
    bool BeginsWith(const std::string &str, const std::string &prefix)
    {
        return strncmp(str.c_str(), prefix.c_str(), prefix.length()) == 0;
    }
    
    bool BeginsWith(const std::string &str, const char *prefix)
    {
        return strncmp(str.c_str(), prefix, strlen(prefix)) == 0;
    }
    
    bool BeginsWith(const char *str, const char *prefix)
    {
        return strncmp(str, prefix, strlen(prefix)) == 0;
    }
    
    bool BeginsWith(const std::string &str, const std::string &prefix, const size_t prefixLength)
    {
        return strncmp(str.c_str(), prefix.c_str(), prefixLength) == 0;
    }
    
    bool EndsWith(const std::string &str, const std::string &suffix)
    {
        return EndsWithSuffix(str.c_str(), str.length(), suffix.c_str(), suffix.length());
    }
    
    bool EndsWith(const std::string &str, const char *suffix)
    {
        return EndsWithSuffix(str.c_str(), str.length(), suffix, strlen(suffix));
    }
    
    bool EndsWith(const char *str, const char *suffix)
    {
        return EndsWithSuffix(str, strlen(str), suffix, strlen(suffix));
    }
    
    bool ContainsToken(const std::string &tokenStr, char delimiter, const std::string &token)
    {
        if (token.empty())
        {
            return false;
        }
        // Compare token with all sub-strings terminated by delimiter or end of string
        std::string::size_type start = 0u;
        do
        {
            std::string::size_type end = tokenStr.find(delimiter, start);
            if (end == std::string::npos)
            {
                end = tokenStr.length();
            }
            const std::string::size_type length = end - start;
            if (length == token.length() && tokenStr.compare(start, length, token) == 0)
            {
                return true;
            }
            start = end + 1u;
        } while (start < tokenStr.size());
        return false;
    }
    
    void ToLower(std::string *str)
    {
        for (char &ch : *str)
        {
            ch = static_cast<char>(::tolower(ch));
        }
    }
    
    void ToUpper(std::string *str)
    {
        for (char &ch : *str)
        {
            ch = static_cast<char>(::toupper(ch));
        }
    }
    
    bool ReplaceSubstring(std::string *str,
                          const std::string &substring,
                          const std::string &replacement)
    {
        size_t replacePos = str->find(substring);
        if (replacePos == std::string::npos)
        {
            return false;
        }
        str->replace(replacePos, substring.size(), replacement);
        return true;
    }
    
    std::vector<std::string> GetStringsFromEnvironmentVarOrAndroidProperty(const char *varName,
                                                                           const char *propertyName,
                                                                           const char *separator)
    {
        std::string environment = GetEnvironmentVarOrAndroidProperty(varName, propertyName);
        return SplitString(environment, separator, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
    }
    
    std::vector<std::string> GetCachedStringsFromEnvironmentVarOrAndroidProperty(
        const char *varName,
        const char *propertyName,
        const char *separator)
    {
        std::string environment = GetEnvironmentVarOrAndroidProperty(varName, propertyName);
        return SplitString(environment, separator, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
    }
    
    // reference name can have *.
    bool NamesMatchWithWildcard(const char *ref, const char *testName)
    {
        // Find the first * in ref.
        const char *firstWildcard = strchr(ref, '*');
    
        // If there are no wildcards, match the strings precisely.
        if (firstWildcard == nullptr)
        {
            return strcmp(ref, testName) == 0;
        }
    
        // Otherwise, match up to the wildcard first.
        size_t preWildcardLen = firstWildcard - ref;
        if (strncmp(ref, testName, preWildcardLen) != 0)
        {
            return false;
        }
    
        const char *postWildcardRef = ref + preWildcardLen + 1;
    
        // As a small optimization, if the wildcard is the last character in ref, accept the match
        // already.
        if (postWildcardRef[0] == '\0')
        {
            return true;
        }
    
        // Try to match the wildcard with a number of characters.
        for (size_t matchSize = 0; testName[matchSize] != '\0'; ++matchSize)
        {
            if (NamesMatchWithWildcard(postWildcardRef, testName + matchSize))
            {
                return true;
            }
        }
    
        return false;
    }
    
    }  // namespace angle