19[[nodiscard]] std::vector<std::string> split_pascal_words(
const std::string &token)
25 std::vector<std::string> words;
26 std::string current_word;
28 for (std::size_t i = 0; i < token.size(); ++i) {
29 const char c = token[i];
31 if (std::isupper(
static_cast<unsigned char>(c))) {
35 if (!current_word.empty()) {
36 const bool prev_is_lower = i > 0 && std::islower(
static_cast<unsigned char>(token[i - 1]));
37 const bool next_is_lower =
38 i + 1 < token.size() && std::islower(
static_cast<unsigned char>(token[i + 1]));
39 if (prev_is_lower || next_is_lower) {
40 words.push_back(current_word);
44 current_word +=
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
47 current_word +=
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
51 if (!current_word.empty()) {
52 words.push_back(current_word);
62[[nodiscard]] std::vector<std::string> split_on_underscores(
const std::string &input)
64 std::vector<std::string> tokens;
67 for (
const char c : input) {
69 if (!current.empty()) {
70 tokens.push_back(current);
79 if (!current.empty()) {
80 tokens.push_back(current);
90[[nodiscard]] std::string capitalize(
const std::string &word)
95 std::string result = word;
96 result[0] =
static_cast<char>(std::toupper(
static_cast<unsigned char>(result[0])));
107void DynamicCasedName::compute_canonical()
110 for (
const auto &segment : segments_) {
111 for (
const auto &word : segment) {
117DynamicCasedName::DynamicCasedName(
const std::string &input)
123 bool has_underscore =
false;
124 bool has_uppercase =
false;
126 for (
const char c : input) {
128 has_underscore =
true;
130 if (std::isupper(
static_cast<unsigned char>(c))) {
131 has_uppercase =
true;
135 if (has_underscore && has_uppercase) {
136 *
this = from_c_identifier(input);
138 else if (has_underscore) {
139 *
this = from_snake_case(input);
141 else if (has_uppercase) {
142 *
this = from_pascal_case(input);
145 *
this = from_flat_case(input);
155 std::vector<std::string> tokens = split_on_underscores(input);
156 std::vector<std::vector<std::string>> segments;
157 segments.reserve(tokens.size());
159 for (
auto &token : tokens) {
162 lower.reserve(token.size());
163 for (
const char c : token) {
164 lower +=
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
166 segments.push_back({std::move(lower)});
178 std::vector<std::string> words = split_pascal_words(input);
183 return DynamicCasedName{std::vector<std::vector<std::string>>{std::move(words)}};
192 std::vector<std::string> tokens = split_on_underscores(input);
193 std::vector<std::vector<std::string>> segments;
194 segments.reserve(tokens.size());
196 for (
const auto &token : tokens) {
197 std::vector<std::string> words = split_pascal_words(token);
198 if (!words.empty()) {
199 segments.push_back(std::move(words));
213 lower.reserve(input.size());
214 for (
const char c : input) {
215 lower +=
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
218 return DynamicCasedName{std::vector<std::vector<std::string>>{{std::move(lower)}}};
221std::string DynamicCasedName::to_snake_case()
const
226 for (
const auto &segment : segments_) {
227 for (
const auto &word : segment) {
239std::string DynamicCasedName::to_pascal_case()
const
243 for (
const auto &segment : segments_) {
244 for (
const auto &word : segment) {
245 result += capitalize(word);
252std::string DynamicCasedName::to_c_identifier()
const
255 bool first_segment =
true;
257 for (
const auto &segment : segments_) {
258 if (!first_segment) {
261 for (
const auto &word : segment) {
262 result += capitalize(word);
264 first_segment =
false;
270std::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.