

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/_/
//_/_/  This file is part of CMSDK version 2.1.1.260726 (26 July 2026)
//_/_/  
//_/_/  developed by
//_/_/  
//_/_/  Communicative Machines Ltd. 
//_/_/    http://cmlabs.com/
//_/_/  Copyright (c) 2026
//_/_/  
//_/_/  in collaboration with 
//_/_/  
//_/_/  Icelandic Institute for Intelligent Machines ses
//_/_/    Menntavegur 1
//_/_/    101 Reykjavik
//_/_/    ICELAND
//_/_/    http://www.iiim.is/
//_/_/
//_/_/  and is released under the following
//_/_/  
//_/_/  EXTENDED BSD License
//_/_/
//_/_/  Redistribution and use in source and binary forms, with or without
//_/_/  modification, is permitted provided that the following conditions 
//_/_/  are met:
//_/_/
//_/_/  - Redistributions of source code must retain the above copyright 
//_/_/    and collaboration notice, this list of conditions and the following 
//_/_/    disclaimer.
//_/_/
//_/_/  - Redistributions in binary form must reproduce the above copyright 
//_/_/    notice, this list of conditions and the following disclaimer in the 
//_/_/    documentation and/or other materials provided with the distribution.
//_/_/
//_/_/  - Neither the name of its copyright holders nor the names of its 
//_/_/    contributors may be used to endorse or promote products derived from 
//_/_/    this software without specific prior written permission.
//_/_/
//_/_/  - CADIA Clause: The license granted in and to the software under this 
//_/_/    agreement is a limited-use license. The software may not be used in 
//_/_/    furtherance of: (i) intentionally causing bodily injury or severe 
//_/_/    emotional harm to any person; (ii) invading the personal privacy or 
//_/_/    violating the human rights of any person; or (iii) committing or 
//_/_/    preparing for any act of war. 
//_/_/
//_/_/  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//_/_/  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//_/_/  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
//_/_/  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
//_/_/  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
//_/_/  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
//_/_/  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
//_/_/  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
//_/_/  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
//_/_/  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
//_/_/  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//_/_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
/*! @file DataMapsMemory.h
    @brief Shared-memory name/id maps: message types, contexts, tags, cranks and cross-process requests.
    @ingroup Memory

    Psyclone identifies message types, contexts, tags and cranks by small integer ids that
    must agree across every process and node. This segment holds five bitfield-indexed
    maps (GenericMapHeader + fixed-size entries) that translate names to ids and back, plus
    the request map used to track cross-component request/reply transactions. Entries are
    created in a two-phase manner (create → confirm/cancel) so ids can be negotiated
    cluster-wide before being marked ready (status: 0 absent, 1 in-sync, 2 ready).

    The GenericMemoryMap template at the bottom implements the shared map algorithms once
    for all entry types (see MemoryMaps.tpl.h).

    @warning Shared-memory layouts; changing any struct here requires a full rebuild of
    all binaries (`make clean && make`) — see MemoryManager.h for the ABI warning. */

#if !defined(_DATAMAPSMEMORY_H_)
#define _DATAMAPSMEMORY_H_

#include "MemoryManager.h"
#include "PsyTime.h"

