1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-09-16 09:06:18 +02:00

Add Variant and VariantList objects.

This commit is contained in:
David Steele
2017-12-22 21:50:27 -05:00
parent c4b30af645
commit 2add6cef95
12 changed files with 996 additions and 1 deletions

View File

@@ -80,6 +80,10 @@
<release-item>
<p>Add <code>Buffer</code> object.</p>
</release-item>
<release-item>
<p>Add <code>Variant</code> and <code>VariantList</code> objects.</p>
</release-item>
</release-development-list>
</release-core-list>

View File

@@ -10,6 +10,8 @@ pgbackrest: \
common/type/list.o \
common/type/string.o \
common/type/stringList.o \
common/type/variant.o \
common/type/variantList.o \
config/config.o \
config/define.o \
config/parse.o \
@@ -23,6 +25,8 @@ pgbackrest: \
common/type/list.o \
common/type/string.o \
common/type/stringList.o \
common/type/variant.o \
common/type/variantList.o \
config/config.o \
config/define.o \
config/parse.o \

View File

@@ -53,6 +53,22 @@ strLstNewSplit(const String *string, const String *delimiter)
return this;
}
/***********************************************************************************************************************************
New string list from a variant list -- all variants in the list must be type string
***********************************************************************************************************************************/
StringList *
strLstNewVarLst(const VariantList *sourceList)
{
// Create the list
StringList *this = strLstNew();
// Copy variants
for (unsigned int listIdx = 0; listIdx < varLstSize(sourceList); listIdx++)
strLstAdd(this, varStr(varLstGet(sourceList, listIdx)));
return this;
}
/***********************************************************************************************************************************
Duplicate a string list
***********************************************************************************************************************************/

View File

@@ -14,8 +14,11 @@ typedef struct StringList StringList;
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
#include "common/type/variantList.h"
StringList *strLstNew();
StringList *strLstNewSplit(const String *string, const String *delimiter);
StringList *strLstNewVarLst(const VariantList *sourceList);
StringList *strLstDup(const StringList *sourceList);
StringList *strLstAdd(StringList *this, String *string);

507
src/common/type/variant.c Normal file
View File

