r_timezone.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       r_timezone.cc
00003 ///             Record parsing class for the timezone database.
00004 ///
00005 
00006 /*
00007     Copyright (C) 2005-2009, Net Direct Inc. (http://www.netdirect.ca/)
00008     Copyright (C) 2008, Brian Edginton
00009 
00010     This program is free software; you can redistribute it and/or modify
00011     it under the terms of the GNU General Public License as published by
00012     the Free Software Foundation; either version 2 of the License, or
00013     (at your option) any later version.
00014 
00015     This program is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00018 
00019     See the GNU General Public License in the COPYING file at the
00020     root directory of this project for more details.
00021 */
00022 
00023 #include "r_timezone.h"
00024 #include "record-internal.h"
00025 #include "protostructs.h"
00026 #include "data.h"
00027 #include "time.h"
00028 #include "debug.h"
00029 #include <ostream>
00030 #include <iomanip>
00031 
00032 using namespace std;
00033 using namespace Barry::Protocol;
00034 
00035 namespace Barry
00036 {
00037 
00038 ///////////////////////////////////////////////////////////////////////////////
00039 // Timezone Class
00040 
00041 // Timezone Field Codes
00042 #define TZFC_INDEX              0x01
00043 #define TZFC_NAME               0x02
00044 #define TZFC_OFFSET             0x03
00045 #define TZFC_DST                0x04
00046 #define TZFC_STARTMONTH 0x06
00047 #define TZFC_ENDMONTH   0x0B
00048 #define TZFC_TZTYPE             0x64
00049 
00050 #define TZFC_END                0xffff
00051 
00052 static FieldLink<Timezone> TimezoneFieldLinks[] = {
00053         { TZFC_NAME,      "Name",        0, 0, &Timezone::TimeZoneName, 0, 0 },
00054         { TZFC_END,       "End of List", 0, 0, 0, 0, 0 },
00055 };
00056 
00057 Timezone::Timezone()
00058 {
00059         Clear();
00060 }
00061 
00062 Timezone::~Timezone()
00063 {
00064 }
00065 
00066 const unsigned char* Timezone::ParseField(const unsigned char *begin,
00067                                           const unsigned char *end,
00068                                           const IConverter *ic)
00069 {
00070         const CommonField *field = (const CommonField *) begin;
00071 
00072         // advance and check size
00073         begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
00074         if( begin > end )       // if begin==end, we are ok
00075                 return begin;
00076 
00077         if( !btohs(field->size) )   // if field has no size, something's up
00078                 return begin;
00079         
00080         if( field->type == TZFC_TZTYPE ) {
00081                 if( ( TZType = field->u.uint32 ) != 1 ) {
00082                         throw Error("Timezone::ParseField: Timezone Type is not valid");
00083                 }
00084                 return begin;
00085         }
00086 
00087         // cycle through the type table
00088         for(    FieldLink<Timezone> *b = TimezoneFieldLinks;
00089                 b->type != TZFC_END;
00090                 b++ )
00091         {
00092                 if( b->type == field->type ) {
00093                         if( b->strMember ) {
00094                                 std::string &s = this->*(b->strMember);
00095                                 s = ParseFieldString(field);
00096                                 return begin;   // done!
00097                         }
00098                 }
00099         }
00100 
00101         switch( field->type )
00102         {
00103         case TZFC_INDEX:
00104                 Index = btohl(field->u.uint32);
00105                 return begin;
00106                 
00107         case TZFC_OFFSET:
00108                 Offset = btohs(field->u.int16);
00109                 if (Offset < 0) {
00110                         Offset =~ Offset;
00111                         Offset++;
00112                         OffsetFraction = Offset % 60;
00113                         Offset = Offset / 60;
00114                         Left = true;
00115                 } else {
00116                         OffsetFraction = Offset % 60;
00117                         Offset = Offset / 60;
00118                         Left = false;
00119                 }
00120                 return begin;
00121                 
00122         case TZFC_DST:
00123                 DSTOffset = btohl(field->u.uint32);
00124                 if (DSTOffset) {
00125                         UseDST = true;
00126                 }
00127                 return begin;
00128                 
00129         case TZFC_STARTMONTH:
00130                 StartMonth = btohl(field->u.uint32);
00131                 return begin;
00132                 
00133         case TZFC_ENDMONTH:
00134                 EndMonth = btohl(field->u.uint32);
00135                 return begin;
00136         }
00137         
00138         // if still not handled, add to the Unknowns list
00139         UnknownField uf;
00140         uf.type = field->type;
00141         uf.data.assign((const char*)field->u.raw, btohs(field->size));
00142         Unknowns.push_back(uf);
00143 
00144         // return new pointer for next field
00145         return begin;
00146 }
00147 
00148 void Timezone::ParseHeader(const Data &data, size_t &offset)
00149 {
00150         // no header in Task records
00151 }
00152 
00153 void Timezone::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
00154 {
00155         const unsigned char *finish = ParseCommonFields(*this,
00156                 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
00157         offset += finish - (data.GetData() + offset);
00158 }
00159 
00160 void Timezone::Clear()
00161 {
00162         TimeZoneName.clear();
00163         
00164         Index = 0;
00165         Left = false;
00166         UseDST = false;
00167         Offset = 0;
00168         OffsetFraction = 0;
00169         DSTOffset = 0;
00170         StartMonth = -1;
00171         EndMonth = -1;
00172 
00173         Unknowns.clear();
00174 }
00175 
00176 void Timezone::Dump(std::ostream &os) const
00177 {
00178         static const char *month[] = {
00179                         "Jan", "Feb", "Mar", "Apr", "May",
00180                         "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 
00181         };
00182         
00183         os << "Task entry: 0x" << setbase(16) << RecordId
00184            << " (" << (unsigned int)RecType << ")\n";
00185 
00186         // cycle through the type table
00187         for(    const FieldLink<Timezone> *b = TimezoneFieldLinks;
00188                 b->type != TZFC_END;
00189                 b++ )
00190         {
00191                 if( b->strMember ) {
00192                         const std::string &s = this->*(b->strMember);
00193                         if( s.size() )
00194                                 os << "       " << b->name << ": " << s << "\n";
00195                 }
00196         }
00197 
00198         os << "      Index: 0x" <<setw(2) << Index << "\n";
00199         os << "     Offset: " << (Left ? "-" : "+") << setbase(10) << Offset << "." << OffsetFraction << "\n";
00200         os << "    Use DST: " << (UseDST ? "true" : "false") << "\n";
00201         if (UseDST) {
00202                 if ((StartMonth > 0) && (StartMonth < 11))
00203                                 os << "Start Month: " << month[StartMonth] << "\n";
00204                 else
00205                                 os << "Start Month: unknown (" << setbase(10) << StartMonth << ")\n";
00206                 if ((EndMonth > 0) && (EndMonth < 11))
00207                         os << "  End Month: " << month[EndMonth] << "\n";
00208                 else
00209                         os << "  End Month: unknown (" << setbase(10) << EndMonth << ")\n";
00210         }
00211 
00212         os << Unknowns;
00213         os << "\n\n";
00214 }
00215 
00216 }

Generated on Mon Jan 12 10:51:13 2009 for Barry by  doxygen 1.5.7.1