Itzam/C++

Main Index

Created by Scott Robert Ladd at Coyote Gulch Productions.


itzam_common.h

00001 //---------------------------------------------------------------------
00002 //  Algorithmic Conjurings @ http://www.coyotegulch.com
00003 //
00004 //  Itzam - An Embedded Database Engine
00005 //
00006 //  itzam_common.h
00007 //
00008 //---------------------------------------------------------------------
00009 //
00010 //  Copyright 2004, 2005, 2006 Scott Robert Ladd
00011 //
00012 //  This program is free software; you can redistribute it and/or modify
00013 //  it under the terms of the GNU General Public License as published by
00014 //  the Free Software Foundation; either version 2 of the License, or
00015 //  (at your option) any later version.
00016 //  
00017 //  This program is distributed in the hope that it will be useful,
00018 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //  GNU General Public License for more details.
00021 //  
00022 //  You should have received a copy of the GNU General Public License
00023 //  along with this program; if not, write to the
00024 //      Free Software Foundation, Inc.
00025 //      59 Temple Place - Suite 330
00026 //      Boston, MA 02111-1307, USA.
00027 //
00028 //-----------------------------------------------------------------------
00029 //
00030 //  For more information on this software package, please visit
00031 //  Scott's web site, Coyote Gulch Productions, at:
00032 //
00033 //      http://www.coyotegulch.com
00034 //  
00035 //-----------------------------------------------------------------------
00036 
00037 #if !defined(LIBITZAM_CPP_ITZAM_COMMON_H)
00038 #define LIBITZAM_CPP_ITZAM_COMMON_H
00039 
00040 // Standard C
00041 #include <sys/types.h>
00042 #include <sys/stat.h>
00043 
00044 #if defined(_MSC_VER)
00045 #include "windows.h"
00046 #else
00047 #include <unistd.h>
00048 #endif
00049 
00050 // Standard C++
00051 #include <string>
00052 #include <stdexcept>
00053 
00055 
00060 namespace itzam
00061 {
00062     using std::runtime_error;
00063     using std::string;
00064     
00065     // include Itzam/Core within itzam namespace
00066     #include "itzam_core/itzam.h"
00067 
00069 
00072     enum database_state
00073     {
00074         ITZAM_DB_BROKEN = -1, 
00075         ITZAM_DB_UNINIT =  0, 
00076         ITZAM_DB_OPEN   =  1, 
00077         ITZAM_DB_CLOSED =  2  
00078     };
00079 
00081 
00086     enum database_error
00087     {
00088         DB_ERROR_NONE,             
00089         DB_ERROR_OPEN_BROKEN,      
00090         DB_ERROR_OPEN_FAILED,      
00091         DB_ERROR_CLOSE_BROKEN,     
00092         DB_ERROR_CLOSE_FAILED,     
00093         DB_ERROR_WRITE_BROKEN,     
00094         DB_ERROR_WRITE_CLOSED,     
00095         DB_ERROR_WRITE_DUPE,       
00096         DB_ERROR_WRITE_FAILED,     
00097         DB_ERROR_READ_BROKEN,      
00098         DB_ERROR_READ_CLOSED,      
00099         DB_ERROR_READ_NOT_FOUND,   
00100         DB_ERROR_READ_FAILED,      
00101         DB_ERROR_EXISTS_BROKEN,    
00102         DB_ERROR_EXISTS_CLOSED,    
00103         DB_ERROR_REMOVE_BROKEN,    
00104         DB_ERROR_REMOVE_CLOSED,    
00105         DB_ERROR_REMOVE_NOT_FOUND, 
00106         DB_ERROR_REMOVE_FAILED,    
00107         DB_ERROR_REFLIST_MISSING,  
00108         DB_ERROR_COUNT             
00109     };
00110 
00112 
00118     class database_exception : public runtime_error
00119     {
00120         private:
00121             // utility function
00122             static string build_error_string(const string & message)
00123             {
00124                 string text("Itzam exception: ");
00125                 text += message;
00126                 return text;
00127             }
00128 
00129             // strings associated with various codes
00130             static const string DB_ERRORS [DB_ERROR_COUNT];
00131             
00132             // data elements
00133             database_error    m_error;
00134 
00135         public:
00137 
00141             database_exception(const string & message)
00142                 : runtime_error(build_error_string(message)),
00143                   m_error(DB_ERROR_NONE)
00144             {
00145                 // nada
00146             }
00147 
00149 
00153             database_exception(itzam_state state)
00154                 : runtime_error(build_error_string(itzam_get_state_description(state))),
00155                   m_error(DB_ERROR_NONE)
00156             {
00157                 // nada
00158             }
00159 
00161 
00165             database_exception(database_error error)
00166                 : runtime_error(build_error_string(DB_ERRORS[error])),
00167                   m_error(error)
00168             {
00169                 // nada
00170             }
00171             
00173 
00177             database_error get_error() const
00178             {
00179                 return m_error;
00180             }
00181     };
00182     
00184 
00189     class serial_data
00190     {
00191         private:
00192             void *       m_data;
00193             size_t       m_size;
00194             bool         m_cleanup;
00195             
00196         public: 
00198             serial_data()
00199                 : m_data(NULL),
00200                   m_size(0),
00201                   m_cleanup(false)
00202             {
00203                 // nada
00204             }
00205             
00207             serial_data(const void * data, size_t size, bool cleanup = false)
00208                 : m_data(const_cast<void *>(data)),
00209                   m_size(size),
00210                   m_cleanup(cleanup)
00211             {
00212                 // nada
00213             }
00214             
00216             serial_data(const serial_data & source)
00217               : m_data(NULL),
00218                 m_size(source.m_size),
00219                 m_cleanup(source.m_cleanup)
00220             {
00221                 if (m_cleanup)
00222                 {
00223                     m_data = malloc(m_size);
00224                     memcpy(m_data,source.m_data,m_size);
00225                 }
00226                 else
00227                     m_data = source.m_data;
00228             }
00229             
00231             serial_data & operator = (const serial_data & source)
00232             {
00233                 if (m_cleanup)
00234                     free(m_data);
00235                 
00236                 m_size    = source.m_size;
00237                 m_cleanup = source.m_cleanup;
00238                 
00239                 if (m_cleanup)
00240                 {
00241                     m_data = malloc(m_size);
00242                     memcpy(m_data,source.m_data,m_size);
00243                 }
00244                 else
00245                     m_data = source.m_data;
00246                 
00247                 return *this;
00248             }
00249             
00251             virtual ~serial_data()
00252             {
00253                 if (m_cleanup)
00254                     free(m_data);
00255             }
00256             
00258             const void * get_data() const
00259             {
00260                 return m_data;
00261             }
00262             
00264             size_t get_size() const
00265             {
00266                 return m_size;
00267             }
00268     };
00269     
00271 
00299     template < typename base_t >
00300          class atomic_record
00301          {
00302              public:
00304 
00307                  atomic_record(const base_t & value = 0)
00308                    : m_value(value)
00309                  {
00310                      // nada
00311                  }
00312 
00314 
00321                  atomic_record(const serial_data & source)
00322                    : m_value(*((base_t *)source.get_data()))
00323                  {
00324                      // nada
00325                  }
00326 
00328 
00333                  atomic_record(const atomic_record & source)
00334                    : m_value(source.m_value)
00335                  {
00336                      // nada
00337                  }
00338 
00340 
00346                  atomic_record & operator = (const atomic_record<base_t> & source)
00347                  {
00348                      m_value = source.m_value;
00349                      return *this;
00350                  }
00351 
00353 
00359                  atomic_record & operator = (const base_t & source)
00360                  {
00361                      m_value = source;
00362                      return *this;
00363                  }
00364 
00366 
00372                  atomic_record & operator = (const serial_data & source)
00373                  {
00374                      m_value = *((base_t *)source.get_data());
00375                      return *this;
00376                  }
00377 
00379 
00384                  virtual ~atomic_record()
00385                  {
00386                      // nada, just for any derived classes
00387                  }
00388                  
00390 
00394                  operator base_t() const
00395                  {
00396                      return m_value;
00397                  }
00398 
00400 
00405                  operator serial_data() const
00406                  {
00407                      return serial_data(&m_value,sizeof(base_t),false);
00408                  }
00409                  
00410             protected:
00412                 base_t m_value;
00413          };
00414          
00416 
00427     template <typename base_t>
00428         class numeric_key
00429           : public atomic_record<base_t>
00430         {
00431              public:
00433 
00436                  numeric_key(const base_t & value = 0)
00437                    : atomic_record<base_t>(value)
00438                  {
00439                      // nada
00440                  }
00441 
00443 
00450                  numeric_key(const serial_data & source)
00451                    : atomic_record<base_t>(source)
00452                  {
00453                      // nada
00454                  }
00455 
00457 
00462                  numeric_key(const numeric_key & source)
00463                    : atomic_record<base_t>(source)
00464                  {
00465                      // nada
00466                  }
00467 
00469 
00475                  numeric_key & operator = (const numeric_key<base_t> & source)
00476                  {
00477                      atomic_record<base_t>::operator = (source);
00478                      return *this;
00479                  }
00480 
00482 
00488                  numeric_key & operator = (const base_t & source)
00489                  {
00490                      atomic_record<base_t>::operator = (source);
00491                      return *this;
00492                  }
00493 
00495 
00501                  numeric_key & operator = (const serial_data & source)
00502                  {
00503                      atomic_record<base_t>::operator = (source);
00504                      return *this;
00505                  }
00506 
00508 
00513                  virtual ~numeric_key()
00514                  {
00515                      // nada, just for any derived classes
00516                  }
00517 
00519 
00527                  static int compare_keys(const void * key1, const void * key2)
00528                  {
00529                      int result = 0;
00530 
00531                      // I can't simply cast this value to int, since if base_t is real,
00532                      //      abs(diff) might be  close enough to zero that nearby keys
00533                      //      would be cast to 0 (equal). Although real keys are unlikely,
00534                      //      it's still a good idea to account for them.
00535                      base_t diff = (*((const base_t *)key1)) - (*((const base_t *)key2));
00536 
00537                      if (diff < 0)
00538                          result = -1;
00539                      else if (diff > 0)
00540                          result = 1;
00541 
00542                      return result;
00543                  }
00544         };
00545 
00547 
00550     class string_key
00551     {
00552          public:
00554 
00557              string_key(const string & value = 0)
00558                : m_value(value)
00559              {
00560                  // nada
00561              }
00562 
00564 
00571              string_key(const serial_data & source)
00572                : m_value(reinterpret_cast<const char *>(source.get_data()))
00573              {
00574                  // nada
00575              }
00576 
00578 
00583              string_key(const string_key & source)
00584                : m_value(source.m_value)
00585              {
00586                  // nada
00587              }
00588 
00590 
00596              string_key & operator = (const string_key & source)
00597              {
00598                  m_value = source.m_value;
00599                  return *this;
00600              }
00601 
00603 
00609              string_key & operator = (const string & source)
00610              {
00611                  m_value = source;
00612                  return *this;
00613              }
00614 
00616 
00622              string_key & operator = (const serial_data & source)
00623              {
00624                  m_value = string(reinterpret_cast<const char *>(source.get_data()));
00625                  return *this;
00626              }
00627 
00629 
00634              virtual ~string_key()
00635              {
00636                  // nada, just for any derived classes
00637              }
00638 
00640 
00644              operator string() const
00645              {
00646                  return m_value;
00647              }
00648 
00650 
00655              operator serial_data() const
00656              {
00657                  char * s = strdup(m_value.c_str());
00658                  return serial_data(s,strlen(s) + 1,true);
00659              }
00660 
00662 
00670              static int compare_keys(const void * key1, const void * key2)
00671              {
00672                  return strcmp((const char *)key1, (const char *)key2);
00673              }
00674                  
00675         protected:
00677             string m_value;
00678     };
00679 
00681 
00688     class mutex
00689     {
00690         public:
00692 
00697             virtual ~mutex()
00698             {
00699                 // nada
00700             }
00701 
00703 
00708             virtual void lock() = 0;
00709 
00711 
00714             virtual void unlock() = 0;
00715 
00717 
00723             virtual void sleep() = 0;
00724     };
00725 
00727 
00731     class null_mutex : public mutex
00732     {
00733         public:
00735 
00738             virtual ~null_mutex()
00739             {
00740                 // nada
00741             }
00742 
00744 
00748             virtual void lock()
00749             {
00750                 // nada
00751             }
00752 
00754 
00757             virtual void unlock()
00758             {
00759                 // nada
00760             }
00761 
00762         protected:
00764 
00767             virtual void sleep()
00768             {
00769                 // nada
00770             }
00771     };
00772 
00774 
00778     class simple_mutex : public mutex
00779     {
00780         public:
00782 
00785             simple_mutex()
00786               : m_locked(false)
00787             {
00788                 // nada
00789             }
00790 
00792 
00795             virtual ~simple_mutex()
00796             {
00797                 // nada
00798             }
00799 
00801 
00806             virtual void lock()
00807             {
00808                 while (m_locked)
00809                 {
00810                     sleep();
00811                 }
00812 
00813                 m_locked = true;
00814             }
00815 
00817 
00820             virtual void unlock()
00821             {
00822                 m_locked = false;
00823             }
00824 
00826 
00831             virtual void sleep()
00832             {
00833 #if defined(_MSC_VER)
00834                 Sleep(50000);
00835 #else
00836                 usleep(50000);
00837 #endif
00838             }
00839 
00840         private:
00841             bool m_locked;
00842     };
00843 
00845 
00852     template < class key_t >
00853         class selector
00854         {
00855             public:
00857 
00860                 virtual ~selector()
00861                 {
00862                     // nada
00863                 }
00864 
00865                 // all derivations of this class must define a static member function of this form
00866                 //     static bool selector(const void * key);
00867         };
00868 
00870 
00876     template < class key_t >
00877         class select_all
00878           : public selector<key_t>
00879         {
00880             public:
00882 
00885                 virtual ~select_all()
00886                 {
00887                     // nada
00888                 }
00889 
00891 
00896                 static bool select(const void * key)
00897                 {
00898                     return true;
00899                 }
00900         };
00901 
00903 
00907     class database_object
00908     {
00909         protected:
00911             database_state m_state;
00912 
00914             itzam_file_lock_mode m_file_lock_mode;
00915         
00917             string m_name;
00918         
00919         public:
00921 
00927             database_object(const string & name, itzam_file_lock_mode lock_mode)
00928               : m_state(ITZAM_DB_UNINIT),
00929                 m_name(name),
00930                 m_file_lock_mode(lock_mode)
00931             {
00932                 // nada
00933             }
00934 
00936 
00940             database_object(const database_object & source)
00941               : m_state(source.m_state),
00942                 m_name(source.m_name),
00943                 m_file_lock_mode(source.m_file_lock_mode)
00944             {
00945                 // nada
00946             }
00947 
00949 
00954             database_object & operator = (const database_object & source)
00955             {
00956                 m_state = source.m_state;
00957                 m_name  = source.m_name;
00958                 m_file_lock_mode = source.m_file_lock_mode;
00959                 return *this;
00960             }
00961 
00963 
00967             database_state get_state() const
00968             {
00969                 return m_state;
00970             }
00971 
00973 
00977             string get_name() const
00978             {
00979                 return m_name;
00980             }
00981 
00983 
00987             itzam_file_lock_mode get_lock_mode() const
00988             {
00989                 return m_file_lock_mode;
00990             }
00991 
00993 
00997             bool is_okay() const
00998             {
00999                 return (m_state != ITZAM_DB_BROKEN);
01000             }
01001 
01003 
01009             bool is_broken() const
01010             {
01011                 return (m_state == ITZAM_DB_BROKEN);
01012             }
01013 
01015 
01019             bool is_open() const
01020             {
01021                 return (m_state == ITZAM_DB_OPEN);
01022             }
01023 
01025 
01029             bool is_closed() const
01030             {
01031                 return (m_state == ITZAM_DB_CLOSED);
01032             }
01033     };
01034     
01035 } // end namespace itzam
01036 
01037 #endif

© 1996-2005 Scott Robert Ladd. All rights reserved.
HTML documentation generated by Dimitri van Heesch's excellent Doxygen tool.