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-2010, 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 
00028 using namespace std;
00029 using namespace Barry::Protocol;
00030 
00031 namespace Barry {
00032 
00033 ///////////////////////////////////////////////////////////////////////////////
00034 // DatabaseDatabase class
00035 
00036 DatabaseDatabase::DatabaseDatabase()
00037 {
00038 }
00039 
00040 DatabaseDatabase::~DatabaseDatabase()
00041 {
00042 }
00043 
00044 template <class RecordType, class FieldType>
00045 void DatabaseDatabase::ParseRec(const RecordType &rec, const unsigned char *end)
00046 {
00047 }
00048 
00049 template <class FieldType>
00050 const unsigned char* DatabaseDatabase::ParseField(const unsigned char *begin,
00051                                                   const unsigned char *end)
00052 {
00053         // check if there is enough data for a header
00054         const unsigned char *headend = begin + sizeof(FieldType);
00055         if( headend > end )
00056                 return headend;
00057 
00058         // get our header
00059         const FieldType *field = (const FieldType *) begin;
00060 
00061         // advance and check size
00062         begin += sizeof(FieldType) - sizeof(field->name) + ConvertHtoB(field->nameSize);
00063         if( begin > end )               // if begin==end, we are ok
00064                 return begin;
00065 
00066         if( !ConvertHtoB(field->nameSize) ) // if field has no size, something's up
00067                 return begin;
00068 
00069         Database db;
00070         db.Number = ConvertHtoB(field->dbNumber);
00071         db.RecordCount = ConvertHtoB(field->dbRecordCount);
00072         db.Name.assign((const char *)field->name, ConvertHtoB(field->nameSize) - 1);
00073         Databases.push_back(db);
00074         return begin;
00075 }
00076 
00077 void DatabaseDatabase::Parse(const Data &data)
00078 {
00079         // check size to make sure we have up to the DBAccess operation byte
00080         if( data.GetSize() < (SB_PACKET_DBACCESS_HEADER_SIZE + 1) )
00081                 return;
00082 
00083         MAKE_PACKET(pack, data);
00084         const unsigned char *begin = 0;
00085         const unsigned char *end = data.GetData() + data.GetSize();
00086 
00087         switch( pack->u.db.u.response.operation )
00088         {
00089         case SB_DBOP_GET_DBDB:
00090                 // using the new protocol
00091                 if( data.GetSize() > SB_PACKET_DBDB_HEADER_SIZE ) {
00092                         begin = (const unsigned char *)
00093                                 &pack->u.db.u.response.u.dbdb.field[0];
00094 
00095                         // this while check is ok, since ParseField checks
00096                         // for header size
00097                         while( begin < end )
00098                                 begin = ParseField<DBDBField>(begin, end);
00099                 }
00100                 else
00101                         dout("DatabaseDatabase: not enough data for parsing");
00102                 break;
00103 
00104         case SB_DBOP_OLD_GET_DBDB:
00105                 // using the old protocol
00106                 if( data.GetSize() > SB_PACKET_OLD_DBDB_HEADER_SIZE ) {
00107                         begin = (const unsigned char *)
00108                                 &pack->u.db.u.response.u.old_dbdb.field[0];
00109 
00110                         // this while check is ok, since ParseField checks
00111                         // for header size
00112                         while( begin < end )
00113                                 begin = ParseField<OldDBDBField>(begin, end);
00114                 }
00115                 else
00116                         dout("DatabaseDatabase: not enough data for parsing");
00117                 break;
00118 
00119         default:
00120                 // unknown protocol
00121                 dout("Unknown protocol");
00122                 break;
00123         }
00124 
00125 
00126 }
00127 
00128 void DatabaseDatabase::Clear()
00129 {
00130         Databases.clear();
00131 }
00132 
00133 bool DatabaseDatabase::GetDBNumber(const std::string &name,
00134                                    unsigned int &number) const
00135 {
00136         DatabaseArrayType::const_iterator b = Databases.begin();
00137         for( ; b != Databases.end(); b++ )
00138                 if( b->Name == name ) {
00139                         number = b->Number;
00140                         return true;
00141                 }
00142         return false;
00143 }
00144 
00145 bool DatabaseDatabase::GetDBName(unsigned int number,
00146                                  std::string &name) const
00147 {
00148         DatabaseArrayType::const_iterator b = Databases.begin();
00149         for( ; b != Databases.end(); b++ )
00150                 if( b->Number == number ) {
00151                         name = b->Name;
00152                         return true;
00153                 }
00154         return false;
00155 }
00156 
00157 void DatabaseDatabase::Dump(std::ostream &os) const
00158 {
00159         DatabaseArrayType::const_iterator b = Databases.begin();
00160         os << "Database database:\n";
00161         for( ; b != Databases.end(); b++ ) {
00162                 os << "    Database: 0x" << setbase(16) << b->Number
00163                    << " '" << b->Name << "' (records: "
00164                    << setbase(10) << b->RecordCount << ")\n";
00165         }
00166 }
00167 
00168 } // namespace Barry
00169 

Generated on 29 Mar 2010 for Barry by  doxygen 1.6.1