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

openrj/cpp/record.hpp

Go to the documentation of this file.
00001 /* /////////////////////////////////////////////////////////////////////////////
00002  * File:    openrj/cpp/record.hpp
00003  *
00004  * Purpose: Record class, in the C++ mapping of the Open-RJ library
00005  *
00006  * Created: 18th June 2004
00007  * Updated: 26th December 2006
00008  *
00009  * Home:    http://openrj.org/
00010  *
00011  * Copyright (c) 2004-2006, Matthew Wilson and Synesis Software
00012  * All rights reserved.
00013  *
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *
00017  * - Redistributions of source code must retain the above copyright notice, this
00018  *   list of conditions and the following disclaimer.
00019  * - Redistributions in binary form must reproduce the above copyright notice,
00020  *   this list of conditions and the following disclaimer in the documentation
00021  *   and/or other materials provided with the distribution.
00022  * - Neither the names of Matthew Wilson and Synesis Software nor the names of
00023  *   any contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036  * POSSIBILITY OF SUCH DAMAGE.
00037  *
00038  * ////////////////////////////////////////////////////////////////////////// */
00039 
00040 
00046 #ifndef OPENRJ_INCL_OPENRJ_CPP_H_RECORD
00047 #define OPENRJ_INCL_OPENRJ_CPP_H_RECORD
00048 
00049 /* /////////////////////////////////////////////////////////////////////////////
00050  * Version information
00051  */
00052 
00053 #ifndef OPENRJ_DOCUMENTATION_SKIP_SECTION
00054 # define OPENRJ_VER_OPENRJ_CPP_H_RECORD_MAJOR       1
00055 # define OPENRJ_VER_OPENRJ_CPP_H_RECORD_MINOR       7
00056 # define OPENRJ_VER_OPENRJ_CPP_H_RECORD_REVISION    4
00057 # define OPENRJ_VER_OPENRJ_CPP_H_RECORD_EDIT        22
00058 #endif /* !OPENRJ_DOCUMENTATION_SKIP_SECTION */
00059 
00060 /* /////////////////////////////////////////////////////////////////////////////
00061  * Includes
00062  */
00063 
00064 #include <openrj/cpp/openrj.hpp>
00065 #include <openrj/cpp/field.hpp>
00066 
00067 #include <stlsoft/stlsoft.h>
00068 #include <stlsoft/memory/auto_buffer.hpp>
00069 #ifdef __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00070 # include <stlsoft/meta/is_integral_type.hpp>
00071 # include <stlsoft/meta/select_first_type_if.hpp>
00072 # include <stlsoft/meta/yesno.hpp>
00073 #endif /* __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT */
00074 
00075 #include <stdio.h>
00076 #include <algorithm>
00077 #include <stdexcept>
00078 
00079 /* /////////////////////////////////////////////////////////////////////////////
00080  * Namespace
00081  */
00082 
00083 namespace openrj
00084 {
00085 namespace cpp
00086 {
00087 
00088 /* /////////////////////////////////////////////////////////////////////////////
00089  * Classes
00090  */
00091 
00093 class Record
00094 {
00095 private:
00096     friend class DatabaseBase;
00097 
00098     Record(ORJRecord const &record)
00099         : m_record(&record)
00100     {}
00101 public:
00103     Record()
00104         : m_record(NULL)
00105     {}
00107     Record(Record const &rhs)
00108         : m_record(rhs.m_record)
00109     {}
00110 
00112     Record &operator =(Record const &rhs)
00113     {
00114         m_record = rhs.m_record;
00115 
00116         return *this;
00117     }
00118 
00119 public:
00121     String GetComment() const
00122     {
00123         openrj_assert(NULL != m_record);
00124 
00125         ORJStringA const *comment;
00126 
00127         return (ORJ_RC_SUCCESS == ORJ_Record_GetCommentA(m_record, &comment)) ? String(comment->ptr, comment->len) : String();
00128     }
00129 
00131     size_t GetNumFields() const
00132     {
00133         openrj_assert(NULL != m_record);
00134 
00135         return ORJ_Record_GetNumFieldsA(m_record);
00136     }
00137 
00154     const Field operator [](size_t index) const
00155     {
00156         openrj_assert(index <= GetNumFields());
00157 
00158         ORJFieldA const  *field;
00159 
00160         if(ORJ_RC_SUCCESS != ORJ_Record_GetFieldA(m_record, index, &field))
00161         {
00162             field = NULL;
00163         }
00164 
00165         return Field(field);
00166     }
00167 
00172     bool has_field_with_name(char const *name, ORJField const **pfield = NULL) const
00173     {
00174         ORJField const  *const  begin   =   &m_record->fields[0];
00175         ORJField const  *const  end     =   &m_record->fields[m_record->numFields];
00176         ORJField const          *it     =   ::std::find_if(begin, end, match_name(name));
00177 
00178         if(NULL != pfield)
00179         {
00180             *pfield = (it == end) ? NULL : it;
00181         }
00182 
00183         return (it != end);
00184     }
00185 
00186     bool HasField(char const *name) const
00187     {
00188         return NULL != ORJ_Record_FindFieldByNameA(m_record, name, NULL);
00189     }
00190 
00191     bool HasField(char const *name, char const *value) const
00192     {
00193         return NULL != ORJ_Record_FindFieldByNameA(m_record, name, value);
00194     }
00195 
00196     bool HasFieldWithValue(char const *value) const
00197     {
00198         return NULL != ORJ_Record_FindFieldByNameA(m_record, NULL, value);
00199     }
00200 
00201 #if !defined(ORJ_NO_EXCEPTIONS)
00219     String operator [](char const *name) const
00220     {
00221         openrj_assert(NULL != name);
00222 
00223         ORJField const  *begin  =   &m_record->fields[0];
00224         ORJField const  *end    =   &m_record->fields[m_record->numFields];
00225         ORJField const  *it     =   ::std::find_if(begin, end, match_name(name));
00226 
00227         if(it == end)
00228         {
00229             const size_t                nameLen     =   ::strlen(name);
00230             static const char           fmt[]       =   "Field \"%s\" not found";
00231             stlsoft::auto_buffer<char>  buff(nameLen + stlsoft_num_elements(fmt));
00232 
00233             throw ::std::out_of_range((0 == buff.size()) ? "Field not found" : (::sprintf(&buff[0], fmt, name), buff.data()));
00234         }
00235 
00236         return String(it->value.ptr, it->value.len);
00237     }
00238 
00239 
00240 # if defined(__STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT) && \
00241      !defined(STLSOFT_COMPILER_IS_BORLAND)
00242     template <typename S>
00243     String subscript_operator_(S const &name, stlsoft::no_type) const
00244     {
00245         return operator [](::stlsoft::c_str_ptr(name));
00246     }
00247 
00248     template <typename I>
00249     Field subscript_operator_(I const &index, stlsoft::yes_type) const
00250     {
00251         return operator [](static_cast<size_t>(index));
00252     }
00253 
00259     template <typename S>
00260     typename stlsoft::select_first_type_if<Field, String, stlsoft::is_integral_type<S>::value>::type operator [](S const &name) const
00261     {
00262         typedef typename stlsoft::is_integral_type<S>::type     yesno_type;
00263 
00264         return subscript_operator_(name, yesno_type());
00265     }
00266 # else /* ? __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT */
00272 #  if !defined(STLSOFT_COMPILER_IS_MSVC) || \
00273       _MSC_VER >= 1200
00274     template <typename S>
00275     typename String operator [](S const &name) const
00276     {
00277         return operator [](::stlsoft::c_str_ptr(name));
00278     }
00279 #  endif /* compiler */
00280 
00281 #  ifndef OPENRJ_DOCUMENTATION_SKIP_SECTION
00282     const Field operator [](int index) const
00283     {
00284         return operator [](static_cast<size_t>(index));
00285     }
00286 //    const Field operator [](long index) const
00287 //    {
00288 //        return operator [](static_cast<size_t>(index));
00289 //    }
00290 #  endif /* !OPENRJ_DOCUMENTATION_SKIP_SECTION */
00291 # endif /* !__STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT */
00292 #endif /* !ORJ_NO_EXCEPTIONS */
00293 
00294 // Implementation
00295 private:
00296     struct match_name
00297     {
00298     public:
00299         match_name(char const *name)
00300             : m_name(name)
00301         {}
00302 
00303     public:
00304         bool operator ()(ORJField const &field) const
00305         {
00306             return 0 == strcmp(m_name, field.name.ptr);
00307         }
00308 
00309     private:
00310         char const  *m_name;
00311     };
00312 
00313 // Members
00314 private:
00315     ORJRecord const *m_record;
00316 };
00317 
00318 /* /////////////////////////////////////////////////////////////////////////////
00319  * Namespace
00320  */
00321 
00322 } // namespace cpp
00323 } // namespace openrj
00324 
00325 /* ////////////////////////////////////////////////////////////////////////// */
00326 
00327 #endif /* !OPENRJ_INCL_OPENRJ_CPP_H_RECORD */
00328 
00329 /* ////////////////////////////////////////////////////////////////////////// */

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