// Copyright 2022 Benjamin Barenblat // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy of // the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. // This is goldfishlocale, a library to help you get your terminal output // encoded correctly. Use it like this: // // int main(int argc, char* argv[]) { // goldfishlocale::SetLocaleFromEnvironment(); // call this once // std::cout << goldfishlocale::ToSystem(u8"These are “curly quotes”.\n"); // } // // Running this on most terminals will produce // // These are “curly quotes”. // // On terminals that lack curly quote characters, this will gracefully degrade // to // // These are "curly quotes". // // rather than // // These are 窶彡urly quotes窶� // // or something similarly unexpected. // // LIBRARY ASSUMPTION: Goldfishlocale assumes your system's locale is set once // (by goldfishlocale) and does not change during program execution. In // practice, this means you should not call std::locale::global or setlocale(3). // By default, goldfishlocale detects and throws on locale changes; however, // this detection does carry a runtime cost, so it's disabled if you define // NDEBUG. #include #include #include namespace goldfishlocale_internal { std::string ToSystem(char*, size_t); } // namespace goldfishlocale_internal namespace goldfishlocale { // Initializes goldfishlocale based on your environment. After this call // returns, the C and C++ libraries are aware of the system locale; this may // affect some behavior, including the way numbers and dates are formatted. // // This function must be called exactly once during the execution of your // program, ideally near the start of main. // // Your program must be single-threaded at the time this function is called. // Having multiple threads executing triggers undefined behavior. void SetLocaleFromEnvironment(); // Converts the specified string to the system locale. Assumes a UTF-8 encoding. inline std::string ToSystem(std::string s) { return goldfishlocale_internal::ToSystem(s.data(), s.size()); } inline std::string ToSystem(std::string_view s) { return ToSystem(std::string(s)); } inline std::string ToSystem(const char s[]) { return ToSystem(std::string(s)); } #if defined(__cpp_char8_t) && defined(__cpp_lib_char8_t) // Converts the specified string to the system locale. inline std::string ToSystem(std::u8string s) { return goldfishlocale_internal::ToSystem(reinterpret_cast(s.data()), s.size()); } inline std::string ToSystem(std::u8string_view s) { return ToSystem(std::u8string(s)); } inline std::string ToSystem(const char8_t s[]) { return ToSystem(std::u8string(s)); } #endif // defined(__cpp_char8_t) && defined(__cpp_lib_char8_t) } // namespace goldfishlocale