Stroika Library 3.0d23
 
Loading...
Searching...
No Matches
MessageUtilities.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#include <cctype>
7#include <locale>
8
11#include "Stroika/Foundation/Containers/Collection.h"
15
16#include "MessageUtilities.h"
17
18using namespace Stroika::Foundation;
23using namespace Stroika::Foundation::Execution;
24
25/*
26 ********************************************************************************
27 *********************************** Impl_en ************************************
28 ********************************************************************************
29 */
30bool Impl_en::AppliesToThisLocale (const locale& l) const
31{
32 return String::FromNarrowSDKString (locale{}.name ()).StartsWith (String::FromNarrowSDKString (l.name ()), eCaseInsensitive);
33 //return l.name ().find ("en") == 0;
34}
35
36pair<String, optional<String>> Impl_en::RemoveTrailingSentencePunctuation (const String& msg) const
37{
38 // super primitive (may want to trim trailing whitespace if any on msg after remove of punctuation but shouldn't be any)
39 if (msg.EndsWith ("."sv)) {
40 return {msg.SubString (0, -1), "."sv};
41 }
42 if (msg.EndsWith ("?"sv)) {
43 return {msg.SubString (0, -1), "?"sv};
44 }
45 if (msg.EndsWith ("!"sv)) {
46 return {msg.SubString (0, -1), "!"sv};
47 }
48 return {msg, nullopt};
49}
50
51String Impl_en::PluralizeNoun (const String& s, const optional<String>& sPlural, int count) const
52{
53 // Implement VERY WEAK ENGLISH rules for now... (ignores y ->ies, and other cases too)
54 if (count == 1) {
55 return s;
56 }
57 else if (sPlural) {
58 return *sPlural;
59 }
60 else {
61 StringBuilder tmp = s;
62 tmp.push_back ('s');
63 return tmp;
64 }
65}
66
67String Impl_en::MakeNounSingular (const String& s) const
68{
69 StringBuilder r = s;
70 // take an ENGLISH string and munge it so its singular (if it happened to have been plural)
71
72 // handle special case of 'wives' -> 'wife' as in 'midwives'
73 // @todo there are more like thief, and thieves
74 if (r.length () >= 5) {
75 size_t l = r.length ();
76 if (s[l - 5] == 'w' and s[l - 4] == 'i' and s[l - 3] == 'v' and s[l - 2] == 'e' and s[l - 1] == 's') {
77 r = s.substr (0, l - 3);
78 r.push_back ('f');
79 r.push_back ('e');
80 return r;
81 }
82 }
83
84 // trim trailing s from the name (if prev letter is a non-s consonant)
85 // or change 'ies' to 'y' at end
86 if (s.length () > 3) {
87 if (s[s.length () - 3] == 'i' and s[s.length () - 2] == 'e' and s[s.length () - 1] == 's') {
88 //r = s.substr (0, s.length () - 3) + "y";
89 r = s.substr (0, s.length () - 3);
90 r.push_back ('y');
91 }
92 else if (s.length () > 4 and s[s.length () - 4] == 's' and s[s.length () - 3] == 's' and s[s.length () - 2] == 'e' and s[s.length () - 1] == 's') {
93 r = s.substr (0, s.length () - 2);
94 }
95 else if (s[s.length () - 3] == 's' and s[s.length () - 2] == 'e' and s[s.length () - 1] == 's') {
96 r = s.substr (0, s.length () - 1);
97 }
98 // because of diabetes mellitus - (and others???? - don't map trailing 'us' to 'u'
99 else if (s[s.length () - 1] == 's' and s[s.length () - 2].IsASCII () and s[s.length () - 2].IsAlphabetic () and
100 (s[s.length () - 2] != 's' and s[s.length () - 2] != 'u')) {
101 r = s.substr (0, s.length () - 1);
102 }
103 }
104 return r;
105}
106
107/*
108 ********************************************************************************
109 ************************************ Manager ***********************************
110 ********************************************************************************
111 */
112Manager::Manager (const Containers::Sequence<shared_ptr<const IRep>>& utilObjs)
113 : fMessageHandlers_{utilObjs}
114{
115}
116
117shared_ptr<const IRep> Manager::LookupHandler (const locale& l) const
118{
119 optional<Common::KeyValuePair<locale, shared_ptr<const IRep>>> cachedVal = fLocaleCache_.load ();
120 if (cachedVal && cachedVal->fKey == l) {
121 return cachedVal->fValue;
122 }
123 cachedVal = [&] () -> KeyValuePair<locale, shared_ptr<const IRep>> {
124 // search here user installed ones with AddHandler ()
125 for (const shared_ptr<const IRep>& h : fMessageHandlers_.load ()) {
126 if (h->AppliesToThisLocale (l)) {
127 return {l, h};
128 }
129 }
130 // if nothing applies, return this...
131 return {l, Memory::MakeSharedPtr<Impl_en> ()};
132 }();
133 fLocaleCache_.store (cachedVal);
134 return cachedVal->fValue;
135}
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
nonvirtual size_t length() const noexcept
number of characters, not bytes or code-points
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
nonvirtual size_t length() const noexcept
Definition String.inl:1051
nonvirtual bool EndsWith(const Character &c, CompareOptions co=eWithCase) const
Definition String.cpp:1089
nonvirtual String SubString(SZ from) const
nonvirtual String substr(size_t from, size_t count=npos) const
Definition String.inl:1092
A generalization of a vector: a container whose elements are keyed by the natural numbers.