blob: 273707b10ee6f90d841a7dd4fcf1a0ac3a1c0aff [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.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;
}
default: {
/* TYPE_UNDEFINED */
Value* result = new Value();
result->setType(TYPE_UNDEFINED);
*_value = result;
}
}
}
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);
}
//bool Value::clearObjectValue(const wchar_t* key) {
// return clearObjectValue(&std::wstring(key));
//}
//bool Value::clearObjectValue(std::wstring* key) {
// if (m_type != TYPE_OBJECT) {
// return false;
// }
//
// std::map<std::wstring, Value*>::iterator iterator = m_objectValue->find(*key);
// if (iterator == m_objectValue->end()) {
// /* not found */
// return false;
// }
// delete (*iterator).second;
// m_objectValue->erase(iterator);
// return true;
//}
bool Value::equals(Value* value) {
if (!value || value->getType() != m_type) {
return false;
}
switch (m_type) {
case TYPE_UNDEFINED:
case TYPE_NULL: {
return true;
}
case TYPE_BOOLEAN: {
return value->getBooleanValue() == getBooleanValue();
}
case TYPE_NUMBER: {
return value->getNumberValue() == getNumberValue();
}
case TYPE_STRING: {
return value->getStringValue()->compare(*getStringValue()) == 0;
}
case TYPE_ARRAY: {
Value** selfItems = NULL;
getArrayValues(&selfItems);
Value** valueItems = NULL;
value->getArrayValues(&valueItems);
bool isEqual = true;
int index = 0;
while (selfItems[index]) {
if (!selfItems[index]->equals(valueItems[index])) {
isEqual = false;
break;
}
index++;
}
if (isEqual) {
isEqual = valueItems[index] == NULL;
}
delete[] valueItems;
delete[] selfItems;
return isEqual;
}
case TYPE_OBJECT: {
std::wstring** selfKeys = NULL;
Value** selfValues = NULL;
getObjectValues(&selfKeys, &selfValues);
bool isEqual = true;
int index = 0;
while (selfKeys[index]) {
Value* valueValue = value->getObjectValue(selfKeys[index]);
if (!valueValue || !selfValues[index]->equals(valueValue)) {
isEqual = false;
break;
}
index++;
}
delete[] selfKeys;
delete[] selfValues;
if (isEqual) {
/* ensure that value does not contain extra keys/values */
std::wstring** valueKeys = NULL;
Value** valueValues = NULL;
value->getObjectValues(&valueKeys, &valueValues);
int length = 0;
while (valueKeys[length++]);
isEqual = length == index;
delete[] valueKeys;
delete[] valueValues;
}
return isEqual;
}
}
return false; /* should never happen */
}
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;
}
delete (*it).second;
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;
}
}
}