namespace cmlabs {

/*! @brief Root header of the data-maps segment; records capacity/size of each contained map.
    Followed in memory by the five maps (types, contexts, tags, cranks, requests), each a
    GenericMapHeader with bitfield and entry array.
    @warning Shared-memory layout; see MemoryManager.h for the ABI/rebuild warning. */
struct DataMapsMemoryStruct {
	uint64 size;			/*!< Total segment size in bytes. */
	uint32 cid;				/*!< Check/magic id validated on attach. */
	uint64 createdTime;		/*!< Creation timestamp (µs). */
	uint32 typesMaxCount;		/*!< Capacity of the type map (entries). */
	uint32 typesBitFieldSize;	/*!< Bytes in the type map's occupancy bitfield. */
	uint64 typesSize;			/*!< Total bytes of the type map. */
	uint32 contextsMaxCount;	/*!< Capacity of the context map (entries). */
	uint32 contextsBitFieldSize;/*!< Bytes in the context map's occupancy bitfield. */
	uint64 contextsSize;		/*!< Total bytes of the context map. */
	uint32 tagsMaxCount;		/*!< Capacity of the tag map (entries). */
	uint32 tagsBitFieldSize;	/*!< Bytes in the tag map's occupancy bitfield. */
	uint64 tagsSize;			/*!< Total bytes of the tag map. */
	uint32 cranksMaxCount;		/*!< Capacity of the crank map (entries). */
	uint32 cranksBitFieldSize;	/*!< Bytes in the crank map's occupancy bitfield. */
	uint64 cranksSize;			/*!< Total bytes of the crank map. */
//	uint32 componentsMaxCount;
//	uint32 componentsBitFieldSize;
//	uint32 componentsSize;
	uint32 requestsMaxCount;	/*!< Capacity of the request map (entries). */
	uint32 requestsBitFieldSize;/*!< Bytes in the request map's occupancy bitfield. */
	uint64 requestsSize;		/*!< Total bytes of the request map. */
};

/*! @brief Common header of every map inside the data-maps segment.
    Followed in memory by the occupancy bitfield and maxID fixed-size entries.
    @warning Shared-memory layout; see MemoryManager.h for the ABI/rebuild warning. */
struct GenericMapHeader {
	uint64 size; // total size of map structure in bytes
	uint32 maxID; // maximum number of entries allocated
	uint32 count; // number of entries
	uint32 bitFieldSize; // number of bytes in the bitfield
	// Bitfield
	// Entries
};

/*! @brief Type-map entry: one registered message type name/id.
    @warning Shared-memory layout; see MemoryManager.h for the ABI/rebuild warning. */
struct TypeMapEntry {
	uint16 id; // id, corresponds to the index in map
	uint8 status; // status = 0: not there, 1: in-sync, 2: ready
	uint64 time; // timestamp when entered
	char name[MAXKEYNAMELEN+1]; // name in text
	std::string toXML() {
		return utils::StringFormat("\t<type id=\"%u\" name=\"%s\" status=\"%u\" time=\"%llu\" />\n", id, name, status, time);
	}
	static std::string GetOuterXMLName() { return "types"; }
	bool writeToMsg(uint32 n, DataMessage* msg) {
		if (!msg) return false;
		msg->setInt((int64)n, "ID", id);
		msg->setInt((int64)n, "Status", status);
		msg->setString((int64)n, "Name", name);
		msg->setTime((int64)n, "CreatedTime", time);
		return true;
	}
	bool writeIDToMsg(const char* arrayname, uint32 n, DataMessage* msg) {
		if (!msg) return false;
		msg->setString((int64)n, arrayname, name);
		return true;
	}
};

/*! @brief Context-map entry: one registered psychological/system context name/id.
    @warning Shared-memory layout; see MemoryManager.h for the ABI/rebuild warning. */
struct ContextMapEntry {
	uint16 id; // id, corresponds to the index in map
	uint8 status; // status = 0: not there, 1: in-sync, 2: ready
	uint64 time; // timestamp when entered
	char name[MAXKEYNAMELEN+1]; // name in text
	std::string toXML() {
		return utils::StringFormat("\t<context id=\"%u\" name=\"%s\" status=\"%u\" time=\"%llu\" />\n", id, name, status, time);
	}
	static std::string GetOuterXMLName() { return "contexts"; }
	bool writeToMsg(uint32 n, DataMessage* msg) {
		if (!msg) return false;
		msg->setInt((int64)n, "ID", id);
		msg->setInt((int64)n, "Status", status);
		msg->setString((int64)n, "Name", name);
		msg->setTime((int64)n, "CreatedTime", time);
		return true;
	}
	bool writeIDToMsg(const char* arrayname, uint32 n, DataMessage* msg) {
		if (!msg) return false;
		msg->setString((int64)n, arrayname, name);
		return true;
	}
};

/*! @brief Tag-map entry: one registered tag name/id.
    @warning Shared-memory layout; see MemoryManager.h for the ABI/rebuild warning. */
struct TagMapEntry {
	uint32 id; // id, corresponds to the index in map
	uint8 status; // status = 0: not there, 1: in-sync, 2: ready
	uint64 time; // timestamp when entered
	char name[MAXKEYNAMELEN+1]; // name in text
	std::string toXML() {
		return utils::StringFormat("\t<tag id=\"%u\" name=\"%s\" status=\"%u\" time=\"%llu\" />\n", id, name, status, time);
	}
	static std::string GetOuterXMLName() { return "tags"; }
	bool writeToMsg(uint32 n, DataMessage* msg) {
		if (!msg) return false;
		msg->setInt((int64)n, "ID", id);
		msg->setInt((int64)n, "Status", status);
		msg->setString((int64)n, "Name", name);
		msg->setTime((int64)n, "CreatedTime", time);
		return true;
	}
	bool writeIDToMsg(const char* arrayname, uint32 n, DataMessage* msg) {
		if (!msg) return false;
		msg->setString((int64)n, arrayname, name);
		return true;
	}
};

/*! @brief Crank-map entry: one registered crank (user callback/script) with its function, library and inline script.
    @warning Shared-memory layout; see MemoryManager.h for the ABI/rebuild warning. */
struct CrankMapEntry {
	uint16 id; // id, corresponds to the index in map
	uint8 status; // status = 0: not there, 1: in-sync, 2: ready
	uint64 time; // timestamp when entered
	uint32 compID; // id of parent component
	char name[MAXKEYNAMELEN + 1]; // name in text
	char language[MAXKEYNAMELEN + 1]; // name in text
	char function[MAXKEYNAMELEN+1]; // name in text
	char libraryFilename[MAXKEYNAMELEN+1]; // name in text
	char script[MAXSCRIPTLEN+1]; // script in text
	std::string toXML() {
		if (strlen(script))
			return utils::StringFormat("\t<crank id=\"%u\" name=\"%s\" status=\"%u\" time=\"%llu\" compid=\"%u\" function=\"%s\" library=\"%s\">\n\t\t%s\n\t</crank>\n",
				id, name, status, time, compID, function, libraryFilename, script);
		else
			return utils::StringFormat("\t<crank id=\"%u\" name=\"%s\" status=\"%u\" time=\"%llu\" compid=\"%u\" function=\"%s\" library=\"%s\" />\n",
				id, name, status, time, compID, function, libraryFilename);
	}
	static std::string GetOuterXMLName() { return "cranks"; }
	bool writeToMsg(uint32 n, DataMessage* msg) {
		if (!msg) return false;
		msg->setInt((int64)n, "ID", id);
		msg->setInt((int64)n, "CompID", compID);
		msg->setInt((int64)n, "Status", status);
		msg->setString((int64)n, "Name", name);
		msg->setString((int64)n, "Language", language);
		msg->setString((int64)n, "Function", function);
		msg->setString((int64)n, "LibraryFilename", libraryFilename);
		msg->setString((int64)n, "Script", script);
		msg->setTime((int64)n, "CreatedTime", time);
		return true;
	}
	bool writeIDToMsg(const char* arrayname, uint32 n, DataMessage* msg) {
		if (!msg) return false;
		msg->setString((int64)n, arrayname, name);
		return true;
	}
};

/*! @name Request lifecycle status values (RequestMapEntry::status)
    A request travels created → received → processing → reply-ready → success/failure;
    _LOCAL/_REMOTE distinguish same-node vs cross-node processing, _DATA/_NODATA whether a
    reply payload exists, and _EOL that the payload has already expired from temporal memory.
    @{ */
#define REQ_CREATED				1
#define REQ_RECEIVED_LOCAL		2
#define REQ_RECEIVED_REMOTE		3
#define REQ_PROCESSING_LOCAL	4
#define REQ_PROCESSING_REMOTE	5
#define REQ_REPLY_READY			6
#define REQ_FAILED_TO_SEND		7
#define REQ_FAILED				8
#define REQ_FAILED_DATA			9
#define REQ_FAILED_NODATA		10
#define REQ_FAILED_DATA_EOL		11
#define REQ_SUCCESS				12
#define REQ_SUCCESS_DATA		13
#define REQ_SUCCESS_NODATA		14
#define REQ_SUCCESS_DATA_EOL	15
/*! @} */

/*! @brief Request-map entry tracking one cross-component request/reply transaction.
    The reply payload itself is stored in TemporalMemory (dataMessageID/dataMessageEOL).
    @warning Shared-memory layout; see MemoryManager.h for the ABI/rebuild warning. */
struct RequestMapEntry {
	uint32 id; 			/*!< Request id; corresponds to the index in the map. */
	uint64 time; 		/*!< Creation timestamp (µs). */
	char name[MAXKEYNAMELEN+1]; /*!< Internal use only, for named events. */
	uint64 lastUpdate; 	/*!< Timestamp of the last status change (µs); used to expire stale requests. */
	uint8 status; 		/*!< REQ_* lifecycle status. */
	uint32 from; 		/*!< Id of the component making the request. */
	uint32 to; 			/*!< Id of the component processing the request. */
	uint32 remoteID; 	/*!< Id of the request at the origin node, if forwarded cross-node. */
	uint64 dataMessageID; 	/*!< TemporalMemory id of the reply DataMessage (0 = none yet). */
	uint64 dataMessageEOL; 	/*!< End-of-life of the reply message; after this the payload is gone (REQ_*_DATA_EOL). */
	std::string toXML() {
		return utils::StringFormat("\t<request id=\"%u\" name=\"%s\" status=\"%u\" time=\"%llu\" lastupdate=\"%llu\" from=\"%u\" to=\"%u\" remoteid=\"%u\" msgid=\"%llu\" msgeol=\"%llu\" />\n",
			id, name, status, time, lastUpdate, from, to, remoteID, dataMessageID, dataMessageEOL);
	}
	static std::string GetOuterXMLName() { return "requests"; }
};

/*! Re-open the data-maps segment if the master's resize serial no longer matches ours;
    bails out of the calling method (returning 0) on failure. */
#define CHECKDATAMAPSMEMORYSERIAL 	if (serial != master->getDataMapsShmemSerial()) {if (!open()) {mutex->leave();return 0;}}

class MasterMemory;
/*! @brief Accessor for the shared name/id maps and the request map.
    @ingroup Memory
    One instance per process (created by MemoryManager); master calls create(), others
    open(). All calls lock the segment's named cross-process mutex and re-attach when the
    segment was resized (serial check). The confirm/cancel method pairs implement two-phase,
    cluster-wide id allocation; sync* methods merge entries received from remote nodes.
    @code
    uint16 id, existing;
    dataMapsMemory->createNewTypeLevel(id, "Vision.Face", now, existing); // reserve
    dataMapsMemory->confirmTypeLevelID(id);                              // commit
    uint16 found; dataMapsMemory->getTypeLevelID("Vision.Face", found);
    @endcode */
class DataMapsMemory {
public:
	/*! @param master Segment bookkeeping interface (borrowed, not owned). */
	DataMapsMemory(MasterMemory* master);
	~DataMapsMemory();

