aboutsummaryrefslogblamecommitdiffstats
path: root/library/cpp/yt/string/string.cpp
blob: 6969448dc9171f718c3365ee2bddea24934bd5d0 (plain) (tree)
1
2
3
4
5
6
7
                   
                   
                                         
 
                              
 


























































                                                                                
                                                             



































                                                                                














                                                                                  
                                                                             








                                                                               
                                                 











                               
                                               



























                                                               
                                               














                                                     
                                                                                      



                                                     
                                                                                               














                                                                                




                                                                     
                                                             

















                                                                                             
                                          
                       
                                                  
                        




                     
                                
                

                                                                        









                                                                                
                  
#include "string.h"
#include "format.h"

#include <library/cpp/yt/assert/assert.h>

#include <util/generic/hash.h>

#include <util/string/ascii.h>

namespace NYT {

////////////////////////////////////////////////////////////////////////////////

void UnderscoreCaseToCamelCase(TStringBuilderBase* builder, TStringBuf str)
{
    bool first = true;
    bool upper = true;
    for (char c : str) {
        if (c == '_') {
            upper = true;
        } else {
            if (upper) {
                if (!std::isalpha(c) && !first) {
                    builder->AppendChar('_');
                }
                c = std::toupper(c);
            }
            builder->AppendChar(c);
            upper = false;
        }
        first = false;
    }
}

TString UnderscoreCaseToCamelCase(TStringBuf str)
{
    TStringBuilder builder;
    UnderscoreCaseToCamelCase(&builder, str);
    return builder.Flush();
}

void CamelCaseToUnderscoreCase(TStringBuilderBase* builder, TStringBuf str)
{
    bool first = true;
    for (char c : str) {
        if (std::isupper(c) && std::isalpha(c)) {
            if (!first) {
                builder->AppendChar('_');
            }
            c = std::tolower(c);
        }
        builder->AppendChar(c);
        first = false;
    }
}

TString CamelCaseToUnderscoreCase(TStringBuf str)
{
    TStringBuilder builder;
    CamelCaseToUnderscoreCase(&builder, str);
    return builder.Flush();
}

////////////////////////////////////////////////////////////////////////////////

TString TrimLeadingWhitespaces(const TString& str)
{
    for (int i = 0; i < static_cast<int>(str.size()); ++i) { 
        if (str[i] != ' ') {
            return str.substr(i);
        }
    }
    return "";
}

TString Trim(const TString& str, const TString& whitespaces)
{
    size_t end = str.size();
    while (end > 0) {
        size_t i = end - 1;
        bool isWhitespace = false;
        for (auto c : whitespaces) {
            if (str[i] == c) {
                isWhitespace = true;
                break;
            }
        }
        if (!isWhitespace) {
            break;
        }
        --end;
    }

    if (end == 0) {
        return "";
    }

    size_t begin = str.find_first_not_of(whitespaces);
    YT_VERIFY(begin != TString::npos);
    YT_VERIFY(begin < end);
    return str.substr(begin, end - begin);
}

////////////////////////////////////////////////////////////////////////////////

namespace {

ui16 DecimalDigits2[100] = {
    12336,  12592,  12848,  13104,  13360,  13616,  13872,  14128,  14384,  14640,
    12337,  12593,  12849,  13105,  13361,  13617,  13873,  14129,  14385,  14641,
    12338,  12594,  12850,  13106,  13362,  13618,  13874,  14130,  14386,  14642,
    12339,  12595,  12851,  13107,  13363,  13619,  13875,  14131,  14387,  14643,
    12340,  12596,  12852,  13108,  13364,  13620,  13876,  14132,  14388,  14644,
    12341,  12597,  12853,  13109,  13365,  13621,  13877,  14133,  14389,  14645,
    12342,  12598,  12854,  13110,  13366,  13622,  13878,  14134,  14390,  14646,
    12343,  12599,  12855,  13111,  13367,  13623,  13879,  14135,  14391,  14647,
    12344,  12600,  12856,  13112,  13368,  13624,  13880,  14136,  14392,  14648,
    12345,  12601,  12857,  13113,  13369,  13625,  13881,  14137,  14393,  14649
};

template <class T>
char* WriteSignedIntToBufferBackwardsImpl(char* ptr, T value, TStringBuf min)
{
    if (value == 0) {
        --ptr;
        *ptr = '0';
        return ptr;
    }

    // The negative value handling code below works incorrectly for min values.
    if (value == std::numeric_limits<T>::min()) {
        ptr -= min.length();
        ::memcpy(ptr, min.begin(), min.length());
        return ptr;
    }

    bool negative = false;
    if (value < 0) {
        negative = true;
        value = -value;
    }

    while (value >= 10) {
        i64 rem = value % 100;
        i64 quot = value / 100;
        ptr -= 2;
        ::memcpy(ptr, &DecimalDigits2[rem], 2);
        value = quot;
    }

    if (value > 0) {
        --ptr;
        *ptr = ('0' + value);
    }

    if (negative) {
        --ptr;
        *ptr = '-';
    }

    return ptr;
}

template <class T>
char* WriteUnsignedIntToBufferBackwardsImpl(char* ptr, T value)
{
    if (value == 0) {
        --ptr;
        *ptr = '0';
        return ptr;
    }

    while (value >= 10) {
        i64 rem = value % 100;
        i64 quot = value / 100;
        ptr -= 2;
        ::memcpy(ptr, &DecimalDigits2[rem], 2);
        value = quot;
    }

    if (value > 0) {
        --ptr;
        *ptr = ('0' + value);
    }

    return ptr;
}

} // namespace

template <>
char* WriteIntToBufferBackwards(char* ptr, i32 value)
{
    return WriteSignedIntToBufferBackwardsImpl(ptr, value, TStringBuf("-2147483647"));
}

template <>
char* WriteIntToBufferBackwards(char* ptr, i64 value)
{
    return WriteSignedIntToBufferBackwardsImpl(ptr, value, TStringBuf("-9223372036854775808"));
}

template <>
char* WriteIntToBufferBackwards(char* ptr, ui32 value)
{
    return WriteUnsignedIntToBufferBackwardsImpl(ptr, value);
}

template <>
char* WriteIntToBufferBackwards(char* ptr, ui64 value)
{
    return WriteUnsignedIntToBufferBackwardsImpl(ptr, value);
}

////////////////////////////////////////////////////////////////////////////////

size_t TCaseInsensitiveStringHasher::operator()(TStringBuf arg) const
{
    auto compute = [&] (char* buffer) {
        for (size_t index = 0; index < arg.length(); ++index) {
            buffer[index] = AsciiToLower(arg[index]);
        }
        return ComputeHash(TStringBuf(buffer, arg.length()));
    };
    const size_t SmallSize = 256;
    if (arg.length() <= SmallSize) {
        std::array<char, SmallSize> stackBuffer;
        return compute(stackBuffer.data());
    } else {
        std::unique_ptr<char[]> heapBuffer(new char[arg.length()]);
        return compute(heapBuffer.get());
    }
}

bool TCaseInsensitiveStringEqualityComparer::operator()(TStringBuf lhs, TStringBuf rhs) const
{
    return AsciiEqualsIgnoreCase(lhs, rhs);
}

////////////////////////////////////////////////////////////////////////////////

bool TryParseBool(TStringBuf value, bool* result)
{
    if (value == "true" || value == "1") {
        *result = true;
        return true;
    } else if (value == "false" || value == "0") {
        *result = false;
        return true;
    } else {
        return false;
    }
}

bool ParseBool(TStringBuf value)
{
    bool result;
    if (!TryParseBool(value, &result)) {
        throw TSimpleException(Format("Error parsing boolean value %Qv",
            value));
    }
    return result;
}

TStringBuf FormatBool(bool value)
{
    return value ? TStringBuf("true") : TStringBuf("false");
}

////////////////////////////////////////////////////////////////////////////////

} // namespace NYT