From 469bbcf0701e1eb8a6670c23145b0da87357e178 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sun, 25 Mar 2012 20:00:08 +0000 Subject: Code is all reorganized. We're about ready to release. I should write up a little explenation of the arrangement. --- src/stable/archive.h | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/stable/archive.h (limited to 'src/stable/archive.h') diff --git a/src/stable/archive.h b/src/stable/archive.h new file mode 100644 index 0000000..61474a4 --- /dev/null +++ b/src/stable/archive.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2007-2011 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#ifndef BU_ARCHIVE_H +#define BU_ARCHIVE_H + +#include +#include "bu/archivebase.h" +#include "bu/hash.h" +#include "bu/util.h" +#include "bu/variant.h" + +namespace Bu +{ + class Archival; + class Stream; + + /** + * Provides a framework for serialization of objects and primitives. The + * archive will handle any basic primitive, a few special types, like char * + * strings, as well as STL classes and anything that inherits from the + * Archival class. Each Archive operates on a Stream, so you can send the + * data using an Archive almost anywhere. + * + * In order to use an Archive to store something to a file, try something + * like: + *@code + * File sOut("output", "wb"); // This is a stream subclass + * Archive ar( sOut, Archive::save ); + * ar << myClass; + @endcode + * In this example myClass is any class that inherits from Archival. When + * the storage operator is called, the Archival::archive() function in the + * myClass object is called with a reference to the Archive. This can be + * handled in one of two ways: + *@code + * void MyClass::archive( Archive &ar ) + * { + * ar && sName && nAge && sJob; + * } + @endcode + * Here we don't worry about weather we're loading or saving by using the + * smart && operator. This allows us to write very consistent, very simple + * archive functions that really do a lot of work. If we wanted to do + * something different in the case of loading or saving we would do: + *@code + * void MyClass::archive( Archive &ar ) + * { + * if( ar.isLoading() ) + * { + * ar >> sName >> nAge >> sJob; + * } else + * { + * ar << sName << nAge << sJob; + * } + * } + @endcode + * Archive currently does not provide facility to make fully portable + * archives. For example, it will not convert between endianness for you, + * nor will it take into account differences between primitive sizes on + * different platforms. This, at the moment, is up to the user to ensure. + * One way of dealing with the latter problem is to make sure and use + * explicit primitive types from the stdint.h header, i.e. int32_t. + */ + class Archive : public ArchiveBase + { + private: + bool bLoading; + public: + bool isLoading(); + + enum + { + load = true, + save = false + }; + + Archive( Stream &rStream, bool bLoading ); + virtual ~Archive(); + virtual void close(); + + virtual void write( const void *pData, size_t iSize ); + virtual void read( void *pData, size_t iSize ); + + /** + * For storage, get an ID for the pointer to the object you're going to + * write. + */ + uint32_t getID( const void *ptr ); + + /** + * For loading. Assosiates an empty pointer with an id. When you wind + * up loading an id reference to a pointer for an object that may or + * may not have loaded yet, call this with the id, if it has been loaded + * already, you'll immediately get a pointer, if not, it will write one + * for you when the time comes. + */ + void assocPtrID( void **ptr, uint32_t id ); + + /** + * For loading. Call this when you load an object that other things may + * have pointers to. It will assosiate every pointer that's been + * registered with assocPtrID to the pointer passed in, and id passed + * in. It will also set things up so future calls to assocPtrID will + * automatically succeed immediately. + */ + void readID( const void *ptr, uint32_t id ); + + template + void setProp( const Bu::String &sId, const t &val ) + { + if( !hProps.has( sId ) ) + { + hProps.insert( sId, Variant() ); + } + hProps.get( sId ) = val; + } + + template + t getProp( const Bu::String &sId ) + { + return hProps.get( sId ); + } + + private: + Stream &rStream; + uint32_t nNextID; + Hash hPtrID; + Hash > hPtrDest; + Hash hProps; + }; +} + +#endif -- cgit v1.2.3