lib: added int32_t to FieldHandle<>
[barry/progweb.git] / src / record.h
blobddd9dd7b27448fdd04dea8b08e7d09a4a1c4728c
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); }
201 struct BXEXPORT UnknownField
203 uint8_t type;
204 UnknownData data;
206 typedef std::vector<UnknownField> UnknownsType;
207 BXEXPORT std::ostream& operator<< (std::ostream &os, const UnknownsType &unknowns);
209 // simple email type and list
210 typedef std::string EmailType;
211 typedef std::vector<EmailType> EmailList;
213 // struct, attempting to combine name + email address, for mail
214 struct BXEXPORT EmailAddress
216 std::string Name;
217 std::string Email;
219 EmailAddress()
223 /// Converts "Name <address@host.com>" into Name + Address
224 /// Will also handle just a plain address too.
225 explicit EmailAddress(const std::string &complex_address);
227 void clear()
229 Name.clear();
230 Email.clear();
233 size_t size() const
235 return Name.size() + Email.size();
238 BXEXPORT std::ostream& operator<<(std::ostream &os, const EmailAddress &msga);
240 class BXEXPORT EmailAddressList : public std::vector<EmailAddress>
242 public:
243 std::string ToCommaSeparated() const;
244 void AddCommaSeparated(const std::string &list);
247 BXEXPORT std::ostream& operator<<(std::ostream &os, const EmailAddressList &elist);
249 struct BXEXPORT PostalAddress
251 std::string
252 Address1,
253 Address2,
254 Address3,
255 City,
256 Province,
257 PostalCode,
258 Country;
260 std::string GetLabel() const;
261 void Clear();
263 bool HasData() const { return Address1.size() || Address2.size() ||
264 Address3.size() || City.size() || Province.size() ||
265 PostalCode.size() || Country.size(); }
267 BXEXPORT std::ostream& operator<<(std::ostream &os, const PostalAddress &msga);
269 struct BXEXPORT Date
271 int Month; // 0 to 11
272 int Day; // 1 to 31
273 int Year; // exact number, eg. 2008
275 Date() : Month(0), Day(0), Year(0) {}
276 explicit Date(const struct tm *timep);
278 bool HasData() const { return Month || Day || Year; }
279 void Clear();
281 void ToTm(struct tm *timep) const;
282 std::string ToYYYYMMDD() const;
283 std::string ToBBString() const; // converts to Blackberry string
284 // format of DD/MM/YYYY
286 bool FromTm(const struct tm *timep);
287 bool FromBBString(const std::string &str);
288 bool FromYYYYMMDD(const std::string &str);
290 BXEXPORT std::ostream& operator<<(std::ostream &os, const Date &date);
292 class BXEXPORT CategoryList : public std::vector<std::string>
294 public:
295 /// Parses the given comma delimited category string into
296 /// this CategoryList object, appending each token to the vector.
297 /// Will clear vector beforehand.
298 void CategoryStr2List(const std::string &str);
300 /// Turns the current vectory into a comma delimited category
301 /// string suitable for use in Calendar, Task, and Memo
302 /// protocol values.
303 void CategoryList2Str(std::string &str) const;
305 using std::vector<std::string>::operator=;
310 //////////////////////////////////////////////////////////////////////////////
311 // Generic Field Handles
313 /// \addtogroup GenericFieldHandles
314 /// Generic field handle classes, used to reference and work
315 /// with record members in a flexible, indirect way.
317 /// There are two ways to access device record data. The obvious
318 /// way is to instantiate a record class, such as Contact, and
319 /// access the public data members of that class to read and
320 /// write. If you always work with the same record class, this
321 /// works fine.
323 /// The other way is to have a list of pointers to members.
324 /// For example, you may wish to compare two records, without
325 /// actually caring what data is in each one. You can compare
326 /// at the record class level, with Contact one, two; and then
327 /// if( one == two ), but this will not tell you what field in
328 /// the record changed.
330 /// This last feature is what Generic Field Handles are meant to
331 /// fix. Each record class will contain a GetFieldHandles()
332 /// member function, which will return a vector of FieldHandle<>
333 /// objects, for that specific record. For example, Contact
334 /// would fill a vector with FieldHandle<Contact> objects.
335 /// Each FieldHandle<> object contains a C++ pointer-to-member,
336 /// which the FieldHandle refers to, as well as a FieldIdentity
337 /// object. The FieldIdentity object contains various identitying
338 /// information, such as the C++ variable name, an English
339 /// (or localized language) display name of the field, suitable
340 /// for user prompts, and other data more useful to the library.
342 /// The FieldHandle<> object has two member functions: Value()
343 /// and Member().
345 /// Value() will call a callback function with the _value_ of
346 /// the variable that FieldHandle<> points to. For example,
347 /// if the FieldHandle<> points to a std::string record member
348 /// variable, then Value() will pass that string value in as
349 /// an argument, along with a reference to the FieldIdentity
350 /// object. Value() requires a callback object and a record
351 /// object to perform this callback.
353 /// Member() will call a callback function/functor with the
354 /// pointer-to-member pointer and the FieldIdentity object.
355 /// This allows the programmer to create a functor with multiple
356 /// record objects, perhaps two objects to compare individual
357 /// fields, and use the pointer-to-member to access the field
358 /// data as needed.
360 /// For now, all data and callbacks are const, meaning that it
361 /// is not possible (without const_casting) to write to the
362 /// record via the pointers-to-members. This design decision
363 /// may need to be revisited someday, depending on its usefulness.
365 /// @{
368 // FieldIdentity
370 /// This class holds data that identifies a given field in a record.
371 /// This is fairly constant data, referenced by the FieldHandle class.
372 /// The information in here should be enough to show the user what kind
373 /// of field this is.
375 struct BXEXPORT FieldIdentity
377 // useful public data
378 const char *Name; // C++ name of field member variable in
379 // record class
380 std::string DisplayName; // localized display name of field
381 // in UTF8
382 // FIXME - should we leave localization
383 // to the application?
385 // subfield detection
386 bool HasSubfields; // true if this field has subfields
387 const char *ParentName; // name of field member variable that
388 // this field is a member of, or NULL
389 // if this field is a member of the
390 // record class.
391 // For example, Contact::PostalAddress
392 // would have HasSubfields == true,
393 // and ParentName == NULL, while all
394 // its subfield strings would have
395 // HasSubfields == false and
396 // ParentName == "WorkAddress" or
397 // "HomeAddress".
398 // The application could then decide
399 // whether to process only main fields,
400 // some of which have subfields,
401 // or only individual subfields.
403 // internal field data
404 int FieldTypeCode; // device type code for this field.
405 // if -1, then this is a conglomerate
406 // C++ field, such as
407 // Contact::PostalAddress, not a device
408 // field.
409 // If -1, then none of the following
410 // fields are valid.
411 const char *Ldif; // matching LDIF field name, or NULL
412 const char *ObjectClass; // matching LDIF object class, or NULL
413 bool IconvNeeded; // if true, the device's data needs to
414 // be passed through an IConverter
416 FieldIdentity(const char *name, const std::string &display_name,
417 int type_code = -1,
418 bool iconvneeded = false,
419 const char *ldif = 0, const char *oclass = 0,
420 bool has_sub = false, const char *parent = 0
422 : Name(name)
423 , DisplayName(display_name)
424 , HasSubfields(has_sub)
425 , ParentName(parent)
426 , FieldTypeCode(type_code)
427 , Ldif(ldif)
428 , ObjectClass(oclass)
429 , IconvNeeded(iconvneeded)
435 // EnumConstants
437 /// This is the base class for the hierarchy of classes to define
438 /// enum record members. This is the base class, which contains the
439 /// common code for creating and defining a list of enum constants for
440 /// a given enum field. The next derived class is EnumFieldBase<RecordT>,
441 /// which defines the virtual API for talking to a given enum field
442 /// in a given record. The next derived class is EnumField<RecordT, EnumT>,
443 /// which implements the pointer-to-member and virtual API for a given
444 /// enum type in a given record class.
446 /// For example, the Bookmark record class has the following enum field:
448 /// <pre>
449 /// enum BrowserIdentityType
450 /// {
451 /// IdentityAuto = 0,
452 /// IdentityBlackBerry,
453 /// IdentityFireFox,
454 /// IdentityInternetExplorer,
455 /// IdentityUnknown
456 /// };
457 /// BrowserIdentityType BrowserIdentity;
458 /// </pre>
460 /// The EnumConstants class will hold a vector of EnumConstant structs
461 /// defining each of the identity constants: Auto, BlackBerry, FireFox,
462 /// InternetExplorer, and Unknown.
464 /// The derived class EnumFieldBase<Bookmark> will define two additional
465 /// pure virtual API calls: GetValue(const Bookmark&) and
466 /// SetValue(Bookmark&, int).
468 /// Finally, the derived class EnumField<Bookmark,Bookmark::BrowserIdentityType>
469 /// will implement the virtual API, and contain a pointer-to-member to
470 /// the Bookmark::BrowserIdentity member field.
472 /// The FieldHandle<Bookmark> class will hold a pointer to
473 /// EnumFieldBase<Bookmark>, which can hold a pointer to a specific
474 /// EnumField<> object, one object for each of Bookmark's enum types,
475 /// of which there are currently 3.
477 class BXEXPORT EnumConstants
479 public:
480 /// This defines one of the enum constants being defined.
481 /// For example, for an enum declaration like:
482 /// enum Mine { A, B, C }; then this struct could contain
483 /// a definition for A, B, or C, but only one at at time.
484 /// All three would be defined by the EnumConstantList.
485 struct EnumConstant
487 const char *Name; //< C++ name of enum constant
488 std::string DisplayName; //< user-friendly name / meaning
489 int Value; //< constant enum value
491 EnumConstant(const char *name, const std::string &display,
492 int value)
493 : Name(name)
494 , DisplayName(display)
495 , Value(value)
500 typedef std::vector<EnumConstant> EnumConstantList;
502 private:
503 EnumConstantList m_constants;
505 public:
506 virtual ~EnumConstants() {}
508 /// Adds a constant definition to the list
509 void AddConstant(const char *name, const std::string &display, int val);
511 /// Returns a vector of EnumConstant objects, describing all enum
512 /// constants valid for this enum field.
513 const EnumConstantList& GetConstantList() const { return m_constants; }
515 /// Returns the EnumConstant for the given value.
516 /// Throws std::logic_error if not found.
517 const EnumConstant& GetConstant(int value) const;
519 /// Returns the constant name (C++ name) based on the given value.
520 /// Throws std::logic_error if not found.
521 const char* GetName(int value) const;
523 /// Returns the display name based on the given value.
524 /// Throws std::logic_error if not found.
525 const std::string& GetDisplayName(int value) const;
527 /// Returns true if the value matches one of the constants in the list.
528 bool IsConstantValid(int value) const;
532 // FieldValueHandlerBase
534 /// This is a pure virtual base class, defining the various types that
535 /// record fields can be. To be able to handle all the types of data
536 /// in all records, override these virtual functions to do with the
537 /// data as you wish.
539 /// All data from the records and fields will be passed in by value.
540 /// i.e. if field is string data, the overloaded std::string handler
541 /// will be called, and a refernce to the string will be passed in.
543 /// The advantage of using this virtual class is that less code will be
544 /// generated by templates. The disadvantage is that this is less flexible.
545 /// You will only get called for one field and record at a time.
546 /// So you can't do comparisons this way.
548 class BXEXPORT FieldValueHandlerBase
550 public:
551 virtual ~FieldValueHandlerBase() {}
553 /// For type std::string
554 virtual void operator()(const std::string &v,
555 const FieldIdentity &id) const = 0;
556 /// For type EmailAddressList
557 virtual void operator()(const EmailAddressList &v,
558 const FieldIdentity &id) const = 0;
559 /// For type time_t
560 virtual void operator()(const time_t &v,
561 const FieldIdentity &id) const = 0;
562 /// For type uint8_t
563 virtual void operator()(const uint8_t &v,
564 const FieldIdentity &id) const = 0;
565 /// For type uint16_t
566 virtual void operator()(const uint16_t &v,
567 const FieldIdentity &id) const = 0;
568 /// For type uint32_t
569 virtual void operator()(const uint32_t &v,
570 const FieldIdentity &id) const = 0;
571 /// For type uint64_t
572 virtual void operator()(const uint64_t &v,
573 const FieldIdentity &id) const = 0;
574 /// For type bool
575 virtual void operator()(const bool &v,
576 const FieldIdentity &id) const = 0;
577 /// For type int32_t
578 virtual void operator()(const int32_t &v,
579 const FieldIdentity &id) const = 0;
580 /// For type EmailList
581 virtual void operator()(const EmailList &v,
582 const FieldIdentity &id) const = 0;
583 /// For type Date
584 virtual void operator()(const Date &v,
585 const FieldIdentity &id) const = 0;
586 /// For type CategoryList
587 virtual void operator()(const CategoryList &v,
588 const FieldIdentity &id) const = 0;
589 /// For type PostalAddress
590 virtual void operator()(const PostalAddress &v,
591 const FieldIdentity &id) const = 0;
592 /// For type UnknownsType
593 virtual void operator()(const UnknownsType &v,
594 const FieldIdentity &id) const = 0;
598 /// EnumFieldBase<RecordT>
600 template <class RecordT>
601 class EnumFieldBase : public EnumConstants
603 public:
604 /// Return value of enum in rec
605 virtual int GetValue(const RecordT &rec) const = 0;
606 /// Set value of enum in rec
607 /// Throws std::logic_error if value is out of range
608 virtual void SetValue(RecordT &rec, int value) = 0;
612 /// EnumField<RecordT, EnumT>
614 template <class RecordT, class EnumT>
615 class EnumField : public EnumFieldBase<RecordT>
617 EnumT RecordT::* m_mp;
619 public:
620 explicit EnumField(EnumT RecordT::* mp)
621 : m_mp(mp)
625 virtual int GetValue(const RecordT &rec) const
627 return rec.*m_mp;
630 virtual void SetValue(RecordT &rec, int value)
632 if( !this->IsConstantValid(value) )
633 throw std::logic_error("Bad enum value in EnumField");
634 rec.*m_mp = (EnumT) value;
639 // FieldHandle<RecordT>
641 /// This is a template class that handles pointers to members of multiple
642 /// types of data and multiple types of records.
644 /// This class contains a union of all known data pointers in all records.
645 /// Therefore this class can hold a pointer to member of any record class.
647 /// To do something with the field that this FieldHandle<> class refers to,
648 /// call either Value() or Member() with appropriate callback functors.
649 /// Value will pass a reference to the field. You can use an object
650 /// derived from FieldValueHandlerBase here. Member() will pass a pointer
651 /// to member. Your functor will need to contain the record data in order
652 /// to access its data via the pointer to member.
654 /// The template functor callback that you pass into member must be
655 /// capable of this:
657 /// <pre>
658 /// template &lt;class RecordT&gt;
659 /// struct Callback
660 /// {
661 /// RecordT m_rec;
663 /// void operator()(typename FieldHandle<RecordT>::PostalPointer pp,
664 /// const FieldIdentity &id) const
665 /// {
666 /// PostalAddress pa = m_rec.*(pp.m_PostalAddress);
667 /// std::string val = pa.*(pp.m_PostalField);
668 /// ...
669 /// }
671 /// template &lt;class TypeT&gt;
672 /// void operator()(TypeT RecordT::* mp,
673 /// const FieldIdentity &id) const
674 /// {
675 /// TypeT val = m_rec.*mp;
676 /// ...
677 /// }
678 /// };
679 /// </pre>
681 /// You don't have to use a TypeT template, but if you don't, then you must
682 /// support all field types that the record class you're processing uses.
685 template <class RecordT>
686 class FieldHandle
688 public:
689 // Need to use this in the union, so no constructor allowed
690 struct PostalPointer
692 PostalAddress RecordT::* m_PostalAddress;
693 std::string PostalAddress::* m_PostalField;
696 // So use a factory function
697 static PostalPointer MakePostalPointer(PostalAddress RecordT::* p1,
698 std::string PostalAddress::* p2)
700 PostalPointer pp;
701 pp.m_PostalAddress = p1;
702 pp.m_PostalField = p2;
703 return pp;
706 private:
707 union PointerUnion
709 std::string RecordT::* m_string; // index 0
710 EmailAddressList RecordT::* m_EmailAddressList; // 1
711 time_t RecordT::* m_time; // 2
712 PostalPointer m_postal; // 3
713 uint8_t RecordT::* m_uint8; // 4
714 uint32_t RecordT::* m_uint32; // 5
715 EmailList RecordT::* m_EmailList; // 6
716 Date RecordT::* m_Date; // 7
717 CategoryList RecordT::* m_CategoryList; // 8
718 // GroupLinksType RecordT::* m_GroupLinksType; // 9
719 UnknownsType RecordT::* m_UnknownsType; // 10
720 bool RecordT::* m_bool; // 11
721 uint64_t RecordT::* m_uint64; // 12
722 uint16_t RecordT::* m_uint16; // 13
723 PostalAddress RecordT::* m_PostalAddress; // 14
724 // used by non-union m_enum below: // 15
725 int32_t RecordT::* m_int32; // 16
728 int m_type_index;
729 PointerUnion m_union;
730 EnumFieldBase<RecordT> *m_enum; // never freed, since this is a
731 // static list, existing to end of
732 // program lifetime
734 FieldIdentity m_id;
736 public:
737 // 0
738 FieldHandle(std::string RecordT::* mp, const FieldIdentity &id)
739 : m_type_index(0)
740 , m_enum(0)
741 , m_id(id)
743 m_union.m_string = mp;
746 // 1
747 FieldHandle(EmailAddressList RecordT::* mp, const FieldIdentity &id)
748 : m_type_index(1)
749 , m_enum(0)
750 , m_id(id)
752 m_union.m_EmailAddressList = mp;
755 // 2
756 FieldHandle(time_t RecordT::* mp, const FieldIdentity &id)
757 : m_type_index(2)
758 , m_enum(0)
759 , m_id(id)
761 m_union.m_time = mp;
764 // 3
765 FieldHandle(const PostalPointer &pp, const FieldIdentity &id)
766 : m_type_index(3)
767 , m_enum(0)
768 , m_id(id)
770 m_union.m_postal = pp;
773 // 4
774 FieldHandle(uint8_t RecordT::* mp, const FieldIdentity &id)
775 : m_type_index(4)
776 , m_enum(0)
777 , m_id(id)
779 m_union.m_uint8 = mp;
782 // 5
783 FieldHandle(uint32_t RecordT::* mp, const FieldIdentity &id)
784 : m_type_index(5)
785 , m_enum(0)
786 , m_id(id)
788 m_union.m_uint32 = mp;
791 // 6
792 FieldHandle(EmailList RecordT::* mp, const FieldIdentity &id)
793 : m_type_index(6)
794 , m_enum(0)
795 , m_id(id)
797 m_union.m_EmailList = mp;
800 // 7
801 FieldHandle(Date RecordT::* mp, const FieldIdentity &id)
802 : m_type_index(7)
803 , m_enum(0)
804 , m_id(id)
806 m_union.m_Date = mp;
809 // 8
810 FieldHandle(CategoryList RecordT::* mp, const FieldIdentity &id)
811 : m_type_index(8)
812 , m_enum(0)
813 , m_id(id)
815 m_union.m_CategoryList = mp;
818 // 9
819 // FieldHandle(GroupLinksType RecordT::* mp, const FieldIdentity &id)
820 // : m_type_index(9)
821 // , m_enum(0)
822 // , m_id(id)
823 // {
824 // m_union.m_GroupLinksType = mp;
825 // }
827 // 10
828 FieldHandle(UnknownsType RecordT::* mp, const FieldIdentity &id)
829 : m_type_index(10)
830 , m_enum(0)
831 , m_id(id)
833 m_union.m_UnknownsType = mp;
836 // 11
837 FieldHandle(bool RecordT::* mp, const FieldIdentity &id)
838 : m_type_index(11)
839 , m_enum(0)
840 , m_id(id)
842 m_union.m_bool = mp;
845 // 12
846 FieldHandle(uint64_t RecordT::* mp, const FieldIdentity &id)
847 : m_type_index(12)
848 , m_enum(0)
849 , m_id(id)
851 m_union.m_uint64 = mp;
854 // 13
855 FieldHandle(uint16_t RecordT::* mp, const FieldIdentity &id)
856 : m_type_index(13)
857 , m_enum(0)
858 , m_id(id)
860 m_union.m_uint16 = mp;
863 // 14
864 FieldHandle(PostalAddress RecordT::* mp, const FieldIdentity &id)
865 : m_type_index(14)
866 , m_enum(0)
867 , m_id(id)
869 m_union.m_PostalAddress = mp;
872 // 15
873 FieldHandle(EnumFieldBase<RecordT> *enum_, const FieldIdentity &id)
874 : m_type_index(15)
875 , m_enum(enum_)
876 , m_id(id)
880 // 16
881 FieldHandle(int32_t RecordT::* mp, const FieldIdentity &id)
882 : m_type_index(16)
883 , m_enum(0)
884 , m_id(id)
886 m_union.m_int32 = mp;
889 /// Extracts FieldIdentity object from FieldHandle<>
890 const FieldIdentity& GetIdentity() const { return m_id; }
892 /// Calls the matching virtual function in FieldValueHandlerBase,
893 /// passing in the value of the field that this FieldHandle<>
894 /// refers to, and a referenct to the FieldIdentity object.
895 /// Caller must pass in a RecordT object as well.
896 void Value(const FieldValueHandlerBase &vh, const RecordT &rec) const
898 switch( m_type_index )
900 case 0:
901 vh(rec.*(m_union.m_string), m_id);
902 break;
903 case 1:
904 vh(rec.*(m_union.m_EmailAddressList), m_id);
905 break;
906 case 2:
907 vh(rec.*(m_union.m_time), m_id);
908 break;
909 case 3:
910 vh(rec.*(m_union.m_postal.m_PostalAddress).*(m_union.m_postal.m_PostalField), m_id);
911 break;
912 case 4:
913 vh(rec.*(m_union.m_uint8), m_id);
914 break;
915 case 5:
916 vh(rec.*(m_union.m_uint32), m_id);
917 break;
918 case 6:
919 vh(rec.*(m_union.m_EmailList), m_id);
920 break;
921 case 7:
922 vh(rec.*(m_union.m_Date), m_id);
923 break;
924 case 8:
925 vh(rec.*(m_union.m_CategoryList), m_id);
926 break;
927 // case 9:
928 // vh(rec.*(m_union.m_GroupLinksType), m_id);
929 // break;
930 case 10:
931 vh(rec.*(m_union.m_UnknownsType), m_id);
932 break;
933 case 11:
934 vh(rec.*(m_union.m_bool), m_id);
935 break;
936 case 12:
937 vh(rec.*(m_union.m_uint64), m_id);
938 break;
939 case 13:
940 vh(rec.*(m_union.m_uint16), m_id);
941 break;
942 case 14:
943 vh(rec.*(m_union.m_PostalAddress), m_id);
944 break;
945 case 15:
946 vh(m_enum->GetValue(rec), m_id);
947 break;
948 case 16:
949 vh(rec.*(m_union.m_int32), m_id);
950 break;
951 default:
952 throw std::logic_error("Unknown field handle type index");
956 /// Calls the callback functor with two arguments: the pointer to
957 /// member that this FieldHandle<> contains, and the FieldIdentity
958 /// object. It is assumed that the functor will either contain
959 /// or know where to find one or more records of type RecordT.
960 template <class CallbackT>
961 void Member(const CallbackT &func) const
963 switch( m_type_index )
965 case 0:
966 func(m_union.m_string, m_id);
967 break;
968 case 1:
969 func(m_union.m_EmailAddressList, m_id);
970 break;
971 case 2:
972 func(m_union.m_time, m_id);
973 break;
974 case 3:
975 func(m_union.m_postal, m_id);
976 break;
977 case 4:
978 func(m_union.m_uint8, m_id);
979 break;
980 case 5:
981 func(m_union.m_uint32, m_id);
982 break;
983 case 6:
984 func(m_union.m_EmailList, m_id);
985 break;
986 case 7:
987 func(m_union.m_Date, m_id);
988 break;
989 case 8:
990 func(m_union.m_CategoryList, m_id);
991 break;
992 // case 9:
993 // func(m_union.m_GroupLinksType, m_id);
994 // break;
995 case 10:
996 func(m_union.m_UnknownsType, m_id);
997 break;
998 case 11:
999 func(m_union.m_bool, m_id);
1000 break;
1001 case 12:
1002 func(m_union.m_uint64, m_id);
1003 break;
1004 case 13:
1005 func(m_union.m_uint16, m_id);
1006 break;
1007 case 14:
1008 func(m_union.m_PostalAddress, m_id);
1009 break;
1010 case 15:
1011 func(m_enum, m_id);
1012 break;
1013 case 16:
1014 func(m_union.m_int32, m_id);
1015 break;
1016 default:
1017 throw std::logic_error("Unknown field handle type index");
1022 /// Factory function to create a FieldHandle<> object.
1023 template <class RecordT, class TypeT>
1024 FieldHandle<RecordT> MakeFieldHandle(TypeT RecordT::* tp,
1025 const FieldIdentity &id)
1027 return FieldHandle<RecordT>(tp, id);
1030 /// Calls FileHandle<>::Member() for each defined field for a given record type.
1031 /// Takes a vector of FileHandle<> objects, and calls Member(func) for each one.
1032 template <class HandlesT, class CallbackT>
1033 void ForEachField(const HandlesT &handles, const CallbackT &func)
1035 typename HandlesT::const_iterator
1036 b = handles.begin(),
1037 e = handles.end();
1038 for( ; b != e; ++b ) {
1039 b->Member(func);
1043 /// Calls FileHandle<>::Value() for each defined field for a given record.
1044 /// Takes a RecordT object and calls Value(vh, rec) for each FileHandle<>
1045 /// object in the record's FileHandles set.
1046 template <class RecordT>
1047 void ForEachFieldValue(const RecordT &rec, const FieldValueHandlerBase &vh)
1049 typename std::vector<FieldHandle<RecordT> >::const_iterator
1050 b = RecordT::GetFieldHandles().begin(),
1051 e = RecordT::GetFieldHandles().end();
1052 for( ; b != e; ++b ) {
1053 b->Value(vh, rec);
1058 // FieldHandle setup macros
1060 // #undef and #define the following macros to override these macros for you:
1062 // CONTAINER_OBJECT_NAME - the new FieldHandles will be .push_back()'d into
1063 // this container
1064 // RECORD_CLASS_NAME - the name of the record class you are defining,
1065 // i.e. Barry::Contact, or Barry::Calendar
1068 // plain field, no connection to device field
1069 #define FHP(name, display) \
1070 CONTAINER_OBJECT_NAME.push_back( \
1071 FieldHandle<RECORD_CLASS_NAME>(&RECORD_CLASS_NAME::name, \
1072 FieldIdentity(#name, display)))
1073 // record field with direct connection to device field, no LDIF data
1074 #define FHD(name, display, type_code, iconv) \
1075 CONTAINER_OBJECT_NAME.push_back( \
1076 FieldHandle<RECORD_CLASS_NAME>(&RECORD_CLASS_NAME::name, \
1077 FieldIdentity(#name, display, type_code, iconv, \
1078 0, 0)))
1079 // record field with direct connection to device field, with LDIF data
1080 #define FHL(name, display, type_code, iconv, ldif, oclass) \
1081 CONTAINER_OBJECT_NAME.push_back( \
1082 FieldHandle<RECORD_CLASS_NAME>(&RECORD_CLASS_NAME::name, \
1083 FieldIdentity(#name, display, type_code, iconv, \
1084 ldif, oclass)))
1085 // a subfield of a conglomerate field, with direct connection to device field,
1086 // with LDIF data
1087 #define FHS(name, subname, display, type, iconv, ldif, oclass) \
1088 CONTAINER_OBJECT_NAME.push_back( \
1089 FieldHandle<RECORD_CLASS_NAME>( \
1090 FieldHandle<RECORD_CLASS_NAME>::MakePostalPointer( \
1091 &RECORD_CLASS_NAME::name, \
1092 &PostalAddress::subname), \
1093 FieldIdentity(#name "::" #subname, display, \
1094 type, iconv, ldif, oclass, \
1095 false, #name)))
1096 // record conglomerate field, which has subfields
1097 #define FHC(name, display) \
1098 CONTAINER_OBJECT_NAME.push_back( \
1099 FieldHandle<RECORD_CLASS_NAME>(&RECORD_CLASS_NAME::name, \
1100 FieldIdentity(#name, display, \
1101 -1, false, 0, 0, true, 0)))
1102 // create a new EnumField<> and add it to the list... use the new_var_name
1103 // to add constants with FHE_CONST below
1104 #define FHE(new_var_name, record_field_type, record_field_name, display) \
1105 EnumField<RECORD_CLASS_NAME, RECORD_CLASS_NAME::record_field_type> \
1106 *new_var_name = new \
1107 EnumField<RECORD_CLASS_NAME, RECORD_CLASS_NAME::record_field_type> \
1108 (&RECORD_CLASS_NAME::record_field_name); \
1109 CONTAINER_OBJECT_NAME.push_back( \
1110 FieldHandle<RECORD_CLASS_NAME>(new_var_name, \
1111 FieldIdentity(#record_field_name, display)))
1112 // add constant to enum created above
1113 #define FHE_CONST(var, name, display) \
1114 var->AddConstant(#name, display, RECORD_CLASS_NAME::name)
1116 /// @}
1118 } // namespace Barry
1121 /// \addtogroup RecordParserClasses
1122 /// Parser and data storage classes. These classes take a
1123 /// Database Database record and convert them into C++ objects.
1124 /// Each of these classes are safe to be used in standard
1125 /// containers, and are meant to be used in conjunction with the
1126 /// RecordParser<> template when calling Controller::LoadDatabase().
1127 /// @{
1128 /// @}
1130 #ifndef __BARRY_LIBRARY_BUILD__
1131 // Include all parser classes, to make it easy for the application to use.
1132 #include "r_calendar.h"
1133 #include "r_calllog.h"
1134 #include "r_bookmark.h"
1135 #include "r_contact.h"
1136 #include "r_cstore.h"
1137 #include "r_memo.h"
1138 #include "r_message.h"
1139 #include "r_servicebook.h"
1140 #include "r_task.h"
1141 #include "r_pin_message.h"
1142 #include "r_saved_message.h"
1143 #include "r_sms.h"
1144 #include "r_folder.h"
1145 #include "r_timezone.h"
1146 #include "r_hhagent.h"
1147 #endif
1149 #endif