@@ -0,0 +1,507 @@
/***********************************************************************************************************************************
Variant Data Type
***********************************************************************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "common/errorType.h"
#include "common/memContext.h"
#include "common/type/variant.h"
/***********************************************************************************************************************************
Information about the variant
***********************************************************************************************************************************/
struct Variant
{
MemContext *memContext; // Mem context
unsigned int type:3; // Variant Type
};
/***********************************************************************************************************************************
Variant type names
***********************************************************************************************************************************/
static const char *variantTypeName[] =
{
"bool", // varTypeBool
"double", // varTypeDouble,
"int", // varTypeInt
"KeyValue", // varTypeKeyValue
"String", // varTypeString
"VariantList", // varTypeVariantList
};
/***********************************************************************************************************************************
New variant of any supported type
***********************************************************************************************************************************/
static Variant *
varNewInternal(VariantType type, void *data, size_t dataSize)
{
// Allocate memory for the variant and set the type
Variant *this = memNew(sizeof(Variant) + dataSize);
this->memContext = memContextCurrent();
this->type = type;
// Copy data if there is any
if (dataSize > 0)
memcpy((unsigned char *)this + sizeof(Variant), data, dataSize);
return this;
}
/***********************************************************************************************************************************
Get a pointer to the data stored in the variant. This hides the complicated pointer arithmetic.
***********************************************************************************************************************************/
static void *
varData(const Variant *this)
{
return (void *)((unsigned char *)this + sizeof(Variant));
}
/***********************************************************************************************************************************
Duplicate a variant
***********************************************************************************************************************************/
Variant *
varDup(const Variant *this)
{
Variant *result = NULL;
if (this != NULL)
{
switch (this->type)
{
case varTypeBool:
{
result = varNewBool(varBool(this));
break;
}
case varTypeDouble:
{
result = varNewDbl(varDbl(this));
break;
}
case varTypeInt:
{
result = varNewInt(varInt(this));
break;
}
case varTypeString:
{
result = varNewStr(varStr(this));
break;
}
case varTypeVariantList:
{
result = varNewVarLst(varVarLst(this));
break;
}
}
}
return result;
}
/***********************************************************************************************************************************
Test if variants are equal
***********************************************************************************************************************************/
bool
varEq(const Variant *this1, const Variant *this2)
{
bool result = false;
// Test if both variants are non-null
if (this1 != NULL && this2 != NULL)
{
// Test if both variants are of the same type
if (varType(this1) == varType(this2))
{
switch (varType(this1))
{
case varTypeBool:
{
result = varBool(this1) == varBool(this2);
break;
}
case varTypeDouble:
{
result = varDbl(this1) == varDbl(this2);
break;
}
case varTypeInt:
{
result = varInt(this1) == varInt(this2);
break;
}
case varTypeString:
{
result = strEq(varStr(this1), varStr(this2));
break;
}
default:
THROW(AssertError, "unable to test equality for %s", variantTypeName[this1->type]);
}
}
}
// Else they are equal if they are both null
else
result = this1 == NULL && this2 == NULL;
return result;
}
/***********************************************************************************************************************************
Get variant type
***********************************************************************************************************************************/
VariantType
varType(const Variant *this)
{
return this->type;
}
/***********************************************************************************************************************************
New bool variant
***********************************************************************************************************************************/
Variant *
varNewBool(bool data)
{
return varNewInternal(varTypeBool, (void *)&data, sizeof(data));
}
/***********************************************************************************************************************************
Return bool
***********************************************************************************************************************************/
bool
varBool(const Variant *this)
{
// Only valid for int
if (this->type != varTypeBool)
THROW(AssertError, "variant type is not bool");
// Get the int
return *((bool *)varData(this));
}
/***********************************************************************************************************************************
Return bool regardless of variant type
***********************************************************************************************************************************/
bool
varBoolForce(const Variant *this)
{
int result = 0;
switch (this->type)
{
case varTypeBool:
result = varBool(this);
break;
case varTypeInt:
result = varInt(this) != 0;
break;
case varTypeString:
{
// List of false/true boolean string values. Note that false/true values must be equal.
static const char *boolString[] =
{
"n", "f", "0", "no", "false", "off",
"y", "t", "1", "yes", "true", "on",
};
// Search for the string
const char *string = strPtr(varStr(this));
unsigned int boolIdx;
for (boolIdx = 0; boolIdx < sizeof(boolString) / sizeof(char *); boolIdx++)
if (strcasecmp(string, boolString[boolIdx]) == 0)
break;
// If string was not found then not a boolean
if (boolIdx == sizeof(boolString) / sizeof(char *))
THROW(FormatError, "unable to convert str '%s' to bool", string);
// False if in first half of list, true if in second half
result = boolIdx / (sizeof(boolString) / sizeof(char *) / 2);
break;
}
default:
THROW(FormatError, "unable to force %s to %s", variantTypeName[this->type], variantTypeName[varTypeBool]);
}
return result;
}
/***********************************************************************************************************************************
New double variant
***********************************************************************************************************************************/
Variant *
varNewDbl(double data)
{
return varNewInternal(varTypeDouble, (unsigned char *)&data, sizeof(data));
}
/***********************************************************************************************************************************
Return double
***********************************************************************************************************************************/
double
varDbl(const Variant *this)
{
// Only valid for double
if (this->type != varTypeDouble)
THROW(AssertError, "variant type is not double");
// Get the int
return *((double *)varData(this));
}
/***********************************************************************************************************************************
Return double regardless of variant type
***********************************************************************************************************************************/
double
varDblForce(const Variant *this)
{
double result = 0;
switch (this->type)
{
case varTypeBool:
{
result = varBool(this);
break;
}
case varTypeDouble:
{
result = varDbl(this);
break;
}
case varTypeInt:
{
result = varInt(this);
break;
}
case varTypeString:
{
sscanf(strPtr(varStr(this)), "%lf", &result);
if (result == 0 && strcmp(strPtr(varStr(this)), "0") != 0)
{
THROW(
FormatError, "unable to force %s '%s' to %s", variantTypeName[this->type], strPtr(varStr(this)),
variantTypeName[varTypeDouble]);
}
break;
}
default:
THROW(FormatError, "unable to force %s to %s", variantTypeName[this->type], variantTypeName[varTypeDouble]);
}
return result;
}
/***********************************************************************************************************************************
New int variant
***********************************************************************************************************************************/
Variant *
varNewInt(int data)
{
return varNewInternal(varTypeInt, (void *)&data, sizeof(data));
}
/***********************************************************************************************************************************
Return int
***********************************************************************************************************************************/
int
varInt(const Variant *this)
{
// Only valid for int
if (this->type != varTypeInt)
THROW(AssertError, "variant type is not int");
// Get the int
return *((int *)varData(this));
}
/***********************************************************************************************************************************
Return int regardless of variant type
***********************************************************************************************************************************/
int
varIntForce(const Variant *this)
{
int result = 0;
switch (this->type)
{
case varTypeBool:
{
result = varBool(this);
break;
}
case varTypeInt:
{
result = varInt(this);
break;
}
case varTypeString:
{
result = atoi(strPtr(varStr(this)));
if (result == 0 && strcmp(strPtr(varStr(this)), "0") != 0)
THROW(FormatError, "unable to convert str '%s' to int", strPtr(varStr(this)));
break;
}
default:
THROW(FormatError, "unable to force %s to %s", variantTypeName[this->type], variantTypeName[varTypeInt]);
}
return result;
}
/***********************************************************************************************************************************
New string variant
***********************************************************************************************************************************/
Variant *
varNewStr(const String *data)
{
// Make sure the string is not NULL
if (data == NULL)
THROW(AssertError, "string variant cannot be NULL");
// Create the variant
String *dataCopy = strDup(data);
return varNewInternal(varTypeString, (void *)&dataCopy, sizeof(dataCopy));
}
/***********************************************************************************************************************************
New string variant from a zero-terminated string
***********************************************************************************************************************************/
Variant *
varNewStrZ(const char *data)
{
// Make sure the string is not NULL
if (data == NULL)
THROW(AssertError, "zero-terminated string cannot be NULL");
// Create the variant
String *dataCopy = strNew(data);
return varNewInternal(varTypeString, (void *)&dataCopy, sizeof(dataCopy));
}
/***********************************************************************************************************************************
Return string
***********************************************************************************************************************************/
String *
varStr(const Variant *this)
{
String *result = NULL;
if (this != NULL)
{
// Only valid for strings
if (this->type != varTypeString)
THROW(AssertError, "variant type is not string");
// Get the string
result = *((String **)varData(this));
}
return result;
}
/***********************************************************************************************************************************
New variant list variant
***********************************************************************************************************************************/
Variant *
varNewVarLst(const VariantList *data)
{
// Create the variant
VariantList *dataCopy = varLstDup(data);
return varNewInternal(varTypeVariantList, (void *)&dataCopy, sizeof(dataCopy));
}
/***********************************************************************************************************************************
New empty variant list variant
***********************************************************************************************************************************/
Variant *
varNewVarLstEmpty()
{
// Create the variant
VariantList *data = varLstNew();
return varNewInternal(varTypeVariantList, (void *)&data, sizeof(data));
}
/***********************************************************************************************************************************
Return key/value
***********************************************************************************************************************************/
VariantList *
varVarLst(const Variant *this)
{
VariantList *result = NULL;
if (this != NULL)
{
// Only valid for key/value
if (this->type != varTypeVariantList)
THROW(AssertError, "variant type is not '%s'", variantTypeName[varTypeVariantList]);
// Get the string
result = *((VariantList **)varData(this));
}
return result;
}
/***********************************************************************************************************************************
Free variant
***********************************************************************************************************************************/
void
varFree(Variant *this)
{
if (this != NULL)
{
MEM_CONTEXT_BEGIN(this->memContext)
{
switch (this->type)
{
case varTypeString:
{
strFree(varStr(this));
break;
}
case varTypeVariantList:
{
varLstFree(varVarLst(this));
break;
}
// Nothing additional to free for these types
case varTypeBool:
case varTypeDouble:
case varTypeInt:
break;
}
memFree(this);
}
MEM_CONTEXT_END();
}
}

