blob: ec99f90dc8e7192aa63378f23bf8e17bbc26097a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
#include "stdafx.h"
#include "Value.h"
Value::Value() {
m_type = TYPE_UNDEFINED;
m_arrayValue = NULL;
m_numberValue = 0;
m_objectValue = NULL;
m_stringValue = NULL;
}
Value::Value(bool value) {
setValue(value);
}
Value::Value(double value) {
setValue(value);
}
Value::Value(const wchar_t* value) {
setValue(value);
}
Value::Value(std::wstring* value) {
setValue(value);
}
Value::~Value() {
clearCurrentValue();
}
void Value::clearCurrentValue() {
switch (m_type) {
case TYPE_STRING: {
delete m_stringValue;
break;
}
case TYPE_ARRAY: {
std::vector<Value*>::iterator iterator = m_arrayValue->begin();
std::vector<Value*>::iterator end = m_arrayValue->end();
while (iterator != end) {
delete *iterator;
iterator++;
}
delete m_arrayValue;
break;
}
case TYPE_OBJECT: {
std::map<std::wstring, Value*>::iterator it = m_objectValue->begin();
std::map<std::wstring, Value*>::iterator end = m_objectValue->end();
while (it != end) {
delete (*it).second;
it++;
}
delete m_objectValue;
break;
}
}
m_type = TYPE_UNDEFINED;
}
void Value::clone(Value** _value) {
switch (getType()) {
case TYPE_NULL: {
Value* result = new Value();
result->setType(TYPE_NULL);
*_value = result;
break;
}
case TYPE_BOOLEAN: {
Value* result = new Value();
result->setValue(getBooleanValue());
*_value = result;
break;
}
case TYPE_NUMBER: {
Value* result = new Value();
result->setValue(getNumberValue());
*_value = result;
break;
}
case TYPE_STRING: {
Value* result = new Value();
result->setValue(getStringValue());
*_value = result;
break;
}
case TYPE_ARRAY: {
Value** values = NULL;
getArrayValues(&values);
Value* result = new Value();
result->setType(TYPE_ARRAY);
int index = 0;
while (values[index]) {
result->addArrayValue(values[index++]);
}
delete[] values;
*_value = result;
break;
}
case TYPE_OBJECT: {
std::wstring** keys = NULL;
Value** values = NULL;
getObjectValues(&keys, &values);
Value* result = new Value();
result->setType(TYPE_OBJECT);
int index = 0;
while (keys[index]) {
std::wstring keyCopy(*keys[index]);
result->addObjectValue(&keyCopy, values[index++]);
}
delete[] values;
delete[] keys;
*_value = result;
break;
}
// TYPE_UNDEFINED
default: {
*_value = NULL;
break;
}
}
}
void Value::addArrayValue(Value *value) {
setType(TYPE_ARRAY);
Value* result = NULL;
value->clone(&result);
m_arrayValue->push_back(result);
}
bool Value::addObjectValue(const wchar_t* key, Value* value) {
return addObjectValue(&std::wstring(key), value);
}
bool Value::addObjectValue(std::wstring* key, Value* value) {
return setObjectValue(key, value, false);
}
void Value::getArrayValues(Value*** __values) {
if (m_type != TYPE_ARRAY) {
*__values = NULL;
return;
}
size_t size = m_arrayValue->size();
Value** result = new Value*[size + 1];
for (int i = 0; i < (int)size; i++) {
result[i] = m_arrayValue->at(i);
}
result[size] = NULL;
*__values = result;
}
bool Value::getBooleanValue() {
if (m_type != TYPE_BOOLEAN) {
return false;
}
return m_numberValue != 0;
}
double Value::getNumberValue() {
if (m_type != TYPE_NUMBER) {
return 0;
}
return m_numberValue;
}
Value* Value::getObjectValue(const wchar_t* key) {
return getObjectValue(&std::wstring(key));
}
Value* Value::getObjectValue(std::wstring* key) {
if (m_type != TYPE_OBJECT) {
return NULL;
}
std::map<std::wstring, Value*>::iterator result = m_objectValue->find(*key);
if (result == m_objectValue->end()) {
/* not found */
return NULL;
}
return result->second;
}
void Value::getObjectValues(std::wstring*** __keys, Value*** __values) {
if (m_type != TYPE_OBJECT) {
*__keys = NULL;
*__values = NULL;
return;
}
size_t size = m_objectValue->size();
std::wstring** keysResult = new std::wstring*[size + 1];
Value** valuesResult = new Value*[size + 1];
std::map<std::wstring, Value*>::iterator it = m_objectValue->begin();
std::map<std::wstring, Value*>::iterator end = m_objectValue->end();
int index = 0;
while (it != end) {
keysResult[index] = (std::wstring*)&(*it).first;
valuesResult[index++] = (*it).second;
it++;
}
keysResult[index] = NULL;
valuesResult[index] = NULL;
*__keys = keysResult;
*__values = valuesResult;
}
bool Value::setObjectValue(const wchar_t* key, Value* value) {
return setObjectValue(&std::wstring(key), value);
}
bool Value::setObjectValue(std::wstring* key, Value* value) {
return setObjectValue(key, value, true);
}
bool Value::setObjectValue(std::wstring* key, Value* value, bool overwrite) {
setType(TYPE_OBJECT);
std::map<std::wstring, Value*>::iterator it = m_objectValue->find(*key);
if (it != m_objectValue->end()) {
/* value with this key already exists in map */
if (!overwrite) {
return false;
}
m_objectValue->erase(it);
}
Value* result = NULL;
value->clone(&result);
m_objectValue->insert(std::pair<std::wstring,Value*>(*key, result));
return true;
}
std::wstring* Value::getStringValue() {
if (m_type != TYPE_STRING) {
return NULL;
}
return m_stringValue;
}
int Value::getType() {
return m_type;
}
void Value::setValue(bool value) {
setType(TYPE_BOOLEAN);
if (value) {
m_numberValue = 1;
} else {
m_numberValue = 0;
}
}
void Value::setValue(double value) {
setType(TYPE_NUMBER);
m_numberValue = value;
}
void Value::setValue(const wchar_t* value) {
setType(TYPE_STRING);
m_stringValue = new std::wstring;
m_stringValue->assign(value);
}
void Value::setValue(std::wstring* value) {
setType(TYPE_STRING);
m_stringValue = new std::wstring;
m_stringValue->assign(*value);
}
void Value::setType(int value) {
if (m_type == value) {
/* nothing to do */
return;
}
clearCurrentValue();
if (value > TYPE_OBJECT) {
/* invalid value */
m_type = TYPE_UNDEFINED;
return;
}
m_type = value;
switch (m_type) {
case TYPE_ARRAY: {
m_arrayValue = new std::vector<Value*>;
break;
}
case TYPE_OBJECT: {
m_objectValue = new std::map<std::wstring, Value*>;
break;
}
}
}