2 /// \file r_recordstate.cc
3 /// RecordStateTable database record parser class
7 Copyright (C) 2005-2012, 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.
24 #include "record-internal.h"
30 using namespace Barry::Protocol
;
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
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
;
67 void RecordStateTable::Parse(const Data
&data
)
69 size_t offset
= 12; // skipping the unknown 2 bytes at start
71 if( offset
>= data
.GetSize() )
74 const unsigned char *begin
= data
.GetData() + offset
;
75 const unsigned char *end
= data
.GetData() + data
.GetSize();
78 begin
= ParseField(begin
, end
);
81 void RecordStateTable::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
) {
96 *pFoundIndex
= i
->first
;
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
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
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
;
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
149 Data::PrintAscii(bPrintAscii
);