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 }

Generated on Tue Mar 1 17:50:16 2011 for Barry by  doxygen 1.5.6