/* This file is part of MAUS: http://micewww.pp.rl.ac.uk/projects/maus
*
* MAUS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MAUS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MAUS. If not, see .
*/
#ifndef _SRC_COMMON_CPP_JSONCPPPROCESSORS_REFERENCERESOLVERCPPTOJSON_HH_
#define _SRC_COMMON_CPP_JSONCPPPROCESSORS_REFERENCERESOLVERCPPTOJSON_HH_
#include
#include
#include
#include "json/value.h"
namespace MAUS {
namespace ReferenceResolver {
namespace CppToJson {
/** @class Resolver abstract type for resolving references
*
* By having an untyped base class, we can put all references in the same
* vector and iterate without knowing about the type of the pointer referenced
*/
class Resolver {
public:
/** Destructor does nothing */
virtual ~Resolver() {}
/** Convert from Cpp pointer to json pointer*/
virtual void ResolveReferences(Json::Value& json_root) = 0;
};
/** @class TypedResolver real type for resolving references
*
* Holds C++ pointer-by-reference of type ChildType* to a Json object. When the
* data tree is filled we can call ResolveReferences to fill the references
* using the pointer-by-value information on the refManager
*
* @tparam ChildType the type pointed to by the C++ pointer-by-reference
*/
template
class TypedResolver : public Resolver {
public:
/** Constructor
*
* @param ref_cpp_address C++ address of the reference
* @param ref_json_address path through the json tree to the point where
* the reference should be written
*/
TypedResolver(ChildType* ref_cpp_address, std::string ref_json_address);
/** Destructor does nothing */
~TypedResolver() {}
/** Resolve this reference
*
* Lookup the C++ pointer-as-reference in the hash table and find the
* json path where the data is stored. Write the path to the data at
* the reference position in the json data structure (walking up from
* json_root).
*
* @param json_root the ref_json_address is dereferenced using json_root
* as the root of the json tree.
*
* throws an exception if the reference isn't in the hash table - i.e. a
* pointer-by-reference was stored but no pointer-by-value
*/
void ResolveReferences(Json::Value& json_root);
private:
ChildType* _cpp_pointer;
std::string _json_pointer;
};
/** @class RefManager stores and subsequently resolves a list of
* pointer-as-reference and a (set of) map of pointer-as-value.
*
* As we traverse the data tree we collect a list of pointer-by-references to
* json and a map of pointer-by-values to json. When the data tree is fully
* traversed we can resolve the pointer-by-references to the appropriate json
* address.
*
* Should be called statically using GetInstance(). The issue here is
* that I use function overloading to determine type leading to static storage
* of pointer-as-value - if several data trees need to be resolved at the same
* time then it is possible to get them confused.
*
* Call Birth() before parsing the data tree and Death() when you are finished
* parsing. Otherwise you will leave stray data that MAUS will attempt to reuse
* next time ResolveReferences() is called. We are reasonably strict about
* throwing Exceptions to encourage the user to be careful about Birth() and
* Death() for this reason.
*/
class RefManager {
public:
/** Get the static instance of the RefManager
*
* throws a Exception if RefManager has not been Birthed.
*/
static RefManager& GetInstance();
/** Return true if RefManager has been birthed
*/
static bool HasInstance();
/** Allocate a static instance of the RefManager
*
* throws a Exception if RefManager has already been birthed
*/
static void Birth();
/** Delete the static instance of the RefManager
*
* throws a Exception if RefManager has not been birthed
*/
static void Death();
/** delete RefManager; if this == static instance, delete the static
* instance also. At the same time clears the PointerAsValue tables.
*/
/** Resolve references
*
* Iterate over the list of references and call ResolveReferences on
* each child reference.
*
* @param json_root the paths of the json references will be
* dereferenced starting from json_root.
*/
inline void ResolveReferences(Json::Value& json_root);
/** Add a new reference
*
* @param reference Append this reference to the list of references
*/
inline void AddReference(Resolver* reference);
/** Add a mapping from Json address to C++ pointer to the manager
*
* @param json_address Json representation of the pointer-as-value (path to
* the data
* @param pointer C++ representation of the pointer-as-value
*/
template
void SetPointerAsValue(PointerType* pointer, std::string json_address);
/** Access the C++ representation of a json address
*
* @param cpp_address C++ address of the data
*
* @returns Json representation of the pointer-as-value (path to the data)
*/
template
std::string GetPointerAsValue(PointerType* cpp_address);
private:
class PointerValueTable;
template
class TypedPointerValueTable;
template
TypedPointerValueTable* GetTypedPointerValueTable();
std::set _value_tables;
std::vector _references;
static RefManager* _instance;
RefManager() {}
inline ~RefManager();
// disabled
RefManager& operator=(const RefManager&);
RefManager(const RefManager&);
};
} // namespace CppToJson
} // namespace ReferenceResolver
} // namespace MAUS
#include "src/common_cpp/JsonCppProcessors/Common/ReferenceResolverCppToJson-inl.hh"
#endif