# r_recordstate.cc

Go to the documentation of this file.

    00001 ///
    00002 /// \file       r_recordstate.cc
    00003 ///             RecordStateTable database 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 <sstream>
    00026 #include <iomanip>
    00027
    00028 using namespace std;
    00029 using namespace Barry::Protocol;
    00030
    00031 namespace Barry {
    00032
    00033 ///////////////////////////////////////////////////////////////////////////////
    00034 // RecordStateTable class
    00035
    00036 RecordStateTable::RecordStateTable()
    00037         : m_LastNewRecordId(1)
    00038 {
    00039 }
    00040
    00041 RecordStateTable::~RecordStateTable()
    00042 {
    00043 }
    00044
    00045 const unsigned char* RecordStateTable::ParseField(const unsigned char *begin,
    00046                                                   const unsigned char *end)
    00047 {
    00048         const RecordStateTableField *field = (const RecordStateTableField *) begin;
    00049
    00050         // advance and check size
    00051         begin += sizeof(RecordStateTableField);
    00052         if( begin > end )               // if begin==end, we are ok
    00053                 return begin;
    00054
    00055         State state;
    00056         state.Index = btohs(field->index);
    00057         state.RecordId = btohl(field->uniqueId);
    00058         state.Dirty = (field->flags & BARRY_RSTF_DIRTY) != 0;
    00059         state.RecType = field->rectype;
    00060         state.Unknown2.assign((const char*)field->unknown2, sizeof(field->unknown2));
    00061         StateMap[state.Index] = state;
    00062
    00063         return begin;
    00064 }
    00065
    00066 void RecordStateTable::Parse(const Data &data)
    00067 {
    00068         size_t offset = 12;     // skipping the unknown 2 bytes at start
    00069
    00070         if( offset >= data.GetSize() )
    00071                 return;
    00072
    00073         const unsigned char *begin = data.GetData() + offset;
    00074         const unsigned char *end = data.GetData() + data.GetSize();
    00075
    00076         while( begin < end )
    00077                 begin = ParseField(begin, end);
    00078 }
    00079
    00080 void RecordStateTable::Clear()
    00081 {
    00082         StateMap.clear();
    00083         m_LastNewRecordId = 1;
    00084 }
    00085
    00086 // Searches the StateMap table for RecordId, and returns the "index"
    00087 // in the map if found.  Returns true if found, false if not.
    00088 // pFoundIndex can be null if only the existence of the index is desired
    00089 bool RecordStateTable::GetIndex(uint32_t RecordId, IndexType *pFoundIndex) const
    00090 {
    00091         StateMapType::const_iterator i = StateMap.begin();
    00092         for( ; i != StateMap.end(); ++i ) {
    00093                 if( i->second.RecordId == RecordId ) {
    00094                         if( pFoundIndex )
    00095                                 *pFoundIndex = i->first;
    00096                         return true;
    00097                 }
    00098         }
    00099         return false;
    00100 }
    00101
    00102 // Generate a new RecordId that is not in the state table.
    00103 // Starts at 1 and keeps incrementing until a free one is found.
    00104 uint32_t RecordStateTable::MakeNewRecordId() const
    00105 {
    00106         // start with next Id
    00107         m_LastNewRecordId++;
    00108
    00109         // make sure it doesn't already exist
    00110         StateMapType::const_iterator i = StateMap.begin();
    00111         while( i != StateMap.end() ) {
    00112                 if( m_LastNewRecordId == i->second.RecordId ) {
    00113                         m_LastNewRecordId++;            // try again
    00114                         i = StateMap.begin();           // start over
    00115                 }
    00116                 else {
    00117                         ++i;                            // next State
    00118                 }
    00119         }
    00120         return m_LastNewRecordId;
    00121 }
    00122
    00123 void RecordStateTable::Dump(std::ostream &os) const
    00124 {
    00125         ios::fmtflags oldflags = os.setf(ios::right);
    00126         char fill = os.fill(' ');
    00127         bool bPrintAscii = Data::PrintAscii();
    00128         Data::PrintAscii(false);
    00129
    00130         os << "  Index  RecordId    Dirty  RecType" << endl;
    00131         os << "-------  ----------  -----  -------" << endl;
    00132
    00133         StateMapType::const_iterator b, e = StateMap.end();
    00134         for( b = StateMap.begin(); b != e ; ++b ) {
    00135                 const State &state = b->second;
    00136
    00137                 os.fill(' ');
    00138                 os << setbase(10) << setw(7) << state.Index;
    00139                 os << "  0x" << setbase(16) << setfill('0') << setw(8) << state.RecordId;
    00140                 os << "  " << setfill(' ') << setw(5) << (state.Dirty ? "yes" : "no");
    00141                 os << "     0x" << setbase(16) << setfill('0') << setw(2) << state.RecType;
    00142                 os << "   " << Data(state.Unknown2.data(), state.Unknown2.size());
    00143         }
    00144
    00145         // cleanup the stream
    00146         os.flags(oldflags);
    00147         os.fill(fill);
    00148         Data::PrintAscii(bPrintAscii);
    00149 }
    00150
    00151
    00152 } // namespace Barry
    00153