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