summaryrefslogblamecommitdiffstats
path: root/crawl-ref/source/store.h
blob: 8a54189caec02c4167372233250c61f00ff663d4 (plain) (tree)
1
2
3
4
5
  


                                                                 
                             









                   

              

                      

                 
                 


                  






















                                                                 

               

             













































                                                                      

                                          

                                           
 












                                                               
                                















                                                                       

                                    

                                  









                                         



                                             

                                              
 

                                 









                                              
      

       
                                                                   


                                                                    
                                                                     











                                                                      









                               

                          

                           
 




                                 
                                 


                                 












                                                            

                                                       

                                                        















                                                         

                               













                                                                    
                                                   








                                                                     
                                                







                                                                  




                                                                        



                                 

                                                             

                               
 

                                              
 




                                                                     









                                                                    






                                           

                                 


                      




























                                                                      

                               








                                                          
                                                                    



                                                                    


                                                        




                                                                     
                                                                   








                                                             

                                 


                     




















                                                                      

                                                      


                                           










                                                                
/*
 *  File:       store.h
 *  Summary:    Saveable hash-table and vector capable of storing
 *              multiple types of data.
 *  Written by: Matthew Cline
 */

#ifndef STORE_H
#define STORE_H

#include <limits.h>
#include <map>
#include <string>
#include <vector>

class  reader;
class  writer;
class  CrawlHashTable;
class  CrawlVector;
struct item_def;
struct coord_def;
struct level_pos;
class  level_id;
class  dlua_chunk;
class  monsters;

typedef unsigned char hash_size;
typedef unsigned char vec_size;
typedef unsigned char store_flags;

#define VEC_MAX_SIZE  255
#define HASH_MAX_SIZE 255

// NOTE: Changing the ordering of these enums will break savefile
// compatibility.
enum store_val_type
{
    SV_NONE = 0,
    SV_BOOL,
    SV_BYTE,
    SV_SHORT,
    SV_LONG,
    SV_FLOAT,
    SV_STR,
    SV_COORD,
    SV_ITEM,
    SV_HASH,
    SV_VEC,
    SV_LEV_ID,
    SV_LEV_POS,
    SV_MONST,
    SV_LUA,
    NUM_STORE_VAL_TYPES
};

enum store_flag_type
{
    SFLAG_UNSET      = (1 << 0),
    SFLAG_CONST_VAL  = (1 << 1),
    SFLAG_CONST_TYPE = (1 << 2),
    SFLAG_NO_ERASE   = (1 << 3)
};


// Can't just cast everything into a void pointer, since a float might
// not fit into a pointer on all systems.
typedef union StoreUnion StoreUnion;
union StoreUnion
{
    bool  boolean;
    char  byte;
    short _short;
    long  _long;
    float _float;
    void* ptr;
};


class CrawlStoreValue
{
public:
    CrawlStoreValue();
    CrawlStoreValue(const CrawlStoreValue &other);

    ~CrawlStoreValue();

    // Conversion constructors
    CrawlStoreValue(const bool val);
    CrawlStoreValue(const char &val);
    CrawlStoreValue(const short &val);
    CrawlStoreValue(const long &val);
    CrawlStoreValue(const float &val);
    CrawlStoreValue(const std::string &val);
    CrawlStoreValue(const char* val);
    CrawlStoreValue(const coord_def &val);
    CrawlStoreValue(const item_def &val);
    CrawlStoreValue(const CrawlHashTable &val);
    CrawlStoreValue(const CrawlVector &val);
    CrawlStoreValue(const level_id &val);
    CrawlStoreValue(const level_pos &val);
    CrawlStoreValue(const monsters &val);
    CrawlStoreValue(const dlua_chunk &val);

    CrawlStoreValue &operator = (const CrawlStoreValue &other);

protected:
    store_val_type type;
    store_flags    flags;
    StoreUnion     val;

public:
    store_flags    get_flags() const;
    store_flags    set_flags(store_flags flags);
    store_flags    unset_flags(store_flags flags);
    store_val_type get_type() const;

    CrawlHashTable &new_table();

    CrawlVector &new_vector(store_flags flags,
                            vec_size max_size = VEC_MAX_SIZE);
    CrawlVector &new_vector(store_val_type type, store_flags flags = 0,
                            vec_size max_size = VEC_MAX_SIZE);

    bool           &get_bool();
    char           &get_byte();
    short          &get_short();
    long           &get_long();
    float          &get_float();
    std::string    &get_string();
    coord_def      &get_coord();
    CrawlHashTable &get_table();
    CrawlVector    &get_vector();
    item_def       &get_item();
    level_id       &get_level_id();
    level_pos      &get_level_pos();
    monsters       &get_monster();
    dlua_chunk     &get_lua();

