1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-10-30 23:37:45 +02:00

Add STR() macro to create constant String objects from runtime strings.

The STRING_CONST() macro worked fine for constants but was not able to constify strings created at runtime.

Add the STR() macro to do this by using strlen() to get the size.

Also rename STRING_CONST() to STRDEF() for brevity and to match the other macro name.
This commit is contained in:
David Steele
2019-04-16 13:39:58 -04:00
parent a029eba8d5
commit 2dac4b5986
27 changed files with 156 additions and 142 deletions

View File

@@ -23,6 +23,10 @@
<p>Use a macro instead of a nested struct to create common <code>String</code> variables.</p>
</release-item>
<release-item>
<p>Add <code>STR()</code> macro to create constant <code>String</code> objects from runtime strings.</p>
</release-item>
<release-item>
<release-item-contributor-list>
<release-item-contributor id="cynthia.shang"/>

View File

@@ -59,7 +59,7 @@ archiveAsyncStatus(ArchiveMode archiveMode, const String *walSegment, bool confe
MEM_CONTEXT_TEMP_BEGIN()
{
String *errorFile = NULL;
const String *errorFile = NULL;
bool errorFileExists = false;
const String *spoolQueue = archiveAsyncSpoolQueue(archiveMode);
@@ -77,7 +77,7 @@ archiveAsyncStatus(ArchiveMode archiveMode, const String *walSegment, bool confe
// If that doesn't exist then check for a global error
if (!errorFileExists)
{
errorFile = strNew(STATUS_FILE_GLOBAL STATUS_EXT_ERROR);
errorFile = STRDEF(STATUS_FILE_GLOBAL STATUS_EXT_ERROR);
errorFileExists = storageExistsNP(storageSpool(), strNewFmt("%s/%s", strPtr(spoolQueue), strPtr(errorFile)));
}
}

View File

@@ -49,7 +49,7 @@ archiveGetCheck(const String *archiveFile, CipherType cipherType, const String *
// Attempt to load the archive info file
InfoArchive *info = infoArchiveNew(
storageRepo(), STRING_CONST(STORAGE_REPO_ARCHIVE "/" INFO_ARCHIVE_FILE), false, cipherType, cipherPass);
storageRepo(), STRDEF(STORAGE_REPO_ARCHIVE "/" INFO_ARCHIVE_FILE), false, cipherType, cipherPass);
// Loop through the pg history in case the WAL we need is not in the most recent archive id
String *archiveId = NULL;

View File

@@ -129,7 +129,7 @@ cmdArchiveGet(void)
// Destination is wherever we were told to move the WAL segment
const String *walDestination =
walPath(strLstGet(commandParam, 1), cfgOptionStr(cfgOptPgPath), strNew(cfgCommandName(cfgCommand())));
walPath(strLstGet(commandParam, 1), cfgOptionStr(cfgOptPgPath), STR(cfgCommandName(cfgCommand())));
// Async get can only be performed on WAL segments, history or other files must use synchronous mode
if (cfgOptionBool(cfgOptArchiveAsync) && walIsSegment(walSegment))
@@ -368,7 +368,7 @@ cmdArchiveGetAsync(void)
// On any global error write a single error file to cover all unprocessed files
CATCH_ANY()
{
archiveAsyncStatusErrorWrite(archiveModeGet, NULL, errorCode(), strNew(errorMessage()));
archiveAsyncStatusErrorWrite(archiveModeGet, NULL, errorCode(), STR(errorMessage()));
RETHROW();
}
TRY_END();

View File

@@ -1,6 +1,7 @@
/***********************************************************************************************************************************
Archive Push Command
***********************************************************************************************************************************/
#include <string.h>
#include <unistd.h>
#include "command/archive/common.h"
@@ -96,7 +97,7 @@ archivePushReadyList(const String *walPath)
StringList *readyListRaw = strLstSort(
storageListP(
storagePg(), strNewFmt("%s/" PG_PATH_ARCHIVE_STATUS, strPtr(walPath)),
.expression = strNew("\\" STATUS_EXT_READY "$"), .errorOnMissing = true),
.expression = STRDEF("\\" STATUS_EXT_READY "$"), .errorOnMissing = true),
sortOrderAsc);
for (unsigned int readyIdx = 0; readyIdx < strLstSize(readyListRaw); readyIdx++)
@@ -135,12 +136,12 @@ archivePushProcessList(const String *walPath)
MEM_CONTEXT_TEMP_BEGIN()
{
// Create the spool out path if it does not already exist
storagePathCreateNP(storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_OUT));
storagePathCreateNP(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT_STR);
// Read the status files from the spool directory, then remove any files that do not end in ok and create a list of the
// ok files for further processing
StringList *statusList = strLstSort(
storageListP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_OUT), .errorOnMissing = true), sortOrderAsc);
storageListP(storageSpool(), STORAGE_SPOOL_ARCHIVE_OUT_STR, .errorOnMissing = true), sortOrderAsc);
StringList *okList = strLstNew();
@@ -216,7 +217,7 @@ archivePushCheck(CipherType cipherType, const String *cipherPass)
// Attempt to load the archive info file
InfoArchive *info = infoArchiveNew(
storageRepo(), STRING_CONST(STORAGE_REPO_ARCHIVE "/" INFO_ARCHIVE_FILE), false, cipherType, cipherPass);
storageRepo(), STRDEF(STORAGE_REPO_ARCHIVE "/" INFO_ARCHIVE_FILE), false, cipherType, cipherPass);
// Get archive id for the most recent version -- archive-push will only operate against the most recent version
String *archiveId = infoPgArchiveId(infoArchivePg(info), infoPgDataCurrentId(infoArchivePg(info)));
@@ -268,7 +269,7 @@ cmdArchivePush(void)
lockStopTest();
// Get the segment name
String *walFile = walPath(strLstGet(commandParam, 0), cfgOptionStr(cfgOptPgPath), strNew(cfgCommandName(cfgCommand())));
String *walFile = walPath(strLstGet(commandParam, 0), cfgOptionStr(cfgOptPgPath), STR(cfgCommandName(cfgCommand())));
String *archiveFile = strBase(walFile);
if (cfgOptionBool(cfgOptArchiveAsync))
@@ -506,7 +507,7 @@ cmdArchivePushAsync(void)
// On any global error write a single error file to cover all unprocessed files
CATCH_ANY()
{
archiveAsyncStatusErrorWrite(archiveModePush, NULL, errorCode(), strNew(errorMessage()));
archiveAsyncStatusErrorWrite(archiveModePush, NULL, errorCode(), STR(errorMessage()));
RETHROW();
}
TRY_END();

