ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
resourcecompiler.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_resources of the \aliblong.
4///
5/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8ALIB_EXPORT namespace alib::camp {
9
10#if ALIB_CAMP_RESOURCE_COMPILATION || DOXYGEN
11
12/// Error values that the function #"LoadResourceFile" may return.
14 OK, ///< No error.
15 RCFileNotFoundOrAccessible, ///< Error opening the resource file.
16 ErrIllegalResourceName, ///< Resource name contains illegal characters. Allowed are ASCII
17 ///< characters \c 33 and \c 35-\c 127.
18 ErrNameTooLong, ///< Resource name exceeds the maximum allowed length of 511
19 ///< characters.
20 ErrLineEndWhileInQuotes, ///< Line ends while inside quotes.
21 DuplicateResourceName, ///< A duplicate resource name was found.
22
23 CPPFileNotFoundOrAccessible, ///< Error opening the cpp file to patch.
24 CPPFileMissingStartMarker, ///< Missing start marker in the cpp file to patch.
25 CPPFileMissingEndMarker, ///< Missing end marker in the cpp file to patch.
26 CPPFileNotWritable, ///< Error writing the cpp file to patch.
27};
28
29/// Represents an error that occurred with the function #"LoadResourceFile".
31 /// The resource key (identifier).
33
34 /// The line number in the resource file where this error occurred.
35 int LineNo =0;
36
37 /// The column number in the resource file where this error occurred.
38 int ColNo =0;
39
40 /// A line number in the resource file where this error also relates to.
41 int LineNo2 =0;
42
43 /// Additional error information. Set as follows:
44 /// - With #"ResourceFileErrors::RCFileNotFoundOrAccessible", contains the file name.
45 /// - With #"ResourceFileErrors::DuplicateResourceName", contains the resource name.
46 /// - With #"ResourceFileErrors::ErrIllegalResourceName", contains the ascii code of the
47 /// character.
49};
50
51
52/// Represents a single resource entry loaded from an <c>.alibrc</c> resource file.
53/// This structure stores the key-value pair along with its source location for diagnostic purposes.
55 NString Key; ///< The resource key (identifier).
56 String Value; ///< The resource value (content).
57 int LineNo; ///< The line number in the resource file where this entry was found.
58};
59
60/// A collection of resource entries, typically loaded from an <c>.alibrc</c> file.
62
63/// A list of errors that occurred with #"LoadResourceFile".
65
66/// Patches a C++ source file with generated resource loading code.
67///
68/// This function updates a designated section in a C++ source file by replacing the content
69/// between two marker comments with generated code that loads resources via
70/// #"ResourcePool::BootstrapBulk;2".
71///
72/// The file given with \p cppFilePath must contain two commented marker lines:
73/// - <c>ALIB-RESOURCE-COMPILER-REPLACEMENT-START</c>
74/// - <c>ALIB-RESOURCE-COMPILER-REPLACEMENT-END</c>
75///
76/// All lines between these markers are replaced with generated key/value pairs formatted
77/// as C++ string literals suitable for #"ResourcePool::BootstrapBulk;2".
78///
79/// The generated code includes:
80/// - Properly escaped string literals for both keys and values
81/// - Multi-line values broken into readable segments
82/// - Aligned formatting for better readability
83///
84/// For an example of the generated output, see #"F;App/sample.cpp;2".
85///
86/// \see This method is typically called by #"DevtimeResourceCompiler::Do;2".
87///
88/// @param cppFilePath The path to the C++ source file to patch.
89/// @param resources The list of resources to generate code for.
90/// @param errors A list receiving errors that might occur.
91/// @param dryRun If given as \c true, the file is not written.
92ALIB_DLL void PatchCPPFile( const Path& cppFilePath,
94 RCErrorList& errors,
95 bool dryRun= false );
96
97
98/// Reads an external resource file (`.alibrc`) and appends parsed resources to \p destination.
99///
100/// ## Syntax Overview
101/// Each resource entry starts at a non-empty, non-comment line:
102///
103/// ```text
104/// <Key> [=] <Value>
105/// ```
106///
107/// - **Key**
108/// - A sequence of printable ASCII characters (code 33..127), excluding `"` (double quote).
109/// - Ends at whitespace or at `=` (if present).
110///
111/// - Optional **`=`**
112/// - Whitespace may surround it:
113/// - `Key Value`
114/// - `Key=Value`
115/// - `Key = Value`
116///
117/// - **Comments**
118/// - A line whose first non-whitespace characters are `#` or `//` is ignored.
119///
120/// ## Value Types
121///
122/// 1. **Quoted**: starts with <c>'"'</c>.
123/// - Supports backslash escapes (e.g. <c>'\\n'</c>, <c>'\\t'</c>, <c>'\\\\'</c>, <c>'\\"'</c>,
124/// ...).
125/// - Preserves spaces and tabs inside the quotes.
126///
127/// 2. **Plain**: anything else on the same line.
128/// - Everything until end-of-line becomes the value (trailing whitespace is trimmed).
129/// - Backslash escapes are processed.
130///
131/// 3. **Block scalars**: start with <c>'|'</c> or <c>'>'</c> (must appear as the first
132/// non-whitespace of the value)
133/// - `Key |` <c>Literal block: preserves newlines.
134/// - `Key >` <c>Folded block</c>: converts line breaks to single spaces, except that empty lines
135/// create paragraph breaks (<c>'\n'</c>).
136/// - Block content starts on the next line and is terminated by a non-empty line whose indentation
137/// is **not greater** than the indentation of the key line. (Empty lines are always part of the block.)
138/// - Backslash escapes are processed in the block content.
139/// - Trailing empty lines are ignored; i.e., trailing <c>'\\n'</c> characters are stripped from
140/// the parsed value. To enforce trailing newlines, use explicit escape sequences at the end
141/// of the last content line.
142///
143/// 4. **Compact scalars**: start with <c>'~'</c>
144/// - Intended for machine-parsed token streams (e.g. `a,1,b,2,...`) that should be
145/// human-formattable in the resource file.
146/// - Outside quoted portions, <b>all whitespace is ignored</b> (including newlines in the
147/// block form).
148/// - Quoted portions are allowed and preserve whitespace:
149/// <c>DateC ~1,now,"1.1.2026",1,,2,file,1,filename,"my file"</c>
150/// - Two forms:
151/// - <c>Key ~</c> : compact until end-of-line.
152/// - <c>Key ~|</c> : compact block (indented), lines may be wrapped/aligned freely.
153/// - Backslash escapes are processed (inside and outside quotes).
154///
155/// @param rcFileName The path to the <c>.alibrc</c> input file.
156/// @param destination The destination vector to receive parsed resource entries.
157/// @param errors A list receiving read errors.
158ALIB_DLL void LoadResourceFile( Path& rcFileName, ResourceList& destination,
159 RCErrorList& errors );
160
161/// Writes a given list of errors (usually generated with function #"LoadResourceFile") to the
162/// given \p{output} in a human-readable format.
163/// @param errors The error list.
164/// @param output The output formatter.
165/// @param fileName The name of the resource file.
166ALIB_DLL void ListErrors( RCErrorList& errors, Paragraphs& output, const PathString& fileName);
167
168#endif // ALIB_CAMP_RESOURCE_COMPILATION || DOXYGEN
169
170/// Manages the compilation of externalized resources from <c>.alibrc</c> files into C++ source code.
171///
172/// This class provides a development-time mechanism to:
173/// 1. Parse human-readable <c>.alibrc</c> resource files
174/// 2. Register the resources in a \alibcamp's resource pool
175/// 3. Generate C++ source code that hard-codes the resources for production builds
176///
177/// This class operates only when the configuration macro #"ALIB_CAMP_RESOURCE_COMPILATION" is set.
178/// Otherwise, the class is an almost empty stub.
179/// This approach allows a two-phase workflow:
180///
181/// <b>Development Phase:</b>
182/// - Resources are defined in editable <c>.alibrc</c> text files
183/// - The compiler parses these files at program startup
184/// - Generated C++ code is written to designated source files
185/// - Changes to resources are immediately reflected
186///
187/// <b>Production Phase:</b>
188/// - The symbol #"ALIB_CAMP_RESOURCE_COMPILATION" is unset
189/// - Resources are loaded from the generated C++ code
190/// - No file I/O or parsing occurs at runtime
191/// - The <c>.alibrc</c> files are not needed for distribution
192///
193/// The compiler uses file modification timestamps to determine when re-compilation is needed.
194/// If the target C++ file is newer than the <c>.alibrc</c> file (with 10ms tolerance), no action
195/// is taken.
196///
197/// \see
198/// - Method #"DevtimeResourceCompiler::Do" for the main entry point.
199/// - File #"F;App/sample.cpp;2" for a complete usage example.
200/// - Chapter #"alib_camp_rc" of the Programmer's Manual of module \alibcamp_nl.
202 protected:
203 #if ALIB_CAMP_RESOURCE_COMPILATION || DOXYGEN
204 /// The allocator to use. Created only in case resources are to be compiled (and a C++ file
205 /// is to be patched).
206 MonoAllocator* ma =nullptr;
207 #endif
208
209 public:
210 #if ALIB_CAMP_RESOURCE_COMPILATION || DOXYGEN
211 /// Destructor. This is empty if the symbol #"ALIB_CAMP_RESOURCE_COMPILATION" is not set.
213
214 /// Main entry point for resource compilation.
215 ///
216 /// This method performs the complete resource compilation workflow:
217 /// 1. Resolves file paths (relative paths are resolved against \p CallingFile's directory)
218 /// 2. Checks file modification timestamps to avoid unnecessary recompilation
219 /// 3. Parses the <c>.alibrc</c> resource file
220 /// 4. Registers all resources in the given camp's resource pool
221 /// 5. Generates C++ code and patches the target source file
222 ///
223 /// **File Path Resolution:**
224 /// - Both \p AlibrcFileName and \p CppFileName may be relative or absolute paths
225 /// - Relative paths are resolved against the directory containing \p CallingFile
226 /// - Typically, pass <c>__FILE__</c> as \p CallingFile to resolve relative to the calling source
227 ///
228 /// **Timestamp-Based Compilation:**
229 /// - Compares modification times of <c>.alibrc</c> and <c>.cpp</c> files
230 /// - If the C++ file is newer (with 10ms tolerance), no action is taken
231 /// - Returns <c>false</c> to indicate no compilation occurred
232 ///
233 /// **Target File Requirements:**
234 /// The C++ file specified by \p CppFileName must contain two marker comments:
235 /// \code
236 /// // ALIB-RESOURCE-COMPILER-REPLACEMENT-START
237 /// ... generated code will replace this section ...
238 /// // ALIB-RESOURCE-COMPILER-REPLACEMENT-END
239 /// \endcode
240 ///
241 /// All lines between these markers are replaced with generated resource loading code.
242 /// The markers themselves are preserved.
243 ///
244 /// **Conditional Compilation:**
245 /// When #"ALIB_CAMP_RESOURCE_COMPILATION" is not set, this method becomes a no-op
246 /// and always returns <c>false</c>.
247 ///
248 /// **Example Usage:**
249 /// \snippet{lineno} "App/sample.cpp" DOX_ALIB_SAMPLE_RESOURCE_COMPILER
250 ///
251 /// For the corresponding <c>.alibrc</c> file format, see manual section
252 /// #"alib_camp_rc_rc_fileformat"..<br>
253 /// For the generated output, see the replacement section in #"F;App/sample.cpp;2".
254 ///
255 /// @param alibrcFileName Path to the input <c>.alibrc</c> resource file.
256 /// @param callingFile Reference file for resolving relative paths
257 /// (typically <c>__FILE__</c>).
258 /// @param campInstance The \alibcamp instance whose resource pool receives the
259 /// resources.
260 /// @param resourceCategory The resource category name for registering resources.
261 /// @param allowReplacements Determines whether overriding existing resource-keys should
262 /// raise an \alib_assertion.
263 /// @param cppFileName Path to the target C++ source file to be patched.
264 /// If an empty string is given, then the resource file will be
265 /// loaded in any case and resources will be added.
266 /// @return
267 /// <c>true</c> if resources were compiled and the C++ file was updated successfully,
268 /// <c>false</c> if compilation was skipped (file already up-to-date), an error occurred,
269 /// or #"ALIB_CAMP_RESOURCE_COMPILATION" is not set.
270 ALIB_DLL bool Do( const NString& alibrcFileName,
271 const NString& callingFile,
272 Camp& campInstance,
273 const NString& resourceCategory,
274 bool allowReplacements,
275 const NString& cppFileName );
276 #else
277 bool Do(const NString&, const NString&, Camp&, const NString&, bool, const NString&)
278 { return false; }
279 #endif
280};
281
282} // namespace [alib::camp]
#define ALIB_DLL
#define ALIB_EXPORT
bool Do(const NString &alibrcFileName, const NString &callingFile, Camp &campInstance, const NString &resourceCategory, bool allowReplacements, const NString &cppFileName)
~DevtimeResourceCompiler()
Destructor. This is empty if the symbol #"ALIB_CAMP_RESOURCE_COMPILATION" is not set.
void LoadResourceFile(Path &rcFileName, ResourceList &destination, RCErrorList &errors)
void ListErrors(RCErrorList &errors, Paragraphs &output, const PathString &fileName)
StdVectorMA< ResourceListEntry > ResourceList
A collection of resource entries, typically loaded from an .alibrc file.
void PatchCPPFile(const Path &cppFilePath, const ResourceList &resources, RCErrorList &errors, bool dryRun=false)
ResourceFileErrors
Error values that the function #"LoadResourceFile" may return.
@ ErrLineEndWhileInQuotes
Line ends while inside quotes.
@ CPPFileMissingEndMarker
Missing end marker in the cpp file to patch.
@ CPPFileNotFoundOrAccessible
Error opening the cpp file to patch.
@ CPPFileMissingStartMarker
Missing start marker in the cpp file to patch.
@ RCFileNotFoundOrAccessible
Error opening the resource file.
@ CPPFileNotWritable
Error writing the cpp file to patch.
@ DuplicateResourceName
A duplicate resource name was found.
StdVectorMA< ResourceFileError > RCErrorList
A list of errors that occurred with #"LoadResourceFile".
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
strings::TString< nchar > NString
Type alias in namespace #"%alib".
Definition string.hpp:2174
boxing::Box Box
Type alias in namespace #"%alib".
Definition box.hpp:1128
strings::TString< character > String
Type alias in namespace #"%alib".
Definition string.hpp:2165
system::Path Path
Type alias in namespace #"%alib".
Definition path.hpp:417
strings::TString< PathCharType > PathString
The string-type used with this ALib Module.
Definition path.hpp:34
format::Paragraphs Paragraphs
Type alias in namespace #"%alib".
std::vector< T, StdMA< T > > StdVectorMA
Type alias in namespace #"%alib".
Represents an error that occurred with the function #"LoadResourceFile".
ResourceFileErrors ErrorCode
The resource key (identifier).
int LineNo2
A line number in the resource file where this error also relates to.
int ColNo
The column number in the resource file where this error occurred.
int LineNo
The line number in the resource file where this error occurred.
NString Key
The resource key (identifier).
String Value
The resource value (content).
int LineNo
The line number in the resource file where this entry was found.