winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

AppInstallerStrings.h (12660B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #pragma once
      4 #include <filesystem>
      5 #include <ostream>
      6 #include <string>
      7 #include <string_view>
      8 #include <vector>
      9 #include <winget/LocIndependent.h>
     10 
     11 namespace AppInstaller::Utility
     12 {
     13     // Converts the given UTF16 string to UTF8
     14     std::string ConvertToUTF8(std::wstring_view input);
     15 
     16     // Converts the given UTF8 string to UTF16
     17     std::wstring ConvertToUTF16(std::string_view input, UINT codePage = CP_UTF8);
     18 
     19     // Tries to convert the given UTF8 string to UTF16
     20     std::optional<std::wstring> TryConvertToUTF16(std::string_view input, UINT codePage = CP_UTF8);
     21 
     22     // Converts the given UTF8 string to UTF32
     23     std::u32string ConvertToUTF32(std::string_view input);
     24 
     25     // Normalizes a UTF8 string to the given form.
     26     std::string Normalize(std::string_view input, NORM_FORM form = NORM_FORM::NormalizationKC);
     27 
     28     // Normalizes a UTF16 string to the given form.
     29     std::wstring Normalize(std::wstring_view input, NORM_FORM form = NORM_FORM::NormalizationKC);
     30 
     31     // Replaces any embedded null character found within the string.
     32     void ReplaceEmbeddedNullCharacters(std::string& s, char c = ' ');
     33 
     34     // Type to hold and force a normalized UTF8 string.
     35     // Also enables further normalization by replacing embedded null characters with spaces.
     36     template <NORM_FORM Form = NORM_FORM::NormalizationKC, bool ConvertEmbeddedNullToSpace = false>
     37     struct NormalizedUTF8 : public std::string
     38     {
     39         NormalizedUTF8() = default;
     40 
     41         template <size_t Size>
     42         NormalizedUTF8(const char(&s)[Size]) { AssignValue(std::string_view{ s, (s[Size - 1] == '\0' ? Size - 1 : Size) }); }
     43 
     44         NormalizedUTF8(std::string_view sv) { AssignValue(sv); }
     45 
     46         NormalizedUTF8(std::string& s) { AssignValue(s); }
     47         NormalizedUTF8(const std::string& s) { AssignValue(s); }
     48         NormalizedUTF8(std::string&& s) { AssignValue(s); }
     49 
     50         NormalizedUTF8(std::wstring_view sv) { AssignValue(sv); }
     51 
     52         NormalizedUTF8(const NormalizedUTF8& other) = default;
     53         NormalizedUTF8& operator=(const NormalizedUTF8& other) = default;
     54 
     55         NormalizedUTF8(NormalizedUTF8&& other) = default;
     56         NormalizedUTF8& operator=(NormalizedUTF8&& other) = default;
     57 
     58         template <size_t Size>
     59         NormalizedUTF8& operator=(const char(&s)[Size])
     60         {
     61             AssignValue(std::string_view{ s, (s[Size - 1] == '\0' ? Size - 1 : Size) });
     62             return *this;
     63         }
     64 
     65         NormalizedUTF8& operator=(std::string_view sv)
     66         {
     67             AssignValue(sv);
     68             return *this;
     69         }
     70 
     71         NormalizedUTF8& operator=(const std::string& s)
     72         {
     73             AssignValue(s);
     74             return *this;
     75         }
     76 
     77         NormalizedUTF8& operator=(std::string&& s)
     78         {
     79             AssignValue(s);
     80             return *this;
     81         }
     82 
     83     private:
     84         void AssignValue(std::string_view sv)
     85         {
     86             assign(Normalize(sv, Form));
     87 
     88             if constexpr (ConvertEmbeddedNullToSpace)
     89             {
     90                 ReplaceEmbeddedNullCharacters(*this);
     91             }
     92         }
     93 
     94         void AssignValue(std::wstring_view sv)
     95         {
     96             assign(ConvertToUTF8(Normalize(sv, Form)));
     97 
     98             if constexpr (ConvertEmbeddedNullToSpace)
     99             {
    100                 ReplaceEmbeddedNullCharacters(*this);
    101             }
    102         }
    103     };
    104 
    105     using NormalizedString = NormalizedUTF8<NORM_FORM::NormalizationKC, true>;
    106 
    107     // Compares the two UTF8 strings in a case-insensitive manner.
    108     // Use this if one of the values is a known value, and thus ToLower is sufficient.
    109     bool CaseInsensitiveEquals(std::string_view a, std::string_view b);
    110 
    111     // Compares the two UTF16 strings in a case-insensitive manner.
    112     // Use this if one of the values is a known value, and thus ToLower is sufficient.
    113     bool CaseInsensitiveEquals(std::wstring_view a, std::wstring_view b);
    114 
    115     // Returns if a UTF8 string is contained within a vector in a case-insensitive manner.
    116     bool CaseInsensitiveContains(const std::vector<std::string_view>& a, std::string_view b);
    117 
    118     // Determines if string a starts with string b. UTF8.
    119     // Use this if one of the values is a known value, and thus ToLower is sufficient.
    120     bool CaseInsensitiveStartsWith(std::string_view a, std::string_view b);
    121 
    122     // Determines if string a starts with string b. UTF16.
    123     // Use this if one of the values is a known value, and thus ToLower is sufficient.
    124     bool CaseInsensitiveStartsWith(std::wstring_view a, std::wstring_view b);
    125 
    126     // Determines if string a contains string b.
    127     // Use this if one of the values is a known value, and thus ToLower is sufficient.
    128     bool CaseInsensitiveContainsSubstring(std::string_view a, std::string_view b);
    129 
    130     // Compares the two UTF8 strings in a case-insensitive manner, using ICU for case folding.
    131     bool ICUCaseInsensitiveEquals(std::string_view a, std::string_view b);
    132 
    133     // Determines if string a starts with string b, using ICU for case folding.
    134     bool ICUCaseInsensitiveStartsWith(std::string_view a, std::string_view b);
    135 
    136     // Returns the number of grapheme clusters (characters) in an UTF8-encoded string.
    137     size_t UTF8Length(std::string_view input);
    138 
    139     // Returns the number of units the UTF8-encoded string will take in terminal output. Some characters take 2 units in terminal output.
    140     size_t UTF8ColumnWidth(const NormalizedUTF8<NormalizationC>& input);
    141 
    142     // Returns a substring view in an UTF8-encoded string. Offset and count are measured in grapheme clusters (characters).
    143     std::string_view UTF8Substring(std::string_view input, size_t offset, size_t count);
    144 
    145     // Returns a substring view in an UTF8-encoded string trimmed to be at most expected length. Length is measured as units taken in terminal output.
    146     // Note the returned substring view might be less than specified length as some characters might take 2 units in terminal output.
    147     std::string UTF8TrimRightToColumnWidth(const NormalizedUTF8<NormalizationC>&, size_t expectedWidth, size_t& actualWidth);
    148 
    149     // Get the lower case version of the given std::string
    150     std::string ToLower(std::string_view in);
    151 
    152     // Get the lower case version of the given std::wstring
    153     std::wstring ToLower(std::wstring_view in);
    154 
    155     // Folds the case of the given std::string
    156     // See https://unicode-org.github.io/icu/userguide/transforms/casemappings.html#case-folding
    157     std::string FoldCase(std::string_view input);
    158 
    159     // Folds the case of the given NormalizedString, returning it as also Normalized
    160     // See https://unicode-org.github.io/icu/userguide/transforms/casemappings.html#case-folding
    161     NormalizedString FoldCase(const NormalizedString& input);
    162 
    163     // Checks if the input string is empty or whitespace
    164     bool IsEmptyOrWhitespace(std::string_view str);
    165     bool IsEmptyOrWhitespace(std::wstring_view str);
    166 
    167     // Find token in the input string and replace with value.
    168     // Returns a value indicating whether a replacement occurred.
    169     bool FindAndReplace(std::string& inputStr, std::string_view token, std::string_view value);
    170 
    171     // Replaces the token in the input string with value while copying to a new result.
    172     std::wstring ReplaceWhileCopying(std::wstring_view input, std::wstring_view token, std::wstring_view value);
    173 
    174     // Removes whitespace from the beginning and end of the string.
    175     std::string& Trim(std::string& str);
    176     std::string Trim(std::string&& str);
    177 
    178     // Removes whitespace from the beginning and end of the string.
    179     std::wstring& Trim(std::wstring& str);
    180 
    181     // Reads the entire stream into a string.
    182     std::string ReadEntireStream(std::istream& stream);
    183 
    184     // Reads the entire stream into a byte array.
    185     std::vector<std::uint8_t> ReadEntireStreamAsByteArray(std::istream& stream);
    186 
    187     // Expands environment variables within the input.
    188     std::wstring ExpandEnvironmentVariables(const std::wstring& input);
    189 
    190     // Converts the candidate path part into one suitable for the actual file system
    191     std::string MakeSuitablePathPart(std::string_view candidate);
    192 
    193     // Splits the file name part off of the given URI.
    194     std::pair<std::string, std::filesystem::path> SplitFileNameFromURI(std::string_view uri);
    195 
    196     // Gets the file name part of the given URI.
    197     std::filesystem::path GetFileNameFromURI(std::string_view uri);
    198 
    199     // Splits the string into words.
    200     std::vector<std::string> SplitIntoWords(std::string_view input);
    201 
    202     // Splits the string into lines.
    203     // Drops empty lines.
    204     std::vector<std::string> SplitIntoLines(std::string_view input, size_t maximum = 0);
    205 
    206     // Removes lines from the vector (and/or characters from the last line) so that it contains the maximum number of lines.
    207     // Returns true if changes were made, false if not.
    208     bool LimitOutputLines(std::vector<std::string>& lines, size_t lineWidth, size_t maximum);
    209 
    210     // Converts a container to a string representation of it.
    211     template <typename T, typename U>
    212     std::string ConvertContainerToString(const T& container, U toString)
    213     {
    214         std::ostringstream strstr;
    215         strstr << '[';
    216 
    217         bool firstItem = true;
    218         for (const auto& item : container)
    219         {
    220             if (firstItem)
    221             {
    222                 firstItem = false;
    223             }
    224             else
    225             {
    226                 strstr << ", ";
    227             }
    228 
    229             strstr << toString(item);
    230         }
    231 
    232         strstr << ']';
    233         return strstr.str();  // We need C++20 to get std::move(strstr).str() to extract the string from inside the stream
    234     }
    235 
    236     template <typename T>
    237     std::string ConvertContainerToString(const T& container)
    238     {
    239         return ConvertContainerToString(container, [](const auto& item) { return item; });
    240     }
    241 
    242     template <typename CharType>
    243     std::basic_string<CharType> StringOrEmptyIfNull(const CharType* string)
    244     {
    245         if (string)
    246         {
    247             return { string };
    248         }
    249         else
    250         {
    251             return {};
    252         }
    253     }
    254 
    255     // Converts the given bytes into a hexadecimal string.
    256     std::string ConvertToHexString(const std::vector<uint8_t>& buffer, size_t byteCount = 0);
    257 
    258     // Converts the given hexadecimal string into bytes.
    259     std::vector<uint8_t> ParseFromHexString(const std::string& value, size_t byteCount = 0);
    260 
    261     // Join a string vector using the provided separator.
    262     LocIndString Join(LocIndView separator, const std::vector<LocIndString>& vector);
    263 
    264     // Join a string vector using the provided separator.
    265     std::string Join(std::string_view separator, const std::vector<std::string>& vector);
    266 
    267     // Splits the string using the provided separator. Entries can also be trimmed.
    268     std::vector<std::string> Split(const std::string& input, char separator, bool trim = false);
    269 
    270     // Format an input string by replacing placeholders {index} with provided values at corresponding indices.
    271     // Note: After upgrading to C++20, this function should be deprecated in favor of std::format.
    272     template <typename ... T>
    273     std::string Format(std::string inputStr, T ... args)
    274     {
    275         int index = 0;
    276         (FindAndReplace(inputStr, "{" + std::to_string(index++) + "}", (std::ostringstream() << args).str()),...);
    277         return inputStr;
    278     }
    279 
    280     // Converts the given boolean value to a string.
    281     std::string_view ConvertBoolToString(bool value);
    282 
    283     // Converts the given GUID value to a string.
    284     std::string ConvertGuidToString(const GUID& value);
    285 
    286     // Creates a new GUID and returns the string value.
    287     std::wstring CreateNewGuidNameWString();
    288 
    289     // Converts the input string to a DWORD value using std::stoul and returns a boolean value based on the resulting DWORD value.
    290     bool IsDwordFlagSet(const std::string& value);
    291 
    292     // Finds the next control code index that would be replaced.
    293     // Returns std::string::npos if not found.
    294     size_t FindControlCodeToConvert(std::string_view input, size_t offset = 0);
    295 
    296     // Converts most control codes in the input to their corresponding control picture in the output.
    297     // Exempts tab, line feed, and carriage return from being replaced.
    298     std::string ConvertControlCodesToPictures(std::string_view input);
    299 
    300     // Generates a random alpha numeric string.
    301     std::string GetRandomString(size_t size = 8);
    302 }