TOML.Helper.pas is an auxiliary unit that provides a simplified and user-friendly API for working with TOML configuration files. This unit extends the functionality of TTOMLTable and TTOMLArray classes through Class Helper technology, without modifying the original class definitions.
Key Features:
- ✅ Type-safe read/write methods
- ✅ Default value support
- ✅ Exception-safe (won't crash)
- ✅ Fluent builder pattern
- ✅ Overwrite protection mechanism
- ✅ File and string operations
- ✅ High-precision floating-point support
- ✅ High-precision date/time support
- ✅ Dot-separated path access
- ✅ Bidirectional conversion with JSON format
All get-style read methods provide default value support, ensuring the program won't crash due to missing keys.
GetStr(const Key: string; const DefaultValue: string = ''): string;Function: Retrieve string value with dot-separated path support
Examples:
// Basic usage
title := Config.GetStr('title', 'Untitled');
// Nested path
owner := Config.GetStr('database.owner', 'admin');
// Quoted key (for keys containing dots)
site := Config.GetStr('"google.com"', 'unknown');GetInt(const Key: string; const DefaultValue: Int64 = 0): Int64;Examples:
port := Config.GetInt('server.port', 8080);
timeout := Config.GetInt('timeout', 30);GetFloat(const Key: string; const DefaultValue: Double = 0.0): Double;Examples:
pi := Config.GetFloat('math.pi', 3.14159);
rate := Config.GetFloat('conversion.rate', 1.0);Preserves exact representation from TOML file, such as "3.14", "6.626e-34", "inf"
GetFloatValue(const Key: string; const DefaultValue: String = ''): String;GetBool(const Key: string; const DefaultValue: Boolean = False): Boolean;Examples:
debug := Config.GetBool('debug', False);
enabled := Config.GetBool('features.logging', True);GetDateTime(const Key: string; const DefaultValue: TDateTime = 0): TDateTime;Examples:
lastModified := Config.GetDateTime('metadata.modified', Now);GetDateTimeValue(const Key: string; const DefaultValue: String = ''): String;Function: Returns raw datetime string, preserving microsecond/nanosecond precision
Examples:
// Read high-precision timestamp
timestamp := Config.GetDateTimeValue('created_at', '');
// Returns: "1979-05-27T00:32:00.999999Z" (preserves microseconds)Use Cases:
- Timestamps requiring microsecond/nanosecond precision
- Preserving original ISO 8601 format
- Logging and time synchronization
All TryGet methods provide exception-safe access, indicating success or failure through return values.
TryGetStr(const Key: string; out Value: string): Boolean;Examples:
var
name: string;
begin
if Config.TryGetStr('user.name', name) then
WriteLn('User: ', name)
else
WriteLn('User name not found');
end;TryGetInt(const Key: string; out Value: Integer): Boolean;Examples:
var
port: Integer;
begin
if Config.TryGetInt('server.port', port) then
Server.Port := port
else
Server.Port := 8080; // Default port
end;TryGetStr- StringTryGetInt- IntegerTryGetFloat- FloatTryGetFloatValue- High-precision floatTryGetBool- BooleanTryGetDateTime- DateTimeTryGetDateTimeValue- High-precision datetimeTryGetArray- ArrayTryGetTable- Table
Advantages:
- ✅ No exception handling mechanism (better performance)
- ✅ Clear success/failure indication
- ✅ Suitable for scenarios requiring distinction between "non-existent" and "empty"
All Set methods support overwrite control to prevent accidental overwriting of existing configuration items.
SetStr(const Key: string; const Value: string;
Overwrite: Boolean = True): Boolean;Parameters:
Key- Key name (path not supported)Value- String valueOverwrite- Whether to overwrite existing value (default True)
Return Value:
True- Value has been setFalse- Key exists and Overwrite=False
Examples:
// Set or overwrite
if Config.SetStr('title', 'MyApp', True) then
WriteLn('Title set');
// Protected mode: only set if key doesn't exist
if Config.SetStr('title', 'Default', False) then
WriteLn('Set new title')
else
WriteLn('Title already exists, not overwritten');SetStr(Key, Value, Overwrite)- StringSetInt(Key, Value, Overwrite)- IntegerSetFloat(Key, Value, Overwrite)- FloatSetFloatValue(key, Value, Overwrite)- High-precision floatSetBool(Key, Value, Overwrite)- BooleanSetDateTime(Key, Value, Overwrite)- DateTimeSetDateTimeValue(key, value, Overwrite)- High-precision datetimeSetArray(Key, Value, Overwrite)- ArraySetTable(Key, Value, Overwrite)- Table
Use Cases:
// Scenario 1: Set default configuration
Config.SetInt('port', 8080, False); // Only set if doesn't exist
Config.SetStr('host', '0.0.0.0', False); // Don't overwrite user config
// Scenario 2: Batch update with failure detection
var Success := True;
Success := Success and Config.SetStr('name', Name, True);
Success := Success and Config.SetInt('age', Age, True);
if not Success then
ShowMessage('Configuration update failed');Put methods support method chaining, providing an elegant configuration building approach.
Put(const Key: string; const Value: <Type>;
Overwrite: Boolean = True): TTOMLTable;Supported Types:
string- StringInt64,Integer- IntegerDouble- FloatBoolean- BooleanTDateTime- DateTimeTTOMLArray- ArrayTTOMLTable- Table
Examples:
// Fluent method chaining
Config := TTOMLTable.e;
Config.Put('app_name', 'MyApp')
.Put('version', '1.0.0')
.Put('port', 8080)
.Put('debug', False)
.Put('max_connections', 100);
// Chaining with overwrite control
Config.Put('width', 1920, True) // Overwrite
.Put('height', 1080, False) // Don't overwrite
.Put('title', 'App', True);
// Building nested structures
var Server := TTOMLTable.e;
Server.Put('host', 'localhost')
.Put('port', 3000);
Config.Put('server', Server)
.Put('timeout', 30);Advantages:
- ✅ Concise and readable code
- ✅ Reduces temporary variables
- ✅ Modern configuration library API style
- ✅ Supports overwrite control
CreateFromFile(const FileName: string; APreserveComments: Boolean = False): TTOMLTable;Parameters:
FileName- File pathAPreserveComments- Whether to read annotations (default False)
LoadFromFile(const FileName: string; ClearExisting: Boolean = True;
APreserveComments: Boolean = False): Boolean;Parameters:
FileName- File pathClearExisting- Whether to clear existing content (default True)APreserveComments- Whether to read annotations (default False)
Return Value:
True- Load successfulFalse- Load failed
Examples:
Config := TTOMLTable.Create;
try
if Config.LoadFromFile('config.toml') then
WriteLn('Configuration loaded successfully')
else
WriteLn('Configuration load failed');
finally
Config.Free;
end;SaveToFile(const FileName: string; WriteBOM: Boolean = True; AWrapWidth: Integer = 0;
APreserveComments: Boolean = False): Boolean;Parameters:
FileName- File pathWriteBOM- Whether to write UTF-8 BOM (default True)AWrapWidth- The line break position when the string is too long. The default value is 0, meaning no line break.- Note: If the string value contains \n, it will be automatically split into a multi-line string.
APreserveComments- Whether to write comments (default False) Examples:
if Config.SaveToFile('config.toml', True) then
WriteLn('Save successful')
else
WriteLn('Save failed');CreateFromString(const ATOML: string; APreserveComments: Boolean = False): TTOMLTable;parameter:
ATOML- TOML string.APreserveComments- Whether to read annotations (default False)
LoadFromString(const ATOML: string; ClearExisting: Boolean = True;
APreserveComments: Boolean = False): Boolean;parameter:
ATOML- TOML string.ClearExisting- Whether to clear existing content (default True)APreserveComments- Whether to read annotations (default False)
Examples:
var TOML := 'title = "MyApp"' + sLineBreak +
'version = "1.0"';
if Config.LoadFromString(TOML) then
WriteLn('Parse successful');ToString(AWrapWidth: Integer; APreserveComments: Boolean = False): string; parameter:
AWrapWidth- The line break position when the string is too long. The default value is 0, meaning no line break.- Note: If the string value contains \n, it will be automatically split into a multi-line string.
APreserveComments- Whether to write comments (default False) Examples:
var TOML := Config.ToString;
WriteLn(TOML);
// Output:
// title = "MyApp"
// version = "1.0"ToJSON(APretty: Boolean; AIndentSize: Integer): string;Parameters:
APretty- Output formatted with indentation (default True)AIndentSize- Number of spaces per indentation level (default 2)
SaveToJSONFile(const FileName: string; APretty: Boolean; ABOM: Boolean): Boolean;Parameters:
FileName- File pathAPretty- Output formatted with indentation (default True)ABOM- Whether to write UTF-8 BOM (default False, JSON typically has no BOM)
LoadFromJSON(const AJSON: string; ANullAsEmptyString: Boolean): Boolean;Parameters:
AJSON- JSON format stringANullAsEmptyString- True converts JSON null to empty string, False ignores null keys (default False)
LoadFromJSONFile(const FileName: string; ANullAsEmptyString: Boolean): Boolean;Filename- File pathANullAsEmptyString- True converts JSON null to empty string, False ignores null keys (default False)
Remove(const Key: string; FreeValue: Boolean = True): Boolean;Parameters:
Key- Key nameFreeValue- Whether to free the value object
Return Value:
True- Key existed and has been deletedFalse- Key doesn't exist
Examples:
if Config.Remove('obsolete_option', True) then
WriteLn('Option removed');procedure Clear(FreeValues: Boolean = True);Parameters:
FreeValues- Whether to free all value objects
Examples:
Config.Clear(True); // Clear and free allCount: Integer;Examples:
WriteLn('Total configuration items: ', Config.Count);HasKey(const Key: string): Boolean;Examples:
if Config.HasKey('server.port') then
WriteLn('Port configuration exists');procedure GetKeys(Keys: TStrings; Recursive: Boolean = False);Parameters:
Keys- Output string listRecursive- Whether to recursively enumerate child table keys
Examples:
var Keys := TStringList.Create;
try
Config.GetKeys(Keys, True); // Get all keys (including nested)
for var Key in Keys do
WriteLn(Key);
finally
Keys.Free;
end;Clone: TTOMLTable;Examples:
var ConfigCopy := Config.Clone;
try
// Modify ConfigCopy without affecting Config
ConfigCopy.SetStr('temp', 'value');
finally
ConfigCopy.Free;
end;TTOMLArray also provides a complete set of helper methods.
GetStr(Index, DefaultValue)- Get string at indexGetInt(Index, DefaultValue)- Get integer at indexGetFloat(Index, DefaultValue)- Get float at indexGetBool(Index, DefaultValue)- Get boolean at indexGetDateTime(Index, DefaultValue)- Get datetime at indexGetArray(Index)- Get sub-array at indexGetTable(Index)- Get table at index
Examples:
var Names := Config.GetArray('users');
for var i := 0 to Names.Count - 1 do
WriteLn(Names.GetStr(i, 'Unknown'));AddStr(Value)- Append stringAddInt(Value)- Append integerAddFloat(Value)- Append floatAddBool(Value)- Append booleanAddDateTime(Value)- Append datetimeAddTable(Value)- Append tableAddArray(Value)- Append array
Examples:
var AllowedIPs := TTOMLArray.Create;
AllowedIPs.AddStr('192.168.1.1')
.AddStr('10.0.0.1')
.AddStr('172.16.0.1');SetStr(Index, Value)- Set string at indexSetInt(Index, Value)- Set integer at indexSetFloat(Index, Value)- Set float at indexSetBool(Index, Value)- Set boolean at indexSetDateTime(Index, Value)- Set datetime at indexSetArray(Index, Value)- Set array at indexSetTable(Index, Value)- Set table at index
Examples:
var Servers := Config.GetArray('servers');
if Servers.SetStr(0, 'updated-server.com') then
WriteLn('First server updated');InsertStr(Index, Value)- Insert string at positionInsertInt(Index, Value)- Insert integer at positionInsertFloat(Index, Value)- Insert float at positionInsertBool(Index, Value)- Insert boolean at positionInsertDateTime(Index, Value)- Insert datetime at positionInsertArray(Index, Value)- Insert array at positionInsertTable(Index, Value)- Insert table at position
Examples:
var List := TTOMLArray.Create;
List.AddStr('first')
.AddStr('third');
List.InsertStr(1, 'second'); // Insert at index 1
// Result: ['first', 'second', 'third']TryGetStr(Index, out Value)- Safe string readTryGetInt(Index, out Value)- Safe integer readTryGetFloat(Index, out Value)- Safe float readTryGetBool(Index, out Value)- Safe boolean readTryGetDateTime(Index, out Value)- Safe datetime readTryGetArray(Index, out Value)- Safe array readTryGetTable(Index, out Value)- Safe table read
Examples:
var
port: Integer;
Ports: TTOMLArray;
begin
Ports := Config.GetArray('ports');
if Ports.TryGetInt(0, port) then
WriteLn('First port: ', port)
else
WriteLn('No port configured');
end;RemoveAt - Remove element at index
function RemoveAt(Index: Integer; FreeItem: Boolean = True): Boolean;Clear - Clear all elements
procedure Clear(FreeItems: Boolean = True);Count - Get element count
function Count: Integer;ForEachTable - Iterate table elements
procedure ForEachTable(Proc: TProc<TTOMLTable>); overload;
procedure ForEachTable(Callback: TFunc<Integer, TTOMLTable, Boolean>;
SkipNonTables: Boolean = True); overload;Examples:
- Simple ForEachTable
var
parameters: TTOMLArray;
procedure ProcessParameter(param: TTOMLTable);
begin
showmessage(param.GetStr('name'));
end;
parameters.ForEachTable(ProcessParameter);- Enhanced ForEachTable
var
Root: TTOMLTable;
UsersArray: TTOMLArray;
TargetUser: TTOMLTable;
begin
Root := LoadTOML('users.toml');
UsersArray := Root.GetArray('users');
TargetUser := nil;
// Use enhanced version: supports early exit
UsersArray.ForEachTable(
function(Index: Integer; User: TTOMLTable): Boolean
begin
if User.GetStr('username') = 'bob' then
begin
TargetUser := User;
Result := False; // Found it, stop iteration
end
else
Result := True; // Continue searching
end,
True // Skip non-table elements
);
if Assigned(TargetUser) then
WriteLn('Found user: ' + TargetUser.GetStr('email'))
else
WriteLn('User not found');
Root.Free;
end;uses
TOML.Types, TOML.Helper;
var
Config: TTOMLTable;
begin
// Create configuration
Config := TTOMLTable.Create;
// or: Config := Newtable;
try
// Use builder pattern to set configuration
Config.Put('app_name', 'MyApplication')
.Put('version', '2.1.0')
.Put('debug', False);
// Set server configuration
var Server := TTOMLTable.Create;
Server.Put('host', '0.0.0.0')
.Put('port', 8080)
.Put('ssl', True);
Config.Put('server', Server);
// Set array
var AllowedIPs := TTOMLArray.Create;
AllowedIPs.AddStr('192.168.1.1')
.AddStr('10.0.0.1');
Config.Put('allowed_ips', AllowedIPs);
// Save to file
if Config.SaveToFile('app_config.toml') then
WriteLn('Configuration saved');
// Read configuration
var AppName := Config.GetStr('app_name', 'Unknown');
var Port := Config.GetInt('server.port', 3000);
var Debug := Config.GetBool('debug', False);
WriteLn('Application: ', AppName);
WriteLn('Port: ', Port);
WriteLn('Debug: ', Debug);
finally
Config.Free;
end;
end;var
Config: TTOMLTable;
Host: string;
Port: Integer;
Timeout: Double;
begin
Config := TTOMLTable.Create;
try
Config.LoadFromFile('config.toml');
// Use TryGet for safe access
if not Config.TryGetStr('server.host', Host) then
Host := 'localhost'; // Default value
if not Config.TryGetInt('server.port', Port) then
Port := 8080;
if not Config.TryGetFloat('server.timeout', Timeout) then
Timeout := 30.0;
WriteLn('Server configuration:');
WriteLn(' Host: ', Host);
WriteLn(' Port: ', Port);
WriteLn(' Timeout: ', Timeout:0:1, ' seconds');
finally
Config.Free;
end;
end;var
Config: TTOMLTable;
begin
Config := TTOMLTable.Create;
try
// Set default configuration
Config.SetStr('theme', 'dark', False);
Config.SetInt('font_size', 12, False);
// Try loading user configuration from file
if FileExists('user_config.toml') then
begin
var UserConfig := TTOMLTable.Create;
try
if UserConfig.LoadFromFile('user_config.toml') then
begin
// Merge configuration (with overwrite protection)
var Keys: TStringList := TStringList.Create;
try
UserConfig.GetKeys(Keys);
for var Key in Keys do
begin
var Value: TTOMLValue;
if UserConfig.TryGetValue(Key, Value) then
Config.SetStr(Key, Value.AsString, True); // User config overrides default
end;
finally
Keys.Free;
end;
end;
finally
UserConfig.Free;
end;
end;
// Now Config contains merged configuration
WriteLn('Theme: ', Config.GetStr('theme'));
WriteLn('Font size: ', Config.GetInt('font_size'));
finally
Config.Free;
end;
end;uses
TOML.Types, TOML.Helper;
var
Config: TTOMLTable;
Timestamp: string;
begin
Config := TTOMLTable.Create;
try
// Parse TOML with high-precision timestamps
var TOML := 'created = 2024-01-15T10:30:45.123456Z' + sLineBreak +
'modified = 2024-01-16T14:22:33.999999Z';
Config.LoadFromString(TOML);
// Get high-precision timestamp (preserves microseconds)
Timestamp := Config.GetDateTimeValue('created', '');
WriteLn('Created: ', Timestamp);
// Output: 2024-01-15T10:30:45.123456Z
Timestamp := Config.GetDateTimeValue('modified', '');
WriteLn('Modified: ', Timestamp);
// Output: 2024-01-16T14:22:33.999999Z
finally
Config.Free;
end;
end;var
Config: TTOMLTable;
begin
Config := TTOMLTable.Create;
try
// Directly add keys containing dots
Config.Items.Add('google.com', TTOMLString.Create('Search Engine'));
Config.Items.Add('github.com', TTOMLString.Create('Code Hosting'));
// Access using quotes
var Google := Config.GetStr('"google.com"', 'Unknown');
var GitHub := Config.GetStr('"github.com"', 'Unknown');
WriteLn('google.com: ', Google);
WriteLn('github.com: ', GitHub);
// Serialization automatically adds quotes
var TOML := Config.ToString;
WriteLn(TOML);
// Output:
// "google.com" = "Search Engine"
// "github.com" = "Code Hosting"
finally
Config.Free;
end;
end;Config := TTOMLTable.Create;
try
// Use Config
finally
Config.Free;
end;When you need to distinguish between "non-existent" and "empty":
if Config.TryGetStr('optional_field', Value) then
// Field exists
else
// Field doesn't exist// Set default values (don't overwrite user configuration)
Config.SetStr('theme', 'default', False);
Config.SetInt('timeout', 30, False);Config.Put('name', 'App')
.Put('version', '1.0')
.Put('enabled', True);if not Config.LoadFromFile('config.toml') then
begin
// Load failed, use default configuration
Config.Put('default', True);
end;// For scenarios requiring precise time like logging, auditing
var Timestamp := Config.GetDateTimeValue('log.timestamp', '');
// Preserves microsecond precision| Method | Return Type | Default Support | Path Support | Exception Safe |
|---|---|---|---|---|
GetStr |
string | ✓ | ✓ | ✓ |
GetInt |
Int64 | ✓ | ✓ | ✓ |
GetFloat |
Double | ✓ | ✓ | ✓ |
GetBool |
Boolean | ✓ | ✓ | ✓ |
GetDateTime |
TDateTime | ✓ | ✓ | ✓ |
GetDateTimeValue |
string | ✓ | ✓ | ✓ |
GetArray |
TTOMLArray | - | ✓ | ✓ |
GetTable |
TTOMLTable | - | ✓ | ✓ |
| Method | Out Parameter Type | Path Support | Returns Boolean |
|---|---|---|---|
TryGetStr |
string | ✓ | ✓ |
TryGetInt |
Integer | ✓ | ✓ |
TryGetFloat |
Double | ✓ | ✓ |
TryGetBool |
Boolean | ✓ | ✓ |
TryGetDateTime |
TDateTime | ✓ | ✓ |
TryGetDateTimeValue |
string | ✓ | ✓ |
TryGetArray |
TTOMLArray | ✓ | ✓ |
TryGetTable |
TTOMLTable | ✓ | ✓ |
| Method | Overwrite Control | Returns Boolean | Chainable |
|---|---|---|---|
SetStr |
✓ | ✓ | - |
SetInt |
✓ | ✓ | - |
SetFloat |
✓ | ✓ | - |
SetBool |
✓ | ✓ | - |
SetDateTime |
✓ | ✓ | - |
SetArray |
✓ | ✓ | - |
SetTable |
✓ | ✓ | - |
Put (all types) |
✓ | - | ✓ |
| Method | Function | Returns Boolean |
|---|---|---|
LoadFromFile |
Load from file | ✓ |
LoadFromJSONFile |
Load from JSON file | ✓ |
SaveToFile |
Save to file | ✓ |
SaveToJSONFile |
Save to JSON file | ✓ |
LoadFromString |
Parse from string | ✓ |
LoadFromJSONString |
Parse from JSON string | ✓ |
ToString |
Serialize to TOML string | - |
ToJSONString |
Serialize to JSON string | - |
TOMLFileToJSONFile |
Convert TOML file to JSON file | - |
JSONFileToTOMLFile |
Convert JSON file to TOML file | - |
Note: TOMLFileToJSONFile and JSONFileToTOMLFile methods are in TOML.JSON.pas unit
-
TryGet vs Get + Try-Except
- TryGet methods don't use exception mechanism, better performance
- Suitable for high-frequency call scenarios
-
Builder Pattern Overhead
- Put method chaining has no additional overhead
- Recommended for initialization scenarios
-
Path Access Performance
- Dot-separated paths require multiple lookups
- For frequent access, consider caching TTOMLTable references
A: Check if you're using the correct path or quotes:
// Wrong: key contains dot but not quoted
val := Config.GetStr('google.com'); // Tries to access path
// Correct: use quotes
val := Config.GetStr('"google.com"'); // Access single keyA: Check Overwrite parameter:
// With Overwrite=False, returns False if key exists
Config.SetStr('key', 'value1');
Config.SetStr('key', 'value2', False); // Returns False
// Use Overwrite=True to force overwrite
Config.SetStr('key', 'value2', True); // Returns TrueA: Possible reasons:
- File doesn't exist
- File permission issues
- TOML syntax errors
if not Config.LoadFromFile('config.toml') then
WriteLn('Load failed, using default configuration');