	bool open();	/*!< Attach to the existing data-maps segment. @return true on success. */
	/*! Create the segment (master only) with the given per-map capacities. @return true on success. */
	bool create(uint32 typesMaxCount, uint32 contextsMaxCount, uint32 tagsMaxCount, uint32 cranksMaxCount, uint32 requestsMaxCount);

	bool getMemoryUsage(uint64& alloc, uint64& usage);	/*!< Report allocation/usage. @return true on success. */
	bool maintenance();									/*!< Periodic cleanup (e.g. stale requests). @return true on success. */

	std::string printFriendlyHTML();	/*!< @return HTML dump of all maps for monitoring UIs. */
	std::string toXML();				/*!< @return XML dump of all maps. */

	bool writeIDsToMsg(DataMessage* msg);	/*!< Write all map names/ids into @a msg for cluster sync. @return true on success. */

	// TypeLevelMap
	/*! @name Type-level map (message type names ↔ uint16 ids)
	    Two-phase creation: createNewTypeLevel() reserves, confirm/cancel commits or rolls
	    back; lookup* returns the sync status (0 absent, 1 in-sync, 2 ready).
	    @{ */
	bool writeTypeLevelsToMsg(DataMessage* msg);
	bool confirmTypeLevelID(uint16 id);
	bool cancelTypeLevelID(uint16 id);
	bool createNewTypeLevel(uint16 id, const char* name, uint64 time, uint16& existingID);
	bool syncTypeLevels(DataMessage* msg);
	bool getTypeLevelName(uint16 id, char* name, uint32 maxSize);
	bool getTypeLevelID(const char* name, uint16 &id);
	uint8 lookupTypeLevelID(const char* name, uint16 &id); // status = 0: not there, 1: in-sync, 2: ready
	bool deleteTypeLevel(const char* name);
	bool deleteTypeLevel(uint16 id);
	uint64 getTypeLevelCreateTime(uint16 id);
	std::string printAllTypes();
	/*! @} */

