File DataNode.c

File List > core > DataNode.c

Go to the documentation of this file

#include "DataNode.h"
#include <libxml/tree.h>
#include "Scripting.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "AssertLib.h"
#include "Log.h"

static bool ContainsChar(const char* str, char c)
{
    while (*str)
    {
        if (*str == c)
        {
            return true;
        }
        str++;
    }
    return false;
}

static enum DNPropValType GetPropType_XMLNode(struct DataNode* pNode, const char* propName)
{
    xmlNode* pXMLNode = (xmlNode*)pNode->pData;
    xmlChar* prop = xmlGetProp(pXMLNode, (const xmlChar*)propName);
    if (prop == NULL)
    {
        return DN_PROP_NOT_FOUND;
    }
    // rudimentary type inference
    // if it looks like an int, its an int
    // if it looks like a float, its a float
    // if it looks like true/false its a bool
    // otherwise its a string
    char* endPtr = NULL;

    endPtr = NULL;
    float floatVal = strtof((const char*)prop, &endPtr);
    if (endPtr != (const char*)prop && *endPtr == '\0')
    {
        /* its a float if it has a . or an e in it, OK?! OK then... */
        if(ContainsChar((const char*)prop, '.') || ContainsChar((const char*)prop, 'e'))
        {
            xmlFree(prop);
            return DN_Float;
        }
    }

    endPtr = NULL;
    long intVal = strtol((const char*)prop, &endPtr, 10);
    if (endPtr != (const char*)prop && *endPtr == '\0')
    {
        xmlFree(prop);
        return DN_Int;
    }

    if (strcmp((const char*)prop, "true") == 0 || strcmp((const char*)prop, "false") == 0)
    {
        xmlFree(prop);
        return DN_Bool;
    }
    xmlFree(prop);
    return DN_String;
}

static float GetFloat_XML(struct DataNode* pNode, const char* propName)
{
    xmlNode* pXMLNode = (xmlNode*)pNode->pData;
    xmlChar* prop = xmlGetProp(pXMLNode, (const xmlChar*)propName);
    if (prop == NULL)
    {
        return -999999999.0;//0.0f / 0.0f; // nan
    }
    char* endPtr = NULL;
    float floatVal = strtof((const char*)prop, &endPtr);
    return floatVal;
}

static int GetInt_XML(struct DataNode* pNode, const char* propName)
{
    xmlNode* pXMLNode = (xmlNode*)pNode->pData;
    xmlChar* prop = xmlGetProp(pXMLNode, (const xmlChar*)propName);
    if (prop == NULL)
    {
        return 0;
    }
    char* endPtr = NULL;
    long intVal = strtol((const char*)prop, &endPtr, 10);
    return (int)intVal;
}

static bool GetBool_XML(struct DataNode* pNode, const char* propName)
{
    xmlNode* pXMLNode = (xmlNode*)pNode->pData;
    xmlChar* prop = xmlGetProp(pXMLNode, (const xmlChar*)propName);
    if (prop == NULL)
    {
        return false;
    }
    bool val = false;
    if (strcmp((const char*)prop, "true") == 0)
    {
        val = true;
    }
    else if(strcmp((const char*)prop, "false") == 0)
    {
        val = false;
    }
    else
    {
        Log_Error("GetBool_XML: property %s value %s is not true or false", propName, (const char*)prop);
    }
    xmlFree(prop);
    return false;
}

static size_t GetStrlen_XML(struct DataNode* pNode, const char* propName)
{
    xmlNode* pXMLNode = (xmlNode*)pNode->pData;
    xmlChar* prop = xmlGetProp(pXMLNode, (const xmlChar*)propName);
    if (prop == NULL)
    {
        return 0;
    }
    size_t len = strlen((const char*)prop);
    xmlFree(prop);
    return len;
}

static void GetStrcpy_XML(struct DataNode* pNode, const char* propName, char* dest)
{
    xmlNode* pXMLNode = (xmlNode*)pNode->pData;
    xmlChar* prop = xmlGetProp(pXMLNode, (const xmlChar*)propName);
    if (prop == NULL)
    {
        dest[0] = '\0';
        return;
    }
    strcpy(dest, (const char*)prop);
    xmlFree(prop);
}

bool StrCmp_XML(struct DataNode* pNode, const char* propName, const char* cmpTo)
{
    xmlNode* pXMLNode = (xmlNode*)pNode->pData;
    xmlChar* prop = xmlGetProp(pXMLNode, (const xmlChar*)propName);
    if (prop == NULL)
    {
        return false;
    }
    bool r = strcmp(prop, cmpTo) == 0;
    xmlFree(prop);
    return r;
}

/*
typedef size_t (*GetDNStrlenContentFn)(struct DataNode* pNode);
typedef void (*GetDNStrcpyContentFn)(struct DataNode* pNode, char* dest);
typedef bool (*GetDNStrCmpContentFn)(struct DataNode* pNode, const char* cmpTo);
*/

size_t StrLenContent_XML(struct DataNode* pNode)
{
    xmlNode* pXMLNode = (xmlNode*)pNode->pData;
    xmlChar* content = xmlNodeGetContent(pXMLNode);
    if (content == NULL)
    {
        return 0;
    }
    size_t len = strlen((const char*)content);
    xmlFree(content);
    return len;
}