59
src/common/type/variant.h Normal file
View File

@@ -0,0 +1,59 @@
/***********************************************************************************************************************************
Variant Data Type
***********************************************************************************************************************************/
#ifndef COMMON_TYPE_VARIANT_H
#define COMMON_TYPE_VARIANT_H
#include <stdbool.h>
/***********************************************************************************************************************************
Variant type
***********************************************************************************************************************************/
typedef enum
{
varTypeBool,
varTypeDouble,
varTypeInt,
varTypeKeyValue,
varTypeString,
varTypeVariantList,
} VariantType;
/***********************************************************************************************************************************
Variant object
***********************************************************************************************************************************/
typedef struct Variant Variant;
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
#include "common/type/string.h"
#include "common/type/variantList.h"
Variant *varNewBool(bool data);
bool varBool(const Variant *this);
bool varBoolForce(const Variant *this);
Variant *varNewDbl(double data);
double varDbl(const Variant *this);
double varDblForce(const Variant *this);
Variant *varNewInt(int data);
int varInt(const Variant *this);
int varIntForce(const Variant *this);
Variant *varNewStr(const String *data);
Variant *varNewStrZ(const char *data);
String *varStr(const Variant *this);
Variant *varNewVarLst(const VariantList *data);
Variant *varNewVarLstEmpty();
VariantList *varVarLst(const Variant *this);
Variant *varDup(const Variant *this);
bool varEq(const Variant *this1, const Variant *this2);
VariantType varType(const Variant *this);
void varFree(Variant *this);
#endif