View File

@@ -144,7 +144,7 @@ helpRender(void)
MEM_CONTEXT_TEMP_BEGIN()
{
// Message for more help when it is available
String *more = NULL;
const String *more = NULL;
// Display general help
if (cfgCommand() == cfgCmdHelp || cfgCommand() == cfgCmdNone)
@@ -187,12 +187,12 @@ helpRender(void)
strCatFmt(
result, " %s%*s%s\n", cfgCommandName(commandId),
(int)(commandSizeMax - strlen(cfgCommandName(commandId)) + 2), "",
strPtr(helpRenderText(strNew(helpSummary), commandSizeMax + 6, false, CONSOLE_WIDTH)));
strPtr(helpRenderText(STR(helpSummary), commandSizeMax + 6, false, CONSOLE_WIDTH)));
}
}
// Construct message for more help
more = strNew("[command]");
more = STRDEF("[command]");
}
else
{
@@ -214,8 +214,8 @@ helpRender(void)
"%s\n"
"\n"
"%s\n",
strPtr(helpRenderText(strNew(cfgDefCommandHelpSummary(commandDefId)), 0, true, CONSOLE_WIDTH)),
strPtr(helpRenderText(strNew(cfgDefCommandHelpDescription(commandDefId)), 0, true, CONSOLE_WIDTH)));
strPtr(helpRenderText(STR(cfgDefCommandHelpSummary(commandDefId)), 0, true, CONSOLE_WIDTH)),
strPtr(helpRenderText(STR(cfgDefCommandHelpDescription(commandDefId)), 0, true, CONSOLE_WIDTH)));
// Construct key/value of sections and options
KeyValue *optionKv = kvNew();
@@ -225,16 +225,16 @@ helpRender(void)
{
if (cfgDefOptionValid(commandDefId, optionDefId) && !cfgDefOptionInternal(commandDefId, optionDefId))
{
String *section = NULL;
const String *section = NULL;
if (cfgDefOptionHelpSection(optionDefId) != NULL)
section = strNew(cfgDefOptionHelpSection(optionDefId));
section = STR(cfgDefOptionHelpSection(optionDefId));
if (section == NULL ||
(!strEqZ(section, "general") && !strEqZ(section, "log") && !strEqZ(section, "repository") &&
!strEqZ(section, "stanza")))
{
section = strNew("command");
section = STRDEF("command");
}
kvAdd(optionKv, varNewStr(section), varNewInt((int)optionDefId));
@@ -333,8 +333,8 @@ helpRender(void)
"\n"
"%s\n",
optionName,
strPtr(helpRenderText(strNew(cfgDefOptionHelpSummary(commandDefId, optionDefId)), 0, true, CONSOLE_WIDTH)),
strPtr(helpRenderText(strNew(cfgDefOptionHelpDescription(commandDefId, optionDefId)), 0, true, CONSOLE_WIDTH)));
strPtr(helpRenderText(STR(cfgDefOptionHelpSummary(commandDefId, optionDefId)), 0, true, CONSOLE_WIDTH)),
strPtr(helpRenderText(STR(cfgDefOptionHelpDescription(commandDefId, optionDefId)), 0, true, CONSOLE_WIDTH)));
// Ouput current and default values if they exist
const String *defaultValue = helpRenderValue(cfgOptionDefault(optionId));

View File

@@ -1,6 +1,8 @@
/***********************************************************************************************************************************
Remote Command
***********************************************************************************************************************************/
#include <string.h>
#include "common/debug.h"
#include "common/io/handleRead.h"
#include "common/io/handleWrite.h"
@@ -55,7 +57,7 @@ cmdRemote(int handleRead, int handleWrite)
}
CATCH_ANY()
{
protocolServerError(server, errorCode(), strNew(errorMessage()));
protocolServerError(server, errorCode(), STR(errorMessage()));
}
TRY_END();

View File

