Created by Scott Robert Ladd at Coyote Gulch Productions.
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.