00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00046 #ifndef OPENRJ_INCL_OPENRJ_STL_HPP_RECORD
00047 #define OPENRJ_INCL_OPENRJ_STL_HPP_RECORD
00048
00049
00050
00051
00052
00053 #ifndef OPENRJ_DOCUMENTATION_SKIP_SECTION
00054 # define OPENRJ_VER_OPENRJ_STL_HPP_RECORD_MAJOR 1
00055 # define OPENRJ_VER_OPENRJ_STL_HPP_RECORD_MINOR 7
00056 # define OPENRJ_VER_OPENRJ_STL_HPP_RECORD_REVISION 4
00057 # define OPENRJ_VER_OPENRJ_STL_HPP_RECORD_EDIT 28
00058 #endif
00059
00060
00061
00062
00063
00064 #include <openrj/openrj.h>
00065 #include <openrj/openrj_assert.h>
00066
00067 #if defined(ORJ_NO_EXCEPTIONS)
00068 # error The Open-RJ STL mapping is not compilable in the absence of exception
00069 #endif
00070
00071 #include <openrj/stl/field.hpp>
00072
00073 #include <algorithm>
00074 #include <iterator>
00075 #include <stdexcept>
00076
00077 #include <stlsoft/iterators/indirect_reverse_iterator.hpp>
00078 #include <stlsoft/iterator.hpp>
00079
00080
00081
00082
00083
00084 #ifdef __BORLANDC__
00085 # pragma warn -8027
00086 #endif
00087
00088
00089
00090
00091
00092 namespace openrj
00093 {
00094
00095 namespace stl
00096 {
00097
00098
00099
00100
00101
00103 class record
00104 {
00105 public:
00107 typedef record class_type;
00109 typedef field value_type;
00111 typedef value_type const const_reference;
00113 typedef value_type const *const_pointer;
00115 typedef ptrdiff_t difference_type;
00116
00117 #ifndef OPENRJ_DOCUMENTATION_SKIP_SECTION
00118 public:
00119 class const_iterator;
00120
00121 friend class const_iterator;
00122 #endif
00123
00124 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00126 # if 0
00127 typedef stlsoft_ns_qual(const_reverse_iterator_base)< const_iterator
00128 , value_type
00129 , value_type
00130 , void
00131 , difference_type
00132 > const_reverse_iterator;
00133 # else
00134
00135
00136
00137 typedef stlsoft_ns_qual(indirect_reverse_iterator)< const_iterator
00138 , value_type
00139 , value_type
00140 , void
00141 , difference_type
00142 , stlsoft_ns_qual_std(random_access_iterator_tag)
00143 > const_reverse_iterator;
00144 # endif
00145 #endif
00146
00147 public:
00149 explicit record(ORJRecord const *record);
00151 record();
00153 record(record const &rhs);
00154
00156 record &operator =(record const &rhs);
00157
00158 public:
00160 size_t size() const;
00161
00163 bool empty() const;
00164
00166 string_t comment() const;
00167
00174 const field operator [](size_t index) const;
00175
00177 bool has_field(string_t const &name) const;
00178
00179 #if defined(STLSOFT_COMPILER_IS_INTEL)
00180 bool has_field(char const *name) const
00181 {
00182 return this->has_field(string_t(name));
00183 }
00184 #endif
00185
00186 #if 0
00188 bool has_field(string_t const &name, string_t const &value) const;
00189 #endif
00190
00192 size_t count_fields(string_t const &name) const;
00193
00200 const string_t operator [](string_t const &name) const;
00201
00202 #if defined(STLSOFT_COMPILER_IS_INTEL)
00203 const string_t operator [](char const *name) const
00204 {
00205 return this->operator [](string_t(name));
00206 }
00207 #endif
00208
00216 string_t get_field_value(string_t const &name, string_t const &defValue) const;
00217
00218 public:
00222 const_iterator begin() const;
00226 const_iterator end() const;
00227
00228 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00232 const_reverse_iterator rbegin() const;
00236 const_reverse_iterator rend() const;
00237 #endif
00238
00239 private:
00248 struct same_name;
00249
00250 private:
00251 static field create_field_(ORJFieldA const *r)
00252 {
00253 return field(r);
00254 }
00255
00256 ORJField const *find_field_(string_t const &name) const;
00257
00258 size_t count_fields_(string_t const &name) const;
00259
00260 private:
00261 ORJRecord const *m_record;
00262 size_t m_flags;
00263 };
00264
00265 class record::const_iterator
00266 : public stlsoft::iterator_base<std::random_access_iterator_tag, const record::value_type, record::difference_type, record::const_pointer, record::const_reference>
00267 {
00268 public:
00269 typedef field value_type;
00270
00271 private:
00272 friend class record;
00273
00274 const_iterator(ORJFieldA const *field);
00275 public:
00276 const_iterator();
00277 const_iterator(const_iterator const &rhs);
00278 const_iterator &operator =(const_iterator const &rhs);
00279
00280 public:
00281 #ifdef OPENRJ_STL_ITERATOR_HOLDS_VALUE
00282 const_reference operator *() const;
00283 #else
00284 value_type operator *() const;
00285 #endif
00286 const_iterator &operator ++();
00287 const_iterator operator ++(int);
00288 const_iterator &operator --();
00289 const_iterator operator --(int);
00290
00291 public:
00292 const_iterator operator -(difference_type d) const;
00293 difference_type operator -(const_iterator const &rhs) const;
00294
00295 public:
00296 bool is_equal(const_iterator const &rhs) const;
00297
00298 #if defined(STLSOFT_COMPILER_IS_BORLAND) || \
00299 defined(STLSOFT_COMPILER_IS_DMC)
00300 bool operator ==(const_iterator const &rhs) const;
00301 bool operator !=(const_iterator const &rhs) const;
00302 #endif
00303
00304 private:
00305 ORJFieldA const *m_field;
00306 #ifdef OPENRJ_STL_ITERATOR_HOLDS_VALUE
00307 mutable value_type m_value;
00308 #endif
00309 };
00310
00311
00312
00313
00314
00315 #if !defined(__BORLANDC__) && \
00316 !defined(__DMC__)
00317 inline bool operator ==(record::const_iterator const &lhs, record::const_iterator const &rhs)
00318 {
00319 return lhs.is_equal(rhs);
00320 }
00321
00322 inline bool operator !=(record::const_iterator const &lhs, record::const_iterator const &rhs)
00323 {
00324 return !lhs.is_equal(rhs);
00325 }
00326 #endif
00327
00328
00329
00330
00331
00332
00333
00334 inline record::const_iterator::const_iterator(ORJFieldA const *field)
00335 : m_field(field)
00336 {}
00337
00338 inline record::const_iterator::const_iterator()
00339 : m_field(NULL)
00340 {}
00341
00342 inline record::const_iterator::const_iterator(const_iterator const &rhs)
00343 : m_field(rhs.m_field)
00344 {}
00345
00346 inline record::const_iterator &record::const_iterator::operator =(const_iterator const &rhs)
00347 {
00348 m_field = rhs.m_field;
00349
00350 return *this;
00351 }
00352
00353 #ifdef OPENRJ_STL_ITERATOR_HOLDS_VALUE
00354 inline record::const_reference record::const_iterator::operator *() const
00355 {
00356 m_value = value_type(m_field);
00357
00358 return m_value;
00359 #else
00360 inline record::value_type record::const_iterator::operator *() const
00361 {
00362 return create_field_(m_field);
00363 #endif
00364 }
00365
00366 inline record::const_iterator &record::const_iterator::operator ++()
00367 {
00368 ++m_field;
00369
00370 return *this;
00371 }
00372
00373 inline record::const_iterator record::const_iterator::operator ++(int)
00374 {
00375 const_iterator ret(*this);
00376
00377 operator ++();
00378
00379 return ret;
00380 }
00381
00382 inline record::const_iterator &record::const_iterator::operator --()
00383 {
00384 --m_field;
00385
00386 return *this;
00387 }
00388
00389 inline record::const_iterator record::const_iterator::operator --(int)
00390 {
00391 const_iterator ret(*this);
00392
00393 operator --();
00394
00395 return ret;
00396 }
00397
00398 inline record::const_iterator record::const_iterator::operator -(record::difference_type d) const
00399 {
00400 return const_iterator(&m_field[-d]);
00401 }
00402
00403 inline record::difference_type record::const_iterator::operator -(record::const_iterator const &rhs) const
00404 {
00405 return &rhs.m_field[0] - &m_field[0];
00406 }
00407
00408 inline bool record::const_iterator::is_equal(record::const_iterator const &rhs) const
00409 {
00410 return rhs.m_field == m_field;
00411 }
00412
00413 #if defined(__BORLANDC__) || \
00414 defined(__DMC__)
00415 inline bool record::const_iterator::operator ==(record::const_iterator const &rhs) const
00416 {
00417 return is_equal(rhs);
00418 }
00419
00420 inline bool record::const_iterator::operator !=(record::const_iterator const &rhs) const
00421 {
00422 return !is_equal(rhs);
00423 }
00424 #endif
00425
00426
00427
00428 struct record::same_name
00429 {
00430 public:
00431 same_name()
00432 : m_name()
00433 {}
00434 same_name(string_t const &name)
00435 : m_name(name)
00436 {}
00437
00438 public:
00439 bool operator ()(string_t const &lhs, string_t const &rhs) const
00440 {
00441 return lhs < rhs;
00442 }
00443 bool operator ()(ORJFieldA const &lhs, ORJFieldA const &rhs) const
00444 {
00445 return operator ()(string_t(lhs.name.ptr, lhs.name.len), string_t(rhs.name.ptr, rhs.name.len));
00446 }
00447 bool operator ()(string_t const &lhs, ORJFieldA const &rhs) const
00448 {
00449 return operator ()(lhs, string_t(rhs.name.ptr, rhs.name.len));
00450 }
00451 bool operator ()(ORJFieldA const &lhs, string_t const &rhs) const
00452 {
00453 return operator ()(string_t(lhs.name.ptr, lhs.name.len), rhs);
00454 }
00455 bool operator ()(ORJFieldA const &f) const
00456 {
00457 return m_name == f.name.ptr;
00458 }
00459 bool operator ()(field const &f) const
00460 {
00461 return m_name == f.name();
00462 }
00463
00464 private:
00465 string_t const m_name;
00466
00467 private:
00468 same_name &operator =(same_name const &);
00469 };
00470
00471
00472
00473 inline ORJField const *record::find_field_(string_t const &name) const
00474 {
00475
00476 ORJField const *const b = &m_record->fields[0];
00477 ORJField const *const e = &m_record->fields[m_record->numFields];
00478 ORJField const *it;
00479 ORJDatabase const *database = ORJ_Record_GetDatabaseA(m_record);
00480
00481 if(ORJ_FLAG_ORDERFIELDS == (database->flags & ORJ_FLAG_ORDERFIELDS))
00482 {
00483
00484 it = std::lower_bound(b, e, name, same_name());
00485
00486 if(e != it)
00487 {
00488 #if defined(STLSOFT_COMPILER_IS_GCC) && \
00489 __GNUC__ < 3
00490
00491
00492 if(0 == string_t((*it).name.ptr, (*it).name.len).compare(name))
00493 #else
00494 if(0 != name.compare(0, (*it).name.len, (*it).name.ptr))
00495 #endif
00496 {
00497 it = e;
00498 }
00499 }
00500 }
00501 else
00502 {
00503
00504 it = std::find_if(b, e, same_name(name));
00505 }
00506
00507 if(e == it)
00508 {
00509 it = NULL;
00510 }
00511
00512 return it;
00513 }
00514
00515 inline size_t record::count_fields_(string_t const &name) const
00516 {
00517 ORJField const *const b = &m_record->fields[0];
00518 ORJField const *const e = &m_record->fields[m_record->numFields];
00519 ORJDatabase const *database = ORJ_Record_GetDatabaseA(m_record);
00520
00521 if(ORJ_FLAG_ORDERFIELDS == (database->flags & ORJ_FLAG_ORDERFIELDS))
00522 {
00523
00524 ORJField const *lower = std::lower_bound(b, e, name, same_name());
00525 ORJField const *upper = std::upper_bound(b, e, name, same_name());
00526
00527 return static_cast<size_t>(std::distance(lower, upper));
00528 }
00529 else
00530 {
00531
00532 return static_cast<size_t>(std::count_if(b, e, same_name(name)));
00533 }
00534 }
00535
00536 inline record::record(ORJRecord const *record)
00537 : m_record(record)
00538 {}
00539
00540 inline record::record()
00541 : m_record(NULL)
00542 {}
00543
00544 inline record::record(record const &rhs)
00545 : m_record(rhs.m_record)
00546 {}
00547
00548 inline record &record::operator =(record const &rhs)
00549 {
00550 m_record = rhs.m_record;
00551
00552 return *this;
00553 }
00554
00555 inline size_t record::size() const
00556 {
00557 openrj_assert(NULL != m_record);
00558
00559 return ORJ_Record_GetNumFieldsA(m_record);
00560 }
00561
00562 inline string_t record::comment() const
00563 {
00564 openrj_assert(NULL != m_record);
00565
00566 return string_t(m_record->comment.ptr, m_record->comment.len);
00567 }
00568
00569 inline bool record::empty() const
00570 {
00571 return 0 == size();
00572 }
00573
00574 inline const field record::operator [](size_t index) const
00575 {
00576 openrj_assert(index <= size());
00577
00578 return field(&m_record->fields[index]);
00579 }
00580
00581 inline bool record::has_field(string_t const &name) const
00582 {
00583 return NULL != find_field_(name);
00584 }
00585
00586 #if 0
00587 inline bool record::has_field(string_t const &name, string_t const &value) const
00588 {
00589 return NULL != find_field_(name, value);
00590 }
00591 #endif
00592
00593 inline size_t record::count_fields(string_t const &name) const
00594 {
00595 return count_fields_(name);
00596 }
00597
00598 #if defined(STLSOFT_COMPILER_IS_MSVC) && \
00599 _MSC_VER >= 1200
00600 # pragma warning(push)
00601 # pragma warning(disable : 4702)
00602 #endif
00603
00604 inline const string_t record::operator [](string_t const &name) const
00605 {
00606 ORJField const *r = find_field_(name);
00607
00608 if(NULL == r)
00609 {
00610 throw std::out_of_range(stlsoft::c_str_ptr("record does not contain field named \"" + name + "\""));
00611 }
00612
00613 return field(&*r).value();
00614 }
00615
00616 #if defined(STLSOFT_COMPILER_IS_MSVC) && \
00617 _MSC_VER >= 1200
00618 # pragma warning(pop)
00619 #endif
00620
00621 inline string_t record::get_field_value(string_t const &name, string_t const &defValue) const
00622 {
00623 ORJField const *r = find_field_(name);
00624
00625 return (NULL == r) ? defValue : field(&*r).value();
00626 }
00627
00628 inline record::const_iterator record::begin() const
00629 {
00630 openrj_assert(NULL != m_record);
00631
00632 return &m_record->fields[0];
00633 }
00634
00635 inline record::const_iterator record::end() const
00636 {
00637 openrj_assert(NULL != m_record);
00638
00639 return &m_record->fields[m_record->numFields];
00640 }
00641
00642 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00643 inline record::const_reverse_iterator record::rbegin() const
00644 {
00645 return const_reverse_iterator(end());
00646 }
00647
00648 inline record::const_reverse_iterator record::rend() const
00649 {
00650 return const_reverse_iterator(begin());
00651 }
00652 #endif
00653
00654
00655
00656
00657
00658 }
00659 }
00660
00661
00662
00663 #endif
00664
00665