lib: added operator==() and operator!=() to basic record types (record.h)
[barry/progweb.git] / src / record.h
blobfa3881b64f102aa08fd07d5cca5b05b5940f2a42
1 ///
2 /// \file record.h
3 /// Blackberry database record classes. Help translate data
4 /// from data packets to useful structurs, and back.
5 /// This header provides the common types and classes
6 /// used by the general record parser classes in the
7 /// r_*.h files. Only application-safe API stuff goes in
8 /// here. Internal library types go in record-internal.h
9 ///
12 Copyright (C) 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 See the GNU General Public License in the COPYING file at the
24 root directory of this project for more details.
27 #ifndef __BARRY_RECORD_H__
28 #define __BARRY_RECORD_H__
30 #include "dll.h"
31 #include <iosfwd>
32 #include <string>
33 #include <vector>
34 #include <map>
35 #include <stdint.h>
36 #include <stdexcept>
38 // forward declarations
39 namespace Barry { class Data; }
41 namespace Barry {
44 // NOTE: All classes here must be container-safe! Perhaps add sorting
45 // operators in the future.
49 // stream-based wrapper to avoid printing strings that contain
50 // the \r carriage return characters
51 class BXEXPORT Cr2LfWrapper
53 friend std::ostream& operator<< (std::ostream &os, const Cr2LfWrapper &str);
54 const std::string &m_str;
55 public:
56 explicit Cr2LfWrapper(const std::string &str)
57 : m_str(str)
61 BXEXPORT std::ostream& operator<< (std::ostream &os, const Cr2LfWrapper &str);
63 struct BXEXPORT CommandTableCommand
65 unsigned int Code;
66 std::string Name;
69 class BXEXPORT CommandTable
71 public:
72 typedef CommandTableCommand Command;
73 typedef std::vector<Command> CommandArrayType;
75 CommandArrayType Commands;
77 private:
78 BXLOCAL const unsigned char* ParseField(const unsigned char *begin,
79 const unsigned char *end);
80 public:
81 CommandTable();
82 ~CommandTable();
84 void Parse(const Data &data, size_t offset);
85 void Clear();
87 // returns 0 if unable to find command name, which is safe, since
88 // 0 is a special command that shouldn't be in the table anyway
89 unsigned int GetCommand(const std::string &name) const;
91 void Dump(std::ostream &os) const;
94 BXEXPORT inline std::ostream& operator<< (std::ostream &os, const CommandTable &command) {
95 command.Dump(os);
96 return os;
101 struct BXEXPORT RecordStateTableState
103 unsigned int Index;
104 uint32_t RecordId;
105 bool Dirty;
106 unsigned int RecType;
107 std::string Unknown2;
110 class BXEXPORT RecordStateTable
112 public:
113 typedef RecordStateTableState State;
114 typedef unsigned int IndexType;
115 typedef std::map<IndexType, State> StateMapType;
117 StateMapType StateMap;
119 private:
120 mutable IndexType m_LastNewRecordId;
122 private:
123 BXLOCAL const unsigned char* ParseField(const unsigned char *begin,
124 const unsigned char *end);
126 public:
127 RecordStateTable();
128 ~RecordStateTable();
130 void Parse(const Data &data);
131 void Clear();
133 bool GetIndex(uint32_t RecordId, IndexType *pFoundIndex = 0) const;
134 uint32_t MakeNewRecordId() const;
136 void Dump(std::ostream &os) const;
139 BXEXPORT inline std::ostream& operator<< (std::ostream &os, const RecordStateTable &rst) {
140 rst.Dump(os);
141 return os;
146 struct BXEXPORT DatabaseItem
148 unsigned int Number;
149 unsigned int RecordCount;
150 std::string Name;
153 class BXEXPORT DatabaseDatabase
155 public:
156 typedef DatabaseItem Database;
157 typedef std::vector<Database> DatabaseArrayType;
159 DatabaseArrayType Databases;
161 private:
162 template <class RecordType, class FieldType>
163 void ParseRec(const RecordType &rec, const unsigned char *end);
165 template <class FieldType>
166 const unsigned char* ParseField(const unsigned char *begin,
167 const unsigned char *end);
169 public:
170 DatabaseDatabase();
171 ~DatabaseDatabase();
173 void Parse(const Data &data);
174 void Clear();
176 void SortByName();
177 unsigned int GetTotalRecordCount() const;
179 // returns true on success, and fills target
180 bool GetDBNumber(const std::string &name, unsigned int &number) const;
181 bool GetDBName(unsigned int number, std::string &name) const;
183 void Dump(std::ostream &os) const;
186 BXEXPORT inline std::ostream& operator<<(std::ostream &os, const DatabaseDatabase &dbdb) {
187 dbdb.Dump(os);
188 return os;
191 struct UnknownData
193 std::string raw_data;
195 const std::string::value_type* data() const { return raw_data.data(); }
196 std::string::size_type size() const { return raw_data.size(); }
197 void assign(const std::string::value_type *s, std::string::size_type n)
198 { raw_data.assign(s, n); }
200 bool operator==(const UnknownData &other) const
202 return raw_data == other.raw_data;
205 bool operator!=(const UnknownData &other) const
207 return !operator==(other);
211 struct BXEXPORT UnknownField
213 uint8_t type;
214 UnknownData data;
216 bool operator==(const UnknownField &other) const
218 return type == other.type &&
219 data == other.data;
222 bool operator!=(const UnknownField &other) const
224 return !operator==(other);
227 typedef std::vector<UnknownField> UnknownsType;
228 BXEXPORT std::ostream& operator<< (std::ostream &os, const UnknownsType &unknowns);
230 // simple email type and list
231 typedef std::string EmailType;
232 typedef std::vector<EmailType> EmailList;
234 // struct, attempting to combine name + email address, for mail
235 struct BXEXPORT EmailAddress
237 std::string Name;
238 std::string Email;
240 EmailAddress()
244 /// Converts "Name <address@host.com>" into Name + Address
245 /// Will also handle just a plain address too.
246 explicit EmailAddress(const std::string &complex_address);
248 void clear()
250 Name.clear();
251 Email.clear();
254 size_t size() const
256 return Name.size() + Email.size();
259 bool operator==(const EmailAddress &other) const
261 return Name == other.Name &&
262 Email == other.Email;
265 bool operator!=(const EmailAddress &other) const
267 return !operator==(other);
270 BXEXPORT std::ostream& operator<<(std::ostream &os, const EmailAddress &msga);
272 class BXEXPORT EmailAddressList : public std::vector<EmailAddress>
274 public:
275 std::string ToCommaSeparated() const;
276 void AddCommaSeparated(const std::string &list);
279 BXEXPORT std::ostream& operator<<(std::ostream &os, const EmailAddressList &elist);
281 struct BXEXPORT PostalAddress
283 std::string
284 Address1,
285 Address2,
286 Address3,
287 City,
288 Province,
289 PostalCode,
290 Country;
292 std::string GetLabel() const;
293 void Clear();
295 bool HasData() const { return Address1.size() || Address2.size() ||
296 Address3.size() || City.size() || Province.size() ||
297 PostalCode.size() || Country.size(); }
299 bool operator==(const PostalAddress &other) const
301 return Address1 == other.Address1 &&
302 Address2 == other.Address2 &&
303 Address3 == other.Address3 &&
304 City == other.City &&
305 Province == other.Province &&
306 PostalCode == other.PostalCode &&
307 Country == other.Country;
309 bool operator!=(const PostalAddress &other) const
311 return !operator==(other);
314 BXEXPORT std::ostream& operator<<(std::ostream &os, const PostalAddress &msga);
316 struct BXEXPORT Date
318 int Month; // 0 to 11
319 int Day; // 1 to 31
320 int Year; // exact number, eg. 2008
322 Date() : Month(0), Day(0), Year(0) {}
323 explicit Date(const struct tm *timep);
325 bool HasData() const { return Month || Day || Year; }
326 void Clear();
328 void ToTm(struct tm *timep) const;
329 std::string ToYYYYMMDD() const;
330 std::string ToBBString() const; // converts to Blackberry string
331 // format of DD/MM/YYYY
333 bool FromTm(const struct tm *timep);
334 bool FromBBString(const std::string &str);
335 bool FromYYYYMMDD(const std::string &str);
337 bool operator==(const Date &other) const
339 return Month == other.Month &&
340 Day == other.Day &&
341 Year == other.Year;
343 bool operator!=(const Date &other) const
345 return !operator==(other);
348 BXEXPORT std::ostream& operator<<(std::ostream &os, const Date &date);
350 class BXEXPORT CategoryList : public std::vector<std::string>
352 public:
353 /// Parses the given comma delimited category string into
354 /// this CategoryList object, appending each token to the vector.
355 /// Will clear vector beforehand.
356 void CategoryStr2List(const std::string &str);
358 /// Turns the current vectory into a comma delimited category
359 /// string suitable for use in Calendar, Task, and Memo
360 /// protocol values.
361 void CategoryList2Str(std::string &str) const;
363 using std::vector<std::string>::operator=;
368 //////////////////////////////////////////////////////////////////////////////
369 // Generic Field Handles
371 /// \addtogroup GenericFieldHandles
372 /// Generic field handle classes, used to reference and work
373 /// with record members in a flexible, indirect way.
375 /// There are two ways to access device record data. The obvious
376 /// way is to instantiate a record class, such as Contact, and
377 /// access the public data members of that class to read and
378 /// write. If you always work with the same record class, this
379 /// works fine.
381 /// The other way is to have a list of pointers to members.
382 /// For example, you may wish to compare two records, without
383 /// actually caring what data is in each one. You can compare
384 /// at the record class level, with Contact one, two; and then
385 /// if( one == two ), but this will not tell you what field in
386 /// the record changed.
388 /// This last feature is what Generic Field Handles are meant to
389 /// fix. Each record class will contain a GetFieldHandles()
390 /// member function, which will return a vector of FieldHandle<>
391 /// objects, for that specific record. For example, Contact
392 /// would fill a vector with FieldHandle<Contact> objects.
393 /// Each FieldHandle<> object contains a C++ pointer-to-member,
394 /// which the FieldHandle refers to, as well as a FieldIdentity
395 /// object. The FieldIdentity object contains various identitying
396 /// information, such as the C++ variable name, an English
397 /// (or localized language) display name of the field, suitable
398 /// for user prompts, and other data more useful to the library.
400 /// The FieldHandle<> object has two member functions: Value()
401 /// and Member().
403 /// Value() will call a callback function with the _value_ of
404 /// the variable that FieldHandle<> points to. For example,
405 /// if the FieldHandle<> points to a std::string record member
406 /// variable, then Value() will pass that string value in as
407 /// an argument, along with a reference to the FieldIdentity
408 /// object. Value() requires a callback object and a record
409 /// object to perform this callback.
411 /// Member() will call a callback function/functor with the
412 /// pointer-to-member pointer and the FieldIdentity object.
413 /// This allows the programmer to create a functor with multiple
414 /// record objects, perhaps two objects to compare individual
415 /// fields, and use the pointer-to-member to access the field
416 /// data as needed.
418 /// For now, all data and callbacks are const, meaning that it
419 /// is not possible (without const_casting) to write to the
420 /// record via the pointers-to-members. This design decision
421 /// may need to be revisited someday, depending on its usefulness.
423 /// @{
426 // FieldIdentity
428 /// This class holds data that identifies a given field in a record.
429 /// This is fairly constant data, referenced by the FieldHandle class.
430 /// The information in here should be enough to show the user what kind
431 /// of field this is.
433 struct BXEXPORT FieldIdentity
435 // useful public data
436 const char *Name; // C++ name of field member variable in
437 // record class
438 std::string DisplayName; // localized display name of field
439 // in UTF8
440 // FIXME - should we leave localization
441 // to the application?
443 // subfield detection
444 bool HasSubfields; // true if this field has subfields
445 const char *ParentName; // name of field member variable that
446 // this field is a member of, or NULL
447 // if this field is a member of the
448 // record class.
449 // For example, Contact::PostalAddress
450 // would have HasSubfields == true,
451 // and ParentName == NULL, while all
452 // its subfield strings would have
453 // HasSubfields == false and
454 // ParentName == "WorkAddress" or
455 // "HomeAddress".
456 // The application could then decide
457 // whether to process only main fields,
458 // some of which have subfields,
459 // or only individual subfields.
461 // internal field data
462 int FieldTypeCode; // device type code for this field.
463 // if -1, then this is a conglomerate
464 // C++ field, such as
465 // Contact::PostalAddress, not a device
466 // field.
467 // If -1, then none of the following
468 // fields are valid.
469 const char *Ldif; // matching LDIF field name, or NULL
470 const char *ObjectClass; // matching LDIF object class, or NULL
471 bool IconvNeeded; // if true, the device's data needs to
472 // be passed through an IConverter
474 FieldIdentity(const char *name, const std::string &display_name,
475 int type_code = -1,
476 bool iconvneeded = false,
477 const char *ldif = 0, const char *oclass = 0,
478 bool has_sub = false, const char *parent = 0
480 : Name(name)
481 , DisplayName(display_name)
482 , HasSubfields(has_sub)
483 , ParentName(parent)
484 , FieldTypeCode(type_code)
485 , Ldif(ldif)
486 , ObjectClass(oclass)
487 , IconvNeeded(iconvneeded)
493 // EnumConstants
495 /// This is the base class for the hierarchy of classes to define
496 /// enum record members. This is the base class, which contains the
497 /// common code for creating and defining a list of enum constants for
498 /// a given enum field. The next derived class is EnumFieldBase<RecordT>,
499 /// which defines the virtual API for talking to a given enum field
500 /// in a given record. The next derived class is EnumField<RecordT, EnumT>,
501 /// which implements the pointer-to-member and virtual API for a given
502 /// enum type in a given record class.
504 /// For example, the Bookmark record class has the following enum field:
506 /// <pre>
507 /// enum BrowserIdentityType
508 /// {
509 /// IdentityAuto = 0,
510 /// IdentityBlackBerry,
511 /// IdentityFireFox,
512 /// IdentityInternetExplorer,
513 /// IdentityUnknown
514 /// };
515 /// BrowserIdentityType BrowserIdentity;
516 /// </pre>
518 /// The EnumConstants class will hold a vector of EnumConstant structs
519 /// defining each of the identity constants: Auto, BlackBerry, FireFox,
520 /// InternetExplorer, and Unknown.
522 /// The derived class EnumFieldBase<Bookmark> will define two additional
523 /// pure virtual API calls: GetValue(const Bookmark&) and
524 /// SetValue(Bookmark&, int).
526 /// Finally, the derived class EnumField<Bookmark,Bookmark::BrowserIdentityType>
527 /// will implement the virtual API, and contain a pointer-to-member to
528 /// the Bookmark::BrowserIdentity member field.
530 /// The FieldHandle<Bookmark> class will hold a pointer to
531 /// EnumFieldBase<Bookmark>, which can hold a pointer to a specific
532 /// EnumField<> object, one object for each of Bookmark's enum types,
533 /// of which there are currently 3.
535 class BXEXPORT EnumConstants
537 public:
538 /// This defines one of the enum constants being defined.
539 /// For example, for an enum declaration like:
540 /// enum Mine { A, B, C }; then this struct could contain
541 /// a definition for A, B, or C, but only one at at time.
542 /// All three would be defined by the EnumConstantList.
543 struct EnumConstant
545 const char *Name; //< C++ name of enum constant
546 std::string DisplayName; //< user-friendly name / meaning
547 int Value; //< constant enum value
549 EnumConstant(const char *name, const std::string &display,
550 int value)
551 : Name(name)
552 , DisplayName(display)
553 , Value(value)
558 typedef std::vector<EnumConstant> EnumConstantList;
560 private:
561 EnumConstantList m_constants;
563 public:
564 virtual ~EnumConstants() {}
566 /// Adds a constant definition to the list
567 void AddConstant(const char *name, const std::string &display, int val);
569 /// Returns a vector of EnumConstant objects, describing all enum
570 /// constants valid for this enum field.
571 const EnumConstantList& GetConstantList() const { return m_constants; }
573 /// Returns the EnumConstant for the given value.
574 /// Throws std::logic_error if not found.
575 const EnumConstant& GetConstant(int value) const;
577 /// Returns the constant name (C++ name) based on the given value.
578 /// Throws std::logic_error if not found.
579 const char* GetName(int value) const;
581 /// Returns the display name based on the given value.
582 /// Throws std::logic_error if not found.
583 const std::string& GetDisplayName(int value) const;
585 /// Returns true if the value matches one of the constants in the list.
586 bool IsConstantValid(int value) const;
590 // FieldValueHandlerBase
592 /// This is a pure virtual base class, defining the various types that
593 /// record fields can be. To be able to handle all the types of data
594 /// in all records, override these virtual functions to do with the
595 /// data as you wish.
597 /// All data from the records and fields will be passed in by value.
598 /// i.e. if field is string data, the overloaded std::string handler
599 /// will be called, and a refernce to the string will be passed in.
601 /// The advantage of using this virtual class is that less code will be
602 /// generated by templates. The disadvantage is that this is less flexible.
603 /// You will only get called for one field and record at a time.
604 /// So you can't do comparisons this way.
606 class BXEXPORT FieldValueHandlerBase
608 public:
609 virtual ~FieldValueHandlerBase() {}
611 /// For type std::string
612 virtual void operator()(const std::string &v,
613 const FieldIdentity &id) const = 0;
614 /// For type EmailAddressList
615 virtual void operator()(const EmailAddressList &v,
616 const FieldIdentity &id) const = 0;
617 /// For type time_t
618 virtual void operator()(const time_t &v,
619 const FieldIdentity &id) const = 0;
620 /// For type uint8_t
621 virtual void operator()(const uint8_t &v,
622 const FieldIdentity &id) const = 0;
623 /// For type uint16_t
624 virtual void operator()(const uint16_t &v,
625 const FieldIdentity &id) const = 0;
626 /// For type uint32_t
627 virtual void operator()(const uint32_t &v,
628 const FieldIdentity &id) const = 0;
629 /// For type uint64_t
630 virtual void operator()(const uint64_t &v,
631 const FieldIdentity &id) const = 0;
632 /// For type bool
633 virtual void operator()(const bool &v,
634 const FieldIdentity &id) const = 0;
635 /// For type int32_t
636 virtual void operator()(const int32_t &v,
637 const FieldIdentity &id) const = 0;
638 /// For type EmailList
639 virtual void operator()(const EmailList &v,
640 const FieldIdentity &id) const = 0;
641 /// For type Date
642 virtual void operator()(const Date &v,
643 const FieldIdentity &id) const = 0;
644 /// For type CategoryList
645 virtual void operator()(const CategoryList &v,
646 const FieldIdentity &id) const = 0;
647 /// For type PostalAddress
648 virtual void operator()(const PostalAddress &v,
649 const FieldIdentity &id) const = 0;
650 /// For type UnknownsType
651 virtual void operator()(const UnknownsType &v,
652 const FieldIdentity &id) const = 0;
656 /// EnumFieldBase<RecordT>
658 template <class RecordT>
659 class EnumFieldBase : public EnumConstants
661 public:
662 /// Return value of enum in rec
663 virtual int GetValue(const RecordT &rec) const = 0;
664 /// Set value of enum in rec
665 /// Throws std::logic_error if value is out of range
666 virtual void SetValue(RecordT &rec, int value) = 0;
670 /// EnumField<RecordT, EnumT>
672 template <class RecordT, class EnumT>
673 class EnumField : public EnumFieldBase<RecordT>
675 EnumT RecordT::* m_mp;
677 public:
678 explicit EnumField(EnumT RecordT::* mp)
679 : m_mp(mp)
683 virtual int GetValue(const RecordT &rec) const
685 return rec.*m_mp;
688 virtual void SetValue(RecordT &rec, int value)
690 if( !this->IsConstantValid(value) )
691 throw std::logic_error("Bad enum value in EnumField");
692 rec.*m_mp = (EnumT) value;
697 // FieldHandle<RecordT>
699 /// This is a template class that handles pointers to members of multiple
700 /// types of data and multiple types of records.
702 /// This class contains a union of all known data pointers in all records.
703 /// Therefore this class can hold a pointer to member of any record class.
705 /// To do something with the field that this FieldHandle<> class refers to,
706 /// call either Value() or Member() with appropriate callback functors.
707 /// Value will pass a reference to the field. You can use an object
708 /// derived from FieldValueHandlerBase here. Member() will pass a pointer
709 /// to member. Your functor will need to contain the record data in order
710 /// to access its data via the pointer to member.
712 /// The template functor callback that you pass into member must be
713 /// capable of this:
715 /// <pre>
716 /// template &lt;class RecordT&gt;
717 /// struct Callback
718 /// {
719 /// RecordT m_rec;
721 /// void operator()(typename FieldHandle<RecordT>::PostalPointer pp,
722 /// const FieldIdentity &id) const
723 /// {
724 /// PostalAddress pa = m_rec.*(pp.m_PostalAddress);
725 /// std::string val = pa.*(pp.m_PostalField);
726 /// ...
727 /// }
729 /// template &lt;class TypeT&gt;
730 /// void operator()(TypeT RecordT::* mp,
731 /// const FieldIdentity &id) const
732 /// {
733 /// TypeT val = m_rec.*mp;
734 /// ...
735 /// }
736 /// };
737 /// </pre>
739 /// You don't have to use a TypeT template, but if you don't, then you must
740 /// support all field types that the record class you're processing uses.
743 template <class RecordT>
744 class FieldHandle
746 public:
747 // Need to use this in the union, so no constructor allowed
748 struct PostalPointer
750 PostalAddress RecordT::* m_PostalAddress;
751 std::string PostalAddress::* m_PostalField;
754 // So use a factory function
755 static PostalPointer MakePostalPointer(PostalAddress RecordT::* p1,
756 std::string PostalAddress::* p2)
758 PostalPointer pp;
759 pp.m_PostalAddress = p1;
760 pp.m_PostalField = p2;
761 return pp;
764 private:
765 union PointerUnion
767 std::string RecordT::* m_string; // index 0
768 EmailAddressList RecordT::* m_EmailAddressList; // 1
769 time_t RecordT::* m_time; // 2
770 PostalPointer m_postal; // 3
771 uint8_t RecordT::* m_uint8; // 4
772 uint32_t RecordT::* m_uint32; // 5
773 EmailList RecordT::* m_EmailList; // 6
774 Date RecordT::* m_Date; // 7
775 CategoryList RecordT::* m_CategoryList; // 8
776 // GroupLinksType RecordT::* m_GroupLinksType; // 9
777 UnknownsType RecordT::* m_UnknownsType; // 10
778 bool RecordT::* m_bool; // 11
779 uint64_t RecordT::* m_uint64; // 12
780 uint16_t RecordT::* m_uint16; // 13
781 PostalAddress RecordT::* m_PostalAddress; // 14
782 // used by non-union m_enum below: // 15
783 int32_t RecordT::* m_int32; // 16
786 int m_type_index;
787 PointerUnion m_union;
788 EnumFieldBase<RecordT> *m_enum; // never freed, since this is a
789 // static list, existing to end of
790 // program lifetime
792 FieldIdentity m_id;
794 public:
795 // 0
796 FieldHandle(std::string RecordT::* mp, const FieldIdentity &id)
797 : m_type_index(0)
798 , m_enum(0)
799 , m_id(id)
801 m_union.m_string = mp;
804 // 1
805 FieldHandle(EmailAddressList RecordT::* mp, const FieldIdentity &id)
806 : m_type_index(1)
807 , m_enum(0)
808 , m_id(id)
810 m_union.m_EmailAddressList = mp;
813 // 2
814 FieldHandle(time_t RecordT::* mp, const FieldIdentity &id)
815 : m_type_index(2)
816 , m_enum(0)
817 , m_id(id)
819 m_union.m_time = mp;
822 // 3
823 FieldHandle(const PostalPointer &pp, const FieldIdentity &id)
824 : m_type_index(3)
825 , m_enum(0)
826 , m_id(id)
828 m_union.m_postal = pp;
831 // 4
832 FieldHandle(uint8_t RecordT::* mp, const FieldIdentity &id)
833 : m_type_index(4)
834 , m_enum(0)
835 , m_id(id)
837 m_union.m_uint8 = mp;
840 // 5
841 FieldHandle(uint32_t RecordT::* mp, const FieldIdentity &id)
842 : m_type_index(5)
843 , m_enum(0)
844 , m_id(id)
846 m_union.m_uint32 = mp;
849 // 6
850 FieldHandle(EmailList RecordT::* mp, const FieldIdentity &id)
851 : m_type_index(6)
852 , m_enum(0)
853 , m_id(id)
855 m_union.m_EmailList = mp;
858 // 7
859 FieldHandle(Date RecordT::* mp, const FieldIdentity &id)
860 : m_type_index(7)
861 , m_enum(0)
862 , m_id(id)
864 m_union.m_Date = mp;
867 // 8
868 FieldHandle(CategoryList RecordT::* mp, const FieldIdentity &id)
869 : m_type_index(8)
870 , m_enum(0)
871 , m_id(id)
873 m_union.m_CategoryList = mp;
876 // 9
877 // FieldHandle(GroupLinksType RecordT::* mp, const FieldIdentity &id)
878 // : m_type_index(9)
879 // , m_enum(0)
880 // , m_id(id)
881 // {
882 // m_union.m_GroupLinksType = mp;
883 // }
885 // 10
886 FieldHandle(UnknownsType RecordT::* mp, const FieldIdentity &id)
887 : m_type_index(10)
888 , m_enum(0)
889 , m_id(id)
891 m_union.m_UnknownsType = mp;
894 // 11
895 FieldHandle(bool RecordT::* mp, const FieldIdentity &id)
896 : m_type_index(11)
897 , m_enum(0)
898 , m_id(id)
900 m_union.m_bool = mp;
903 // 12
904 FieldHandle(uint64_t RecordT::* mp, const FieldIdentity &id)
905 : m_type_index(12)
906 , m_enum(0)
907 , m_id(id)
909 m_union.m_uint64 = mp;
912 // 13
913 FieldHandle(uint16_t RecordT::* mp, const FieldIdentity &id)
914 : m_type_index(13)
915 , m_enum(0)
916 , m_id(id)
918 m_union.m_uint16 = mp;
921 // 14
922 FieldHandle(PostalAddress RecordT::* mp, const FieldIdentity &id)
923 : m_type_index(14)
924 , m_enum(0)
925 , m_id(id)
927 m_union.m_PostalAddress = mp;
930 // 15
931 FieldHandle(EnumFieldBase<RecordT> *enum_, const FieldIdentity &id)
932 : m_type_index(15)
933 , m_enum(enum_)
934 , m_id(id)
938 // 16
939 FieldHandle(int32_t RecordT::* mp, const FieldIdentity &id)
940 : m_type_index(16)
941 , m_enum(0)
942 , m_id(id)
944 m_union.m_int32 = mp;
947 /// Extracts FieldIdentity object from FieldHandle<>
948 const FieldIdentity& GetIdentity() const { return m_id; }
950 /// Calls the matching virtual function in FieldValueHandlerBase,
951 /// passing in the value of the field that this FieldHandle<>
952 /// refers to, and a referenct to the FieldIdentity object.
953 /// Caller must pass in a RecordT object as well.
954 void Value(const FieldValueHandlerBase &vh, const RecordT &rec) const
956 switch( m_type_index )
958 case 0:
959 vh(rec.*(m_union.m_string), m_id);
960 break;
961 case 1:
962 vh(rec.*(m_union.m_EmailAddressList), m_id);
963 break;
964 case 2:
965 vh(rec.*(m_union.m_time), m_id);
966 break;
967 case 3:
968 vh(rec.*(m_union.m_postal.m_PostalAddress).*(m_union.m_postal.m_PostalField), m_id);
969 break;
970 case 4:
971 vh(rec.*(m_union.m_uint8), m_id);
972 break;
973 case 5:
974 vh(rec.*(m_union.m_uint32), m_id);
975 break;
976 case 6:
977 vh(rec.*(m_union.m_EmailList), m_id);
978 break;
979 case 7:
980 vh(rec.*(m_union.m_Date), m_id);
981 break;
982 case 8:
983 vh(rec.*(m_union.m_CategoryList), m_id);
984 break;
985 // case 9:
986 // vh(rec.*(m_union.m_GroupLinksType), m_id);
987 // break;
988 case 10:
989 vh(rec.*(m_union.m_UnknownsType), m_id);
990 break;
991 case 11:
992 vh(rec.*(m_union.m_bool), m_id);
993 break;
994 case 12:
995 vh(rec.*(m_union.m_uint64), m_id);
996 break;
997 case 13:
998 vh(rec.*(m_union.m_uint16), m_id);
999 break;
1000 case 14:
1001 vh(rec.*(m_union.m_PostalAddress), m_id);
1002 break;
1003 case 15:
1004 vh(m_enum->GetValue(rec), m_id);
1005 break;
1006 case 16:
1007 vh(rec.*(m_union.m_int32), m_id);
1008 break;
1009 default:
1010 throw std::logic_error("Unknown field handle type index");
1014 /// Calls the callback functor with two arguments: the pointer to
1015 /// member that this FieldHandle<> contains, and the FieldIdentity
1016 /// object. It is assumed that the functor will either contain
1017 /// or know where to find one or more records of type RecordT.
1018 template <class CallbackT>
1019 void Member(const CallbackT &func) const
1021 switch( m_type_index )
1023 case 0:
1024 func(m_union.m_string, m_id);
1025 break;
1026 case 1:
1027 func(m_union.m_EmailAddressList, m_id);
1028 break;
1029 case 2:
1030 func(m_union.m_time, m_id);
1031 break;
1032 case 3:
1033 func(m_union.m_postal, m_id);
1034 break;
1035 case 4:
1036 func(m_union.m_uint8, m_id);
1037 break;
1038 case 5:
1039 func(m_union.m_uint32, m_id);
1040 break;
1041 case 6:
1042 func(m_union.m_EmailList, m_id);
1043 break;
1044 case 7:
1045 func(m_union.m_Date, m_id);
1046 break;
1047 case 8:
1048 func(m_union.m_CategoryList, m_id);
1049 break;
1050 // case 9:
1051 // func(m_union.m_GroupLinksType, m_id);
1052 // break;
1053 case 10:
1054 func(m_union.m_UnknownsType, m_id);
1055 break;
1056 case 11:
1057 func(m_union.m_bool, m_id);
1058 break;
1059 case 12:
1060 func(m_union.m_uint64, m_id);
1061 break;
1062 case 13:
1063 func(m_union.m_uint16, m_id);
1064 break;
1065 case 14:
1066 func(m_union.m_PostalAddress, m_id);
1067 break;
1068 case 15:
1069 func(m_enum, m_id);
1070 break;
1071 case 16:
1072 func(m_union.m_int32, m_id);
1073 break;
1074 default:
1075 throw std::logic_error("Unknown field handle type index");
1080 /// Factory function to create a FieldHandle<> object.
1081 template <class RecordT, class TypeT>
1082 FieldHandle<RecordT> MakeFieldHandle(TypeT RecordT::* tp,
1083 const FieldIdentity &id)
1085 return FieldHandle<RecordT>(tp, id);
1088 /// Calls FileHandle<>::Member() for each defined field for a given record type.
1089 /// Takes a vector of FileHandle<> objects, and calls Member(func) for each one.
1090 template <class HandlesT, class CallbackT>
1091 void ForEachField(const HandlesT &handles, const CallbackT &func)
1093 typename HandlesT::const_iterator
1094 b = handles.begin(),
1095 e = handles.end();
1096 for( ; b != e; ++b ) {
1097 b->Member(func);
1101 /// Calls FileHandle<>::Value() for each defined field for a given record.
1102 /// Takes a RecordT object and calls Value(vh, rec) for each FileHandle<>
1103 /// object in the record's FileHandles set.
1104 template <class RecordT>
1105 void ForEachFieldValue(const RecordT &rec, const FieldValueHandlerBase &vh)
1107 typename std::vector<FieldHandle<RecordT> >::const_iterator
1108 b = RecordT::GetFieldHandles().begin(),
1109 e = RecordT::GetFieldHandles().end();
1110 for( ; b != e; ++b ) {
1111 b->Value(vh, rec);
1116 // FieldHandle setup macros
1118 // #undef and #define the following macros to override these macros for you:
1120 // CONTAINER_OBJECT_NAME - the new FieldHandles will be .push_back()'d into
1121 // this container
1122 // RECORD_CLASS_NAME - the name of the record class you are defining,
1123 // i.e. Barry::Contact, or Barry::Calendar
1126 // plain field, no connection to device field
1127 #define FHP(name, display) \
1128 CONTAINER_OBJECT_NAME.push_back( \
1129 FieldHandle<RECORD_CLASS_NAME>(&RECORD_CLASS_NAME::name, \
1130 FieldIdentity(#name, display)))
1131 // record field with direct connection to device field, no LDIF data
1132 #define FHD(name, display, type_code, iconv) \
1133 CONTAINER_OBJECT_NAME.push_back( \
1134 FieldHandle<RECORD_CLASS_NAME>(&RECORD_CLASS_NAME::name, \
1135 FieldIdentity(#name, display, type_code, iconv, \
1136 0, 0)))
1137 // record field with direct connection to device field, with LDIF data
1138 #define FHL(name, display, type_code, iconv, ldif, oclass) \
1139 CONTAINER_OBJECT_NAME.push_back( \
1140 FieldHandle<RECORD_CLASS_NAME>(&RECORD_CLASS_NAME::name, \
1141 FieldIdentity(#name, display, type_code, iconv, \
1142 ldif, oclass)))
1143 // a subfield of a conglomerate field, with direct connection to device field,
1144 // with LDIF data
1145 #define FHS(name, subname, display, type, iconv, ldif, oclass) \
1146 CONTAINER_OBJECT_NAME.push_back( \
1147 FieldHandle<RECORD_CLASS_NAME>( \
1148 FieldHandle<RECORD_CLASS_NAME>::MakePostalPointer( \
1149 &RECORD_CLASS_NAME::name, \
1150 &PostalAddress::subname), \
1151 FieldIdentity(#name "::" #subname, display, \
1152 type, iconv, ldif, oclass, \
1153 false, #name)))
1154 // record conglomerate field, which has subfields
1155 #define FHC(name, display) \
1156 CONTAINER_OBJECT_NAME.push_back( \
1157 FieldHandle<RECORD_CLASS_NAME>(&RECORD_CLASS_NAME::name, \
1158 FieldIdentity(#name, display, \
1159 -1, false, 0, 0, true, 0)))
1160 // create a new EnumField<> and add it to the list... use the new_var_name
1161 // to add constants with FHE_CONST below
1162 #define FHE(new_var_name, record_field_type, record_field_name, display) \
1163 EnumField<RECORD_CLASS_NAME, RECORD_CLASS_NAME::record_field_type> \
1164 *new_var_name = new \
1165 EnumField<RECORD_CLASS_NAME, RECORD_CLASS_NAME::record_field_type> \
1166 (&RECORD_CLASS_NAME::record_field_name); \
1167 CONTAINER_OBJECT_NAME.push_back( \
1168 FieldHandle<RECORD_CLASS_NAME>(new_var_name, \
1169 FieldIdentity(#record_field_name, display)))
1170 // same as FHE, but for when RECORD_CLASS_NAME is a template argument
1171 #define FHET(new_var_name, record_field_type, record_field_name, display) \
1172 EnumField<RECORD_CLASS_NAME, typename RECORD_CLASS_NAME::record_field_type> \
1173 *new_var_name = new \
1174 EnumField<RECORD_CLASS_NAME, typename RECORD_CLASS_NAME::record_field_type> \
1175 (&RECORD_CLASS_NAME::record_field_name); \
1176 CONTAINER_OBJECT_NAME.push_back( \
1177 FieldHandle<RECORD_CLASS_NAME>(new_var_name, \
1178 FieldIdentity(#record_field_name, display)))
1179 // add constant to enum created above
1180 #define FHE_CONST(var, name, display) \
1181 var->AddConstant(#name, display, RECORD_CLASS_NAME::name)
1183 /// @}
1185 } // namespace Barry
1188 /// \addtogroup RecordParserClasses
1189 /// Parser and data storage classes. These classes take a
1190 /// Database Database record and convert them into C++ objects.
1191 /// Each of these classes are safe to be used in standard
1192 /// containers, and are meant to be used in conjunction with the
1193 /// RecordParser<> template when calling Controller::LoadDatabase().
1194 /// @{
1195 /// @}
1197 #ifndef __BARRY_LIBRARY_BUILD__
1198 // Include all parser classes, to make it easy for the application to use.
1199 #include "r_calendar.h"
1200 #include "r_calllog.h"
1201 #include "r_bookmark.h"
1202 #include "r_contact.h"
1203 #include "r_cstore.h"
1204 #include "r_memo.h"
1205 #include "r_message.h"
1206 #include "r_servicebook.h"
1207 #include "r_task.h"
1208 #include "r_pin_message.h"
1209 #include "r_saved_message.h"
1210 #include "r_sms.h"
1211 #include "r_folder.h"
1212 #include "r_timezone.h"
1213 #include "r_hhagent.h"
1214 #endif
1216 #endif