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 

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