# r_dbdb.cc

Go to the documentation of this file.

    00001 ///
    00002 /// \file       r_dbdb.cc
    00003 ///             DatabaseDatabase record parser class
    00004 ///
    00005
    00006 /*
    00007     Copyright (C) 2005-2011, Net Direct Inc. (http://www.netdirect.ca/)
    00008
    00009     This program is free software; you can redistribute it and/or modify
    00010     it under the terms of the GNU General Public License as published by
    00011     the Free Software Foundation; either version 2 of the License, or
    00012     (at your option) any later version.
    00013
    00014     This program is distributed in the hope that it will be useful,
    00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00017
    00018     See the GNU General Public License in the COPYING file at the
    00019     root directory of this project for more details.
    00020 */
    00021
    00022 #include "record.h"
    00023 #include "record-internal.h"
    00024 #include "data.h"
    00025 #include "protocol.h"
    00026 #include "debug.h"
    00027 #include <algorithm>
    00028
    00029 using namespace std;
    00030 using namespace Barry::Protocol;
    00031
    00032 namespace Barry {
    00033
    00034 ///////////////////////////////////////////////////////////////////////////////
    00035 // DatabaseDatabase class
    00036
    00037 DatabaseDatabase::DatabaseDatabase()
    00038 {
    00039 }
    00040
    00041 DatabaseDatabase::~DatabaseDatabase()
    00042 {
    00043 }
    00044
    00045 template <class RecordType, class FieldType>
    00046 void DatabaseDatabase::ParseRec(const RecordType &rec, const unsigned char *end)
    00047 {
    00048 }
    00049
    00050 template <class FieldType>
    00051 const unsigned char* DatabaseDatabase::ParseField(const unsigned char *begin,
    00052                                                   const unsigned char *end)
    00053 {
    00054         // check if there is enough data for a header
    00055         const unsigned char *headend = begin + sizeof(FieldType);
    00056         if( headend > end )
    00057                 return headend;
    00058
    00059         // get our header
    00060         const FieldType *field = (const FieldType *) begin;
    00061
    00062         // advance and check size
    00063         begin += sizeof(FieldType) - sizeof(field->name) + ConvertHtoB(field->nameSize);
    00064         if( begin > end )               // if begin==end, we are ok
    00065                 return begin;
    00066
    00067         if( !ConvertHtoB(field->nameSize) ) // if field has no size, something's up
    00068                 return begin;
    00069
    00070         Database db;
    00071         db.Number = ConvertHtoB(field->dbNumber);
    00072         db.RecordCount = ConvertHtoB(field->dbRecordCount);
    00073         db.Name.assign((const char *)field->name, ConvertHtoB(field->nameSize) - 1);
    00074         Databases.push_back(db);
    00075         return begin;
    00076 }
    00077
    00078 void DatabaseDatabase::Parse(const Data &data)
    00079 {
    00080         // check size to make sure we have up to the DBAccess operation byte
    00081         if( data.GetSize() < (SB_PACKET_DBACCESS_HEADER_SIZE + 1) )
    00082                 return;
    00083
    00084         MAKE_PACKET(pack, data);
    00085         const unsigned char *begin = 0;
    00086         const unsigned char *end = data.GetData() + data.GetSize();
    00087
    00088         switch( pack->u.db.u.response.operation )
    00089         {
    00090         case SB_DBOP_GET_DBDB:
    00091                 // using the new protocol
    00092                 if( data.GetSize() > SB_PACKET_DBDB_HEADER_SIZE ) {
    00093                         begin = (const unsigned char *)
    00094                                 &pack->u.db.u.response.u.dbdb.field[0];
    00095
    00096                         // this while check is ok, since ParseField checks
    00097                         // for header size
    00098                         while( begin < end )
    00099                                 begin = ParseField<DBDBField>(begin, end);
    00100                 }
    00101                 else
    00102                         dout("DatabaseDatabase: not enough data for parsing");
    00103                 break;
    00104
    00105         case SB_DBOP_OLD_GET_DBDB:
    00106                 // using the old protocol
    00107                 if( data.GetSize() > SB_PACKET_OLD_DBDB_HEADER_SIZE ) {
    00108                         begin = (const unsigned char *)
    00109                                 &pack->u.db.u.response.u.old_dbdb.field[0];
    00110
    00111                         // this while check is ok, since ParseField checks
    00112                         // for header size
    00113                         while( begin < end )
    00114                                 begin = ParseField<OldDBDBField>(begin, end);
    00115                 }
    00116                 else
    00117                         dout("DatabaseDatabase: not enough data for parsing");
    00118                 break;
    00119
    00120         default:
    00121                 // unknown protocol
    00122                 dout("Unknown protocol");
    00123                 break;
    00124         }
    00125
    00126
    00127 }
    00128
    00129 void DatabaseDatabase::Clear()
    00130 {
    00131         Databases.clear();
    00132 }
    00133
    00134 namespace {
    00135         bool NameSort(const DatabaseDatabase::Database &one,
    00136                 const DatabaseDatabase::Database &two)
    00137         {
    00138                 return one.Name < two.Name;
    00139         }
    00140 }
    00141
    00142 void DatabaseDatabase::SortByName()
    00143 {
    00144         std::sort(Databases.begin(), Databases.end(), NameSort);
    00145 }
    00146
    00147 bool DatabaseDatabase::GetDBNumber(const std::string &name,
    00148                                    unsigned int &number) const
    00149 {
    00150         DatabaseArrayType::const_iterator b = Databases.begin();
    00151         for( ; b != Databases.end(); b++ )
    00152                 if( b->Name == name ) {
    00153                         number = b->Number;
    00154                         return true;
    00155                 }
    00156         return false;
    00157 }
    00158
    00159 bool DatabaseDatabase::GetDBName(unsigned int number,
    00160                                  std::string &name) const
    00161 {
    00162         DatabaseArrayType::const_iterator b = Databases.begin();
    00163         for( ; b != Databases.end(); b++ )
    00164                 if( b->Number == number ) {
    00165                         name = b->Name;
    00166                         return true;
    00167                 }
    00168         return false;
    00169 }
    00170
    00171 void DatabaseDatabase::Dump(std::ostream &os) const
    00172 {
    00173         DatabaseArrayType::const_iterator b = Databases.begin();
    00174         os << "Database database:\n";
    00175         for( ; b != Databases.end(); b++ ) {
    00176                 os << "    Database: 0x" << setbase(16) << b->Number
    00177                    << " '" << b->Name << "' (records: "
    00178                    << setbase(10) << b->RecordCount << ")\n";
    00179         }
    00180 }
    00181
    00182 } // namespace Barry
    00183