ultimatepp/uppdev/ValueMap2/ValueMap.cpp
cxl 2e4b276e07 Merge continued
git-svn-id: svn://ultimatepp.org/upp/trunk@10263 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2016-10-04 08:34:39 +00:00

187 lines
3.6 KiB
C++

#include "ValueMap.h"
bool ValueMap::Data::IsNull() const {
return this == &Single<ValueMap::NullData>();
}
void ValueMap::Data::Serialize(Stream& s) {
s % key % value % unlinked;
}
unsigned ValueMap::Data::GetHashValue() const {
CombineHash w(key.GetCount());
for(int i = 0; i < key.GetCount(); i++)
w.Put(key[i].GetHashValue());
w.Put(value.GetHashValue());
return w;
}
static bool sCmp(const Index<Value>& a, const Index<Value>& b) {
if(&a == &b) return true;
if(a.GetCount() != b.GetCount()) return false;
for(int i = 0; i < a.GetCount(); i++) {
if(a[i] != b[i]) return false;
}
return true;
}
bool ValueMap::Data::IsEqual(const Value::Void *p) {
return sCmp(((Data *)p)->key, key) && ((Data *)p)->value == value;
}
bool ValueMap::operator==(const ValueMap& v) const {
return sCmp(data->key, v.data->key) && data->value == v.data->value;
}
String ValueMap::Data::AsString() const
{
String s;
s << "{ ";
bool was = false;
for(int i = 0; i < key.GetCount(); i++) {
if(!key.IsUnlinked(i)) {
if(was) s << ", ";
was = true;
s << "(" << key[i] << ", " << value[i] << ")";
}
}
s << " }";
return s;
}
ValueArray ValueMap::Data::SweepedKeys()
{
ValueArray va;
for(int i = 0; i < key.GetCount(); i++)
if(!key.IsUnlinked(i))
va.Add(key[i]);
return va;
}
ValueArray ValueMap::Data::SweepedArray()
{
if(unlinked == 0)
return value;
ValueArray va;
for(int i = 0; i < key.GetCount(); i++)
if(!key.IsUnlinked(i))
va.Add(value[i]);
return va;
}
void ValueMap::Data::Sweep()
{
value = SweepedArray();
key.Sweep();
unlinked = 0;
}
ValueMap::Data& ValueMap::Create()
{
data = new Data;
return *data;
}
ValueMap::Data& ValueMap::Clone() {
if(data->GetRefCount() != 1) {
Data *d = new Data;
d->key <<= data->key;
d->value = data->value;
d->unlinked = data->unlinked;
data->Release();
data = d;
}
return *data;
}
ValueMap::ValueMap() {
data = &Single<NullData>();
data->Retain();
}
ValueMap::ValueMap(const ValueMap& v) {
data = v.data;
data->Retain();
}
ValueMap::ValueMap(const Nuller&) {
data = &Single<NullData>();
data->Retain();
}
ValueMap::operator Value() const {
data->Retain();
return Value(data);
}
ValueMap::ValueMap(const Value& src)
{
if(!::IsNull(src)) {
ASSERT(dynamic_cast<const ValueMap::Data *>(src.GetVoidPtr()));
data = (ValueMap::Data *)src.GetVoidPtr();
}
else
data = &Single<NullData>();
data->Retain();
}
void ValueMap::Serialize(Stream& s) {
if(s.IsStoring())
Clone();
data->Serialize(s);
}
ValueMap::~ValueMap() {
ASSERT(data->GetRefCount() > 0);
data->Release();
}
ValueMap& ValueMap::operator=(const ValueMap& v) {
v.data->Retain();
data->Release();
data = v.data;
return *this;
}
void ValueMap::Clear() {
Data& d = Clone();
d.key.Clear();
d.value.Clear();
}
void ValueMap::Put(const Value& key, const Value& value) {
Data& d = Clone();
int q = d.key.Find(key);
if(d.unlinked > (d.key.GetCount() >> 1))
d.Sweep();
d.key.Add(key);
d.value.Add(value);
}
void ValueMap::Remove(const Value& key) {
Data& d = Clone();
int q = d.key.Find(key);
if(q >= 0) {
d.key.Unlink(q);
d.unlinked++;
}
}
Value ValueMap::operator[](const Value& key) const
{
int q = data->key.Find(key);
return q >= 0 ? data->value[q] : ErrorValue();
}
ValueArray ValueMap::GetKeys() const
{
return data->SweepedKeys();
}
ValueArray ValueMap::GetValues() const
{
return data->SweepedArray();
}
//RichValue<ValueMap>::Registrator ValueMapRegistrator;