    bool           get_bool()      const;
    char           get_byte()      const;
    short          get_short()     const;
    long           get_long()      const;
    float          get_float()     const;
    std::string    get_string()    const;
    coord_def      get_coord()     const;
    level_id       get_level_id()  const;
    level_pos      get_level_pos() const;

    const CrawlHashTable& get_table()  const;
    const CrawlVector&    get_vector() const;
    const item_def&       get_item()   const;
    const monsters&       get_monster() const;
    const dlua_chunk&     get_lua() const;

#if 0
    // These don't actually exist
    void set_bool(const bool val);
    void set_byte(const char val);
    void set_short(const short val);
    void set_long(const long val);
    void set_float(const float val);
    void set_string(const std::string &val);
    void set_coord(const coord_def &val);
    void set_table(const CrawlHashTable &val);
    void set_vector(const CrawlVector &val);
    void set_item(const item_def &val);
#endif

public:
    // NOTE: All operators will assert if the value is of the wrong
    // type for the operation.  If the value has no type yet, the
    // operation will set it to the appropriate type.  If the value
    // has no type yet and the operation modifies the existing value
    // rather than replacing it (e.g., ++) the value will be set to a
    // default before the operation is done.

    // If the value is a hash table or vector, the container's values
    // can be accessed with the [] operator with the approriate key
    // type (strings for hashes, longs for vectors).
    CrawlStoreValue &operator [] (const std::string   &key);
    CrawlStoreValue &operator [] (const vec_size &index);

    const CrawlStoreValue &operator [] (const std::string &key) const;
    const CrawlStoreValue &operator [] (const vec_size &index)  const;

    // Typecast operators
    operator bool&();
    operator char&();
    operator short&();
    operator long&();
    operator float&();
    operator std::string&();
    operator coord_def&();
    operator CrawlHashTable&();
    operator CrawlVector&();
    operator item_def&();
    operator level_id&();
    operator level_pos&();
    operator monsters&();
    operator dlua_chunk&();

    operator bool()        const;
    operator char()        const;
    operator short()       const;
    operator long()        const;
    operator float()       const;
    operator std::string() const;
    operator coord_def()   const;
    operator level_id()    const;
    operator level_pos()   const;

    // Assignment operators
    CrawlStoreValue &operator = (const bool &val);
    CrawlStoreValue &operator = (const char &val);
    CrawlStoreValue &operator = (const short &val);
    CrawlStoreValue &operator = (const long &val);
    CrawlStoreValue &operator = (const float &val);
    CrawlStoreValue &operator = (const std::string &val);
    CrawlStoreValue &operator = (const char* val);
    CrawlStoreValue &operator = (const coord_def &val);
    CrawlStoreValue &operator = (const CrawlHashTable &val);
    CrawlStoreValue &operator = (const CrawlVector &val);
    CrawlStoreValue &operator = (const item_def &val);
    CrawlStoreValue &operator = (const level_id &val);
    CrawlStoreValue &operator = (const level_pos &val);
    CrawlStoreValue &operator = (const monsters &val);
    CrawlStoreValue &operator = (const dlua_chunk &val);

    // Misc operators
    std::string &operator += (const std::string &val);

    // Prefix
    long operator ++ ();
    long operator -- ();

    // Postfix
    long operator ++ (int);
    long operator -- (int);

protected:
    CrawlStoreValue(const store_flags flags,
                    const store_val_type type = SV_NONE);

    void write(writer &) const;
    void read(reader &);

    void unset(bool force = false);

    friend class CrawlHashTable;
    friend class CrawlVector;
};


// A hash table can have a maximum of 255 key/value pairs.  If you
// want more than that you can use nested hash tables.
//
// By default a hash table's value data types are heterogeneous.  To
// make it homogeneous (which causes dynamic type checking) you have
// to give a type to the hash table constructor; once it's been
// created its type (or lack of type) is immutable.
//
// An empty hash table will take up only 1 byte in the savefile.  A
// non-empty hash table will have an overhead of 3 bytes for the hash
// table overall and 2 bytes per key/value pair, over and above the
// number of bytes needed to store the keys and values themselves.
class CrawlHashTable
{
public:
    CrawlHashTable();
    CrawlHashTable(const CrawlHashTable& other);

    ~CrawlHashTable();

    typedef std::map<std::string, CrawlStoreValue> hash_map_type;
    typedef hash_map_type::iterator                iterator;
    typedef hash_map_type::const_iterator          const_iterator;

protected:
    // NOTE: Not using std::auto_ptr because making hash_map an auto_ptr
    // causes compile weirdness in externs.h
    hash_map_type *hash_map;

