r_cstore.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "r_cstore.h"
00024 #include "record-internal.h"
00025 #include "data.h"
00026
00027 #include <iostream>
00028 #include <sstream>
00029 #include <iomanip>
00030
00031 #define __DEBUG_MODE__
00032 #include "debug.h"
00033
00034 using namespace std;
00035 using namespace Barry::Protocol;
00036
00037 namespace Barry {
00038
00039
00040
00041
00042
00043
00044 #define CSFC_FILENAME 0x01 // may not always be a complete file,but
00045
00046 #define CSFC_FOLDER_FLAG 0x05
00047 #define CSFC_FILE_DESCRIPTOR 0x06
00048 #define CSFC_FILE_CONTENT 0x07
00049
00050
00051 #define MAX_CONTENT_BLOCK_SIZE 0xfffe
00052
00053 ContentStore::ContentStore()
00054 {
00055 Clear();
00056 }
00057
00058 ContentStore::~ContentStore()
00059 {
00060 }
00061
00062 const unsigned char* ContentStore::ParseField(const unsigned char *begin,
00063 const unsigned char *end,
00064 const IConverter *ic)
00065 {
00066 const CommonField *field = (const CommonField *) begin;
00067
00068
00069 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
00070 if( begin > end )
00071 return begin;
00072
00073 if( !btohs(field->size) )
00074 return begin;
00075
00076 switch( field->type )
00077 {
00078 case CSFC_FILENAME:
00079 Filename = ParseFieldString(field);
00080 return begin;
00081
00082 case CSFC_FOLDER_FLAG:
00083 FolderFlag = false;
00084 {
00085
00086
00087 string s = ParseFieldString(field);
00088 if( s == "folder" ) {
00089 FolderFlag = true;
00090 }
00091 }
00092 return begin;
00093
00094 case CSFC_FILE_CONTENT:
00095 if( FileSize ) {
00096
00097 FileContent.append((const char*)field->u.raw,
00098 btohs(field->size));
00099 }
00100 else {
00101 FileSize = btohll(field->u.uint64);
00102 }
00103 return begin;
00104
00105 case CSFC_FILE_DESCRIPTOR:
00106
00107
00108 FileDescriptor.assign((const char*)field->u.raw,
00109 btohs(field->size));
00110 return begin;
00111 }
00112
00113
00114 UnknownField uf;
00115 uf.type = field->type;
00116 uf.data.assign((const char*)field->u.raw, btohs(field->size));
00117 Unknowns.push_back(uf);
00118
00119
00120 return begin;
00121 }
00122
00123 void ContentStore::ParseHeader(const Data &data, size_t &offset)
00124 {
00125
00126 }
00127
00128 void ContentStore::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
00129 {
00130 const unsigned char *finish = ParseCommonFields(*this,
00131 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
00132 offset += finish - (data.GetData() + offset);
00133 }
00134
00135 void ContentStore::BuildHeader(Data &data, size_t &offset) const
00136 {
00137 }
00138
00139 void ContentStore::BuildFields(Data &data, size_t &offset, const IConverter *ic) const
00140 {
00141 data.Zap();
00142
00143 if( !Filename.size() )
00144 throw BadData("Content Store must have a name.");
00145
00146 if( !FolderFlag && !FileContent.size() )
00147 throw BadData("Content Store item without any data.");
00148
00149
00150 BuildField(data, offset, CSFC_FILENAME, Filename);
00151
00152
00153 if( FolderFlag ) {
00154 BuildField(data, offset, CSFC_FOLDER_FLAG, string("folder"));
00155 }
00156 else {
00157
00158 BuildField(data, offset, CSFC_FILE_DESCRIPTOR,
00159 FileDescriptor.data(), FileDescriptor.size());
00160
00161
00162
00163
00164
00165
00166
00167 uint64_t RealSize = FileContent.size();
00168 BuildField(data, offset, CSFC_FILE_CONTENT, RealSize);
00169
00170
00171 for( size_t foff = 0; foff < FileContent.size(); ) {
00172 size_t blocksize = FileContent.size() - foff;
00173 if( blocksize > MAX_CONTENT_BLOCK_SIZE )
00174 blocksize = MAX_CONTENT_BLOCK_SIZE;
00175 BuildField(data, offset, CSFC_FILE_CONTENT,
00176 FileContent.data() + foff, blocksize);
00177
00178
00179 foff += blocksize;
00180 }
00181 }
00182
00183
00184 UnknownsType::const_iterator
00185 ub = Unknowns.begin(), ue = Unknowns.end();
00186 for( ; ub != ue; ub++ ) {
00187 BuildField(data, offset, *ub);
00188 }
00189
00190 data.ReleaseBuffer(offset);
00191 }
00192
00193 void ContentStore::Clear()
00194 {
00195 RecType = GetDefaultRecType();
00196 RecordId = 0;
00197
00198 Filename.clear();
00199 FolderFlag = false;
00200 FileContent.clear();
00201 FileDescriptor.clear();
00202
00203 Unknowns.clear();
00204
00205
00206 FileSize = 0;
00207 }
00208
00209 std::string ContentStore::GetDescription() const
00210 {
00211 return Filename;
00212 }
00213
00214 void ContentStore::Dump(std::ostream &os) const
00215 {
00216 ios::fmtflags oldflags = os.setf(ios::left);
00217 char fill = os.fill(' ');
00218
00219 os << "ContentStore: 0x" << hex << RecordId
00220 << " (" << (unsigned int)RecType << ")\n";
00221
00222 os << " Filename: " << Filename << endl;
00223 os << " Folder: " << (FolderFlag ? "yes" : "no") << endl;
00224 os << " BB Size: " << dec << FileSize << endl;
00225 os << " Actual Size: " << FileContent.size() << endl;
00226 os << " Descriptor:\n"
00227 << Data(FileDescriptor.data(), FileDescriptor.size()) << endl;
00228 os << " Content:\n"
00229 << Data(FileContent.data(), FileContent.size()) << endl;
00230
00231
00232 os << Unknowns;
00233
00234
00235 os.flags(oldflags);
00236 os.fill(fill);
00237 }
00238
00239 bool ContentStore::operator<(const ContentStore &other) const
00240 {
00241 return RecordId < other.RecordId;
00242 }
00243
00244 }
00245