View File

@@ -0,0 +1,92 @@
/***********************************************************************************************************************************
Variant List Handler
***********************************************************************************************************************************/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "common/memContext.h"
#include "common/type/list.h"
#include "common/type/variantList.h"
/***********************************************************************************************************************************
Wrapper for lstNew()
***********************************************************************************************************************************/
VariantList *
varLstNew()
{
return (VariantList *)lstNew(sizeof(Variant *));
}
/***********************************************************************************************************************************
Create a variant list from a string list
***********************************************************************************************************************************/
VariantList *
varLstNewStrLst(const StringList *stringList)
{
VariantList *result = NULL;
if (stringList != NULL)
{
result = varLstNew();
for (unsigned int listIdx = 0; listIdx < strLstSize(stringList); listIdx++)
varLstAdd(result, varNewStr(strLstGet(stringList, listIdx)));
}
return result;
}
/***********************************************************************************************************************************
Duplicate a variant list
***********************************************************************************************************************************/
VariantList *
varLstDup(const VariantList *source)
{
VariantList *result = NULL;
if (source != NULL)
{
result = varLstNew();
for (unsigned int listIdx = 0; listIdx < varLstSize(source); listIdx++)
varLstAdd(result, varDup(varLstGet(source, listIdx)));
}
return result;
}
/***********************************************************************************************************************************
Wrapper for lstAdd()
***********************************************************************************************************************************/
VariantList *
varLstAdd(VariantList *this, Variant *data)
{
return (VariantList *)lstAdd((List *)this, &data);
}
/***********************************************************************************************************************************
Wrapper for lstGet()
***********************************************************************************************************************************/
Variant *
varLstGet(const VariantList *this, unsigned int listIdx)
{
return *(Variant **)lstGet((List *)this, listIdx);
}
/***********************************************************************************************************************************
Wrapper for lstSize()
***********************************************************************************************************************************/
unsigned int
varLstSize(const VariantList *this)
{
return lstSize((List *)this);
}
/***********************************************************************************************************************************
Wrapper for lstFree()
***********************************************************************************************************************************/
void varLstFree(VariantList *this)
{
lstFree((List *)this);
}

View File

