Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Atom.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_DataExchange_Atom_h_
5#define _Stroika_Foundation_DataExchange_Atom_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <compare>
10
13#include "Stroika/Foundation/Common/Concepts.h"
14
15/**
16 * \file
17 *
18 * TODO:
19 * @todo Very weak (performance), first draft implementation of AtomManager_Default.
20 *
21 * Instead, store a linked list of BLOBs - and for each BLOB keep
22 * a map<> of strings in each BLOB.
23 *
24 * Use that to fairly quickly and cheaply lookup (Intern).
25 * Then change ptrdiff_t to be the pointer to the actual string.
26 *
27 * @todo Better document and define having AtomManagers with custom arenas.
28 */
29
31
32 using Characters::String;
33
34 /**
35 * Default is single global registry. Implement using compact storage - with strings allocated
36 * in memory blocks next to one another (not full string objects)
37 * and then return String_Constant objects that point into it.
38 *
39 * like block allocation - gains in performance due to not ever having to free anything
40 *
41 * @todo - CLEANUP DOCS
42 *
43 * \note \em Thread-Safety <a href="Thread-Safety.md#Internally-Synchronized-Thread-Safety">Internally-Synchronized-Thread-Safety</a>
44 */
46 using AtomInternalType = ptrdiff_t;
47 static constexpr AtomInternalType kEmpty = -1;
48 // This API must accept an empty string as argument and return kEmpty
49 static AtomInternalType Intern (const String& s);
50 // if given kEmpty, Extract will return an empty String{} object
51 static String Extract (AtomInternalType atomI);
52 };
53
54 /*
55 *
56 * \note \em Thread-Safety <a href="Thread-Safety.md#Internally-Synchronized-Thread-Safety">Internally-Synchronized-Thread-Safety</a>
57 */
58 struct AtomManager_CaseInsensitive {
59 using AtomInternalType = ptrdiff_t;
60 static constexpr AtomInternalType kEmpty = -1;
61 static AtomInternalType Intern (const String& s);
62 static String Extract (AtomInternalType atomI);
63 };
64
65 /**
66 * \brief An Atom is like a String, except that its much cheaper to copy/store/compare, and the semantics of compare are queer
67 *
68 * An Atom is a wrapper on an underlying String object. You can always extract the original String.
69 *
70 * The name 'atom' comes from LISP, and how it represented symbol names.
71 *
72 * An Atom is much cheaper to copy/store and compare than a String. However - note that the compare is NOT the same as
73 * the traditional string compare. One Atom is equal to another IFF the underlying Strings would be
74 * equal. But the < behavior is very arbitrary. The only guarantee is that its consistent for the lifetime
75 * of the ATOM_MANAGER.
76 *
77 * Note converting a String to an Atom maybe expensive, but if you can store the values as Atoms, future lookups
78 * with something like a hashtable can be much faster.
79 *
80 * Atom can even be used with Set_Bitstring () – esp if you don’t use generic Atom<> but one with its own custom arena!
81 *
82 * \em Design Choice:
83 * In some ways, this could be more powerful if the Atom construction took a ATOM_MANAGER as parameter.
84 * Then we could store the pointer, and do wholesale clearing / throwing away of atom names. But to make
85 * that work would have a lot of cost (always passing in extra param to construction), and
86 * tracking that pointer in each atom instance (would have to use shared_ptr to manage lifetimes or somehow
87 * assure lifetimes of atoms longer than their owning manager.
88 *
89 * That might make sense todo, but would have a lot of cost. It COULD be done in the future (this API would then
90 * just be a type specialization).
91 *
92 * But that's not where we start.
93 *
94 * \em Extending Atom type and funky Managers
95 *
96 * In HealthFrame, we use 'atoms' for user-defined strings, but specially formatted strings
97 * like C00013044, or H342341 are concepts. Also - the objects returned internally are concepts.
98 *
99 * This fits perfectly. You can use:
100 * struct AtomManager_Concepts {
101 * typedef ConceptKey AtomInternalType;
102 * static constexpr Concept kEmpty = ConceptKey();
103 * static AtomInternalType Intern (const String& s);
104 * static String Extract (AtomInternalType atomI);
105 * };
106 *
107 * and then use for
108 *
109 * struct Concept : Atom<AtomManager_Concepts> {
110 * // just constructors /forwarding
111 * Concept () = default;
112 * Concept (const String& s) = default;
113 * Concept (const Concept& concept) = default;
114 * Concept (const ConceptKey& concept) = default;
115 *
116 * // and access concept key
117 * inline ConceptKey GetConceptKey () const { return _GetInternalRep (); }
118 * };
119 *
120 * AtomManager_Concepts::Intern () just indirects to AtomManager_Default::Intern () and
121 * then differently, and Extract() can look at the fields of the concept key and either
122 * algorithmically generate a name or indirect to AtomManager_Default::Extract ();
123 *
124 * @see Microsoft.net String::Intern () - http://msdn.microsoft.com/en-us/library/system.string.intern(v=vs.110).aspx
125 *
126 * \note <a href="Design-Overview.md#Comparisons">Comparisons</a>:
127 * o Standard Stroika Comparison support (operator<=>,operator==, etc);
128 *
129 * Atom's are compared in a way that will NOT in general be the same as print name compare.
130 * In general, their comparison will persist for app lifetime.
131 */
132 template <typename ATOM_MANAGER = AtomManager_Default>
133 class Atom {
134 public:
135 using AtomInternalType = typename ATOM_MANAGER::AtomInternalType;
136
137 public:
138 /**
139 * with the Atom (AtomInternalType) CTOR, we \pre the value already be interned in the ATOM_MANAGER.
140 */
141 constexpr Atom () noexcept;
142 template <Characters::IConvertibleToString STRING_LIKE>
143 Atom (STRING_LIKE&& src);
144 constexpr Atom (const Atom& src) noexcept = default;
145 constexpr Atom (AtomInternalType src) noexcept;
146
147 public:
148 /**
149 */
150 nonvirtual Atom& operator= (Atom&& rhs) = default;
151 nonvirtual Atom& operator= (const Atom& rhs) = default;
152
153 public:
154 /**
155 */
156 nonvirtual String GetPrintName () const;
157
158 public:
159 /**
160 */
161 nonvirtual strong_ordering operator<=> (const Atom& rhs) const;
162
163 public:
164 /**
165 */
166 nonvirtual bool operator== (const Atom& rhs) const;
167
168 public:
169 /**
170 * This corresponds to an empty string. An 'empty' Atom can be constructed with:
171 * \code
172 * Atom<> a1;
173 * Atom<> a2 = "";
174 * \endcode
175 */
176 nonvirtual constexpr bool empty () const;
177
178 public:
179 /**
180 * Set the state to empty
181 */
182 nonvirtual void clear ();
183
184 public:
185 /**
186 * Template on <T> only defined for
187 * T == String
188 * T == wstring
189 * AtomInternalType
190 */
191 template <Common::IAnyOf<String, wstring, typename ATOM_MANAGER::AtomInternalType> T>
192 nonvirtual T As () const;
193
194 public:
195 /**
196 * @see Characters::ToString ();
197 */
198 nonvirtual String ToString () const;
199
200 private:
201 template <typename T>
202 struct type_ {};
203
204 template <typename T>
205 nonvirtual T As_ (type_<T>) const;
206 nonvirtual String As_ (type_<String>) const;
207 nonvirtual wstring As_ (type_<wstring>) const;
208 nonvirtual AtomInternalType As_ (type_<AtomInternalType>) const;
209
210 protected:
211 /**
212 */
213 nonvirtual AtomInternalType _GetInternalRep () const;
214
215 private:
216 AtomInternalType fValue_;
217 };
218
219}
220
221/*
222 ********************************************************************************
223 ***************************** Implementation Details ***************************
224 ********************************************************************************
225 */
226#include "Atom.inl"
227
228#endif /*_Stroika_Foundation_DataExchange_Atom_h_*/
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
An Atom is like a String, except that its much cheaper to copy/store/compare, and the semantics of co...
Definition Atom.h:133
nonvirtual String ToString() const
Definition Atom.inl:79
nonvirtual constexpr bool empty() const
Definition Atom.inl:43