You've already forked pgbackrest
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:
@@ -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>
|
||||
|
||||
|
@@ -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 \
|
||||
|
@@ -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
|
||||
***********************************************************************************************************************************/
|
||||
|
@@ -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
507
src/common/type/variant.c
Normal 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
59
src/common/type/variant.h
Normal 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
|
92
src/common/type/variantList.c
Normal file
92
src/common/type/variantList.c
Normal 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);
|
||||
}
|
25
src/common/type/variantList.h
Normal file
25
src/common/type/variantList.h
Normal 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
|
@@ -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,
|
||||
|
@@ -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()"))
|
||||
{
|
||||
|
57
test/src/module/common/typeVariantListTest.c
Normal file
57
test/src/module/common/typeVariantListTest.c
Normal 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");
|
||||
}
|
||||
}
|
195
test/src/module/common/typeVariantTest.c
Normal file
195
test/src/module/common/typeVariantTest.c
Normal 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");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user