Bumped copyright dates for 2013
[barry.git] / src / r_recordstate.cc
blobc873981df26b2b505c8d159a1c6809e21015d574
1 ///
2 /// \file r_recordstate.cc
3 /// RecordStateTable database record parser class
4 ///
6 /*
7 Copyright (C) 2005-2013, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "i18n.h"
23 #include "record.h"
24 #include "record-internal.h"
25 #include "data.h"
26 #include <sstream>
27 #include <iomanip>
29 using namespace std;
30 using namespace Barry::Protocol;
32 namespace Barry {
34 ///////////////////////////////////////////////////////////////////////////////
35 // RecordStateTable class
37 RecordStateTable::RecordStateTable()
38 : m_LastNewRecordId(1)
42 RecordStateTable::~RecordStateTable()
46 const unsigned char* RecordStateTable::ParseField(const unsigned char *begin,
47 const unsigned char *end)
49 const RecordStateTableField *field = (const RecordStateTableField *) begin;
51 // advance and check size
52 begin += sizeof(RecordStateTableField);
53 if( begin > end ) // if begin==end, we are ok
54 return begin;
56 State state;
57 state.Index = btohs(field->index);
58 state.RecordId = btohl(field->uniqueId);
59 state.Dirty = (field->flags & BARRY_RSTF_DIRTY) != 0;
60 state.RecType = field->rectype;
61 state.Unknown2.assign((const char*)field->unknown2, sizeof(field->unknown2));
62 StateMap[state.Index] = state;
64 return begin;
67 void RecordStateTable::Parse(const Data &data)
69 size_t offset = 12; // skipping the unknown 2 bytes at start
71 if( offset >= data.GetSize() )
72 return;
74 const unsigned char *begin = data.GetData() + offset;
75 const unsigned char *end = data.GetData() + data.GetSize();
77 while( begin < end )
78 begin = ParseField(begin, end);
81 void RecordStateTable::Clear()
83 StateMap.clear();
84 m_LastNewRecordId = 1;
87 // Searches the StateMap table for RecordId, and returns the "index"
88 // in the map if found. Returns true if found, false if not.
89 // pFoundIndex can be null if only the existence of the index is desired
90 bool RecordStateTable::GetIndex(uint32_t RecordId, IndexType *pFoundIndex) const
92 StateMapType::const_iterator i = StateMap.begin();
93 for( ; i != StateMap.end(); ++i ) {
94 if( i->second.RecordId == RecordId ) {
95 if( pFoundIndex )
96 *pFoundIndex = i->first;
97 return true;
100 return false;
103 // Generate a new RecordId that is not in the state table.
104 // Starts at 1 and keeps incrementing until a free one is found.
105 uint32_t RecordStateTable::MakeNewRecordId() const
107 // start with next Id
108 m_LastNewRecordId++;
110 // make sure it doesn't already exist
111 StateMapType::const_iterator i = StateMap.begin();
112 while( i != StateMap.end() ) {
113 if( m_LastNewRecordId == i->second.RecordId ) {
114 m_LastNewRecordId++; // try again
115 i = StateMap.begin(); // start over
117 else {
118 ++i; // next State
121 return m_LastNewRecordId;
124 void RecordStateTable::Dump(std::ostream &os) const
126 ios::fmtflags oldflags = os.setf(ios::right);
127 char fill = os.fill(' ');
128 bool bPrintAscii = Data::PrintAscii();
129 Data::PrintAscii(false);
131 os << _(" Index RecordId Dirty RecType") << endl;
132 os << "------- ---------- ----- -------" << endl;
134 StateMapType::const_iterator b, e = StateMap.end();
135 for( b = StateMap.begin(); b != e ; ++b ) {
136 const State &state = b->second;
138 os.fill(' ');
139 os << setbase(10) << setw(7) << state.Index;
140 os << " 0x" << setbase(16) << setfill('0') << setw(8) << state.RecordId;
141 os << " " << setfill(' ') << setw(5) << (state.Dirty ? _("yes") : _("no"));
142 os << " 0x" << setbase(16) << setfill('0') << setw(2) << state.RecType;
143 os << " " << Data(state.Unknown2.data(), state.Unknown2.size());
146 // cleanup the stream
147 os.flags(oldflags);
148 os.fill(fill);
149 Data::PrintAscii(bPrintAscii);
153 } // namespace Barry