X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Futil%2Fareastore.cpp;h=cea526336b66b8d5ec1e16e9baf2833c8bbbc2bd;hb=3f702fa1a9ace33111256ed7b7d5579099830015;hp=cf972586c495731b21d417824891c2f43ce2349d;hpb=2e74e9ee20cee987a7326378c6ab73ec93e25457;p=minetest.git diff --git a/src/util/areastore.cpp b/src/util/areastore.cpp index cf972586c..cea526336 100644 --- a/src/util/areastore.cpp +++ b/src/util/areastore.cpp @@ -54,72 +54,69 @@ AreaStore *AreaStore::getOptimalImplementation() #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::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 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; -} - -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; -} + bool read_ids = is.good(); // EOF for old formats - -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) { @@ -127,6 +124,19 @@ void AreaStore::invalidateCache() } } +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; @@ -182,8 +192,9 @@ void AreaStore::getAreasForPos(std::vector *result, v3s16 pos) bool VectorAreaStore::insertArea(Area *a) { - a->id = getNextId(); - std::pair::iterator, bool> res = + if (a->id == U32_MAX) + a->id = getNextId(); + std::pair res = areas_map.insert(std::make_pair(a->id, *a)); if (!res.second) // ID is not unique @@ -193,38 +204,29 @@ bool VectorAreaStore::insertArea(Area *a) return true; } -void VectorAreaStore::reserve(size_t count) -{ - m_areas.reserve(count); -} - bool VectorAreaStore::removeArea(u32 id) { - std::map::iterator itr = areas_map.find(id); - if (itr != areas_map.end()) { - size_t msiz = m_areas.size(); - for (size_t i = 0; i < msiz; i++) { - Area * b = m_areas[i]; - if (b->id == id) { - areas_map.erase(itr); - m_areas.erase(m_areas.begin() + i); - invalidateCache(); - return true; - } + AreaMap::iterator it = areas_map.find(id); + if (it == areas_map.end()) + return false; + Area *a = &it->second; + for (std::vector::iterator v_it = m_areas.begin(); + v_it != m_areas.end(); ++v_it) { + if (*v_it == a) { + m_areas.erase(v_it); + break; } - // we should never get here, it means we did find it in map, - // but not in the vector } - return false; + areas_map.erase(it); + invalidateCache(); + return true; } void VectorAreaStore::getAreasForPosImpl(std::vector *result, v3s16 pos) { - size_t msiz = m_areas.size(); - for (size_t i = 0; i < msiz; 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); } } } @@ -232,29 +234,14 @@ void VectorAreaStore::getAreasForPosImpl(std::vector *result, v3s16 pos) void VectorAreaStore::getAreasInArea(std::vector *result, v3s16 minedge, v3s16 maxedge, bool accept_overlap) { - size_t msiz = m_areas.size(); - for (size_t i = 0; i < msiz; 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); + for (Area *area : m_areas) { + if (accept_overlap ? AST_AREAS_OVERLAP(minedge, maxedge, area) : + AST_CONTAINS_AREA(minedge, maxedge, area)) { + result->push_back(area); } } } -#if 0 -bool VectorAreaStore::forEach(bool (*callback)(void *args, Area *a), void *args) const -{ - size_t msiz = m_areas.size(); - for (size_t i = 0; i < msiz; i++) { - if (callback(args, m_areas[i])) { - return true; - } - } - return false; -} -#endif - #if USE_SPATIAL static inline SpatialIndex::Region get_spatial_region(const v3s16 minedge, @@ -276,11 +263,12 @@ static inline SpatialIndex::Point get_spatial_point(const v3s16 pos) 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; } @@ -292,6 +280,7 @@ bool SpatialAreaStore::removeArea(u32 id) 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 { @@ -317,14 +306,6 @@ void SpatialAreaStore::getAreasInArea(std::vector *result, } } -#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;