mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-18 03:31:18 +08:00
[xlsb] add binary stream reader
This commit is contained in:
@ -408,4 +408,146 @@ bool FileStreamCacheReader::isEOF()
|
||||
return !records_cache.size() && (file_.GetFilePosition() >= file_.GetFileSize());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
BinaryStreamCacheReader::BinaryStreamCacheReader( std::shared_ptr<NSBinPptxRW::CBinaryFileReader>& binaryStream, GlobalWorkbookInfoPtr global_info)
|
||||
: StreamCacheReader(global_info)
|
||||
{
|
||||
binaryStream_ = std::make_shared<NSBinPptxRW::CBinaryFileReader>(*binaryStream);
|
||||
}
|
||||
BinaryStreamCacheReader::~BinaryStreamCacheReader()
|
||||
{
|
||||
|
||||
}
|
||||
// Skip the specified number of unsigned chars without processing
|
||||
void BinaryStreamCacheReader::skipNunBytes(const size_t n)
|
||||
{
|
||||
binaryStream_->Seek(n);
|
||||
}
|
||||
// Reads the next CFRecord from the CFStream and if its type is not the desired one, caches it for the next call
|
||||
CFRecordPtr BinaryStreamCacheReader::getNextRecord(const CFRecordType::TypeId desirable_type, const bool gen_except)
|
||||
{
|
||||
CFRecordType::TypeId what_we_actually_read = rt_NONE;
|
||||
|
||||
while(readFromStream(1))
|
||||
{
|
||||
CFRecordType::TypeString rec_name = records_cache.front()->getTypeString();
|
||||
|
||||
Log::warning(rec_name);
|
||||
|
||||
if (desirable_type == rt_MsoDrawingGroup) // объединяем rt_MsoDrawingGroup + rt_Continue в один блок
|
||||
{
|
||||
if (checkNextRecord(desirable_type, 1))
|
||||
{
|
||||
readFromStream(2);
|
||||
|
||||
for(std::list<CFRecordPtr>::iterator good = records_cache.begin(), it = ++records_cache.begin();
|
||||
it != records_cache.end(); ++it, ++good)
|
||||
{
|
||||
while ((it != records_cache.end()) && (desirable_type == (*it)->getTypeId()))
|
||||
{
|
||||
(*good)->appendRawData(*it);
|
||||
records_cache.erase(it);
|
||||
if (binaryStream_->GetPos() < binaryStream_->GetSize())
|
||||
{
|
||||
records_cache.push_back(CFRecordPtr(new CFRecord(*binaryStream_, global_info_)));
|
||||
}
|
||||
it = good;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(0 == rec_name.length())
|
||||
{
|
||||
Log::warning(L"The extracted record has obsoleted or unknown type(0x" + STR::int2hex_wstr(records_cache.front()->getTypeId(), sizeof(CFRecordType::TypeId)) + L")");
|
||||
records_cache.pop_front();
|
||||
continue;
|
||||
}
|
||||
if(skippable_records_names.end() != std::find(skippable_records_names.begin(), skippable_records_names.end(), rec_name))
|
||||
{
|
||||
//Log::warning("The extracted record has been skipped (" + rec_name + ")");
|
||||
records_cache.pop_front();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(0 != records_cache.size())
|
||||
{
|
||||
what_we_actually_read = records_cache.front()->getTypeId();
|
||||
|
||||
// if we get what was requested
|
||||
if ( desirable_type == what_we_actually_read ||
|
||||
desirable_type == CFRecordType::ANY_TYPE ||
|
||||
(desirable_type == rt_BOF_BIFF8 && (what_we_actually_read == rt_BOF_BIFF4 ||
|
||||
what_we_actually_read == rt_BOF_BIFF3 || what_we_actually_read == rt_BOF_BIFF2)))
|
||||
{
|
||||
CFRecordPtr ret = records_cache.front();
|
||||
records_cache.pop_front();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if(gen_except)
|
||||
{
|
||||
// теги разные
|
||||
std::string inType = XLS::CFRecordType::getStringById(desirable_type);
|
||||
std::string outType = CFRecordType::getStringById(what_we_actually_read);
|
||||
|
||||
Log::warning("The extracted record is not of requested type.\nRequested: \"" +
|
||||
XLS::CFRecordType::getStringById(desirable_type) + "\" Extracted: \"" + CFRecordType::getStringById(what_we_actually_read) + "\"");
|
||||
}
|
||||
return CFRecordPtr();
|
||||
}
|
||||
// Make sure the internal buffer has concrete number of records. Returns number of records read
|
||||
const size_t BinaryStreamCacheReader::readFromStream(const size_t num_of_records_min_necessary)
|
||||
{
|
||||
const size_t current_records_num = records_cache.size();
|
||||
if (current_records_num >= num_of_records_min_necessary)
|
||||
{
|
||||
return current_records_num;
|
||||
}
|
||||
|
||||
while (records_cache.size() < num_of_records_min_necessary && binaryStream_->GetPos() < binaryStream_->GetSize())
|
||||
{
|
||||
records_cache.push_back(CFRecordPtr(new CFRecord(*binaryStream_, global_info_)));
|
||||
}
|
||||
|
||||
checkAndAppendContinueData();
|
||||
return records_cache.size();
|
||||
}
|
||||
|
||||
// Checks whether the next record is Continue and append its data to the real record if so
|
||||
void BinaryStreamCacheReader::checkAndAppendContinueData()
|
||||
{
|
||||
if (!records_cache.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::list<CFRecordPtr>::iterator good = records_cache.begin(), it = ++records_cache.begin();
|
||||
it != records_cache.end(); ++it, ++good)
|
||||
{
|
||||
size_t typeRecord = (*it)->getTypeId();
|
||||
while (it != records_cache.end() && (rt_Continue == (*it)->getTypeId()) )
|
||||
{
|
||||
(*good)->appendRawData(*it);
|
||||
records_cache.erase(it); // now 'it' is invalid
|
||||
if (binaryStream_->GetPos() < binaryStream_->GetSize())
|
||||
{
|
||||
records_cache.push_back(CFRecordPtr(new CFRecord(*binaryStream_, global_info_)));
|
||||
}
|
||||
it = good;
|
||||
++it; // Now it may became end(), checked in 'for'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BinaryStreamCacheReader::isEOF()
|
||||
{
|
||||
return !records_cache.size() && (binaryStream_->GetPos() >= binaryStream_->GetSize());
|
||||
}
|
||||
|
||||
|
||||
} // namespace XLS
|
||||
|
||||
Reference in New Issue
Block a user