@@ -96,7 +96,7 @@ lockAcquireFile(const String *lockFile, TimeMSec lockTimeout, bool failOnNoLock)
const String *errorHint = NULL;
if (errNo == EWOULDBLOCK)
errorHint = STRING_CONST("\nHINT: is another " PROJECT_NAME " process running?");
errorHint = STRDEF("\nHINT: is another " PROJECT_NAME " process running?");
else if (errNo == EACCES)
{
errorHint = strNewFmt(

View File

@@ -14,8 +14,11 @@ String Handler
/***********************************************************************************************************************************
Constant strings that are generally useful
***********************************************************************************************************************************/
STRING_EXTERN(BRACKETL_STR, "[");
STRING_EXTERN(BRACKETR_STR, "]");
STRING_EXTERN(CR_STR, "\r");
STRING_EXTERN(EMPTY_STR, "");
STRING_EXTERN(EQ_STR, "=");
STRING_EXTERN(FSLASH_STR, "/");
STRING_EXTERN(LF_STR, "\n");
STRING_EXTERN(N_STR, "n");
@@ -821,14 +824,7 @@ size_t strObjToLog(const void *object, StrObjToLogFormat formatFunc, char *buffe
MEM_CONTEXT_TEMP_BEGIN()
{
const String *string = NULL;
if (object == NULL)
string = NULL_STR;
else
string = formatFunc(object);
result = (size_t)snprintf(buffer, bufferSize, "%s", strPtr(string));
result = (size_t)snprintf(buffer, bufferSize, "%s", object == NULL ? strPtr(NULL_STR) : strPtr(formatFunc(object)));
}
MEM_CONTEXT_TEMP_END();

View File

@@ -94,27 +94,34 @@ String * will result in a segfault due to modifying read-only memory.
By convention all string constant identifiers are appended with _STR.
***********************************************************************************************************************************/
// Create a string constant inline. Useful when the constant will only be use once.
#define STRING_CONST(value) \
((const String *)&(const StringConst){.size = sizeof(value) - 1, .buffer = (char *)value})
// Create a String constant inline from any zero-terminated string
#define STR(bufferParam) \
((const String *)&(const StringConst){.buffer = (char *)(bufferParam), .size = (unsigned int)strlen(bufferParam)})
// Used to declare string constants that will be externed using STRING_DECLARE(). Must be used in a .c file.
#define STRING_EXTERN(name, value) \
const String *name = STRING_CONST(value)
// Create a String constant inline from a #define or inline string constant
#define STRDEF(bufferParam) \
((const String *)&(const StringConst){.buffer = (char *)(bufferParam), .size = (unsigned int)sizeof(bufferParam) - 1})
// Used to declare string constants that will be local to the .c file. Must be used in a .c file.
#define STRING_STATIC(name, value) \
static const String *name = STRING_CONST(value)
// Used to declare String constants that will be externed using STRING_DECLARE(). Must be used in a .c file.
#define STRING_EXTERN(name, buffer) \
const String *name = STRDEF(buffer)
// Used to extern string constants declared with STRING_EXTERN(. Must be used in a .h file.
// Used to declare String constants that will be local to the .c file. Must be used in a .c file.
#define STRING_STATIC(name, buffer) \
static const String *name = STRDEF(buffer)
// Used to extern String constants declared with STRING_EXTERN(). Must be used in a .h file.
#define STRING_DECLARE(name) \
extern const String *name
/***********************************************************************************************************************************
Constant strings that are generally useful
***********************************************************************************************************************************/
STRING_DECLARE(BRACKETL_STR);
STRING_DECLARE(BRACKETR_STR);
STRING_DECLARE(CR_STR);
STRING_DECLARE(EMPTY_STR);
STRING_DECLARE(EQ_STR);
STRING_DECLARE(FSLASH_STR);
STRING_DECLARE(LF_STR);
STRING_DECLARE(N_STR);

View File

@@ -931,7 +931,7 @@ varToLog(const Variant *this)
String *result = NULL;
if (this == NULL)
result = strNew("null");
result = strDup(NULL_STR);
else
{
switch (varType(this))

View File

@@ -8,7 +8,7 @@ Exec Configuration
#include "config/exec.h"
/***********************************************************************************************************************************
Load log settings
Generate a list of options required for execution of a new command, replacing options as specified in optionReplace
***********************************************************************************************************************************/
StringList *
cfgExecParam(ConfigCommand commandId, const KeyValue *optionReplace)
@@ -35,7 +35,7 @@ cfgExecParam(ConfigCommand commandId, const KeyValue *optionReplace)
continue;
// First check for a replacement
const Variant *key = varNewStr(strNew(cfgOptionName(optionId)));
const Variant *key = varNewStr(STR(cfgOptionName(optionId)));
const Variant *value = NULL;
bool exists = false;

View File

@@ -111,7 +111,7 @@ convertToByte(String **value, double *valueDbl)
String *result = strLower(strDup(*value));
// Match the value against possible values
if (regExpMatchOne(STRING_CONST("^[0-9]+(kb|k|mb|m|gb|g|tb|t|pb|p|b)*$"), result))
if (regExpMatchOne(STRDEF("^[0-9]+(kb|k|mb|m|gb|g|tb|t|pb|p|b)*$"), result))
{
// Get the character array and size
const char *strArray = strPtr(result);
@@ -303,7 +303,7 @@ cfgFileLoad( // NOTE: Pas
{
if (result != NULL)
{
// Validate the file by parsing it as an Ini object. If the file is not properly formed, en error will occur.
// Validate the file by parsing it as an Ini object. If the file is not properly formed, an error will occur.
Ini *ini = iniNew();
iniParse(ini, result);
}
@@ -318,7 +318,7 @@ cfgFileLoad( // NOTE: Pas
// Get a list of conf files from the specified path -error on missing directory if the option was passed on the command line
StringList *list = storageListP(
storageLocal(), configIncludePath, .expression = STRING_CONST(".+\\.conf$"), .errorOnMissing = configIncludeRequired);
storageLocal(), configIncludePath, .expression = STRDEF(".+\\.conf$"), .errorOnMissing = configIncludeRequired);
// If conf files are found, then add them to the config string
if (list != NULL && strLstSize(list) > 0)
@@ -382,7 +382,7 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
MEM_CONTEXT_TEMP_BEGIN()
{
// Set the exe
cfgExeSet(strNew(argList[0]));
cfgExeSet(STR(argList[0]));
// Phase 1: parse command line parameters
// -------------------------------------------------------------------------------------------------------------------------
@@ -438,7 +438,7 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
if (commandParamList == NULL)
commandParamList = strLstNew();
strLstAdd(commandParamList, strNew(argList[optind - 1]));
strLstAdd(commandParamList, STR(argList[optind - 1]));
}
break;
@@ -484,7 +484,7 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
// Only set the argument if the option requires one
if (optionList[optionListIdx].has_arg == required_argument)
parseOptionList[optionId].valueList = strLstAdd(strLstNew(), strNew(optarg));
parseOptionList[optionId].valueList = strLstAdd(strLstNew(), STR(optarg));
}
else
{
@@ -577,10 +577,10 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
ASSERT(equalPtr != NULL);
// Get key and value
String *key = strReplaceChr(
const String *key = strReplaceChr(
strLower(strNewN(keyValue + PGBACKREST_ENV_SIZE, (size_t)(equalPtr - (keyValue + PGBACKREST_ENV_SIZE)))),
'_', '-');
String *value = strNew(equalPtr + 1);
const String *value = STR(equalPtr + 1);
// Find the option
unsigned int optionIdx = optionFind(key);
@@ -647,8 +647,8 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
// ---------------------------------------------------------------------------------------------------------------------
// Load the configuration file(s)
String *configString = cfgFileLoad(parseOptionList,
strNew(cfgDefOptionDefault(commandDefId, cfgOptionDefIdFromId(cfgOptConfig))),
strNew(cfgDefOptionDefault(commandDefId, cfgOptionDefIdFromId(cfgOptConfigIncludePath))),
STR(cfgDefOptionDefault(commandDefId, cfgOptionDefIdFromId(cfgOptConfig))),
STR(cfgDefOptionDefault(commandDefId, cfgOptionDefIdFromId(cfgOptConfigIncludePath))),
PGBACKREST_CONFIG_ORIG_PATH_FILE_STR);
if (configString != NULL)
@@ -886,7 +886,7 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
if (!dependResolved && optionSet && parseOption->source == cfgSourceParam)
{
// Get the depend option name
String *dependOptionName = strNew(cfgOptionName(dependOptionId));
const String *dependOptionName = STR(cfgOptionName(dependOptionId));
// Build the list of possible depend values
StringList *dependValueList = strLstNew();
@@ -930,7 +930,7 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
}
// Build the error string
String *errorValue = strNew("");
const String *errorValue = EMPTY_STR;
if (strLstSize(dependValueList) == 1)
errorValue = strNewFmt(" = %s", strPtr(strLstGet(dependValueList, 0)));
@@ -975,7 +975,7 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
strPtr(strLstGet(parseOption->valueList, listIdx)), cfgOptionName(optionId));
}
kvPut(keyValue, varNewStr(strNewN(pair, (size_t)(equal - pair))), varNewStr(strNew(equal + 1)));
kvPut(keyValue, varNewStr(strNewN(pair, (size_t)(equal - pair))), varNewStr(STR(equal + 1)));
}
cfgOptionSet(optionId, parseOption->source, value);

View File

@@ -87,7 +87,7 @@ infoBackupNew(const Storage *storage, const String *fileName, bool ignoreMissing
TRY_END();
const Ini *infoIni = infoPgIni(this->infoPg);
const String *backupCurrentSection = strNew(INFO_BACKUP_SECTION_BACKUP_CURRENT);
const String *backupCurrentSection = STRDEF(INFO_BACKUP_SECTION_BACKUP_CURRENT);
// If there are current backups, then parse the json for each into a list object
if (strLstExists(iniSectionList(infoIni), backupCurrentSection))

View File

@@ -1,6 +1,8 @@
/***********************************************************************************************************************************
Perl Configuration
***********************************************************************************************************************************/
#include <string.h>
#include "common/debug.h"
#include "common/memContext.h"
#include "common/type/json.h"
@@ -29,7 +31,7 @@ perlOptionJson(void)
Variant *optionVar = varNewKv();
// Add valid
kvPut(varKv(optionVar), varNewStr(strNew("valid")), varNewBool(true));
kvPut(varKv(optionVar), varNewStr(STRDEF("valid")), varNewBool(true));
// Add source
const char *source = NULL;
@@ -55,11 +57,11 @@ perlOptionJson(void)
}
}
kvPut(varKv(optionVar), varNewStr(strNew("source")), varNewStr(strNew(source)));
kvPut(varKv(optionVar), varNewStr(STRDEF("source")), varNewStr(STR(source)));
// Add negate and reset
kvPut(varKv(optionVar), varNewStr(strNew("negate")), varNewBool(cfgOptionNegate(optionId)));
kvPut(varKv(optionVar), varNewStr(strNew("reset")), varNewBool(cfgOptionReset(optionId)));
kvPut(varKv(optionVar), varNewStr(STRDEF("negate")), varNewBool(cfgOptionNegate(optionId)));
kvPut(varKv(optionVar), varNewStr(STRDEF("reset")), varNewBool(cfgOptionReset(optionId)));
// Add value if it is set
if (cfgOptionTest(optionId))
@@ -105,10 +107,10 @@ perlOptionJson(void)
}
}
kvPut(varKv(optionVar), varNewStr(strNew("value")), valueVar);
kvPut(varKv(optionVar), varNewStr(STRDEF("value")), valueVar);
}
kvPut(configKv, varNewStr(strNew(cfgOptionName(optionId))), optionVar);
kvPut(configKv, varNewStr(STR(cfgOptionName(optionId))), optionVar);
}
memContextSwitch(MEM_CONTEXT_OLD());

