Open-RJ C/C++ User's Journal Synesis Software STLSoft - ... Robust, Lightweight, Cross-platform, Template Software ...

openrj/stl/database.hpp

Go to the documentation of this file.
00001 /* /////////////////////////////////////////////////////////////////////////////
00002  * File:    openrj/stl/database.hpp
00003  *
00004  * Purpose: file_database and memory_database classes, in the STL mapping of the
00005  *          Open-RJ library
00006  *
00007  * Created: 15th June 2004
00008  * Updated: 26th December 2006
00009  *
00010  * Home:    http://openrj.org/
00011  *
00012  * Copyright (c) 2004-2006, Matthew Wilson and Synesis Software
00013  * All rights reserved.
00014  *
00015  * Redistribution and use in source and binary forms, with or without
00016  * modification, are permitted provided that the following conditions are met:
00017  *
00018  * - Redistributions of source code must retain the above copyright notice, this
00019  *   list of conditions and the following disclaimer.
00020  * - Redistributions in binary form must reproduce the above copyright notice,
00021  *   this list of conditions and the following disclaimer in the documentation
00022  *   and/or other materials provided with the distribution.
00023  * - Neither the names of Matthew Wilson and Synesis Software nor the names of
00024  *   any contributors may be used to endorse or promote products derived from
00025  *   this software without specific prior written permission.
00026  *
00027  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00028  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00029  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00030  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00031  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00032  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00033  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00034  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00035  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00036  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00037  * POSSIBILITY OF SUCH DAMAGE.
00038  *
00039  * ////////////////////////////////////////////////////////////////////////// */
00040 
00041 
00048 #ifndef OPENRJ_INCL_OPENRJ_STL_HPP_DATABASE
00049 #define OPENRJ_INCL_OPENRJ_STL_HPP_DATABASE
00050 
00051 /* /////////////////////////////////////////////////////////////////////////////
00052  * Version information
00053  */
00054 
00055 #ifndef OPENRJ_DOCUMENTATION_SKIP_SECTION
00056 # define OPENRJ_VER_OPENRJ_STL_HPP_DATABASE_MAJOR       1
00057 # define OPENRJ_VER_OPENRJ_STL_HPP_DATABASE_MINOR       7
00058 # define OPENRJ_VER_OPENRJ_STL_HPP_DATABASE_REVISION    7
00059 # define OPENRJ_VER_OPENRJ_STL_HPP_DATABASE_EDIT        39
00060 #endif /* !OPENRJ_DOCUMENTATION_SKIP_SECTION */
00061 
00062 /* /////////////////////////////////////////////////////////////////////////////
00063  * Includes
00064  */
00065 
00066 #include <openrj/openrj.h>
00067 #include <openrj/openrj_assert.h>
00068 
00069 #include <openrj/stl/openrj.hpp>
00070 #include <openrj/stl/field.hpp>
00071 #include <openrj/stl/record.hpp>
00072 
00073 #if defined(ORJ_NO_EXCEPTIONS)
00074 # error The Open-RJ STL mapping is not compilable in the absence of exception
00075 #endif /* ORJ_NO_EXCEPTIONS */
00076 
00077 #include <iterator>
00078 
00079 #include <stlsoft/iterators/indirect_reverse_iterator.hpp>
00080 #include <stlsoft/iterator.hpp>
00081 #include <stlsoft/proxy_iterator.hpp>
00082 
00083 /* /////////////////////////////////////////////////////////////////////////////
00084  * Compiler warnings
00085  */
00086 
00087 #ifdef __BORLANDC__
00088 # pragma warn -8027
00089 #endif /* __BORLANDC__ */
00090 
00091 /* /////////////////////////////////////////////////////////////////////////////
00092  * Compiler compatibility
00093  */
00094 
00095 #if defined(__BORLANDC__) || \
00096     defined(__COMO__x) || \
00097     (   defined(__DMC__) && \
00098         __DMC__ < 0x0843)|| \
00099     (   defined(__GNUC__) && \
00100         (   __GNUC__ < 3) || \
00101             (   __GNUC__ == 3 && \
00102                 __GNUC_MINOR__ < 2)) || \
00103     (   defined(_MSC_VER) && \
00104         (   _MSC_VER < 1200 || \
00105             _MSC_VER == 1300)) /* For some reason VC++ 7.0 (not 6.0, 7.1) has a fit with this. */
00106 # define OPENRJ_STL_DATABASE_NO_FIELD_ITERATORS
00107 #endif /* compiler */
00108 
00109 /* /////////////////////////////////////////////////////////////////////////////
00110  * Namespace
00111  */
00112 
00113 namespace openrj
00114 {
00115 
00116 namespace stl
00117 {
00118 
00119 /* /////////////////////////////////////////////////////////////////////////////
00120  * Classes
00121  */
00122 
00125 class database_base
00126 {
00127 private:
00128     struct proxy_traits_type
00129     {
00130         static field make_value(ORJField const &field_)
00131         {
00132             return field(&field_);
00133         }
00134     };
00135 protected:
00137     typedef database_base                   class_type;
00138 public:
00140     typedef record                          value_type;
00142 #ifdef OPENRJ_STL_ITERATOR_HOLDS_VALUE
00143     typedef value_type const                &const_reference;
00144 #else /* ? OPENRJ_STL_ITERATOR_HOLDS_VALUE */
00145     typedef value_type const                const_reference;
00146 #endif /* OPENRJ_STL_ITERATOR_HOLDS_VALUE */
00148     typedef value_type const                *const_pointer;
00150     typedef ptrdiff_t                       difference_type;
00152     typedef size_t                          size_type;
00153 #ifndef OPENRJ_STL_DATABASE_NO_FIELD_ITERATORS
00154     // For some reason yet to be explained, these compilers fail to use
00155     // operator == / != on the proxy_iterator, irrespective of whether it's
00156     // implemented as a member function or a free function. I have, as yet, failed
00157     // to find any workaround.
00159     typedef stlsoft::proxy_iterator<const ORJField
00160                                 ,   field
00161                                 ,   proxy_traits_type
00162                                 ,   std::random_access_iterator_tag
00163                                 ,   field
00164                                 >           const_field_iterator;
00165 
00166 # if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00168     typedef stlsoft_ns_qual(const_reverse_iterator_base)<   const_field_iterator
00169                                                         ,   field
00170                                                         ,   field // Return by value!
00171                                                         ,   void
00172                                                         ,   difference_type
00173                                                         >   const_reverse_field_iterator;
00174 # endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00175 #endif /* !OPENRJ_STL_DATABASE_NO_FIELD_ITERATORS */
00177     typedef size_t                          distance_type;
00178 
00179 #ifndef OPENRJ_DOCUMENTATION_SKIP_SECTION
00180 public:
00182     class const_iterator;
00183 #endif /* !OPENRJ_DOCUMENTATION_SKIP_SECTION */
00184 
00185 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00187 #  if 0
00188     typedef stlsoft_ns_qual(const_reverse_iterator_base)<   const_iterator
00189                                                         ,   value_type
00190                                                         ,   value_type // Return by value!
00191                                                         ,   void
00192                                                         ,   difference_type
00193                                                         >   const_reverse_iterator;
00194 #  else /* ? 0 */
00195     // Can't use reverse_iterator, because const_iterator is a forward-declared member 
00196     // class - this now appears incorrect. Somehow I've made subsequent changes that
00197     // nullify the requirement. TODO: Investigate further ...
00198     typedef stlsoft_ns_qual(indirect_reverse_iterator)<     const_iterator
00199                                                         ,   value_type
00200                                                         ,   value_type // Return by value!
00201                                                         ,   void
00202                                                         ,   difference_type
00203                                                         ,   std::random_access_iterator_tag
00204                                                         >   const_reverse_iterator;
00205 #  endif /* 0 */
00206 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00207 
00208 protected:
00209     explicit database_base(ORJDatabase const *database);
00210 public:
00212     ~database_base();
00213 
00214 public:
00216     size_t num_lines() const;
00218     size_t num_fields() const;
00220     size_t num_records() const;
00222     size_t size() const;
00223 
00224 public:
00229     const record operator [](size_t index) const;
00230 
00231 public:
00235     const_iterator begin() const;
00239     const_iterator end() const;
00240 
00241 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00245     const_reverse_iterator rbegin() const;
00249     const_reverse_iterator rend() const;
00250 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00251 
00252 #ifndef OPENRJ_STL_DATABASE_NO_FIELD_ITERATORS
00253     const_field_iterator fields_begin() const;
00254     const_field_iterator fields_end() const;
00255 # if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00256     const_reverse_field_iterator fields_rbegin() const;
00257     const_reverse_field_iterator fields_rend() const;
00258 # endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00259 #endif /* !OPENRJ_STL_DATABASE_NO_FIELD_ITERATORS */
00260 
00261 // Members
00262 private:
00263     ORJDatabase const *m_database;
00264 
00265 // Not to be implemented
00266 private:
00267     database_base(class_type const &);
00268     class_type const &operator =(class_type const &);
00269 };
00270 
00271 #ifndef OPENRJ_NO_FILE_HANDLING
00273 class file_database
00274     : public database_base
00275 {
00276 private:
00277     typedef database_base       parent_class_type;
00278 public:
00279     typedef file_database       class_type;
00280 
00281 public:
00287     explicit file_database(char const *jarName, unsigned flags = 0);
00293     template <typename S>
00294     explicit file_database(S const &jarName, unsigned flags = 0)
00295         : parent_class_type(create_database_(::stlsoft::c_str_ptr(jarName), flags))
00296     {}
00297 
00298 // Implementation
00299 private:
00300     static ORJDatabase const *create_database_(char const *jarName, unsigned flags);
00301 
00302 // Not to be implemented
00303 private:
00304     file_database(class_type const &);
00305     class_type const &operator =(class_type const &);
00306 };
00307 
00308 typedef file_database   database;
00309 #endif /* !OPENRJ_NO_FILE_HANDLING */
00310 
00312 class memory_database
00313     : public database_base
00314 {
00315 private:
00316     typedef database_base       parent_class_type;
00317 public:
00318     typedef memory_database     class_type;
00319 
00320 public:
00327     explicit memory_database(char const *contents, size_t cbContents, unsigned flags = 0);
00333     template <typename S>
00334     explicit memory_database(S const &contents, unsigned flags = 0)
00335         : parent_class_type(create_database_(::stlsoft::c_str_data(contents), ::stlsoft::c_str_len(contents), flags))
00336     {}
00337 #ifdef __STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT
00343     template <size_t N>
00344     explicit memory_database(const char (&contents)[N], unsigned flags = 0)
00345         : parent_class_type(create_database_(&contents[0], N, flags))
00346     {}
00347 #endif /* __STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT */
00348 
00349 // Implementation
00350 private:
00351     static ORJDatabase const *create_database_(char const *contents, size_t cbContents, unsigned flags);
00352 
00353 // Not to be implemented
00354 private:
00355     memory_database(class_type const &);
00356     class_type const &operator =(class_type const &);
00357 };
00358 
00360 class database_base::const_iterator
00361     : public stlsoft::iterator_base<std::random_access_iterator_tag, const database_base::value_type, database_base::distance_type, database_base::const_pointer, database_base::const_reference>
00362 {
00363 public:
00364     typedef database_base::value_type        value_type;
00365     typedef database_base::distance_type     distance_type;
00366     typedef database_base::difference_type   difference_type;
00367 
00368 private:
00369     friend class database_base;
00370 
00371     const_iterator(ORJRecordA const *record);
00372 public:
00373     const_iterator();
00374     const_iterator(const_iterator const &rhs);
00375 
00376     const_iterator &operator =(const_iterator const &rhs);
00377 
00378 public:
00379 #ifdef OPENRJ_STL_ITERATOR_HOLDS_VALUE
00380     const_reference operator *() const;
00381 #else /* ? OPENRJ_STL_ITERATOR_HOLDS_VALUE */
00382     value_type operator *() const;
00383 #endif /* OPENRJ_STL_ITERATOR_HOLDS_VALUE */
00384     const_iterator &operator ++();
00385     const_iterator operator ++(int);
00386     const_iterator &operator --();
00387     const_iterator operator --(int);
00388 
00389 public:
00390     const_iterator operator -(difference_type d) const;
00391     difference_type operator -(const_iterator const &rhs) const;
00392 
00393 public:
00394     bool equal(const_iterator const &rhs) const;
00395 
00396 #if defined(__BORLANDC__) || \
00397 defined(__DMC__)
00398     bool operator ==(const_iterator const &rhs) const;
00399     bool operator !=(const_iterator const &rhs) const;
00400 #endif /* compiler */
00401 
00402 private:
00403     ORJRecordA const    *m_record;
00404 #ifdef OPENRJ_STL_ITERATOR_HOLDS_VALUE
00405     mutable value_type  m_value;
00406 #endif /* OPENRJ_STL_ITERATOR_HOLDS_VALUE */
00407 };
00408 
00409 /* /////////////////////////////////////////////////////////////////////////////
00410  * Operators
00411  */
00412 
00413 #if !defined(__BORLANDC__) && \
00414     !defined(__DMC__)
00415 inline bool operator ==(database_base::const_iterator const &lhs, database_base::const_iterator const &rhs)
00416 {
00417     return lhs.equal(rhs);
00418 }
00419 
00420 inline bool operator !=(database_base::const_iterator const &lhs, database_base::const_iterator const &rhs)
00421 {
00422     return !lhs.equal(rhs);
00423 }
00424 #endif /* compiler */
00425 
00426 /* /////////////////////////////////////////////////////////////////////////////
00427  * Implementation
00428  */
00429 
00430 // database_base::const_iterator
00431 
00432 inline database_base::const_iterator::const_iterator(ORJRecordA const *record)
00433     : m_record(record)
00434 {}
00435 
00436 inline database_base::const_iterator::const_iterator()
00437     : m_record(NULL)
00438 {}
00439 
00440 inline database_base::const_iterator::const_iterator(database_base::const_iterator const &rhs)
00441     : m_record(rhs.m_record)
00442 {}
00443 
00444 inline database_base::const_iterator &database_base::const_iterator::operator =(database_base::const_iterator const &rhs)
00445 {
00446     m_record = rhs.m_record;
00447 
00448     return *this;
00449 }
00450 
00451 #ifdef OPENRJ_STL_ITERATOR_HOLDS_VALUE
00452 inline database_base::const_reference database_base::const_iterator::operator *() const
00453 {
00454     m_value = value_type(m_record);
00455 
00456     return m_value;
00457 }
00458 #else /* ? OPENRJ_STL_ITERATOR_HOLDS_VALUE */
00459 inline database_base::value_type database_base::const_iterator::operator *() const
00460 {
00461     return record(m_record);
00462 }
00463 #endif /* OPENRJ_STL_ITERATOR_HOLDS_VALUE */
00464 
00465 inline database_base::const_iterator &database_base::const_iterator::operator ++()
00466 {
00467     ++m_record;
00468 
00469     return *this;
00470 }
00471 
00472 inline database_base::const_iterator database_base::const_iterator::operator ++(int)
00473 {
00474     const_iterator  ret(*this);
00475 
00476     operator ++();
00477 
00478     return ret;
00479 }
00480 
00481 inline database_base::const_iterator &database_base::const_iterator::operator --()
00482 {
00483     --m_record;
00484 
00485     return *this;
00486 }
00487 
00488 inline database_base::const_iterator database_base::const_iterator::operator --(int)
00489 {
00490     const_iterator  ret(*this);
00491 
00492     operator --();
00493 
00494     return ret;
00495 }
00496 
00497 inline database_base::const_iterator database_base::const_iterator::operator -(database_base::const_iterator::difference_type d) const
00498 {
00499     return const_iterator(&m_record[-d]);
00500 }
00501 
00502 inline database_base::difference_type database_base::const_iterator::operator -(database_base::const_iterator const &rhs) const
00503 {
00504     return &rhs.m_record[0] - &m_record[0];
00505 }
00506 
00507 inline bool database_base::const_iterator::equal(database_base::const_iterator const &rhs) const
00508 {
00509     return rhs.m_record == m_record;
00510 }
00511 
00512 #if defined(__BORLANDC__) || \
00513     defined(__DMC__)
00514 inline bool database_base::const_iterator::operator ==(database_base::const_iterator const &rhs) const
00515 {
00516     return equal(rhs);
00517 }
00518 
00519 inline bool database_base::const_iterator::operator !=(database_base::const_iterator const &rhs) const
00520 {
00521     return !equal(rhs);
00522 }
00523 #endif /* compiler */
00524 
00525 // file_database
00526 
00527 #ifndef OPENRJ_NO_FILE_HANDLING
00528 inline /* static */ ORJDatabase const *file_database::create_database_(char const *jarName, unsigned flags)
00529 {
00530     ORJDatabase const   *database;
00531     ORJError            error;
00532     ORJRC               rc = ORJ_ReadDatabase(jarName, NULL, flags, &database, &error);
00533 
00534     if(ORJ_RC_SUCCESS != rc)
00535     {
00536         throw database_exception(rc, error);
00537     }
00538 
00539     return database;
00540 }
00541 
00542 inline file_database::file_database(char const *jarName, unsigned flags /* = 0 */)
00543     : parent_class_type(create_database_(jarName, flags))
00544 {}
00545 #endif /* !OPENRJ_NO_FILE_HANDLING */
00546 
00547 // memory_database
00548 
00549 inline /* static */ ORJDatabase const *memory_database::create_database_(char const *contents, size_t cbContents, unsigned flags)
00550 {
00551     ORJDatabase const   *database;
00552     ORJError            error;
00553     ORJRC               rc = ORJ_CreateDatabaseFromMemory(contents, cbContents, NULL, flags, &database, &error);
00554 
00555     if(ORJ_RC_SUCCESS != rc)
00556     {
00557         throw database_exception(rc, error);
00558     }
00559 
00560     return database;
00561 }
00562 
00563 inline memory_database::memory_database(char const *contents, size_t cbContents, unsigned flags)
00564     : parent_class_type(create_database_(contents, cbContents, flags))
00565 {}
00566 
00567 // database_base
00568 
00569 inline database_base::database_base(ORJDatabase const *database)
00570     : m_database(database)
00571 {
00572     stlsoft_message_assert("Initialisng database_base with NULL database", NULL != m_database);
00573 }
00574 
00575 inline database_base::~database_base()
00576 {
00577     ORJ_FreeDatabase(m_database);
00578 }
00579 
00580 inline size_t database_base::num_lines() const
00581 {
00582     openrj_assert(NULL != m_database);
00583 
00584     return m_database->numLines;
00585 }
00586 
00587 inline size_t database_base::num_fields() const
00588 {
00589     openrj_assert(NULL != m_database);
00590 
00591     return m_database->numFields;
00592 }
00593 
00594 inline size_t database_base::num_records() const
00595 {
00596     openrj_assert(NULL != m_database);
00597 
00598     return m_database->numRecords;
00599 }
00600 
00601 inline size_t database_base::size() const
00602 {
00603     return num_records();
00604 }
00605 
00606 inline const record database_base::operator [](size_t index) const
00607 {
00608     openrj_assert(index <= num_records());
00609 
00610     return record(&m_database->records[index]);
00611 }
00612 
00613 inline database_base::const_iterator database_base::begin() const
00614 {
00615     openrj_assert(NULL != m_database);
00616 
00617     return &m_database->records[0];
00618 }
00619 
00620 inline database_base::const_iterator database_base::end() const
00621 {
00622     openrj_assert(NULL != m_database);
00623 
00624     return &m_database->records[m_database->numRecords];
00625 }
00626 
00627 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00628 inline database_base::const_reverse_iterator database_base::rbegin() const
00629 {
00630     return const_reverse_iterator(end());
00631 }
00632 
00633 inline database_base::const_reverse_iterator database_base::rend() const
00634 {
00635     return const_reverse_iterator(begin());
00636 }
00637 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00638 
00639 #ifndef OPENRJ_STL_DATABASE_NO_FIELD_ITERATORS
00640 inline database_base::const_field_iterator database_base::fields_begin() const
00641 {
00642     openrj_assert(NULL != m_database);
00643 
00644     return const_field_iterator(&m_database->fields[0], &m_database->fields[m_database->numFields]);
00645 }
00646 
00647 inline database_base::const_field_iterator database_base::fields_end() const
00648 {
00649     openrj_assert(NULL != m_database);
00650 
00651     return const_field_iterator(&m_database->fields[m_database->numFields], &m_database->fields[m_database->numFields]);
00652 }
00653 
00654 # if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00655 inline database_base::const_reverse_field_iterator database_base::fields_rbegin() const
00656 {
00657     return const_reverse_field_iterator(fields_end());
00658 }
00659 
00660 inline database_base::const_reverse_field_iterator database_base::fields_rend() const
00661 {
00662     return const_reverse_field_iterator(fields_begin());
00663 }
00664 # endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00665 #endif /* !OPENRJ_STL_DATABASE_NO_FIELD_ITERATORS */
00666 
00667 /* /////////////////////////////////////////////////////////////////////////////
00668  * Namespace
00669  */
00670 
00671 } // namespace stl
00672 } // namespace openrj
00673 
00674 /* ////////////////////////////////////////////////////////////////////////// */
00675 
00676 #endif /* !OPENRJ_INCL_OPENRJ_STL_HPP_DATABASE */
00677 
00678 /* ////////////////////////////////////////////////////////////////////////// */

Open-RJ Library documentation © Synesis Software Pty Ltd, 2004-2005