Rune Caster 1.0.0
Modern C++ Text Processing Framework
Loading...
Searching...
No Matches
case_converter.cpp
Go to the documentation of this file.
3#include <string>
4
5#ifdef RUNE_CASTER_HAS_UTFCPP
6 #include <utf8.h>
7 #include <cwctype>
8#elif defined(RUNE_CASTER_HAS_ICU)
9 #include <unicode/uchar.h>
10 #include <unicode/unistr.h>
11#endif
12
13namespace rune_caster {
14namespace spell {
15namespace core {
16
19
21 if (input.empty()) {
22 return RuneSequence();
23 }
24
25 std::string utf8_text = input.to_utf8();
26 std::string converted;
27
28 try {
29#ifdef RUNE_CASTER_HAS_UTFCPP
30 std::u32string utf32;
31 utf8::utf8to32(utf8_text.begin(), utf8_text.end(), std::back_inserter(utf32));
32 bool at_word_start = true;
33 for (char32_t cp : utf32) {
34 char32_t out = cp;
35 switch (case_type_) {
36 case CaseType::Lower:
37 out = static_cast<char32_t>(std::towlower(static_cast<wint_t>(cp)));
38 break;
39 case CaseType::Upper:
40 out = static_cast<char32_t>(std::towupper(static_cast<wint_t>(cp)));
41 break;
42 case CaseType::Title:
43 if (at_word_start)
44 out = static_cast<char32_t>(std::towupper(static_cast<wint_t>(cp)));
45 else
46 out = static_cast<char32_t>(std::towlower(static_cast<wint_t>(cp)));
47 at_word_start = unicode::is_whitespace(cp);
48 break;
49 default:
50 break;
51 }
52 utf8::append(out, std::back_inserter(converted));
53 }
54#elif defined(RUNE_CASTER_HAS_ICU)
55 // Use ICU for case conversion (placeholder implementation)
56 converted = utf8_text;
57#else
58 converted.reserve(utf8_text.size());
59 bool at_word_start = true;
60
61 for (char ch : utf8_text) {
62 switch (case_type_) {
63 case CaseType::Lower:
64 if (ch >= 'A' && ch <= 'Z') {
65 converted.push_back(ch + 32);
66 } else {
67 converted.push_back(ch);
68 }
69 break;
70 case CaseType::Upper:
71 if (ch >= 'a' && ch <= 'z') {
72 converted.push_back(ch - 32);
73 } else {
74 converted.push_back(ch);
75 }
76 break;
77 case CaseType::Title:
78 if (ch == ' ' || ch == '\t' || ch == '\n') {
79 at_word_start = true;
80 converted.push_back(ch);
81 } else if (at_word_start && ch >= 'a' && ch <= 'z') {
82 converted.push_back(ch - 32);
83 at_word_start = false;
84 } else {
85 if (ch >= 'A' && ch <= 'Z' && !at_word_start) {
86 converted.push_back(ch + 32);
87 } else {
88 converted.push_back(ch);
89 }
90 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
91 at_word_start = false;
92 }
93 }
94 break;
95 }
96 }
97#endif
98 } catch (...) {
99 converted = utf8_text;
100 }
101
102 return RuneSequence::from_utf8(converted);
103}
104
105std::string CaseConverter::description() const {
106 switch (case_type_) {
107 case CaseType::Lower:
108 return "Lowercase Conversion";
109 case CaseType::Upper:
110 return "Uppercase Conversion";
111 case CaseType::Title:
112 return "Titlecase Conversion";
113 default:
114 return "Case Conversion";
115 }
116}
117
118} // namespace core
119} // namespace spell
120} // namespace rune_caster
bool empty() const noexcept
static RuneString from_utf8(std::string_view utf8_text)
Create a RuneString from UTF-8 text.
std::string to_utf8() const
Convert the sequence to UTF-8 string.
@ Title
Convert to titlecase (first letter of each word)
std::string description() const override
Get the spell's description.
CaseType case_type() const noexcept
Get the case type of this converter.
CaseConverter(CaseType case_type)
Construct a CaseConverter.
RuneSequence operator()(const RuneSequence &input) const override
Apply the spell transformation.
constexpr bool is_whitespace(char32_t cp) noexcept
Definition unicode.hpp:72
RuneString RuneSequence
Backward compatibility alias for RuneString.
Simple and unified spell system for text transformation.