#endif
}
-u16 AreaStore::size() const
+const Area *AreaStore::getArea(u32 id) const
{
- return areas_map.size();
+ AreaMap::const_iterator it = areas_map.find(id);
+ if (it == areas_map.end())
+ return nullptr;
+ return &it->second;
}
-const Area *AreaStore::getArea(u32 id) const
+void AreaStore::serialize(std::ostream &os) const
{
- const Area *res = NULL;
- std::map<u32, Area>::const_iterator itr = areas_map.find(id);
- if (itr != areas_map.end()) {
- res = &itr->second;
+ // WARNING:
+ // Before 5.1.0-dev: version != 0 throws SerializationError
+ // After 5.1.0-dev: version >= 5 throws SerializationError
+ // Forwards-compatibility is assumed before version 5.
+
+ writeU8(os, 0); // Serialisation version
+
+ // TODO: Compression?
+ writeU16(os, areas_map.size());
+ for (const auto &it : areas_map) {
+ const Area &a = it.second;
+ writeV3S16(os, a.minedge);
+ writeV3S16(os, a.maxedge);
+ writeU16(os, a.data.size());
+ os.write(a.data.data(), a.data.size());
}
- return res;
+
+ // Serialize IDs
+ for (const auto &it : areas_map)
+ writeU32(os, it.second.id);
}
-#if 0
-Currently, serialisation is commented out. This is because of multiple reasons:
-1. Why do we store the areastore into a file, why not into the database?
-2. We don't use libspatial's serialisation, but we should, or perhaps not, because
- it would remove the ability to switch. Perhaps write migration routines?
-3. Various things need fixing, e.g. the size is serialized as
- c++ implementation defined size_t
-bool AreaStore::deserialize(std::istream &is)
+void AreaStore::deserialize(std::istream &is)
{
u8 ver = readU8(is);
- if (ver != 1)
- return false;
- u16 count_areas = readU16(is);
- for (u16 i = 0; i < count_areas; i++) {
- // deserialize an area
- Area a;
- a.id = readU32(is);
+ // Assume forwards-compatibility before version 5
+ if (ver >= 5)
+ throw SerializationError("Unknown AreaStore "
+ "serialization version!");
+
+ u16 num_areas = readU16(is);
+ std::vector<Area> areas;
+ for (u32 i = 0; i < num_areas; ++i) {
+ Area a(U32_MAX);
a.minedge = readV3S16(is);
a.maxedge = readV3S16(is);
- a.datalen = readU16(is);
- a.data = new char[a.datalen];
- is.read((char *) a.data, a.datalen);
- insertArea(a);
+ u16 data_len = readU16(is);
+ char *data = new char[data_len];
+ is.read(data, data_len);
+ a.data = std::string(data, data_len);
+ areas.emplace_back(a);
+ delete [] data;
}
- return true;
-}
+ bool read_ids = is.good(); // EOF for old formats
-static bool serialize_area(void *ostr, Area *a)
-{
- std::ostream &os = *((std::ostream *) ostr);
- writeU32(os, a->id);
- writeV3S16(os, a->minedge);
- writeV3S16(os, a->maxedge);
- writeU16(os, a->datalen);
- os.write(a->data, a->datalen);
-
- return false;
-}
-
-
-void AreaStore::serialize(std::ostream &os) const
-{
- // write initial data
- writeU8(os, 1); // serialisation version
- writeU16(os, areas_map.size()); //DANGER: not platform independent
- forEach(&serialize_area, &os);
+ for (auto &area : areas) {
+ if (read_ids)
+ area.id = readU32(is);
+ insertArea(&area);
+ }
}
-#endif
-
void AreaStore::invalidateCache()
{
if (m_cache_enabled) {
}
}
+u32 AreaStore::getNextId() const
+{
+ u32 free_id = 0;
+ for (const auto &area : areas_map) {
+ if (area.first > free_id)
+ return free_id; // Found gap
+
+ free_id = area.first + 1;
+ }
+ // End of map
+ return free_id;
+}
+
void AreaStore::setCacheParams(bool enabled, u8 block_radius, size_t limit)
{
m_cache_enabled = enabled;
bool VectorAreaStore::insertArea(Area *a)
{
- a->id = getNextId();
+ if (a->id == U32_MAX)
+ a->id = getNextId();
std::pair<AreaMap::iterator, bool> res =
areas_map.insert(std::make_pair(a->id, *a));
if (!res.second)
void VectorAreaStore::getAreasForPosImpl(std::vector<Area *> *result, v3s16 pos)
{
- for (size_t i = 0; i < m_areas.size(); ++i) {
- Area *b = m_areas[i];
- if (AST_CONTAINS_PT(b, pos)) {
- result->push_back(b);
+ for (Area *area : m_areas) {
+ if (AST_CONTAINS_PT(area, pos)) {
+ result->push_back(area);
}
}
}
void VectorAreaStore::getAreasInArea(std::vector<Area *> *result,
v3s16 minedge, v3s16 maxedge, bool accept_overlap)
{
- for (size_t i = 0; i < m_areas.size(); ++i) {
- Area *b = m_areas[i];
- if (accept_overlap ? AST_AREAS_OVERLAP(minedge, maxedge, b) :
- AST_CONTAINS_AREA(minedge, maxedge, b)) {
- result->push_back(b);
- }
- }
-}
-
-#if 0
-bool SimpleAreaStore::forEach(bool (*callback)(void *args, Area *a), void *args) const
-{
- for (size_t i = 0; i < m_areas.size(); ++i) {
- if (callback(m_areas[i], arg)) {
- return true;
+ for (Area *area : m_areas) {
+ if (accept_overlap ? AST_AREAS_OVERLAP(minedge, maxedge, area) :
+ AST_CONTAINS_AREA(minedge, maxedge, area)) {
+ result->push_back(area);
}
}
- return false;
}
-#endif
#if USE_SPATIAL
bool SpatialAreaStore::insertArea(Area *a)
{
- a->id = getNextId();
+ if (a->id == U32_MAX)
+ a->id = getNextId();
if (!areas_map.insert(std::make_pair(a->id, *a)).second)
// ID is not unique
return false;
- m_tree->insertData(0, NULL, get_spatial_region(a->minedge, a->maxedge), a->id);
+ m_tree->insertData(0, nullptr, get_spatial_region(a->minedge, a->maxedge), a->id);
invalidateCache();
return true;
}
Area *a = &itr->second;
bool result = m_tree->deleteData(get_spatial_region(a->minedge,
a->maxedge), id);
+ areas_map.erase(itr);
invalidateCache();
return result;
} else {
}
}
-#if 0
-bool SpatialAreaStore::forEach(bool (*callback)(void *args, Area *a), void *args) const
-{
- // TODO ?? (this is only needed for serialisation, but libspatial has its own serialisation)
- return false;
-}
-#endif
-
SpatialAreaStore::~SpatialAreaStore()
{
delete m_tree;