	// ContextLevelMap
	/*! @name Context-level map (context names ↔ uint16 ids); same two-phase pattern as types.
	    @{ */
	bool writeContextLevelsToMsg(DataMessage* msg);
	bool confirmContextLevelID(uint16 id);
	bool cancelContextLevelID(uint16 id);
	bool createNewContextLevel(uint16 id, const char* name, uint64 time, uint16& existingID);
	bool syncContextLevels(DataMessage* msg);
	bool getContextLevelName(uint16 id, char* name, uint32 maxSize);
	bool getContextLevelID(const char* name, uint16 &id);
	uint8 lookupContextLevelID(const char* name, uint16 &id); // status = 0: not there, 1: in-sync, 2: ready
	bool deleteContextLevel(const char* name);
	bool deleteContextLevel(uint16 id);
	uint64 getContextLevelCreateTime(uint16 id);
	std::string printAllContexts();
	/*! @} */

	// TagMap
	/*! @name Tag map (tag names ↔ uint32 ids); same two-phase pattern as types.
	    @{ */
	bool writeTagsToMsg(DataMessage* msg);
	bool confirmTagID(uint32 id);
	bool cancelTagID(uint32 id);
	bool createNewTag(uint32 id, const char* name, uint64 time, uint32& existingID);
	bool syncTags(DataMessage* msg);
	bool getTagName(uint32 id, char* name, uint32 maxSize);
	bool getTagID(const char* name, uint32 &id);
	uint8 lookupTagID(const char* name, uint32 &id); // status = 0: not there, 1: in-sync, 2: ready
	bool deleteTag(const char* name);
	bool deleteTag(uint32 id);
	uint64 getTagCreateTime(uint32 id);
	/*! @} */

