void Scope::Adopt(Scope& child, const std::string& key, std::uint32_t index) { if (key == std::string()) throw std::exception("Key cannot be an empty string."); child.Orphan(); child.mParent = this; // try to find entry first in this scope Datum* d = Find(key); if (d != nullptr) { if (d->GetType() != Datum::Table) throw std::exception("Found entry is not a table!"); if (d->IsExternal()) throw std::exception("Table is external. Cannot modify data owned by something else."); std::uint32_t originalDatumSize = d->Size(); // if a scope is empty or not pointing to anything at the given index, we can just have it point to something else if (originalDatumSize <= index || d->GetTable(index) == nullptr || d->GetTable(index)->mOrder.Size() == 0) d->Set(&child, index); // otherwise, we add in the child scope and rearrange the datum array if necessary else { if (index < originalDatumSize) { d->SetSize(originalDatumSize + 1); for (std::uint32_t i = originalDatumSize; i > index; --i) { d->Set(d->GetTable(i - 1), i); } } else if (index > originalDatumSize) { index = originalDatumSize; } d->Set(&child, index); } } else { Datum scopeDatum; scopeDatum = &child; std::pair<std::string, Datum> pair(key, scopeDatum); HashMap<std::string, Datum>::Iterator iterator = mTable.Insert(pair); mOrder.PushBack(&(*iterator)); } }
void Scope::Orphan() { std::string scopeName; if (mParent != nullptr) { #ifdef DEBUG assert(mParent->FindName(this, scopeName)); #else mParent->FindName(this, scopeName); #endif Datum* d = mParent->Find(scopeName); std::uint32_t datumSize = d->Size(); for (std::uint32_t i = 0; i < datumSize; ++i) { if (d->GetTable(i) == this) { d->Set((Scope*)nullptr, i); break; } } } mParent = nullptr; }
Scope& Scope::AppendScope(const std::string& key) { if (key == std::string()) throw std::exception("Key cannot be an empty string."); Scope* newScope = new Scope(); newScope->mParent = this; // try to find entry first in this scope Datum* d = Find(key); if (d != nullptr) { if (d->GetType() != Datum::Table && d->GetType() != Datum::Unknown) { delete newScope; throw std::exception("Found entry is not a table!"); } if (d->IsExternal()) { delete newScope; throw std::exception("Table entry is external. Cannot modify data owned by something else."); } // a new scope gets added into this table datum std::uint32_t datumSize = d->Size(); d->Set(newScope, datumSize); return *d->GetTable(datumSize); } // if no entry is found, create new datum with this scope Datum scopeDatum; scopeDatum = newScope; std::pair<std::string, Datum> pair(key, scopeDatum); HashMap<std::string, Datum>::Iterator iterator = mTable.Insert(pair); mOrder.PushBack(&(*iterator)); return *(iterator->second.GetTable()); }