| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- // ================================================================================
- // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
- // == See tb_core.h for more information. ==
- // ================================================================================
- #include "tb_value.h"
- #include "tb_object.h"
- #include "tb_str.h"
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- namespace tb {
- // FIX: ## Floating point string conversions might be locale dependant. Force "." as decimal!
- // == Helper functions ============================
- char *next_token(char *&str, const char *delim) {
- str += strspn(str, delim);
- if (!*str)
- return nullptr;
- char *token = str;
- str += strcspn(str, delim);
- if (*str)
- *str++ = '\0';
- return token;
- }
- bool is_start_of_number(const char *str)
- {
- if (*str == '-')
- str++;
- if (*str == '.')
- str++;
- return *str >= '0' && *str <= '9';
- }
- bool contains_non_trailing_space(const char *str)
- {
- if (const char *p = strstr(str, " "))
- {
- while (*p == ' ')
- p++;
- return *p != '\0';
- }
- return false;
- }
- bool is_number_only(const char *s)
- {
- if (!s || *s == 0 || *s == ' ')
- return 0;
- char *p;
- strtod(s, &p);
- while (*p == ' ')
- p++;
- return *p == '\0';
- }
- bool is_number_float(const char *str)
- {
- while (*str) if (*str++ == '.') return true;
- return false;
- }
- // == TBValueArray ==================================
- TBValueArray::TBValueArray()
- {
- }
- TBValueArray::~TBValueArray()
- {
- }
- TBValue *TBValueArray::AddValue()
- {
- TBValue *v;
- if ((v = new TBValue()) && m_list.Add(v))
- return v;
- delete v;
- return nullptr;
- }
- TBValue *TBValueArray::GetValue(int index)
- {
- if (index >= 0 && index < m_list.GetNumItems())
- return m_list[index];
- return nullptr;
- }
- TBValueArray *TBValueArray::Clone(TBValueArray *source)
- {
- TBValueArray *new_arr = new TBValueArray;
- if (!new_arr)
- return nullptr;
- for (int i = 0; i < source->m_list.GetNumItems(); i++)
- {
- TBValue *new_val = new_arr->AddValue();
- if (!new_val)
- {
- delete new_arr;
- return nullptr;
- }
- new_val->Copy(*source->GetValue(i));
- }
- return new_arr;
- }
- // == TBValue =======================================
- TBValue::TBValue()
- : m_packed_init(0)
- {
- }
- TBValue::TBValue(const TBValue &value)
- : m_packed_init(0)
- {
- Copy(value);
- }
- TBValue::TBValue(TYPE type)
- : m_packed_init(0)
- {
- switch (type)
- {
- case TYPE_NULL:
- SetNull();
- break;
- case TYPE_STRING:
- SetString("", SET_AS_STATIC);
- break;
- case TYPE_FLOAT:
- SetFloat(0);
- break;
- case TYPE_INT:
- SetInt(0);
- break;
- case TYPE_OBJECT:
- SetObject(nullptr);
- break;
- case TYPE_ARRAY:
- if (TBValueArray *arr = new TBValueArray())
- SetArray(arr, SET_TAKE_OWNERSHIP);
- break;
- default:
- assert(!"Not implemented!");
- };
- }
- TBValue::TBValue(int value)
- : m_packed_init(0)
- {
- SetInt(value);
- }
- TBValue::TBValue(float value)
- : m_packed_init(0)
- {
- SetFloat(value);
- }
- TBValue::TBValue(const char *value, SET set)
- : m_packed_init(0)
- {
- SetString(value, set);
- }
- TBValue::TBValue(TBTypedObject *object)
- : m_packed_init(0)
- {
- SetObject(object);
- }
- TBValue::~TBValue()
- {
- SetNull();
- }
- void TBValue::TakeOver(TBValue &source_value)
- {
- if (source_value.m_packed.type == TYPE_STRING)
- SetString(source_value.val_str, source_value.m_packed.allocated ? SET_TAKE_OWNERSHIP : SET_NEW_COPY);
- else if (source_value.m_packed.type == TYPE_ARRAY)
- SetArray(source_value.val_arr, source_value.m_packed.allocated ? SET_TAKE_OWNERSHIP : SET_NEW_COPY);
- else
- *this = source_value;
- source_value.m_packed.type = TYPE_NULL;
- }
- void TBValue::Copy(const TBValue &source_value)
- {
- if (source_value.m_packed.type == TYPE_STRING)
- SetString(source_value.val_str, SET_NEW_COPY);
- else if (source_value.m_packed.type == TYPE_ARRAY)
- SetArray(source_value.val_arr, SET_NEW_COPY);
- else if (source_value.m_packed.type == TYPE_OBJECT)
- {
- assert(!"We can't copy objects! The value will be nulled!");
- SetObject(nullptr);
- }
- else
- {
- SetNull();
- memcpy(this, &source_value, sizeof(TBValue));
- }
- }
- void TBValue::SetNull()
- {
- if (m_packed.allocated)
- {
- if (m_packed.type == TYPE_STRING)
- free(val_str);
- else if (m_packed.type == TYPE_OBJECT)
- delete val_obj;
- else if (m_packed.type == TYPE_ARRAY)
- delete val_arr;
- }
- m_packed.type = TYPE_NULL;
- }
- void TBValue::SetInt(int val)
- {
- SetNull();
- m_packed.type = TYPE_INT;
- val_int = val;
- }
- void TBValue::SetFloat(float val)
- {
- SetNull();
- m_packed.type = TYPE_FLOAT;
- val_float = val;
- }
- void TBValue::SetString(const char *val, SET set)
- {
- SetNull();
- m_packed.allocated = (set == SET_NEW_COPY || set == SET_TAKE_OWNERSHIP);
- if (set != SET_NEW_COPY)
- {
- val_str = const_cast<char *>(val);
- m_packed.type = TYPE_STRING;
- }
- else if ((val_str = strdup(val)))
- m_packed.type = TYPE_STRING;
- }
- void TBValue::SetObject(TBTypedObject *object)
- {
- SetNull();
- m_packed.type = TYPE_OBJECT;
- m_packed.allocated = true;
- val_obj = object;
- }
- void TBValue::SetArray(TBValueArray *arr, SET set)
- {
- SetNull();
- m_packed.allocated = (set == SET_NEW_COPY || set == SET_TAKE_OWNERSHIP);
- if (set != SET_NEW_COPY)
- {
- val_arr = arr;
- m_packed.type = TYPE_ARRAY;
- }
- else if ((val_arr = TBValueArray::Clone(arr)))
- m_packed.type = TYPE_ARRAY;
- }
- void TBValue::SetFromStringAuto(const char *str, SET set)
- {
- if (!str)
- SetNull();
- else if (is_number_only(str))
- {
- if (is_number_float(str))
- SetFloat((float)atof(str));
- else
- SetInt(atoi(str));
- }
- else if (is_start_of_number(str) && contains_non_trailing_space(str))
- {
- // If the number has nontrailing space, we'll assume a list of numbers (example: "10 -4 3.5")
- SetNull();
- if (TBValueArray *arr = new TBValueArray)
- {
- TBStr tmpstr;
- if (tmpstr.Set(str))
- {
- char *str_next = tmpstr.CStr();
- while (char *token = next_token(str_next, ", "))
- {
- if (TBValue *new_val = arr->AddValue())
- new_val->SetFromStringAuto(token, SET_NEW_COPY);
- }
- }
- SetArray(arr, SET_TAKE_OWNERSHIP);
- }
- }
- else if (*str == '[')
- {
- SetNull();
- if (TBValueArray *arr = new TBValueArray)
- {
- assert(!"not implemented! Split out the tokenizer code above!");
- SetArray(arr, SET_TAKE_OWNERSHIP);
- }
- }
- else
- {
- SetString(str, set);
- return;
- }
- // We didn't set as string, so we might need to deal with the passed in string data.
- if (set == SET_TAKE_OWNERSHIP)
- {
- // Delete the passed in data
- TBValue tmp;
- tmp.SetString(str, SET_TAKE_OWNERSHIP);
- }
- }
- int TBValue::GetInt() const
- {
- if (m_packed.type == TYPE_STRING)
- return atoi(val_str);
- else if (m_packed.type == TYPE_FLOAT)
- return (int) val_float;
- return m_packed.type == TYPE_INT ? val_int : 0;
- }
- float TBValue::GetFloat() const
- {
- if (m_packed.type == TYPE_STRING)
- return (float) atof(val_str);
- else if (m_packed.type == TYPE_INT)
- return (float) val_int;
- return m_packed.type == TYPE_FLOAT ? val_float : 0;
- }
- const char *TBValue::GetString()
- {
- if (m_packed.type == TYPE_INT)
- {
- char tmp[32];
- sprintf(tmp, "%d", val_int);
- SetString(tmp, SET_NEW_COPY);
- }
- else if (m_packed.type == TYPE_FLOAT)
- {
- char tmp[32];
- sprintf(tmp, "%f", val_float);
- SetString(tmp, SET_NEW_COPY);
- }
- else if (m_packed.type == TYPE_OBJECT)
- return val_obj ? val_obj->GetClassName() : "";
- return m_packed.type == TYPE_STRING ? val_str : "";
- }
- }; // namespace tb
|