# 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-2011, 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 "iconv.h"
    00029 #include "debug.h"
    00030 #include <iostream>
    00031 #include <sstream>
    00032 #include <iomanip>
    00033
    00034 using namespace std;
    00035 using namespace Barry::Protocol;
    00036
    00037 namespace Barry
    00038 {
    00039
    00040 ///////////////////////////////////////////////////////////////////////////////
    00041 // Timezone Class
    00042
    00043 // Timezone Field Codes
    00044 #define TZFC_INDEX              0x01
    00045 #define TZFC_NAME               0x02
    00046 #define TZFC_OFFSET             0x03
    00047 #define TZFC_DST                0x04
    00048 #define TZFC_STARTMONTH         0x06
    00049 #define TZFC_ENDMONTH           0x0B
    00050 #define TZFC_TZTYPE             0x64
    00051
    00052 #define TZFC_END                0xffff
    00053
    00054 static FieldLink<Timezone> TimezoneFieldLinks[] = {
    00055    { TZFC_NAME,   "Name",        0, 0, &Timezone::TimeZoneName, 0, 0, 0, 0, true },
    00056    { TZFC_END,    "End of List", 0, 0, 0, 0, 0, 0, 0, false },
    00057 };
    00058
    00059 Timezone::Timezone()
    00060 {
    00061         Clear();
    00062 }
    00063
    00064 Timezone::~Timezone()
    00065 {
    00066 }
    00067
    00068 const unsigned char* Timezone::ParseField(const unsigned char *begin,
    00069                                           const unsigned char *end,
    00070                                           const IConverter *ic)
    00071 {
    00072         const CommonField *field = (const CommonField *) begin;
    00073
    00074         // advance and check size
    00075         begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
    00076         if( begin > end )       // if begin==end, we are ok
    00077                 return begin;
    00078
    00079         if( !btohs(field->size) )   // if field has no size, something's up
    00080                 return begin;
    00081
    00082         if( field->type == TZFC_TZTYPE ) {
    00083                 if( ( TZType = field->u.uint32 ) != 1 ) {
    00084                         throw Error("Timezone::ParseField: Timezone Type is not valid");
    00085                 }
    00086                 return begin;
    00087         }
    00088
    00089         // cycle through the type table
    00090         for(    FieldLink<Timezone> *b = TimezoneFieldLinks;
    00091                 b->type != TZFC_END;
    00092                 b++ )
    00093         {
    00094                 if( b->type == field->type ) {
    00095                         if( b->strMember ) {
    00096                                 std::string &s = this->*(b->strMember);
    00097                                 s = ParseFieldString(field);
    00098                                 if( b->iconvNeeded && ic )
    00099                                         s = ic->FromBB(s);
    00100                                 return begin;   // done!
    00101                         }
    00102                 }
    00103         }
    00104
    00105         switch( field->type )
    00106         {
    00107         case TZFC_INDEX:
    00108                 Index = btohl(field->u.uint32);
    00109                 return begin;
    00110
    00111         case TZFC_OFFSET:
    00112                 Offset = btohs(field->u.int16);
    00113                 if (Offset < 0) {
    00114                         Offset =~ Offset;
    00115                         Offset++;
    00116                         OffsetFraction = Offset % 60;
    00117                         Offset = Offset / 60;
    00118                         Left = true;
    00119                 } else {
    00120                         OffsetFraction = Offset % 60;
    00121                         Offset = Offset / 60;
    00122                         Left = false;
    00123                 }
    00124                 return begin;
    00125
    00126         case TZFC_DST:
    00127                 DSTOffset = btohl(field->u.uint32);
    00128                 if (DSTOffset) {
    00129                         UseDST = true;
    00130                 }
    00131                 return begin;
    00132
    00133         case TZFC_STARTMONTH:
    00134                 StartMonth = btohl(field->u.uint32);
    00135                 return begin;
    00136
    00137         case TZFC_ENDMONTH:
    00138                 EndMonth = btohl(field->u.uint32);
    00139                 return begin;
    00140         }
    00141
    00142         // if still not handled, add to the Unknowns list
    00143         UnknownField uf;
    00144         uf.type = field->type;
    00145         uf.data.assign((const char*)field->u.raw, btohs(field->size));
    00146         Unknowns.push_back(uf);
    00147
    00148         // return new pointer for next field
    00149         return begin;
    00150 }
    00151
    00152 void Timezone::ParseHeader(const Data &data, size_t &offset)
    00153 {
    00154         // no header in Task records
    00155 }
    00156
    00157 void Timezone::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
    00158 {
    00159         const unsigned char *finish = ParseCommonFields(*this,
    00160                 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
    00161         offset += finish - (data.GetData() + offset);
    00162 }
    00163
    00164 void Timezone::BuildHeader(Data &data, size_t &offset) const
    00165 {
    00166         // not yet implemented
    00167 }
    00168
    00169 void Timezone::BuildFields(Data &data, size_t &offset, const IConverter *ic) const
    00170 {
    00171         // not yet implemented
    00172 }
    00173
    00174 void Timezone::Clear()
    00175 {
    00176         RecType = GetDefaultRecType();
    00177         RecordId = 0;
    00178
    00179         TZType = 0;
    00180         DSTOffset = 0;
    00181         Index = 0;
    00182         Offset = 0;
    00183         OffsetFraction = 0;
    00184         StartMonth = -1;
    00185         EndMonth = -1;
    00186         Left = false;
    00187         UseDST = false;
    00188
    00189         TimeZoneName.clear();
    00190
    00191         Unknowns.clear();
    00192 }
    00193
    00194 std::string Timezone::GetDescription() const
    00195 {
    00196         ostringstream oss;
    00197         oss << TimeZoneName << " ("
    00198             << (Left ? "-" : "+") << dec << Offset << "." << OffsetFraction
    00199             << ")";
    00200         return oss.str();
    00201 }
    00202
    00203 void Timezone::Dump(std::ostream &os) const
    00204 {
    00205         static const char *month[] = {
    00206                         "Jan", "Feb", "Mar", "Apr", "May",
    00207                         "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    00208         };
    00209
    00210         os << "Task entry: 0x" << setbase(16) << RecordId
    00211            << " (" << (unsigned int)RecType << ")\n";
    00212
    00213         // cycle through the type table
    00214         for(    const FieldLink<Timezone> *b = TimezoneFieldLinks;
    00215                 b->type != TZFC_END;
    00216                 b++ )
    00217         {
    00218                 if( b->strMember ) {
    00219                         const std::string &s = this->*(b->strMember);
    00220                         if( s.size() )
    00221                                 os << "       " << b->name << ": " << s << "\n";
    00222                 }
    00223         }
    00224
    00225         os << "      Index: 0x" <<setw(2) << Index << "\n";
    00226         os << "     Offset: " << (Left ? "-" : "+") << setbase(10) << Offset << "." << OffsetFraction << "\n";
    00227         os << "    Use DST: " << (UseDST ? "true" : "false") << "\n";
    00228         if (UseDST) {
    00229                 if ((StartMonth > 0) && (StartMonth < 11))
    00230                                 os << "Start Month: " << month[StartMonth] << "\n";
    00231                 else
    00232                                 os << "Start Month: unknown (" << setbase(10) << StartMonth << ")\n";
    00233                 if ((EndMonth > 0) && (EndMonth < 11))
    00234                         os << "  End Month: " << month[EndMonth] << "\n";
    00235                 else
    00236                         os << "  End Month: unknown (" << setbase(10) << EndMonth << ")\n";
    00237         }
    00238
    00239         os << Unknowns;
    00240         os << "\n\n";
    00241 }
    00242
    00243 }