	// CrankMap
	/*! @name Crank map (crank callbacks/scripts ↔ uint16 ids); same two-phase pattern, with
	    extra fields for function, library filename, language and inline script.
	    @{ */
	bool writeCranksToMsg(DataMessage* msg);
	bool confirmCrankID(uint16 id);
	bool cancelCrankID(uint16 id);
	bool createNewCrank(uint16 id, uint32 compID, const char* name, const char* function, const char* libraryFilename, const char* language, const char* script, uint64 time, uint16& existingID);
	bool syncCranks(DataMessage* msg);
	bool getCrankName(uint16 id, char* name, uint32 maxSize);
	bool getCrankFunction(uint16 id, char* function, uint32 maxSize);
	bool getCrankLanguage(uint16 id, char* language, uint32 maxSize);
	bool getCrankLibraryFilename(uint16 id, char* libraryFilename, uint32 maxSize);
	bool getCrankID(const char* name, uint16 &id);
	uint8 lookupCrankID(const char* name, uint16 &id); // status = 0: not there, 1: in-sync, 2: ready
	uint32 getCrankCompID(uint16 id);
	bool getCrankScript(uint16 id, char* script, uint32 maxSize);
	bool deleteCrank(uint16 id);
	bool deleteCrank(const char* name);
	uint64 getCrankCreateTime(uint16 id);
	/*! @} */

	// RequestMap
	/*! @name Request map (cross-component request/reply tracking)
	    createNewRequest() allocates a transaction id; setRequestStatus() advances it through
	    the REQ_* lifecycle (optionally attaching the temporal-memory id of the reply);
	    waitForRequestReply() blocks the caller up to @a timeout ms until a terminal status.
	    @{ */
	bool createNewRequest(uint32 from, uint32 to, uint32 remoteID, uint32 &id);
	bool getRequestInfo(uint32 id, uint32& from, uint32& to, uint32& remoteID);
	bool getRequestStatus(uint32 id, uint8& status, uint64& time, uint64& msgID, uint64& msgEOL);
	bool setRequestStatus(uint32 id, uint8 status);
	bool setRequestStatus(uint32 id, uint8 status, uint64 msgID, uint64 msgEOL);
	bool waitForRequestReply(uint32 id, uint32 timeout, uint8& status, uint64& time, uint64& msgID, uint64& msgEOL);
	bool deleteRequest(uint32 id);
	uint32 getRequestCount();
	/*! @} */

private:
	bool resize(uint16 port, uint32 serial, uint32 typesMaxCount, uint32 contextsMaxCount, uint32 tagsMaxCount, uint32 cranksMaxCount, uint32 requestsMaxCount);

