aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src/vcpkg_Strings.cpp
blob: 35ebcc90f36b5265e71cd0ec44a167879dc5345f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "pch.h"
#include "vcpkg_Strings.h"

namespace vcpkg::Strings::details
{
    // To disambiguate between two overloads
    static const auto isspace = [](const char c)
    {
        return std::isspace(c);
    };

    // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower()
    static char tolower_char(const char c)
    {
        return static_cast<char>(std::tolower(c));
    }

    std::string format_internal(const char* fmtstr, ...)
    {
        va_list lst;
        va_start(lst, fmtstr);

        const int sz = _vscprintf(fmtstr, lst);
        std::string output(sz, '\0');
        _vsnprintf_s(&output[0], output.size() + 1, output.size() + 1, fmtstr, lst);
        va_end(lst);

        return output;
    }

    std::wstring wformat_internal(const wchar_t* fmtstr, ...)
    {
        va_list lst;
        va_start(lst, fmtstr);

        const int sz = _vscwprintf(fmtstr, lst);
        std::wstring output(sz, '\0');
        _vsnwprintf_s(&output[0], output.size() + 1, output.size() + 1, fmtstr, lst);
        va_end(lst);

        return output;
    }
}

namespace vcpkg::Strings
{
    std::wstring utf8_to_utf16(const std::string& s)
    {
        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conversion;
        return conversion.from_bytes(s);
    }

    std::string utf16_to_utf8(const std::wstring& w)
    {
        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conversion;
        return conversion.to_bytes(w);
    }

    std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern)
    {
        const std::string pattern_as_lower_case(ascii_to_lowercase(pattern));
        return search(s.begin(), s.end(), pattern_as_lower_case.begin(), pattern_as_lower_case.end(), [](const char a, const char b)
                      {
                          return details::tolower_char(a) == b;
                      });
    }

    std::string ascii_to_lowercase(const std::string& input)
    {
        std::string output(input);
        std::transform(output.begin(), output.end(), output.begin(), &details::tolower_char);
        return output;
    }

    std::string join(const std::vector<std::string>& v, const std::string& prefix, const std::string& delimiter, const std::string& suffix)
    {
        return join(v, prefix, delimiter, suffix, [](const std::string& i) -> std::string
        {
            return i;
        });
    }

    Joiner Joiner::on(const std::string& delimiter)
    {
        return Joiner(delimiter);
    }

    Joiner& Joiner::prefix(const std::string& prefix)
    {
        this->m_prefix = prefix;
        return *this;
    }

    Joiner& Joiner::suffix(const std::string& suffix)
    {
        this->m_suffix = suffix;
        return *this;
    }

    std::string Joiner::join(const std::vector<std::string>& v) const
    {
        return Strings::join(v, this->m_prefix, this->m_delimiter, this->m_suffix);
    }

    Joiner::Joiner(const std::string& delimiter) : m_prefix(""), m_delimiter(delimiter), m_suffix("")
    {
    }

    void trim(std::string* s)
    {
        s->erase(std::find_if_not(s->rbegin(), s->rend(), details::isspace).base(), s->end());
        s->erase(s->begin(), std::find_if_not(s->begin(), s->end(), details::isspace));
    }

    std::string trimmed(const std::string& s)
    {
        auto whitespace_back = std::find_if_not(s.rbegin(), s.rend(), details::isspace).base();
        auto whitespace_front = std::find_if_not(s.begin(), whitespace_back, details::isspace);
        return std::string(whitespace_front, whitespace_back);
    }

    void trim_all_and_remove_whitespace_strings(std::vector<std::string>* strings)
    {
        for (std::string& s : *strings)
        {
            trim(&s);
        }

        strings->erase(std::remove_if(strings->begin(), strings->end(), [](const std::string& s)-> bool
                                      {
                                          return s == "";
                                      }), strings->end());
    }

    std::vector<std::string> split(const std::string& s, const std::string& delimiter)
    {
        std::vector<std::string> output;

        size_t i = 0;
        for (size_t pos = s.find(delimiter); pos != std::string::npos; pos = s.find(delimiter, pos))
        {
            output.push_back(s.substr(i, pos - i));
            i = ++pos;
        }

        // Add the rest of the string after the last delimiter, unless there is nothing after it
        if (i != s.length())
        {
            output.push_back(s.substr(i, s.length()));
        }

        return output;
    }
}