@@ -0,0 +1,25 @@
/***********************************************************************************************************************************
Variant List Handler
***********************************************************************************************************************************/
#ifndef COMMON_TYPE_VARIANT_LIST_H
#define COMMON_TYPE_VARIANT_LIST_H
/***********************************************************************************************************************************
Variant list type
***********************************************************************************************************************************/
typedef struct VariantList VariantList;
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
#include "common/type/variant.h"
VariantList *varLstNew();
VariantList *varLstNewStrLst(const StringList *stringList);
VariantList *varLstDup(const VariantList *source);
VariantList *varLstAdd(VariantList *this, Variant *data);
Variant *varLstGet(const VariantList *this, unsigned int listIdx);
unsigned int varLstSize(const VariantList *this);
void varLstFree(VariantList *this);
#endif

View File

@@ -153,7 +153,7 @@ my $oTestDef =
},
{
&TESTDEF_NAME => 'type-string-list',
&TESTDEF_TOTAL => 4,
&TESTDEF_TOTAL => 5,
&TESTDEF_C => true,
&TESTDEF_COVERAGE =>
@@ -171,6 +171,26 @@ my $oTestDef =
'common/type/buffer' => TESTDEF_COVERAGE_FULL,
},
},
{
&TESTDEF_NAME => 'type-variant',
&TESTDEF_TOTAL => 5,
&TESTDEF_C => true,
&TESTDEF_COVERAGE =>
{
'common/type/variant' => TESTDEF_COVERAGE_FULL,
},
},
{
&TESTDEF_NAME => 'type-variant-list',
&TESTDEF_TOTAL => 3,
&TESTDEF_C => true,
&TESTDEF_COVERAGE =>
{
'common/type/variantList' => TESTDEF_COVERAGE_FULL,
},
},
{
&TESTDEF_NAME => 'encode',
&TESTDEF_TOTAL => 1,

View File

@@ -73,6 +73,19 @@ void testRun()
strLstFree(list);
}
// *****************************************************************************************************************************
if (testBegin("strLstNewVarLst()"))
{
VariantList *varList = varLstNew();
varLstAdd(varList, varNewStr(strNew("string1")));
varLstAdd(varList, varNewStr(strNew("string2")));
TEST_RESULT_STR(strPtr(strLstJoin(strLstNewVarLst(varList), ", ")), "string1, string2", "string list from variant list");
varLstFree(varList);
}
// *****************************************************************************************************************************
if (testBegin("strLstJoin()"))
{

View File

@@ -0,0 +1,57 @@
/***********************************************************************************************************************************
Test Variant Lists
***********************************************************************************************************************************/
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void testRun()
{
// *****************************************************************************************************************************
if (testBegin("varLstNew(), varLstAdd(), varLstSize(), varLstGet(), and varListFree()"))
{
VariantList *list = NULL;
TEST_ASSIGN(list, varLstNew(), "new list");
TEST_RESULT_PTR(varLstAdd(list, varNewInt(27)), list, "add int");
TEST_RESULT_PTR(varLstAdd(list, varNewStr(strNew("test-str"))), list, "add string");
TEST_RESULT_INT(varLstSize(list), 2, "list size");
TEST_RESULT_INT(varInt(varLstGet(list, 0)), 27, "check int");
TEST_RESULT_STR(strPtr(varStr(varLstGet(list, 1))), "test-str", "check string");
TEST_RESULT_VOID(varLstFree(list), "free list");
}
// *****************************************************************************************************************************
if (testBegin("varLstDup()"))
{
VariantList *list = varLstNew();
varLstAdd(list, varNewStr(strNew("string1")));
varLstAdd(list, varNewStr(strNew("string2")));
TEST_RESULT_STR(
strPtr(strLstJoin(strLstNewVarLst(varLstDup(list)), ", ")),
"string1, string2", "duplicate variant list");
TEST_RESULT_PTR(varLstDup(NULL), NULL, "duplicate null list");
}
// *****************************************************************************************************************************
if (testBegin("varLstNewStrLst()"))
{
StringList *listStr = strLstNew();
strLstAdd(listStr, strNew("string1"));
strLstAdd(listStr, strNew("string2"));
TEST_RESULT_STR(
strPtr(strLstJoin(strLstNewVarLst(varLstNewStrLst(listStr)), ", ")),
"string1, string2", "variant list from string list");
TEST_RESULT_PTR(varLstNewStrLst(NULL), NULL, "variant list from null string list");
}
}

View File

@@ -0,0 +1,195 @@
/***********************************************************************************************************************************
Test Variant Data Type
***********************************************************************************************************************************/
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void testRun()
{
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("bool"))
{
Variant *boolean = varNewBool(false);
boolean->type = varTypeString;
TEST_ERROR(varBool(boolean), AssertError, "variant type is not bool");
boolean->type = varTypeBool;
varFree(boolean);
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_BOOL(varBool(varNewBool(true)), true, "true bool variant");
TEST_RESULT_BOOL(varBool(varNewBool(false)), false, "false bool variant");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_BOOL(varBoolForce(varNewBool(false)), false, "force bool to bool");
TEST_RESULT_BOOL(varBoolForce(varNewInt(1)), true, "force int to bool");
TEST_ERROR(varBoolForce(varNewVarLstEmpty()), FormatError, "unable to force VariantList to bool");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_VOID(varFree(NULL), "ok to free null variant");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_BOOL(varBool(varDup(varNewBool(true))), true, "dup bool");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_BOOL(varEq(varNewBool(true), varNewInt(1)), false, "bool, int not eq");
TEST_RESULT_BOOL(varEq(varNewBool(true), varNewBool(true)), true, "bool, bool eq");
TEST_RESULT_BOOL(varEq(varNewBool(false), varNewBool(true)), false, "bool, bool not eq");
}
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("double"))
{
Variant *var = varNewDbl(44.44);
TEST_RESULT_DOUBLE(varDbl(var), 44.44, "double variant");
varFree(var);
// -------------------------------------------------------------------------------------------------------------------------
var = varNewDbl(-1.1);
var->type = varTypeString;
TEST_ERROR(varDbl(var), AssertError, "variant type is not double");
var->type = varTypeDouble;
varFree(var);
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_DOUBLE(varDblForce(varNewDbl(4.567)), 4.567, "force double to double");
TEST_RESULT_DOUBLE(varDblForce(varNewBool(false)), 0, "force bool to double");
TEST_RESULT_DOUBLE(varDblForce(varNewInt(123)), 123, "force int to double");
TEST_RESULT_DOUBLE(varDblForce(varNewStr(strNew("879.01"))), 879.01, "force String to double");
TEST_ERROR(varDblForce(varNewStr(strNew("AAA"))), FormatError, "unable to force String 'AAA' to double");
TEST_ERROR(varDblForce(varNewVarLstEmpty()), FormatError, "unable to force VariantList to double");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_DOUBLE(varDbl(varDup(varNewDbl(3.1415))), 3.1415, "dup double");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_BOOL(varEq(varNewDbl(1.234), varNewDbl(1.234)), true, "double, double eq");
TEST_RESULT_BOOL(varEq(varNewDbl(4.321), varNewDbl(1.234)), false, "double, double not eq");
}
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("int"))
{
Variant *integer = varNewInt(44);
TEST_RESULT_INT(varInt(integer), 44, "int variant");
TEST_RESULT_INT(varIntForce(integer), 44, "force int to int");
varFree(integer);
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_INT(varIntForce(varNewBool(true)), 1, "force bool to int");
TEST_ERROR(varIntForce(varNewVarLstEmpty()), FormatError, "unable to force VariantList to int");
// -------------------------------------------------------------------------------------------------------------------------
integer = varNewInt(-1);
integer->type = varTypeString;
TEST_ERROR(varInt(integer), AssertError, "variant type is not int");
integer->type = varTypeInt;
varFree(integer);
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_INT(varInt(varDup(varNewInt(88976))), 88976, "dup int");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_BOOL(varEq(NULL, NULL), true, "null, null eq");
TEST_RESULT_BOOL(varEq(NULL, varNewInt(123)), false, "null, int not eq");
TEST_RESULT_BOOL(varEq(varNewInt(123), varNewInt(123)), true, "int, int eq");
TEST_RESULT_BOOL(varEq(varNewInt(444), varNewInt(123)), false, "int, int not eq");
}
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("String"))
{
TEST_ERROR(varNewStr(NULL), AssertError, "string variant cannot be NULL");
// -------------------------------------------------------------------------------------------------------------------------
Variant *string = varNewStr(strNew("test-str"));
TEST_RESULT_STR(strPtr(varStr(string)), "test-str", "string pointer");
varFree(string);
// -------------------------------------------------------------------------------------------------------------------------
string = varNewStr(strNew("not-a-string"));
string->type = varTypeInt;
TEST_ERROR(strPtr(varStr(string)), AssertError, "variant type is not string");
varFree(string);
// -------------------------------------------------------------------------------------------------------------------------
string = varNewStr(strNew("777"));
TEST_RESULT_INT(varIntForce(string), 777, "int from string");
varFree(string);
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_INT(varBoolForce(varNewStr(strNew("y"))), true, "bool from string");
TEST_RESULT_INT(varBoolForce(varNewStr(strNew("on"))), true, "bool from string");
TEST_RESULT_INT(varBoolForce(varNewStr(strNew("n"))), false, "bool from string");
TEST_RESULT_INT(varBoolForce(varNewStr(strNew("off"))), false, "bool from string");
TEST_RESULT_INT(varBoolForce(varNewStr(strNew("OFF"))), false, "bool from string");
TEST_ERROR(varBoolForce(varNewStr(strNew(BOGUS_STR))), FormatError, "unable to convert str 'BOGUS' to bool");
// -------------------------------------------------------------------------------------------------------------------------
string = varNewStr(strNew("not-an-int"));
TEST_ERROR(varIntForce(string), FormatError, "unable to convert str 'not-an-int' to int");
varFree(string);
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_STR(strPtr(varStr(varNewStrZ("test-z-str"))), "test-z-str", "new zero-terminated string");
TEST_ERROR(varNewStrZ(NULL), AssertError, "zero-terminated string cannot be NULL");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_STR(strPtr(varStr(varDup(varNewStr(strNew("yabba-dabba-doo"))))), "yabba-dabba-doo", "dup string");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_PTR(varDup(NULL), NULL, "dup NULL");
TEST_RESULT_BOOL(varEq(varNewStr(strNew("expect-equal")), varNewStr(strNew("expect-equal"))), true, "string, string eq");
TEST_RESULT_BOOL(varEq(varNewStr(strNew("Y")), varNewStr(strNew("X"))), false, "string, string not eq");
}
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("VariantList"))
{
TEST_ERROR(varVarLst(varNewInt(66)), AssertError, "variant type is not 'VariantList'");
// -------------------------------------------------------------------------------------------------------------------------
Variant *listVar = NULL;
TEST_ASSIGN(listVar, varNewVarLstEmpty(), "new empty");
TEST_RESULT_INT(varLstSize(varVarLst(listVar)), 0, " empty size");
TEST_RESULT_PTR(varLstAdd(varVarLst(listVar), varNewBool(true)), varVarLst(listVar), " add bool");
TEST_RESULT_PTR(varLstAdd(varVarLst(listVar), varNewInt(55)), varVarLst(listVar), " add int");
TEST_RESULT_INT(varLstSize(varVarLst(listVar)), 2, " size with items");
TEST_RESULT_BOOL(varBool(varLstGet(varVarLst(listVar), 0)), true, " get bool");
TEST_RESULT_INT(varInt(varLstGet(varVarLst(listVar), 1)), 55, " get int");
// -------------------------------------------------------------------------------------------------------------------------
TEST_ASSIGN(listVar, varNewVarLst(varVarLst(listVar)), "new with items");
TEST_RESULT_INT(varLstSize(varVarLst(listVar)), 2, " size with items");
// -------------------------------------------------------------------------------------------------------------------------
Variant *listVarDup = NULL;
TEST_ASSIGN(listVarDup, varDup(listVar), "duplicate");
TEST_RESULT_INT(varLstSize(varVarLst(listVarDup)), 2, " size with items");
varFree(listVar);
varFree(listVarDup);
// -------------------------------------------------------------------------------------------------------------------------
TEST_ERROR(varEq(varNewVarLstEmpty(), varNewVarLstEmpty()), AssertError, "unable to test equality for VariantList");
}
}