	utils::Mutex* mutex;			/*!< Named cross-process mutex guarding the segment (owned). */
	MasterMemory* master;			/*!< Bookkeeping interface for size/serial (borrowed). */
	DataMapsMemoryStruct* header;	/*!< Mapped segment header (owned by the OS). */
	uint64 memorySize;				/*!< Size of our current mapping in bytes. */
	uint16 port;					/*!< Node port used in segment naming. */
	uint32 serial;					/*!< Cached resize serial; mismatch triggers re-open. */

	// headers for each map type
	GenericMapHeader* typeMapHeader;	/*!< Type map within the mapped segment. */
	GenericMapHeader* contextMapHeader;	/*!< Context map within the mapped segment. */
	GenericMapHeader* tagMapHeader;		/*!< Tag map within the mapped segment. */
	GenericMapHeader* crankMapHeader;	/*!< Crank map within the mapped segment. */
//	GenericMapHeader* componentMapHeader;
	GenericMapHeader* requestMapHeader;	/*!< Request map within the mapped segment. */
};

/*! @brief Static algorithms shared by all bitfield-indexed maps in the data-maps segment.
    @ingroup Memory
    @tparam T Entry struct (TypeMapEntry, TagMapEntry, ...), @tparam ID its id type.
    All functions take the raw mapped map address (@a data = GenericMapHeader*); callers
    must hold the segment mutex. Returned entry pointers point into shared memory and are
    only valid while the segment mapping and lock are held. Implemented in MemoryMaps.tpl.h. */
template <typename T, typename ID>
class GenericMemoryMap {
public:
	// Generic MemoryMap
	static T* CreateEntry(char* data, ID id, const char* name);			/*!< Reserve entry @a id with @a name (status 1). @return Entry or NULL. */
	static T* CreateFirstFreeEntry(char* data, ID &id, const char* name);	/*!< Reserve the first free id. @param data Mapped map region. @param id Receives it. @param name Entry name. @return Entry or NULL. */
	static T* GetEntry(char* data, ID id);					/*!< @return Entry @a id or NULL if free/out of range. */
	static bool ConfirmEntry(char* data, ID id);			/*!< Mark entry ready (status 2). @return true on success. */
	static bool CancelEntry(char* data, ID id);				/*!< Roll back a reserved entry. @return true on success. */
	static bool DeleteEntry(char* data, ID id);				/*!< Free the entry and its bit. @return true on success. */
	static uint64 GetEntryTime(char* data, ID id);			/*!< @return Entry creation time, 0 if absent. */
	static bool GetEntryName(char* data, ID id, char* name, uint32 maxSize);	/*!< Copy the entry name. @return true if found. */
	static ID GetEntryID(char* data, const char* name, bool force = false);		/*!< @return Id for @a name (@a force also matches unconfirmed). */
	static uint8 LookupEntryID(char* data, const char* name, ID& id);			/*!< @return Status (0 absent, 1 in-sync, 2 ready); @a id receives the id. */
	static uint32 GetCount(char* data);		/*!< @return Number of entries in use. */
	static uint32 GetUsage(char* data);		/*!< @return Bytes in use by the map. */
	static std::string PrintAllEntries(char* data);			/*!< @return Text dump of all entries. */
	static std::string PrintAllEntriesHTML(char* data);		/*!< @return HTML dump of all entries. */
	static std::string ToXML(char* data);					/*!< @return XML dump of all entries. */
	static bool WriteAllEntriesToMsg(char* data, DataMessage* msg);					/*!< Serialize all entries into @a msg. @return true on success. */
	static bool WriteAllIDsToMsg(const char* arrayname, char* data, DataMessage* msg);	/*!< Write just names into @a msg under @a arrayname. @return true on success. */
};

} // namespace cmlabs

#include "MemoryMaps.tpl.h"

#endif //_DATAMAPSMEMORY_H_

