Click here to Skip to main content
15,884,388 members
Articles / Desktop Programming / MFC

Persistence is the Key

Rate me:
Please Sign up or sign in to vote.
4.73/5 (16 votes)
24 Jan 2013Ms-PL16 min read 79K   563   42  
Tutorial for using the Calvin C++ persistence library.
#ifndef FS_ARCHIVE_H
#define FS_ARCHIVE_H

/*-----------------------------------------------------------------------------
File  :	fs_archive.H
Title :	File System archive class for calvin persistence library
Owner :	Jay Kint

	Copyright (C) 2005, Jay Kint, All Rights Reserved
-------------------------------------------------------------------------------
Description:

*/



//-----------------------------------------------------------------------------
//							Include Files
//-----------------------------------------------------------------------------

// module includes

// system includes
#include <istream>
#include <ostream>
#include <boost/filesystem/operations.hpp> // includes boost/filesystem/path.hpp
#include <boost/filesystem/fstream.hpp>    // ditto
#include <boost/shared_ptr.hpp>


//-----------------------------------------------------------------------------
//							Namespace
//-----------------------------------------------------------------------------

namespace calvin {

#if 0
}   // namespace indentation hack
#endif

//-----------------------------------------------------------------------------
//							Types and Structures
//-----------------------------------------------------------------------------


// forward declarations

namespace fs = boost::filesystem;

// implementation of archives where objects are stored in individual files.
// any data type can be used as the key as long as it can be converted to a
// string using the << operator.

template <typename Key>
class file_archive : public archive<Key> {
 public:
    // Types and constants
	// Constructors
    file_archive( const std::string& base_dir );
	// Destructor
    ~file_archive( void );
	// Operations
    // Accessors
    const std::string& base_directory( void ) { return _base_dir; }
	// Class Functions
 protected:
	// Constructors
	// Attributes
	// Operations
	// Class Attributes
	// Class Functions
 private:
	// Attributes
    std::string _base_dir;
    boost::filesystem::path _root;   
    boost::shared_ptr<std::ostream> _current_ostream;
    boost::shared_ptr<std::istream> _current_istream;
	// Operations
    virtual boost::shared_ptr<std::ostream> resolve_output( const Key& );
    virtual boost::shared_ptr<std::istream> resolve_input( const Key& );
	// Class Attributes

	// Class Functions
};

// shortcut for conventional file names
typedef class file_archive<std::string> filesys_archive;


//-----------------------------------------------------------------------------
//							Constants and Definitions
//-----------------------------------------------------------------------------

// explicit instantiation for filesys_archive in archive.h
// You muse use similar to these if you define persistent classes and archives
// that use other types for keys and put them in a .h file included by
// the application that imports it.  See the comments for the defintion 
// of CALVIN_EXPORT and CALVIN_DECLSPEC.
#pragma warning(push)
#pragma warning(disable:4231)
CALVIN_EXPORT template CALVIN_DECLSPEC archive<std::string>;

CALVIN_EXPORT template archive<std::string>* archive<std::string>::default_archive_;
CALVIN_EXPORT template archive<std::string>* archive<std::string>::current_archive_;
#pragma warning(pop)


//-----------------------------------------------------------------------------
//							Module Functions
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
//							Inline functions
//-----------------------------------------------------------------------------

template <typename Key>
file_archive< Key >::file_archive( const std::string& base )
{
    _root = boost::filesystem::path( base, fs::native );
}

template <typename Key>
file_archive< Key >::~file_archive( void )
{
    _current_ostream.reset();
    _current_istream.reset();
}

template <typename Key>
boost::shared_ptr<std::ostream> file_archive< Key >::resolve_output( const Key& key )
{
    // if the persistent object doesn't have a name, put it in the same stream
    if( key == Key() )
        return _current_ostream;

    std::ostringstream key_to_string;
    key_to_string << key;

    boost::shared_ptr<std::ostream> s( static_cast<std::ostream*>( new fs::ofstream( _root / key_to_string.str(), std::ios::out | std::ios::binary )));
    if( !s->good() )
        CALVIN_ERROR( "failed to open output stream" );
    _current_ostream = s;
    return s;
}

template <typename Key>
boost::shared_ptr<std::istream> file_archive< Key >::resolve_input( const Key& key )
{
    // close off any outstanding output streams
    if( _current_ostream != NULL )
        _current_ostream.reset();

    // if this persistent object doesn't have a name, read it from the same stream
    if( key == Key() )
        return _current_istream;

    std::ostringstream key_to_string;
    key_to_string << key;

    boost::shared_ptr<std::istream> s( static_cast<std::istream*>( new fs::ifstream( _root / key_to_string.str(), std::ios::in | std::ios::binary )));
    if( !s->good() ) {
        std::string err( "failed to open file " );
        err += key;
        CALVIN_ERROR( err );
    }
    _current_istream = s;
    return s;
}



}   // namespace calvin

#endif		// ARCHIVE_H

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 Microsoft Public License (Ms-PL)


Written By
Web Developer
United States United States
Jay Kint has been a software engineer/hacker for most of his life, starting with 8 bit Ataris. After a lengthy stint in the game industry, he now works at Microsoft in SQL Server.

Comments and Discussions