void StrCpyContent_XML(struct DataNode* pNode, char* dest)
{
    xmlNode* pXMLNode = (xmlNode*)pNode->pData;
    xmlChar* content = xmlNodeGetContent(pXMLNode);
    if (content == NULL)
    {
        return;
    }
    strcpy(dest, (const char*)content);
    xmlFree(content);
}

bool StrCmpContent_XML(struct DataNode* pNode, const char* cmpTo)
{
    xmlNode* pXMLNode = (xmlNode*)pNode->pData;
    xmlChar* content = xmlNodeGetContent(pXMLNode);
    if (content == NULL)
    {
        return false;
    }
    bool r = strcmp((const char*)content, cmpTo) == 0;
    xmlFree(content);
    return r;
}

void DN_InitForXMLNode(struct DataNode* pOutNode, xmlNode* pXMLNode)
{
    pOutNode->fnGetPropType = &GetPropType_XMLNode;
    pOutNode->fnGetFloat = &GetFloat_XML;
    pOutNode->fnGetInt = &GetInt_XML;
    pOutNode->fnGetBool = &GetBool_XML;
    pOutNode->fnGetStrlen = &GetStrlen_XML;
    pOutNode->fnGetStrcpy = &GetStrcpy_XML;
    pOutNode->fnStrCmp = &StrCmp_XML;
    pOutNode->fnGetContentStrlen = &StrLenContent_XML;
    pOutNode->fnGetContentStrcpy = &StrCpyContent_XML;
    pOutNode->fnContentStrCmp = &StrCmpContent_XML;
    pOutNode->pData = pXMLNode;
}

static enum DNPropValType GetPropType_Lua(struct DataNode* pNode, const char* propName)
{
    Sc_TableGet(propName);
    if (Sc_IsNil())
    {
        Sc_Pop();
        return DN_PROP_NOT_FOUND;
    }
    else if (Sc_IsInteger())
    {
        Sc_Pop();
        return DN_Int;
    }
    else if (Sc_IsBool())
    {
        Sc_Pop();
        return DN_Bool;
    }
    else if (Sc_IsNumber())
    {
        Sc_Pop();
        return DN_Float;
    }
    else if (Sc_IsString())
    {
        Sc_Pop();
        return DN_String;
    }

    Sc_Pop();
    return DN_UNKNOWN;
}

static float GetFloat_Lua(struct DataNode* pNode, const char* propName)
{
    Sc_TableGet(propName);
    EASSERT(Sc_IsNumber());
    float val = (float)Sc_Float();
    Sc_Pop();
    return val;
}

static int GetInt_Lua(struct DataNode* pNode, const char* propName)
{
    Sc_TableGet(propName);
    EASSERT(Sc_IsInteger());
    int val = Sc_Int();
    Sc_Pop();
    return val;
}

static bool GetBool_Lua(struct DataNode* pNode, const char* propName)
{
    Sc_TableGet(propName);
    EASSERT(Sc_IsBool());
    bool val = Sc_Bool();
    Sc_Pop();
    return val;
}

static size_t GetStrlen_Lua(struct DataNode* pNode, const char* propName)
{
    Sc_TableGet(propName);
    EASSERT(Sc_IsString());
    size_t len = Sc_StackTopStringLen();
    Sc_Pop();
    return len;
}

static void GetStrcpy_Lua(struct DataNode* pNode, const char* propName, char* dest)
{
    Sc_TableGet(propName);
    EASSERT(Sc_IsString());
    Sc_StackTopStrCopy(dest);
    Sc_Pop();
}

static bool StrCmp_Lua(struct DataNode* pNode, const char* propName, const char* cmpTo)
{
    Sc_TableGet(propName);
    if (!Sc_IsString())
    {
        Log_Error("StrCmp_Lua: property %s is not a string", propName);
        Sc_Pop();
        return false;
    }
    bool r = Sc_StringCmp(cmpTo);
    Sc_Pop();
    return r;
}

size_t StrLenContent_Lua(struct DataNode* pNode)
{
    Sc_TableGet("content");
    EASSERT(Sc_IsString());
    size_t len = Sc_StackTopStringLen();
    Sc_Pop();
    return len;
}

void StrCpyContent_Lua(struct DataNode* pNode, char* dest)
{
    Sc_TableGet("content");
    EASSERT(Sc_IsString());
    Sc_StackTopStrCopy(dest);
    Sc_Pop();
}
bool StrCmpContent_Lua(struct DataNode* pNode, const char* cmpTo)
{
    Sc_TableGet("content");
    EASSERT(Sc_IsString());
    bool r = Sc_StringCmp(cmpTo);
    Sc_Pop();
    return r;
}

void DN_InitForLuaTableOnTopOfStack(struct DataNode* pOutNode)
{
    pOutNode->fnGetPropType = &GetPropType_Lua;
    pOutNode->fnGetFloat = &GetFloat_Lua;
    pOutNode->fnGetInt = &GetInt_Lua;
    pOutNode->fnGetBool = &GetBool_Lua;
    pOutNode->fnGetStrlen = &GetStrlen_Lua;
    pOutNode->fnGetStrcpy = &GetStrcpy_Lua;
    pOutNode->fnStrCmp = &StrCmp_Lua;
    pOutNode->fnGetContentStrlen = &StrLenContent_Lua;
    pOutNode->fnGetContentStrcpy = &StrCpyContent_Lua;
    pOutNode->fnContentStrCmp = &StrCmpContent_Lua;
    pOutNode->pData = NULL;
}