tzwrapper.cc: fixed use of iterator after erase
[barry.git] / src / recordtmpl.h
blob26cecb5450433fc94dc6a8f729caf90ee0809a30
1 ///
2 /// \file recordtmpl.h
3 /// Standalone templates related to the record classes.
4 /// Split into a separate file to speed compile times.
5 ///
7 /*
8 Copyright (C) 2005-2013, Net Direct Inc. (http://www.netdirect.ca/)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License in the COPYING file at the
20 root directory of this project for more details.
23 #ifndef __BARRY_RECORD_TEMPLATES_H__
24 #define __BARRY_RECORD_TEMPLATES_H__
26 #include "dll.h"
27 #include <iosfwd>
28 #include <iostream>
29 #include <sstream>
31 namespace Barry {
33 //////////////////////////////////////////////////////////////////////////////
34 // Generic Field Handles
36 /// \addtogroup GenericFieldHandles
37 /// @{
39 //////////////////////////////////////////////////////////////////////////////
40 // *NamedFieldCmp classes
42 /// FieldSorter<> is a helper class for NamedFieldCmp<>, used as the
43 /// callback for FieldHandle<>::Member(). It uses operator< to store
44 /// a comparison result for the given record and field.
45 template <class RecordT>
46 class FieldSorter
48 const RecordT &m_one, &m_two;
49 mutable bool m_comparison, m_equal;
51 public:
52 FieldSorter(const RecordT &a, const RecordT &b)
53 : m_one(a)
54 , m_two(b)
55 , m_comparison(false)
56 , m_equal(false)
60 bool GetComparison() const { return m_comparison; }
61 bool IsEqual() const { return m_equal; }
63 void operator()(EnumFieldBase<RecordT> *ep,
64 const FieldIdentity &id) const
66 m_comparison = ep->GetValue(m_one) < ep->GetValue(m_two);
67 m_equal = !m_comparison &&
68 !(ep->GetValue(m_two) < ep->GetValue(m_one));
71 void operator()(typename FieldHandle<RecordT>::PostalPointer pp,
72 const FieldIdentity &id) const
74 const std::string
75 &a = m_one.*(pp.m_PostalAddress).*(pp.m_PostalField),
76 &b = m_two.*(pp.m_PostalAddress).*(pp.m_PostalField);
78 m_comparison = a < b;
79 m_equal = !m_comparison && !(b < a);
82 template <class TypeT>
83 void operator()(TypeT RecordT::* mp, const FieldIdentity &id) const
85 m_comparison = m_one.*mp < m_two.*mp;
86 m_equal = !m_comparison && !(m_two.*mp < m_one.*mp);
91 // NamedFieldCmp<>
93 /// A comparison functor, intended to be used in std::sort(), which
94 /// allows sorting by a particular record's member variable, selected
95 /// by string name. eg. It allows you to sort a vector of Contact
96 /// records by Name, HomeAddress, WorkPhone, or Company name, etc.
97 ///
98 /// This template takes the record type as template argument, and works
99 /// with only that record type.
101 /// If the given name is not found the FieldHandles for RecordT, this
102 /// class will throw a std::logic_error exception.
104 template <class RecordT>
105 class NamedFieldCmp
107 const std::string &m_name;
109 public:
110 NamedFieldCmp(const std::string &field_name)
111 : m_name(field_name)
115 bool operator() (const RecordT &a, const RecordT &b) const
117 bool comparison = false;
118 std::string token;
119 std::istringstream iss(m_name);
120 while( std::getline(iss, token, ',') ) {
121 typename FieldHandle<RecordT>::ListT::const_iterator
122 fhi = RecordT::GetFieldHandles().begin(),
123 fhe = RecordT::GetFieldHandles().end();
125 for( ; fhi != fhe; ++fhi ) {
126 if( token == fhi->GetIdentity().Name ) {
127 FieldSorter<RecordT> fs(a, b);
128 fhi->Member(fs);
129 comparison = fs.GetComparison();
130 if( fs.IsEqual() ) {
131 // if equal, compare next token
132 break;
134 else {
135 // done!
136 return comparison;
141 if( fhi == fhe )
142 throw std::logic_error("NamedFieldCmp: No field named '" + token + "' in '" + RecordT::GetDBName() + "'");
145 // return last seen comparison
146 return comparison;
150 class IConverter;
151 class DBData;
154 // DBNamedFieldCmp
156 /// This class is a wrapper around the NamedFieldCmp<>, allowing you to
157 /// sort a vector (or other container) of DBData objects. This class will
158 /// parse each record before passing the result on to NamedFieldCmp<>
159 /// and returning the result. All the parsing work is then thrown away,
160 /// so this is more of a convenience class than for performance.
162 /// This class expects that all the DBData given to it is one of the
163 /// known records which have a parser. If the record unrecognized, it
164 /// will throw a std::logic_error exception.
166 class DBNamedFieldCmp
168 const std::string &m_name;
169 const IConverter *m_ic;
171 public:
172 explicit DBNamedFieldCmp(const std::string &field_name,
173 const Barry::IConverter *ic = 0);
175 bool operator() (const Barry::DBData &a, const Barry::DBData &b) const;
178 /// @}
180 } // namespace Barry
182 #endif