/** ** ** @RDE_HEADER@ ** Simple Id Handler ** $Id$ ** $HeadURL$ ** $Author$ ** ** ----------------------------------------------------------------------------------------------- ** ** Hardware-Environment: Intel-PC ** Software-Environment: Linux, Windows 7, Qt 5.4. ArcGIS 10.2.5 ** ** Language ........: C++ 11 ** ** ----------------------------------------------------------------------------------------------- ** ** Author ...........: Jörg Turla, SPD G, Tel. 3132 ** ** ----------------------------------------------------------------------------------------------- ** ** Notes .........: ** ** ??.??.1994, JT : First edition for use with Tcl/Tk in START Feature Editor fe ** 16.08.2004, JT : Refactoring for use in Geo-Map Library GeISiR ** 11.05.2015, JT : Refactoring for use with Qt5 ** ** ----------------------------------------------------------------------------------------------- */ #include "id_handler.h" #include #include "referenced.h" namespace SituationMap { const IdHandler::UniqueId IdHandler::BadId = static_cast(-1); bool IdHandler::isIdValid(const UniqueId &id) { return id != BadId; } IdHandler::IdHandler(unsigned int maxItems, unsigned int blockS) : _blockSize(blockS) , _maxIds(maxItems) , _freeIds(maxItems) , _firstFree(BadId) , _lastAlloc(BadId) , _notify(getLogger("IdHandler")) , _idVector() { } // IdHandler::IdHandler IdHandler::~IdHandler() { if (!_idVector.isEmpty()) { if (_lastAlloc != BadId) { for (UniqueId i = 0; i <= _lastAlloc; ++i) _idVector[i] = nullptr; } _maxIds = 0; _freeIds = 0; _firstFree = BadId; _lastAlloc = BadId; } } // IdHandler::~IdHandler bool IdHandler::initMemHandler() { if (_idVector.empty()) { _idVector.resize(_maxIds); _freeIds = _maxIds; _firstFree = 0; _lastAlloc = BadId; return false; } return true; } // IdHandler::initMemHandler void IdHandler::lookForNextFreeId() { ++_firstFree; while (_firstFree < _lastAlloc) { if (!_idVector[_firstFree]) break; ++_firstFree; } if (_firstFree >= _lastAlloc) _firstFree = _maxIds; } //IdHandler::lookForNextFreeId bool IdHandler::valid() const { return ((static_cast(_idVector.size()) == _maxIds) && (_firstFree != BadId)); } // IdHandler::valid unsigned int IdHandler::countReservedIds() const { return _maxIds; } unsigned int IdHandler::countUsedIds() const { return _maxIds - _freeIds; } unsigned int IdHandler::countFreeIds() const { return _freeIds; } bool IdHandler::resize(quint32 maxItems) { if (initMemHandler()) { if (maxItems > static_cast(_idVector.size())) { _freeIds += maxItems - _maxIds; _maxIds = maxItems; _idVector.resize(_maxIds); } } return (static_cast(_idVector.size()) == _maxIds); } // IdHandler::resize IdHandler::UniqueId IdHandler::createId(AccessableId *idPtr) { initMemHandler(); UniqueId id((_lastAlloc == BadId) ? 0 : _lastAlloc + 1); if (id < _maxIds) { _idVector[id] = idPtr; _lastAlloc = id; if (_firstFree == id) ++_firstFree; } else { if (_firstFree >= _maxIds) { resize(_maxIds + _blockSize); if (id < _maxIds) { _idVector[id] = idPtr; _lastAlloc = id; if (_firstFree == id) ++_firstFree; } else { ERROR_LOG(_notify) << LOGFUNCTION << QStringLiteral("Id table overflow, object <%1> of type <%2>, reserved Ids %3") .arg(reinterpret_cast(idPtr), 0, 16) .arg(QLatin1String(typeid(idPtr).name())) .arg(_maxIds); return BadId; } } else { id = _firstFree; _idVector[id] = idPtr; lookForNextFreeId(); } } _freeIds--; return (id); } // IdHandler::createId bool IdHandler::reserveId(UniqueId id, AccessableId *idPtr) { initMemHandler(); if (!valid()) { ERROR_LOG(_notify) << LOGFUNCTION << QStringLiteral("IdHandler is not initialzed, object <%1> of type <%2> ") .arg(reinterpret_cast(idPtr), 0, 16) .arg(QLatin1String(typeid(idPtr).name())); return false; } if (id == BadId) { ERROR_LOG(_notify) << LOGFUNCTION << " Requested id is bad id <" << id << ">"; return false; } if (id >= _maxIds) { if (!resize((((id + 1) / _blockSize) + 1) * _blockSize)) { ERROR_LOG(_notify) << LOGFUNCTION << QStringLiteral("Requested id is to large, id <%1> object <%2> of type <%3>.") .arg(id) .arg(reinterpret_cast(idPtr), 0, 16) .arg(QLatin1String(typeid(idPtr).name())); return false; } } if (_idVector[id]) { ERROR_LOG(_notify) << LOGFUNCTION << QStringLiteral("Requested id is already in use, object <%1> of type <%2>.") .arg(reinterpret_cast(idPtr), 0, 16) .arg(QLatin1String(typeid(idPtr).name())); return false; } _idVector[id] = idPtr; if ((_lastAlloc == BadId) || (id > _lastAlloc)) _lastAlloc = id; if (id == _firstFree) { ++_firstFree; lookForNextFreeId(); } _freeIds--; return true; } // IdHandler::reserveId bool IdHandler::freeId(UniqueId id) { if (valid() && (_lastAlloc != BadId) && (id != BadId)) { if (id <= _lastAlloc) { if (_idVector[id]) { _idVector[id] = nullptr; if (id < _firstFree) _firstFree = id; if (id == _lastAlloc) { /* --------------------------------------------------------- * Last allocated id is now free. Search new lastAlloc ... * ---------------------------------------------------------- */ if (_lastAlloc > 0) { --_lastAlloc; while (!_idVector[_lastAlloc]) { if (_lastAlloc < 1) { _lastAlloc = BadId; break; } else --_lastAlloc; } // while } else _lastAlloc = BadId; } _freeIds++; return true; } } else { ERROR_LOG(_notify) << LOGFUNCTION << "Id is not in use, id <" << id << ">"; } } else { if (id != BadId) { ERROR_LOG(_notify) << LOGFUNCTION << "IdHandler is not initialzed."; } else { ERROR_LOG(_notify) << LOGFUNCTION << "Bad id, id <" << id << ">"; } } return false; } // IdHandler::freeId IdHandler::AccessableId *IdHandler::accessId(UniqueId id) const { if (valid()) { if ((id != BadId) && (id <= _lastAlloc)) return _idVector[id].get(); else { ERROR_LOG(_notify) << LOGFUNCTION << "Bad id or id is not in use, id <" << id << ">"; #ifdef UseDebugBreaks #ifdef WIN32 #ifdef _DEBUG __asm int 3 #endif #endif #endif } } else { ERROR_LOG(_notify) << LOGFUNCTION << "IdHandler is not initialzed"; } return nullptr; } // IdHandler::accessId bool IdHandler::isIdInUse(UniqueId id) const { if (valid()) { if ((id != BadId) && (id <= _lastAlloc)) return (_idVector[id].get() != nullptr); } return false; } // IdHandler::isIdInUse } // SituationMap