summaryrefslogtreecommitdiff
path: root/goldfishlocale.h
blob: c9448c13b3f84cdab41754d2ba0ee8140e502b70 (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
// 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 <stddef.h>

#include <string>
#include <string_view>

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<char*>(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