View File

@@ -506,7 +506,7 @@ pgVersionFromStr(const String *version)
MEM_CONTEXT_TEMP_BEGIN()
{
// If format is not number.number (9.4) or number only (10) then error
if (!regExpMatchOne(STRING_CONST("^[0-9]+[.]*[0-9]+$"), version))
if (!regExpMatchOne(STRDEF("^[0-9]+[.]*[0-9]+$"), version))
THROW_FMT(AssertError, "version %s format is invalid", strPtr(version));
// If there is a dot set the major and minor versions, else just the major

View File

@@ -75,9 +75,9 @@ protocolClientNew(const String *name, const String *service, IoRead *read, IoWri
const String *expected[] =
{
PROTOCOL_GREETING_NAME_STR, strNew(PROJECT_NAME),
PROTOCOL_GREETING_NAME_STR, STRDEF(PROJECT_NAME),
PROTOCOL_GREETING_SERVICE_STR, service,
PROTOCOL_GREETING_VERSION_STR, strNew(PROJECT_VERSION),
PROTOCOL_GREETING_VERSION_STR, STRDEF(PROJECT_VERSION),
};
for (unsigned int expectedIdx = 0; expectedIdx < sizeof(expected) / sizeof(char *) / 2; expectedIdx++)

View File

@@ -85,7 +85,7 @@ protocolLocalParam(ProtocolStorageType protocolStorageType, unsigned int protoco
KeyValue *optionReplace = kvNew();
// Add the command option
kvPut(optionReplace, varNewStr(CFGOPT_COMMAND_STR), varNewStr(strNew(cfgCommandName(cfgCommand()))));
kvPut(optionReplace, varNewStr(CFGOPT_COMMAND_STR), varNewStrZ(cfgCommandName(cfgCommand())));
// Add the process id -- used when more than one process will be called
kvPut(optionReplace, varNewStr(CFGOPT_PROCESS_STR), varNewInt((int)protocolId));
@@ -94,7 +94,7 @@ protocolLocalParam(ProtocolStorageType protocolStorageType, unsigned int protoco
kvPut(optionReplace, varNewStr(CFGOPT_HOST_ID_STR), varNewInt(1));
// Add the type
kvPut(optionReplace, varNewStr(CFGOPT_TYPE_STR), varNewStr(strNew("backup")));
kvPut(optionReplace, varNewStr(CFGOPT_TYPE_STR), varNewStrZ("backup"));
// Only enable file logging on the local when requested
kvPut(
@@ -212,7 +212,7 @@ protocolRemoteParam(ProtocolStorageType protocolStorageType, unsigned int protoc
// Add the command option (or use the current command option if it is valid)
if (!cfgOptionTest(cfgOptCommand))
kvPut(optionReplace, varNewStr(CFGOPT_COMMAND_STR), varNewStr(strNew(cfgCommandName(cfgCommand()))));
kvPut(optionReplace, varNewStr(CFGOPT_COMMAND_STR), varNewStrZ(cfgCommandName(cfgCommand())));
// Add the process id (or use the current process id if it is valid)
if (!cfgOptionTest(cfgOptProcess))
@@ -231,7 +231,7 @@ protocolRemoteParam(ProtocolStorageType protocolStorageType, unsigned int protoc
kvPut(optionReplace, varNewStr(CFGOPT_LOG_LEVEL_STDERR_STR), varNewStrZ("error"));
// Add the type
kvPut(optionReplace, varNewStr(CFGOPT_TYPE_STR), varNewStr(strNew("backup")));
kvPut(optionReplace, varNewStr(CFGOPT_TYPE_STR), varNewStrZ("backup"));
StringList *commandExec = cfgExecParam(cfgCmdRemote, optionReplace);
strLstInsert(commandExec, 0, cfgOptionStr(cfgOptRepoHostCmd));

View File

@@ -1,6 +1,7 @@
/***********************************************************************************************************************************
Protocol Parallel Executor
***********************************************************************************************************************************/
#include <string.h>
#include <sys/select.h>
#include "common/debug.h"
@@ -182,7 +183,7 @@ protocolParallelProcess(ProtocolParallel *this)
}
CATCH_ANY()
{
protocolParallelJobErrorSet(job, errorCode(), strNew(errorMessage()));
protocolParallelJobErrorSet(job, errorCode(), STR(errorMessage()));
}
TRY_END();

View File

@@ -1,6 +1,8 @@
/***********************************************************************************************************************************
Protocol Server
***********************************************************************************************************************************/
#include <string.h>
#include "common/debug.h"
#include "common/log.h"
#include "common/memContext.h"
@@ -59,9 +61,9 @@ protocolServerNew(const String *name, const String *service, IoRead *read, IoWri
MEM_CONTEXT_TEMP_BEGIN()
{
KeyValue *greetingKv = kvNew();
kvPut(greetingKv, varNewStr(PROTOCOL_GREETING_NAME_STR), varNewStr(strNew(PROJECT_NAME)));
kvPut(greetingKv, varNewStr(PROTOCOL_GREETING_NAME_STR), varNewStrZ(PROJECT_NAME));
kvPut(greetingKv, varNewStr(PROTOCOL_GREETING_SERVICE_STR), varNewStr(service));
kvPut(greetingKv, varNewStr(PROTOCOL_GREETING_VERSION_STR), varNewStr(strNew(PROJECT_VERSION)));
kvPut(greetingKv, varNewStr(PROTOCOL_GREETING_VERSION_STR), varNewStrZ(PROJECT_VERSION));
ioWriteLine(this->write, kvToJson(greetingKv, 0));
ioWriteFlush(this->write);
@@ -107,7 +109,7 @@ protocolServerError(ProtocolServer *this, int code, const String *message)
KeyValue *error = kvNew();
kvPut(error, varNewStr(PROTOCOL_ERROR_STR), varNewInt(errorCode()));
kvPut(error, varNewStr(PROTOCOL_OUTPUT_STR), varNewStr(strNew(errorMessage())));
kvPut(error, varNewStr(PROTOCOL_OUTPUT_STR), varNewStrZ(errorMessage()));
ioWriteLine(this->write, kvToJson(error, 0));
ioWriteFlush(this->write);
@@ -174,7 +176,7 @@ protocolServerProcess(ProtocolServer *this)
}
CATCH_ANY()
{
protocolServerError(this, errorCode(), strNew(errorMessage()));
protocolServerError(this, errorCode(), STR(errorMessage()));
}
TRY_END();
}

View File

@@ -5,6 +5,7 @@ Posix Storage Driver
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -197,14 +198,12 @@ storageDriverPosixList(StorageDriverPosix *this, const String *path, bool errorO
while (dirEntry != NULL)
{
String *entry = strNew(dirEntry->d_name);
const String *entry = STR(dirEntry->d_name);
// Exclude current/parent directory and apply the expression if specified
if (!strEqZ(entry, ".") && !strEqZ(entry, "..") && (regExp == NULL || regExpMatch(regExp, entry)))
strLstAdd(result, entry);
strFree(entry);
dirEntry = readdir(dir);
}

View File

@@ -157,7 +157,7 @@ storageDriverRemoteFileWriteClose(StorageDriverRemoteFileWrite *this)
// Close if the file has not already been closed
if (this->client != NULL)
{
ioWriteLine(protocolClientIoWrite(this->client), strNew(PROTOCOL_BLOCK_HEADER "0"));
ioWriteLine(protocolClientIoWrite(this->client), STRDEF(PROTOCOL_BLOCK_HEADER "0"));
ioWriteFlush(protocolClientIoWrite(this->client));
protocolClientReadOutput(this->client, false);
@@ -319,7 +319,7 @@ storageDriverRemoteFileWriteFree(StorageDriverRemoteFileWrite *this)
// If freed without closing then notify the remote to close the file
if (this->client != NULL)
{
ioWriteLine(protocolClientIoWrite(this->client), strNew(PROTOCOL_BLOCK_HEADER "-1"));
ioWriteLine(protocolClientIoWrite(this->client), STRDEF(PROTOCOL_BLOCK_HEADER "-1"));
ioWriteFlush(protocolClientIoWrite(this->client));
protocolClientReadOutput(this->client, false);

View File

@@ -104,7 +104,7 @@ storageDriverRemoteProtocol(const String *command, const VariantList *paramList,
while (!ioReadEof(fileRead));
// Write a zero block to show file is complete
ioWriteLine(protocolServerIoWrite(server), strNew(PROTOCOL_BLOCK_HEADER "0"));
ioWriteLine(protocolServerIoWrite(server), STRDEF(PROTOCOL_BLOCK_HEADER "0"));
ioWriteFlush(protocolServerIoWrite(server));
}
}

View File

@@ -1,6 +1,7 @@
/***********************************************************************************************************************************
S3 Storage Driver
***********************************************************************************************************************************/
#include <string.h>
#include <time.h>
#include "common/crypto/hash.h"
@@ -326,14 +327,14 @@ storageDriverS3Request(
char md5Hash[HASH_TYPE_MD5_SIZE_HEX];
encodeToStr(encodeBase64, bufPtr(cryptoHashOne(HASH_TYPE_MD5_STR, body)), HASH_TYPE_M5_SIZE, md5Hash);
httpHeaderAdd(requestHeader, HTTP_HEADER_CONTENT_MD5_STR, strNew(md5Hash));
httpHeaderAdd(requestHeader, HTTP_HEADER_CONTENT_MD5_STR, STR(md5Hash));
}
// Generate authorization header
storageDriverS3Auth(
this, verb, uri, query, storageDriverS3DateTime(time(NULL)), requestHeader,
body == NULL || bufUsed(body) == 0 ?
strNew("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") :
STRDEF("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") :
bufHex(cryptoHashOne(HASH_TYPE_SHA256_STR, body)));
// Process request

View File

@@ -199,7 +199,7 @@ storageHelperRepoInit(void)
{
MEM_CONTEXT_BEGIN(memContextTop())
{
storageHelper.walRegExp = regExpNew(STRING_CONST("^[0-F]{24}"));
storageHelper.walRegExp = regExpNew(STRDEF("^[0-F]{24}"));
}
MEM_CONTEXT_END();
}

View File

@@ -455,7 +455,7 @@ storagePath(const Storage *this, const String *pathExp)
String *expression = strNewN(strPtr(pathExp), (size_t)(end - strPtr(pathExp) + 1));
// Create a string from the path if there is anything left after the expression
String *path = NULL;
const String *path = NULL;
if (strSize(expression) < strSize(pathExp))
{
@@ -467,7 +467,7 @@ storagePath(const Storage *this, const String *pathExp)
if (end[2] == 0)
THROW_FMT(AssertError, "path '%s' should not end in '/'", strPtr(pathExp));
path = strNew(end + 2);
path = STR(end + 2);
}
// Evaluate the path
@@ -482,7 +482,6 @@ storagePath(const Storage *this, const String *pathExp)
// Free temp vars
strFree(expression);
strFree(path);
}
if (this->path == NULL)

View File

@@ -63,15 +63,15 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("strBase() and strPath()"))
{
TEST_RESULT_STR(strPtr(strBase(strNew(""))), "", "empty string");
TEST_RESULT_STR(strPtr(strBase(strNew("/"))), "", "/ only");
TEST_RESULT_STR(strPtr(strBase(strNew("/file"))), "file", "root file");
TEST_RESULT_STR(strPtr(strBase(strNew("/dir1/dir2/file"))), "file", "subdirectory file");
TEST_RESULT_STR(strPtr(strBase(STRDEF(""))), "", "empty string");
TEST_RESULT_STR(strPtr(strBase(STRDEF("/"))), "", "/ only");
TEST_RESULT_STR(strPtr(strBase(STRDEF("/file"))), "file", "root file");
TEST_RESULT_STR(strPtr(strBase(STRDEF("/dir1/dir2/file"))), "file", "subdirectory file");
TEST_RESULT_STR(strPtr(strPath(strNew(""))), "", "empty string");
TEST_RESULT_STR(strPtr(strPath(strNew("/"))), "/", "/ only");
TEST_RESULT_STR(strPtr(strPath(strNew("/file"))), "/", "root path");
TEST_RESULT_STR(strPtr(strPath(strNew("/dir1/dir2/file"))), "/dir1/dir2", "subdirectory file");
TEST_RESULT_STR(strPtr(strPath(STRDEF(""))), "", "empty string");
TEST_RESULT_STR(strPtr(strPath(STRDEF("/"))), "/", "/ only");
TEST_RESULT_STR(strPtr(strPath(STRDEF("/file"))), "/", "root path");
TEST_RESULT_STR(strPtr(strPath(STRDEF("/dir1/dir2/file"))), "/dir1/dir2", "subdirectory file");
}
// *****************************************************************************************************************************
@@ -93,7 +93,7 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("strDup()"))
{
String *string = strNew("duplicated string");
const String *string = STRDEF("duplicated string");
String *stringDup = strDup(string);
TEST_RESULT_STR(strPtr(stringDup), strPtr(string), "duplicated strings match");
@@ -103,39 +103,39 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("strBeginsWith() and strBeginsWithZ()"))
{
TEST_RESULT_BOOL(strBeginsWith(strNew(""), strNew("aaa")), false, "empty string");
TEST_RESULT_BOOL(strBeginsWith(strNew("astring"), strNew("")), true, "empty begins with");
TEST_RESULT_BOOL(strBeginsWithZ(strNew("astring"), "astr"), true, "partial begins with");
TEST_RESULT_BOOL(strBeginsWithZ(strNew("astring"), "astring"), true, "equal strings");
TEST_RESULT_BOOL(strBeginsWith(STRDEF(""), STRDEF("aaa")), false, "empty string");
TEST_RESULT_BOOL(strBeginsWith(STRDEF("astring"), STRDEF("")), true, "empty begins with");
TEST_RESULT_BOOL(strBeginsWithZ(STRDEF("astring"), "astr"), true, "partial begins with");
TEST_RESULT_BOOL(strBeginsWithZ(STRDEF("astring"), "astring"), true, "equal strings");
}
// *****************************************************************************************************************************
if (testBegin("strEndsWith() and strEndsWithZ()"))
{
TEST_RESULT_BOOL(strEndsWith(strNew(""), strNew(".doc")), false, "empty string");
TEST_RESULT_BOOL(strEndsWith(strNew("astring"), strNew("")), true, "empty ends with");
TEST_RESULT_BOOL(strEndsWithZ(strNew("astring"), "ing"), true, "partial ends with");
TEST_RESULT_BOOL(strEndsWithZ(strNew("astring"), "astring"), true, "equal strings");
TEST_RESULT_BOOL(strEndsWith(STRDEF(""), STRDEF(".doc")), false, "empty string");
TEST_RESULT_BOOL(strEndsWith(STRDEF("astring"), STRDEF("")), true, "empty ends with");
TEST_RESULT_BOOL(strEndsWithZ(STRDEF("astring"), "ing"), true, "partial ends with");
TEST_RESULT_BOOL(strEndsWithZ(STRDEF("astring"), "astring"), true, "equal strings");
}
// *****************************************************************************************************************************
if (testBegin("strEq(), strEqZ(), strCmp(), strCmpZ()"))
{
TEST_RESULT_BOOL(strEq(strNew("equalstring"), strNew("equalstring")), true, "strings equal");
TEST_RESULT_BOOL(strEq(strNew("astring"), strNew("anotherstring")), false, "strings not equal");
TEST_RESULT_BOOL(strEq(strNew("astring"), strNew("bstring")), false, "equal length strings not equal");
TEST_RESULT_BOOL(strEq(STRDEF("equalstring"), STRDEF("equalstring")), true, "strings equal");
TEST_RESULT_BOOL(strEq(STRDEF("astring"), STRDEF("anotherstring")), false, "strings not equal");
TEST_RESULT_BOOL(strEq(STRDEF("astring"), STRDEF("bstring")), false, "equal length strings not equal");
TEST_RESULT_INT(strCmp(strNew("equalstring"), strNew("equalstring")), 0, "strings equal");
TEST_RESULT_INT(strCmp(strNew("a"), strNew("b")), -1, "a < b");
TEST_RESULT_INT(strCmp(strNew("b"), strNew("a")), 1, "b > a");
TEST_RESULT_INT(strCmp(STRDEF("equalstring"), STRDEF("equalstring")), 0, "strings equal");
TEST_RESULT_INT(strCmp(STRDEF("a"), STRDEF("b")), -1, "a < b");
TEST_RESULT_INT(strCmp(STRDEF("b"), STRDEF("a")), 1, "b > a");
TEST_RESULT_BOOL(strEqZ(strNew("equalstring"), "equalstring"), true, "strings equal");
TEST_RESULT_BOOL(strEqZ(strNew("astring"), "anotherstring"), false, "strings not equal");
TEST_RESULT_BOOL(strEqZ(strNew("astring"), "bstring"), false, "equal length strings not equal");
TEST_RESULT_BOOL(strEqZ(STRDEF("equalstring"), "equalstring"), true, "strings equal");
TEST_RESULT_BOOL(strEqZ(STRDEF("astring"), "anotherstring"), false, "strings not equal");
TEST_RESULT_BOOL(strEqZ(STRDEF("astring"), "bstring"), false, "equal length strings not equal");
TEST_RESULT_INT(strCmpZ(strNew("equalstring"), "equalstring"), 0, "strings equal");
TEST_RESULT_INT(strCmpZ(strNew("a"), "b"), -1, "a < b");
TEST_RESULT_INT(strCmpZ(strNew("b"), "a"), 1, "b > a");
TEST_RESULT_INT(strCmpZ(STRDEF("equalstring"), "equalstring"), 0, "strings equal");
TEST_RESULT_INT(strCmpZ(STRDEF("a"), "b"), -1, "a < b");
TEST_RESULT_INT(strCmpZ(STRDEF("b"), "a"), 1, "b > a");
}
// *****************************************************************************************************************************
@@ -163,7 +163,7 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("strQuote()"))
{
TEST_RESULT_STR(strPtr(strQuote(strNew("abcd"), strNew("'"))), "'abcd'", "quote string");
TEST_RESULT_STR(strPtr(strQuote(STRDEF("abcd"), STRDEF("'"))), "'abcd'", "quote string");
}
// *****************************************************************************************************************************
@@ -175,8 +175,8 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("strSub() and strSubN()"))
{
TEST_RESULT_STR(strPtr(strSub(strNew("ABCD"), 2)), "CD", "sub string");
TEST_RESULT_STR(strPtr(strSubN(strNew("ABCD"), 1, 2)), "BC", "sub string with length");
TEST_RESULT_STR(strPtr(strSub(STRDEF("ABCD"), 2)), "CD", "sub string");
TEST_RESULT_STR(strPtr(strSubN(STRDEF("ABCD"), 1, 2)), "BC", "sub string with length");
}
// *****************************************************************************************************************************
@@ -195,10 +195,10 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("strChr() and strTrunc()"))
{
TEST_RESULT_INT(strChr(strNew("abcd"), 'c'), 2, "c found");
TEST_RESULT_INT(strChr(strNew("abcd"), 'C'), -1, "capital C not found");
TEST_RESULT_INT(strChr(strNew("abcd"), 'i'), -1, "i not found");
TEST_RESULT_INT(strChr(strNew(""), 'x'), -1, "empty string - x not found");
TEST_RESULT_INT(strChr(STRDEF("abcd"), 'c'), 2, "c found");
TEST_RESULT_INT(strChr(STRDEF("abcd"), 'C'), -1, "capital C not found");
TEST_RESULT_INT(strChr(STRDEF("abcd"), 'i'), -1, "i not found");
TEST_RESULT_INT(strChr(STRDEF(""), 'x'), -1, "empty string - x not found");
String *val = strNew("abcdef");
TEST_ERROR(
@@ -218,14 +218,14 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("strToLog() and strObjToLog()"))
{
TEST_RESULT_STR(strPtr(strToLog(strNew("test"))), "{\"test\"}", "format string");
TEST_RESULT_STR(strPtr(strToLog(STRDEF("test"))), "{\"test\"}", "format string");
TEST_RESULT_STR(strPtr(strToLog(NULL)), "null", "format null string");
char buffer[256];
TEST_RESULT_UINT(strObjToLog(NULL, (StrObjToLogFormat)strToLog, buffer, sizeof(buffer)), 4, "format null string");
TEST_RESULT_STR(buffer, "null", "check null string");
TEST_RESULT_UINT(strObjToLog(strNew("teststr"), (StrObjToLogFormat)strToLog, buffer, sizeof(buffer)), 11, "format string");
TEST_RESULT_UINT(strObjToLog(STRDEF("teststr"), (StrObjToLogFormat)strToLog, buffer, sizeof(buffer)), 11, "format string");
TEST_RESULT_STR(buffer, "{\"teststr\"}", "check string");
}
@@ -289,24 +289,24 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("strLstNewSplit()"))
{
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplit(strNew(""), strNew(", ")), ", ")), "", "empty list");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplit(strNew("item1"), strNew(", ")), ", ")), "item1", "one item");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplit(STRDEF(""), STRDEF(", ")), ", ")), "", "empty list");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplit(STRDEF("item1"), STRDEF(", ")), ", ")), "item1", "one item");
TEST_RESULT_STR(
strPtr(strLstJoin(strLstNewSplit(strNew("item1, item2"), strNew(", ")), ", ")), "item1, item2", "two items");
strPtr(strLstJoin(strLstNewSplit(STRDEF("item1, item2"), STRDEF(", ")), ", ")), "item1, item2", "two items");
}
// *****************************************************************************************************************************
if (testBegin("strLstNewSplitSize()"))
{
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSize(strNew(""), strNew(" "), 0), ", ")), "", "empty list");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSizeZ(strNew("abc def"), " ", 3), "-")), "abc-def", "two items");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSizeZ(strNew("abc def"), " ", 4), "-")), "abc-def", "one items");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSizeZ(strNew("abc def ghi"), " ", 4), "-")), "abc-def-ghi", "three items");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSizeZ(strNew("abc def ghi"), " ", 8), "-")), "abc def-ghi", "three items");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSizeZ(strNew("abc def "), " ", 4), "-")), "abc-def ", "two items");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSize(STRDEF(""), STRDEF(" "), 0), ", ")), "", "empty list");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSizeZ(STRDEF("abc def"), " ", 3), "-")), "abc-def", "two items");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSizeZ(STRDEF("abc def"), " ", 4), "-")), "abc-def", "one items");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSizeZ(STRDEF("abc def ghi"), " ", 4), "-")), "abc-def-ghi", "three items");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSizeZ(STRDEF("abc def ghi"), " ", 8), "-")), "abc def-ghi", "three items");
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewSplitSizeZ(STRDEF("abc def "), " ", 4), "-")), "abc-def ", "two items");
TEST_RESULT_STR(
strPtr(strLstJoin(strLstNewSplitSize(strNew("this is a short sentence"), strNew(" "), 10), "\n")),
strPtr(strLstJoin(strLstNewSplitSize(STRDEF("this is a short sentence"), STRDEF(" "), 10), "\n")),
"this is a\n"
"short\n"
"sentence",
@@ -318,8 +318,8 @@ testRun(void)
{
VariantList *varList = varLstNew();
varLstAdd(varList, varNewStr(strNew("string1")));
varLstAdd(varList, varNewStr(strNew("string2")));
varLstAdd(varList, varNewStr(STRDEF("string1")));
varLstAdd(varList, varNewStr(STRDEF("string2")));
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewVarLst(varList), ", ")), "string1, string2", "string list from variant list");
TEST_RESULT_PTR(strLstNewVarLst(NULL), NULL, "null list from null var list");
@@ -368,8 +368,8 @@ testRun(void)
strLstAddZ(list, "A");
strLstAddZ(list, "C");
TEST_RESULT_BOOL(strLstExists(list, strNew("B")), false, "string does not exist");
TEST_RESULT_BOOL(strLstExists(list, strNew("C")), true, "string exists");
TEST_RESULT_BOOL(strLstExists(list, STRDEF("B")), false, "string does not exist");
TEST_RESULT_BOOL(strLstExists(list, STRDEF("C")), true, "string exists");
TEST_RESULT_BOOL(strLstExistsZ(list, "B"), false, "string does not exist");
TEST_RESULT_BOOL(strLstExistsZ(list, "C"), true, "string exists");
}
@@ -381,7 +381,7 @@ testRun(void)
TEST_RESULT_STR(strPtr(strLstJoin(list, ", ")), "", "empty list");
strLstAdd(list, strNew("item1"));
strLstAdd(list, STRDEF("item1"));
strLstAddZ(list, "item2");
TEST_RESULT_STR(strPtr(strLstJoin(list, ", ")), "item1, item2", "list");
@@ -463,7 +463,7 @@ testRun(void)
strLstInsertZ(list, 0, "item3");
TEST_RESULT_STR(strPtr(strLstToLog(list)), "{[\"item3\"]}", "format 1 item list");
strLstInsert(list, 0, strNew("item1"));
strLstInsert(list, 0, STRDEF("item1"));
strLstInsertZ(list, 1, "item2");
TEST_RESULT_STR(strPtr(strLstToLog(list)), "{[\"item1\", \"item2\", \"item3\"]}", "format 3 item list");
}