    void init_hash_map();

    friend class CrawlStoreValue;

public:
    CrawlHashTable &operator = (const CrawlHashTable &other);

    void write(writer &) const;
    void read(reader &);

    bool exists(const std::string &key) const;
    void assert_validity() const;

    // NOTE: If the const versions of get_value() or [] are given a
    // key which doesn't exist, they will assert.
    const CrawlStoreValue& get_value(const std::string &key) const;
    const CrawlStoreValue& operator[] (const std::string &key) const;

    // NOTE: If get_value() or [] is given a key which doesn't exist
    // in the table, an unset/empty CrawlStoreValue will be created
    // with that key and returned.  If it is not then given a value
    // then the next call to assert_validity() will fail.  If the
    // hash table has a type (rather than being heterogeneous)
    // then trying to assign a different type to the CrawlStoreValue
    // will assert.
    CrawlStoreValue& get_value(const std::string &key);
    CrawlStoreValue& operator[] (const std::string &key);

    // std::map style interface
    hash_size size() const;
    bool      empty() const;

    void      erase(const std::string key);
    void      clear();

    const_iterator begin() const;
    const_iterator end() const;

    iterator  begin();
    iterator  end();
};

// A CrawlVector is the vector version of CrawlHashTable, except that
// a non-empty CrawlVector has one more byte of savefile overhead that
// a hash table, and that can specify a maximum size to make it act
// similarly to a FixedVec.
class CrawlVector
{
public:
    CrawlVector();
    CrawlVector(store_flags flags, vec_size max_size = VEC_MAX_SIZE);
    CrawlVector(store_val_type type, store_flags flags = 0,
                vec_size max_size = VEC_MAX_SIZE);

    ~CrawlVector();

    typedef std::vector<CrawlStoreValue> vector_type;
    typedef vector_type::iterator        iterator;
    typedef vector_type::const_iterator  const_iterator;

protected:
    store_val_type type;
    store_flags    default_flags;
    vec_size       max_size;
    vector_type    vector;

    friend class CrawlStoreValue;

public:
    void write(writer &) const;
    void read(reader &);

    store_flags    get_default_flags() const;
    store_flags    set_default_flags(store_flags flags);
    store_flags    unset_default_flags(store_flags flags);
    store_val_type get_type() const;
    void           assert_validity() const;
    void           set_max_size(vec_size size);
    vec_size       get_max_size() const;

    // NOTE: If the const versions of get_value() or [] are given an
    // index which doesn't exist, they will assert.
    const CrawlStoreValue& get_value(const vec_size &index) const;
    const CrawlStoreValue& operator[] (const vec_size &index) const;

    CrawlStoreValue& get_value(const vec_size &index);
    CrawlStoreValue& operator[] (const vec_size &index);

    // std::vector style interface
    vec_size size() const;
    bool     empty() const;

    // NOTE: push_back() and insert() have val passed by value rather
    // than by reference so that conversion constructors will work.
    CrawlStoreValue& pop_back();
    void             push_back(CrawlStoreValue val);
    void insert(const vec_size index, CrawlStoreValue val);

    // resize() will assert if the maximum size has been set.
    void resize(const vec_size size);
    void erase(const vec_size index);
    void clear();

    const_iterator begin() const;
    const_iterator end() const;

    iterator begin();
    iterator end();
};

// A wrapper for non-heterogeneous hash tables, so that the values can
// be accessed without using get_foo().  T needs to have both normal
// and const type-cast operators defined by CrawlStoreValue for this
// template to work.
template <typename T, store_val_type TYPE>
class CrawlTableWrapper
{
public:
    CrawlTableWrapper();
    CrawlTableWrapper(CrawlHashTable& table);
    CrawlTableWrapper(CrawlHashTable* table);

protected:
    CrawlHashTable* table;

public:
    void wrap(CrawlHashTable& table);
    void wrap(CrawlHashTable* table);

    const CrawlHashTable* get_table() const;
    const T operator[] (const std::string &key) const;

    CrawlHashTable* get_table();
    T& operator[] (const std::string &key);
};

typedef CrawlTableWrapper<bool, SV_BOOL>       CrawlBoolTable;
typedef CrawlTableWrapper<char, SV_BYTE>       CrawlByteTable;
typedef CrawlTableWrapper<short, SV_SHORT>     CrawlShortTable;
typedef CrawlTableWrapper<long, SV_LONG>       CrawlLongTable;
typedef CrawlTableWrapper<float, SV_FLOAT>     CrawlFloatTable;
typedef CrawlTableWrapper<std::string, SV_STR> CrawlStringTable;
typedef CrawlTableWrapper<coord_def, SV_COORD> CrawlCoordTable;

#endif