Click here to Skip to main content
15,893,663 members
Articles / Programming Languages / C++

ESS: Extremely Simple Serialization for C++

Rate me:
Please Sign up or sign in to vote.
4.94/5 (14 votes)
26 Nov 2012BSD15 min read 87.3K   1.7K   68  
An article on persistent C++ objects. Includes several console mode test apps and an MFC GUI demo.
/*

	ESS Extremely Simple Serialization for C++

	http://www.novadsp.com/ess

	Copyright (c) Jerry Evans, 2008-2009
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright 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.

	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 HOLDER 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.

*/

#ifndef ESS_DEBUG_H
#define ESS_DEBUG_H

#include "ess_binary.h"

namespace ess
{

//-----------------------------------------------------------------------------
// This adapter class simply dumps the contents of a binary archive to the nominated
// text file in a verbose format.
class binary_debug_adapter  : public stream_adapter
{
	binary_debug_adapter& operator=(const binary_debug_adapter&);

	// reference to our buffer
	binary_medium& m_buffer_ref;

	// virtual base class for conversion
	struct IConverter
	{
		virtual std::string convert(binary_medium&) = 0;
		// helper for deleting instances stored in a map
		static void Delete(std::pair<TypeEnum,IConverter*> kvp)
		{
			delete kvp.second;
		}
	};

	// converts a given type T to a string, given the existing of a
	// toString() function with the correct type signature ...
	template <typename T>
	struct Converter : public IConverter
	{
		virtual std::string convert(binary_medium& buffer)
		{
			// create
			T thing;
			// read
			buffer.read(&thing,sizeof(thing));
			// convert
			return Chordia::toString(thing);
		}
	};

	// special case for strings ... should cope with wstring but untested
	template <typename T = std::string>
	struct StringConverter : public IConverter
	{
		virtual std::string convert(binary_medium& buffer)
		{
			size_t chars = 0;
			buffer.read(&chars,sizeof(chars));
			// is the string empty?
			T thing;
			if (chars == 0)
			{
				thing = "empty string!";
			}
			else
			{
				thing.assign(chars,0);
				// copy (!)
				buffer.read(&thing[0],chars);
			}
			// convert
			return thing;
		}
	};

	typedef std::map<TypeEnum,IConverter*> conversion_map;
	typedef conversion_map::iterator conversion_map_iterator;
	typedef conversion_map::const_iterator conversion_map_const_iterator;

	// for automated debugging
	conversion_map mapper;

	public:

	// set up and set initial size
	binary_debug_adapter(binary_medium& ref,int version = 1) :
		stream_adapter(version),
		m_buffer_ref(ref)
	{
		mapper[bool_e] = new Converter<bool>();
		mapper[sint_e] = new Converter<signed int>();
		mapper[uint_e] = new Converter<unsigned int>();
		mapper[sshort_e] = new Converter<short>();
		mapper[ushort_e] = new Converter<unsigned short>();
		mapper[slong_e] = new Converter<long>();
		mapper[ulong_e] = new Converter<unsigned long>();
		mapper[float_e] = new Converter<float>();
		mapper[double_e] = new Converter<double>();
		mapper[GUID_e] = new Converter<GUID>();
		mapper[string_e] = new StringConverter<std::string>();
	}

	virtual ~binary_debug_adapter()
	{
		std::for_each(mapper.begin(),mapper.end(),IConverter::Delete);
		mapper.clear();
	}

	//
	virtual bool storing() const { return false; }

	// this is one that got lost!
	virtual bool dump(const char* filename)
	{
		// dump to a file
		std::ofstream ofs(filename);
		if (ofs.good() == false)
		{
			return false;
		}

		// start from the beginning of the buffer
		m_buffer_ref.reset();

		TypeEnum te;
		long sl = 0;
		while (m_buffer_ref.offset() < m_buffer_ref.size())
		{
			// read a type tag
			m_buffer_ref.read(&sl,sizeof(sl));
			te = static_cast<TypeEnum>(sl);
			ofs << "Tag: " << sl << " ";
			// lookup in the conversion map
			conversion_map_const_iterator cmit = mapper.find(te);
			if (cmit != mapper.end())
			{
				//
				ofs << typeTS[te].text
					<< ": "
					<< 	cmit->second->convert(m_buffer_ref)	// this converts to a string
					<< std::endl;
			}
			else
			{
				ofs << "Unknown tag: " << sl << " at offset " << m_buffer_ref.offset() << std::endl;
				return false;
			}
		}
		return true;
	}
};


}

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The BSD License


Written By
Architect
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions