21[[nodiscard]] std::vector<std::string> split_pascal_words(
const std::string &token)
27 std::vector<std::string> words;
28 std::string current_word;
30 for (std::size_t i = 0; i < token.size(); ++i) {
31 const char c = token[i];
33 if (std::isupper(
static_cast<unsigned char>(c))) {
39 if (!current_word.empty()) {
40 const bool prev_is_lower = i > 0 && std::islower(
static_cast<unsigned char>(token[i - 1]));
41 const bool next_is_lower =
42 i + 1 < token.size() && std::islower(
static_cast<unsigned char>(token[i + 1]));
43 if (prev_is_lower || next_is_lower) {
44 words.push_back(current_word);
48 current_word +=
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
51 current_word +=
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
55 if (!current_word.empty()) {
56 words.push_back(current_word);
68[[nodiscard]] std::vector<std::string> split_on_underscores(
const std::string &input)
70 std::vector<std::string> tokens;
73 for (
const char c : input) {
75 if (!current.empty()) {
76 tokens.push_back(current);
85 if (!current.empty()) {
86 tokens.push_back(current);
98[[nodiscard]] std::string capitalize(
const std::string &word)
103 std::string result = word;
104 result[0] =
static_cast<char>(std::toupper(
static_cast<unsigned char>(result[0])));
115void DynamicCasedName::compute_canonical()
118 for (
const auto &segment : segments_) {
119 for (
const auto &word : segment) {
125DynamicCasedName::DynamicCasedName(
const std::string &input)
131 bool has_underscore =
false;
132 bool has_uppercase =
false;
134 for (
const char c : input) {
136 has_underscore =
true;
138 if (std::isupper(
static_cast<unsigned char>(c))) {
139 has_uppercase =
true;
143 if (has_underscore && has_uppercase) {
144 *
this = from_c_identifier(input);
146 else if (has_underscore) {
147 *
this = from_snake_case(input);
149 else if (has_uppercase) {
150 *
this = from_pascal_case(input);
153 *
this = from_flat_case(input);
163 std::vector<std::string> tokens = split_on_underscores(input);
164 std::vector<std::vector<std::string>> segments;
165 segments.reserve(tokens.size());
167 for (
auto &token : tokens) {
170 lower.reserve(token.size());
171 for (
const char c : token) {
172 lower +=
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
174 segments.push_back({std::move(lower)});
186 std::vector<std::string> words = split_pascal_words(input);
191 return DynamicCasedName{std::vector<std::vector<std::string>>{std::move(words)}};
200 std::vector<std::string> tokens = split_on_underscores(input);
201 std::vector<std::vector<std::string>> segments;
202 segments.reserve(tokens.size());
204 for (
const auto &token : tokens) {
205 std::vector<std::string> words = split_pascal_words(token);
206 if (!words.empty()) {
207 segments.push_back(std::move(words));
221 lower.reserve(input.size());
222 for (
const char c : input) {
223 lower +=
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
226 return DynamicCasedName{std::vector<std::vector<std::string>>{{std::move(lower)}}};
229std::string DynamicCasedName::to_snake_case()
const
234 for (
const auto &segment : segments_) {
235 for (
const auto &word : segment) {
247std::string DynamicCasedName::to_pascal_case()
const
251 for (
const auto &segment : segments_) {
252 for (
const auto &word : segment) {
253 result += capitalize(word);
260std::string DynamicCasedName::to_c_identifier()
const
263 bool first_segment =
true;
265 for (
const auto &segment : segments_) {
266 if (!first_segment) {
269 for (
const auto &word : segment) {
270 result += capitalize(word);
272 first_segment =
false;
278std::string DynamicCasedName::to_flat_case()
const
A smart string wrapper that preserves word structure for lossless case format conversion.
std::string to_snake_case() const
Outputs all words flattened and joined with underscores.
DynamicCasedName()=default
std::string to_string(const PrimaryPairingMode m)
Converts a PrimaryPairingMode to its canonical string representation.