8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
19 module ALib.Variables;
30 if( substitutionVariableStart.
IsEmpty() )
37 int maxReplacements = 50;
41 integer repStart= orig.
IndexOf( substitutionVariableStart, searchStartIdx );
44 buf << orig.
Substring( searchStartIdx, repStart - searchStartIdx );
45 searchStartIdx = repStart;
46 integer varStart= repStart + substitutionVariableStart.
Length();
51 if ( substitutionVariableEnd.
IsEmpty() ) {
56 varLen= idx - varStart;
62 ALIB_WARNING(
"VARIABLES",
"End of substitution variable not found "
63 "(while start was found). Variable name: ",
Name(namebuf) )
67 varLen= idx - varStart;
68 searchStartIdx= idx + substitutionVariableEnd.
Length();
74 buf << substitutionVariableStart;
85 if( replVar.
Try(replVarName) )
86 replVar.
Export( buf, escaper );
93 replVar.
Export( buf, escaper );
99 while( --maxReplacements );
101 if( maxReplacements < 50) {
111 auto it= Tree<Configuration>().types.Find(typeName);
113 "No Meta-Handler found for given variable type \"{}\".\n"
114 "Probably the type was not registered during bootstrap.\n"
115 "Use macro ALIB_VARIABLES_REGISTER_TYPE in bootstrap phase "
116 "'PrepareConfig' to register your custom types.", typeName)
117 auto* meta= Cursor::Value().meta= *it;
120 Cursor::Value().data =
reinterpret_cast<detail::VDATA*
>(Tree<Configuration>().Pool().Alloc( meta->size(),
alignof(
detail::VDATA)));
121 meta->construct(Cursor::Value().data, Tree<Configuration>().Pool );
122 Cursor::Value().priority= Priority::NONE;
137 for (
int i = 0; i < Tree<Configuration>().CountPlugins(); ++i) {
138 auto& plugin= *Tree<Configuration>().GetPlugin(i);
139 auto plPrio= plugin.GetPriority();
140 if( Cursor::Value().priority <= plPrio && plugin.Get(varName, buf) ) {
142 Cursor::Value().priority= plPrio;
143 Cursor::Value().meta->imPort( Cursor::Value().data,
GetConfiguration(), plugin.GetEscaper(),
144 substitute(buf, substBuf, &plugin.GetEscaper()) );
148 auto cursor= Tree<Configuration>().Root();
149 if( cursor.GoToChild(
A_CHAR(
"$PRESETS"))
150 && cursor.GoTo(varName).IsEmpty()
151 && cursor->meta !=
nullptr )
154 "Internal error. This must never happen. ")
156 "Internal error. This must never happen. ")
158 auto* escaper= cursor->declaration ?
reinterpret_cast<const StringEscaper*
>( cursor->declaration )
160 Cursor::Value().priority= cursor->priority;
162 Cursor::Value().meta->imPort( Cursor::Value().data,
170 if( Cursor::Value().priority <= Priority::DefaultValues && defaultValue.
IsNotEmpty() ) {
173 Cursor::Value().priority= Priority::DefaultValues;
174 Cursor::Value().meta->imPort( Cursor::Value().data,
GetConfiguration(), escaper,
175 substitute( defaultValue, substBuf, &escaper) );
188 const String& defaultValue ) {
190 "Invalid Variable. Not associated with a Configuration. Probably a default constructed "
191 "instance.\nCopy or move a valid Variable object before usage.")
194 "Variable name with placeholder(s) given: ", name )
198 if( GoToCreatedPathIfNotExistent(name) == 0
199 && Cursor::Value().meta !=
nullptr )
202 auto it= Tree<Configuration>().types.Find(typeName);
203 if( it == Tree<Configuration>().types.end() ) {
205 "No Meta-Handler found for given variable type \"{}\".\n"
206 "Probably the type was not registered during bootstrap.\n"
207 "Use macro ALIB_VARIABLES_REGISTER_TYPE in bootstrap phase "
208 "'PrepareConfig' to register your custom types.", typeName )
210 if( *it != Cursor::Value().meta ) {
212 "Variable \"{}\" redeclared with a different typename.\n"
213 "Previous typename: ", Cursor::Value().meta->typeName(), typeName )
220 Cursor::Value().declaration=
nullptr;
221 create( typeName, defaultValue );
227 "Invalid Variable. Not associated with a Configuration.\n"
228 "Probably a default constructed instance.\n"
229 "Copy or move a valid Variable object before usage.")
232 "Variable descriptor \"{}\" with unset placeholders given.", decl->
Name() )
236 if( 0 == GoToCreatedPathIfNotExistent( decl->
Name() )) {
239 "Variable \"{}\" redeclared with different declaration record pointer.\n"
240 "Declaration records should be singletons and their life-time needs to survive\n"
241 "that of the variable. New record will be ignored.", decl->
Name() )
243 auto it= Tree<Configuration>().types.Find(decl->
typeName);
244 if( it == Tree<Configuration>().types.end() ) {
246 "No Meta-Handler found for given variable type \"{}\".\n"
247 "Probably the type was not registered during bootstrap.\n"
248 "Use macro ALIB_VARIABLES_REGISTER_TYPE in bootstrap phase "
249 "'PrepareConfig' to register your custom types.",
GetDeclaration()->typeName)
256 Cursor::Value().declaration= decl;
262 if( Cursor::Value().priority > requestedPriority )
264 auto prevPriority= Cursor::Value().priority;
265 Cursor::Value().priority= requestedPriority ;
279 Cursor::node=
nullptr;
284 "Invalid Variable. Not associated with a Configuration. Probably a default constructed "
285 "instance.\nCopy or move a valid Variable object before usage.")
288 if( Cursor::GoToRoot().GoTo( name ).IsEmpty()
293 auto cursor= Tree<Configuration>().Root();
294 if( cursor.GoToChild(
A_CHAR(
"$PRESETS")) && cursor.GoTo(name).IsEmpty() ) {
296 "Internal error. This must never happen.")
298 if( Cursor::Value().priority < cursor->priority) {
300 auto* escaper= cursor->declaration ?
reinterpret_cast<const StringEscaper*
>( cursor->declaration )
303 Cursor::Value().priority= cursor->priority;
304 Cursor::Value().meta->imPort( Cursor::Value().data,
318 || Cursor::Value().declaration == decl,
"CONFIG/VARDECL",
319 "Variable \"{}\" redeclared with different declaration record pointer.\n"
320 "Declaration records should be singletons and their life-time needs to survive\n"
321 "that of the variable. New record will be ignored.", decl->
Name() )
323 if( Cursor::Value().declaration==
nullptr)
324 Cursor::Value().declaration= decl;
333 "Tried to import nulled string for variable \"{}\"",
this )
constexpr integer Length() const
constexpr bool IsEmpty() const
integer IndexOf(TChar needle, integer startIdx=0) const
constexpr bool IsNotNull() const
constexpr bool IsNotEmpty() const
integer IndexOfAny(const TString &needles, integer startIdx=0) const
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
String SubstitutionVariableStart
CString SubstitutionVariableDelimiters
String SubstitutionVariableEnd
const String & DefaultValue() const
const String & TypeName() const
const String & Name() const
ALIB_DLL bool Define(Priority requestedPriority=Priority::Standard)
ALIB_DLL void Import(const String &src, Priority priority, const StringEscaper *escaper=nullptr)
AString & Export(AString &dest, const StringEscaper *escaper=nullptr) const
AString & Name(AString &target) const
void create(const String &typeName, const String &defaultValue)
Priority GetPriority() const
bool Try(const String &name)
ALIB_DLL Variable & Declare(const String &name, const String &typeName, const String &defaultValue=NULL_STRING)
const Declaration * GetDeclaration() const
Configuration & GetConfiguration() const
const String & substitute(const String &importString, AString &buf, const StringEscaper *escaper)
#define ALIB_WARNING(domain,...)
#define ALIB_ASSERT_WARNING(cond, domain,...)
#define ALIB_ERROR(domain,...)
#define ALIB_ASSERT_ERROR(cond, domain,...)
@ Include
Chooses inclusion.
strings::util::StringEscaper StringEscaper
Type alias in namespace alib.
LocalString< 512 > String512
Type alias name for TLocalString<character,512>.
LocalString< 256 > String256
Type alias name for TLocalString<character,256>.
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
strings::TSubstring< character > Substring
Type alias in namespace alib.
@ Definition
A variable was defined or re-defined with the same or a higher priority.
@ Creation
A variable was declared for the first time.