XlsFormat - ...

This commit is contained in:
Elena.Subbotina
2020-07-20 14:46:21 +03:00
parent 3ae5b6b0f9
commit 60b032bb06
27 changed files with 189 additions and 170 deletions

View File

@ -202,9 +202,9 @@ public:
}
_UINT32 GetLen()
size_t GetLen()
{
_UINT32 dwLen = 6 * m_lCount;
size_t dwLen = 6 * m_lCount;
for (size_t nIndex = 0; nIndex < m_lCount; ++nIndex)
{
if (m_arProperties[nIndex].m_bComplex)

View File

@ -40,7 +40,6 @@
namespace XLS
{
// Binary representation of a stream in BIFF8
class CFStream
{
public:

View File

@ -33,18 +33,13 @@
#include "CFStreamCacheReader.h"
#include "CFRecord.h"
#include "CFStream.h"
#include <Logic/Biff_records/BOF.h>
#include "../Logic/Biff_records/BOF.h"
namespace XLS
{
CFStreamCacheReader::CFStreamCacheReader(CFStreamPtr stream, GlobalWorkbookInfoPtr global_info)
: stream_(stream),
global_info_(global_info)
StreamCacheReader::StreamCacheReader(const GlobalWorkbookInfoPtr global_info)
: global_info_(global_info)
{
skippable_records_names.push_back("StartBlock");
skippable_records_names.push_back("EndBlock");
@ -52,12 +47,98 @@ global_info_(global_info)
skippable_records_names.push_back("FrtWrapper");
}
CFStreamCacheReader::~CFStreamCacheReader()
StreamCacheReader::~StreamCacheReader()
{
}
// Check if the next read record would be of desired type
const bool StreamCacheReader::checkNextRecord(const CFRecordType::TypeId desirable_type, const size_t num_records_to_check)
{
readFromStream(num_records_to_check);
// if we would get what was requested
// ANY_TYPE is checked just to make the fake read from stream and get an error if the stream is ended
for(std::list<CFRecordPtr>::const_iterator it = records_cache.begin(), itEnd = records_cache.end(); it != itEnd; ++it)
{
size_t type = (*it)->getTypeId();
if(desirable_type == (*it)->getTypeId() || desirable_type == CFRecordType::ANY_TYPE)
{
return true;
}
}
return false;
}
// Seek to the next substream (Read all records till EOF then skip EOF)
// Doesn't generate EndOfStreamReached if the stream is the last one
void StreamCacheReader::SkipRecord()
{
if (records_cache.begin() != records_cache.end())
{
CFRecordType::TypeString rec_name = records_cache.front()->getTypeString();
if (rec_name.empty())
Log::warning(L"The extracted record has obsoleted or unknown type(0x" + STR::int2hex_wstr(records_cache.front()->getTypeId(), sizeof(CFRecordType::TypeId)) + L")");
else
Log::warning("The record has been skipped (" + rec_name + ")");
records_cache.pop_front();
}
}
const bool StreamCacheReader::SeekToEOF()
{
while(readFromStream(1))
{
if(rt_EOF == records_cache.front()->getTypeId())
{
// records_cache.pop_front(); // Skip EOF
break;
}
records_cache.pop_front(); // Skip non-EOF
}
return true;
}
// Extract the next record from the stream leaving it in the cache for future read.
// Always call resetPointerToBegin for the extracted CFRecord after using it
CFRecordPtr StreamCacheReader::touchTheNextRecord()
{
if(readFromStream(1))// make sure something is in cache
{
return records_cache.front();
}
return CFRecordPtr();
}
// Check the next record type
const CFRecordType::TypeId StreamCacheReader::getNextRecordType()
{
if(isEOF())
{
return rt_NONE;
}
readFromStream(1); // I don't check the result of readFromStream() because it was done implicitly in isEOF()
return records_cache.front()->getTypeId();
}
//---------------------------------------------------------------------------------------------------------
CFStreamCacheReader::CFStreamCacheReader(CFStreamPtr stream, GlobalWorkbookInfoPtr global_info)
: StreamCacheReader(global_info), stream_(stream)
{
}
CFStreamCacheReader::~CFStreamCacheReader()
{
}
// Skip the specified number of unsigned chars without processing
void CFStreamCacheReader::skipNunBytes(const size_t n)
{
if (stream_)
{
stream_->seekFromCurForward(n);
}
}
// Reads the next CFRecord from the CFStream and if its type is not the desired one, caches it for the next call
CFRecordPtr CFStreamCacheReader::getNextRecord(const CFRecordType::TypeId desirable_type, const bool gen_except)
{
@ -132,26 +213,6 @@ CFRecordPtr CFStreamCacheReader::getNextRecord(const CFRecordType::TypeId desira
}
return CFRecordPtr();
}
// Check if the next read record would be of desired type
const bool CFStreamCacheReader::checkNextRecord(const CFRecordType::TypeId desirable_type, const size_t num_records_to_check)
{
readFromStream(num_records_to_check);
// if we would get what was requested
// ANY_TYPE is checked just to make the fake read from stream and get an error if the stream is ended
for(std::list<CFRecordPtr>::const_iterator it = records_cache.begin(), itEnd = records_cache.end(); it != itEnd; ++it)
{
size_t type = (*it)->getTypeId();
if(desirable_type == (*it)->getTypeId() || desirable_type == CFRecordType::ANY_TYPE)
{
return true;
}
}
return false;
}
// Make sure the internal buffer has concrete number of records. Returns number of records read
const size_t CFStreamCacheReader::readFromStream(const size_t num_of_records_min_necessary)
{
@ -170,7 +231,6 @@ const size_t CFStreamCacheReader::readFromStream(const size_t num_of_records_min
return records_cache.size();
}
// Checks whether the next record is Continue and append its data to the real record if so
void CFStreamCacheReader::checkAndAppendContinueData()
{
@ -197,7 +257,6 @@ void CFStreamCacheReader::checkAndAppendContinueData()
}
}
const bool CFStreamCacheReader::isEOF() const
{
if (stream_ == NULL) return true;
@ -205,71 +264,4 @@ const bool CFStreamCacheReader::isEOF() const
return !records_cache.size() && stream_->isEOF();
}
// Skip the specified number of unsigned chars without processing
void CFStreamCacheReader::skipNunBytes(const size_t n)
{
if (stream_)
{
stream_->seekFromCurForward(n);
}
}
// Seek to the next substream (Read all records till EOF then skip EOF)
// Doesn't generate EndOfStreamReached if the stream is the last one
void CFStreamCacheReader::SkipRecord()
{
if (records_cache.begin() != records_cache.end())
{
CFRecordType::TypeString rec_name = records_cache.front()->getTypeString();
if (rec_name.empty())
Log::warning(L"The extracted record has obsoleted or unknown type(0x" + STR::int2hex_wstr(records_cache.front()->getTypeId(), sizeof(CFRecordType::TypeId)) + L")");
else
Log::warning("The record has been skipped (" + rec_name + ")");
records_cache.pop_front();
}
}
const bool CFStreamCacheReader::SeekToEOF()
{
while(readFromStream(1))
{
if(rt_EOF == records_cache.front()->getTypeId())
{
// records_cache.pop_front(); // Skip EOF
break;
}
records_cache.pop_front(); // Skip non-EOF
}
return true;
}
// Extract the next record from the stream leaving it in the cache for future read.
// Always call resetPointerToBegin for the extracted CFRecord after using it
CFRecordPtr CFStreamCacheReader::touchTheNextRecord()
{
if(readFromStream(1))// make sure something is in cache
{
return records_cache.front();
}
return CFRecordPtr();
}
// Check the next record type
const CFRecordType::TypeId CFStreamCacheReader::getNextRecordType()
{
if(isEOF())
{
return rt_NONE;
}
readFromStream(1); // I don't check the result of readFromStream() because it was done implicitly in isEOF()
return records_cache.front()->getTypeId();
}
} // namespace XLS

View File

@ -33,8 +33,8 @@
#include "CFRecordType.h"
#include "BinSmartPointers.h"
#include <Logic/GlobalWorkbookInfo.h>
#include <Logic/Biff_structures/ODRAW/OfficeArtRecordHeader.h>
#include "../Logic/GlobalWorkbookInfo.h"
#include "../Logic/Biff_structures/ODRAW/OfficeArtRecordHeader.h"
namespace XLS
{
@ -46,22 +46,23 @@ namespace XLS
// PIVOTTH = SXTH *ContinueFrt
// ContinueFrt may appear in the stream and may not. So, this class will increase performance much
class CFStreamCacheReader
class StreamCacheReader
{
public:
CFStreamCacheReader(CFStreamPtr stream, const GlobalWorkbookInfoPtr global_info);
~CFStreamCacheReader();
StreamCacheReader(const GlobalWorkbookInfoPtr global_info);
virtual ~StreamCacheReader();
// Reads the next CFRecord from the CFStream and if it's type is not the desired one, caches it for the next call
CFRecordPtr getNextRecord(const CFRecordType::TypeId desirable_type, const bool gen_except = false);
virtual CFRecordPtr getNextRecord(const CFRecordType::TypeId desirable_type, const bool gen_except = false) = 0;
// Check if the next read record would be of desired type
const bool checkNextRecord(const CFRecordType::TypeId desirable_type, const size_t num_records_to_check = 1);
// Checks whether the next record is Continue and append its data to the real record if so
void checkAndAppendContinueData();
virtual void checkAndAppendContinueData() = 0;
const bool isEOF() const;
virtual const bool isEOF() const = 0;
// Skip the specified number of unsigned chars without processing
void skipNunBytes(const size_t n);
virtual void skipNunBytes(const size_t n) = 0;
void SkipRecord();
// Seek to the next substream (Read all records till EOF then skip EOF)
@ -74,15 +75,27 @@ public:
const CFRecordType::TypeId getNextRecordType();
GlobalWorkbookInfoPtr getGlobalWorkbookInfo() { return global_info_; }
private:
// Make sure the internal buffer has concrete number of records. Returns number of records read
const size_t readFromStream(const size_t num_of_records_min_necessary);
private:
CFStreamPtr stream_;
// Make sure the internal buffer has concrete number of records. Returns number of records read
virtual const size_t readFromStream(const size_t num_of_records_min_necessary) = 0;
CFRecordPtrList records_cache;
GlobalWorkbookInfoPtr global_info_;
std::vector<std::string> skippable_records_names;
};
class CFStreamCacheReader : public StreamCacheReader
{
public:
CFStreamCacheReader(CFStreamPtr stream, const GlobalWorkbookInfoPtr global_info);
virtual ~CFStreamCacheReader();
virtual CFRecordPtr getNextRecord(const CFRecordType::TypeId desirable_type, const bool gen_except = false);
virtual void skipNunBytes(const size_t n);
virtual void checkAndAppendContinueData();
virtual const bool isEOF() const;
private:
virtual const size_t readFromStream(const size_t num_of_records_min_necessary);
CFStreamPtr stream_;
};
} // namespace XLS

View File

@ -36,7 +36,7 @@
namespace XLS
{;
class CFStreamCacheReader;
class StreamCacheReader;
// Logical representation of a record in BIFF8
class AnyObject: public BiffRecord

View File

@ -45,10 +45,12 @@ namespace XLS
class CFStream;
class BinProcessor;
class CFStreamCacheReader;
class StreamCacheReader;
typedef boost::shared_ptr<StreamCacheReader> StreamCacheReaderPtr;
class BaseObject;
typedef boost::shared_ptr<BaseObject> BaseObjectPtr;
typedef boost::shared_ptr<BaseObject> BaseObjectPtr;
class BaseObject
{
@ -58,7 +60,7 @@ public:
virtual boost::shared_ptr<BaseObject> clone() = 0;
virtual const bool read(CFStreamCacheReader& reader, BaseObject* parent, const bool mandatory) = 0; // Read self and children
virtual const bool read(StreamCacheReaderPtr reader, BaseObject* parent, const bool mandatory) = 0; // Read self and children
virtual const std::string & getClassName() const = 0; // Must be overridden in every deriver. The return value must be a reference to a static variable inside the getter

View File

@ -51,7 +51,7 @@ public:
BaseObjectPtr clone() {return BaseObjectPtr(new BaseObjectDocument(*this));}
virtual const bool read(CFStreamCacheReader& reader, BaseObject* parent, const bool mandatory){return false;}
virtual const bool read(StreamCacheReader& reader, BaseObject* parent, const bool mandatory){return false;}
};
typedef boost::shared_ptr<BaseObjectDocument> BaseObjectDocumentPtr;

View File

@ -37,7 +37,7 @@
namespace XLS
{
class CFStreamCacheReader;
class StreamCacheReader;
// Logical representation of BOF record in BIFF8
class BOF: public BiffRecord

View File

@ -31,7 +31,7 @@
*/
#include "BiffRecord.h"
#include <Binary/CFStream.h>
#include "Binary/CFStream.h"
#include "Binary/CFStreamCacheReader.h"
@ -48,12 +48,15 @@ BiffRecord::~BiffRecord()
}
const bool BiffRecord::read(CFStreamCacheReader& reader, BaseObject* parent, const bool is_mandatory)
const bool BiffRecord::read(StreamCacheReaderPtr reader, BaseObject* parent, const bool is_mandatory)
{
parent_ = parent;
if (!reader)
return false;
// Find and read the required record
CFRecordPtr record = reader.getNextRecord(getTypeId(), is_mandatory);
CFRecordPtr record = reader->getNextRecord(getTypeId(), is_mandatory);
if(!record)
{
return false; // Required record hasn't been found
@ -82,7 +85,7 @@ const bool BiffRecord::read(CFStreamCacheReader& reader, BaseObject* parent, con
return true; // Record reading OK
}
void BiffRecord::readFollowingContinue(CFStreamCacheReader& reader)
void BiffRecord::readFollowingContinue(StreamCacheReaderPtr reader)
{
}

View File

@ -46,7 +46,7 @@ public:
BiffRecord();
~BiffRecord();
virtual const bool read(CFStreamCacheReader& reader, BaseObject* parent, const bool is_mandatory); // Read self and children
virtual const bool read(StreamCacheReaderPtr reader, BaseObject* parent, const bool is_mandatory); // Read self and children
virtual void readFields(CFRecord& record) = 0;
@ -55,7 +55,7 @@ public:
static const ElementType type = typeBiffRecord;
virtual ElementType get_type() { return type; }
//-----------------------------
virtual void readFollowingContinue(CFStreamCacheReader& reader);
virtual void readFollowingContinue(StreamCacheReaderPtr reader);
virtual const bool storeRecordAndDecideProceeding(CFRecordPtr record); // This function is overridden in BiffRecordSplit
protected:

View File

@ -58,13 +58,16 @@ BiffRecordContinued::~BiffRecordContinued()
// Read all the Continue records that follow the record
void BiffRecordContinued::readFollowingContinue(CFStreamCacheReader& reader)
void BiffRecordContinued::readFollowingContinue(StreamCacheReaderPtr reader)
{
if (!reader)
return;
CFRecordType::TypeId type;
while(CFRecordType::isContinue(type = reader.getNextRecordType()))
while(CFRecordType::isContinue(type = reader->getNextRecordType()))
{
CFRecordPtr record = reader.getNextRecord(rt_ANY_TYPE, false);
CFRecordPtr record = reader->getNextRecord(rt_ANY_TYPE, false);
if(!record)
{
return;

View File

@ -48,7 +48,7 @@ protected:
ContinuesMap continue_records; // All records must be removed from the list that means they are processed
//-----------------------------
virtual void readFollowingContinue(CFStreamCacheReader& reader);
virtual void readFollowingContinue(StreamCacheReaderPtr reader);
};

View File

@ -61,7 +61,7 @@ void Compat12::readFields(CFRecord& record)
_UINT32 flag = 0;
record >> flag;
fNoCompatChk = (bool)flag;
fNoCompatChk = (flag != 0);
}
} // namespace XLS

View File

@ -42,7 +42,7 @@ static std::wstring replace_zero (const std::wstring &str, const std::wstring &d
if (str.empty()) return L"";
std::wstring out;
int pos = 0;
size_t pos = 0;
while(true)
{
if (pos >= str.size()) break;

View File

@ -39,7 +39,7 @@
namespace XLS
{
class CFStreamCacheReader;
class StreamCacheReader;
class FilePass: public BiffRecord

View File

@ -55,7 +55,7 @@ void ForceFullCalculation::readFields(CFRecord& record)
_UINT32 temp;
record >> frtHeader >> temp;
fNoDeps = temp;
fNoDeps = (temp != 0);
}
} // namespace XLS

View File

@ -36,7 +36,7 @@
namespace XLS
{
class CFStreamCacheReader;
class StreamCacheReader;
// Logical representation of InterfaceHdr record in BIFF8
class InterfaceHdr: public BiffRecord

View File

@ -36,7 +36,7 @@
namespace XLS
{
class CFStreamCacheReader;
class StreamCacheReader;
// Logical representation of Mms record in BIFF8

View File

@ -36,7 +36,7 @@
namespace XLS
{
class CFStreamCacheReader;
class StreamCacheReader;
// Logical representation of Template record in BIFF8

View File

@ -36,7 +36,7 @@
namespace XLS
{
class CFStreamCacheReader;
class StreamCacheReader;
// Logical representation of WriteProtect record in BIFF8

View File

@ -35,7 +35,7 @@
namespace XLS
{
class CFStreamCacheReader;
class StreamCacheReader;
// Logical representation of INTERFACE union of records
// _T suffix is to avoid confusing with one of standard defines

View File

@ -31,9 +31,9 @@
*/
#include "BinProcessor.h"
#include <Binary/CFStream.h>
#include <Binary/CFStreamCacheReader.h>
#include <Logic/Biff_structures/BiffString.h>
#include "../Binary/CFStream.h"
#include "../Binary/CFStreamCacheReader.h"
#include "../Logic/Biff_structures/BiffString.h"
namespace XLS
@ -83,14 +83,14 @@ const int BinProcessor::repeated(BaseObject& object, const int fromN, const int
// =========================== Reader ======================================
BinReaderProcessor::BinReaderProcessor(CFStreamCacheReader& reader, BaseObject* parent, const bool is_mandatory)
BinReaderProcessor::BinReaderProcessor(StreamCacheReaderPtr reader, BaseObject* parent, const bool is_mandatory)
: reader_(reader),
BinProcessor(parent, reader.getGlobalWorkbookInfo()),
BinProcessor(parent, reader ? reader->getGlobalWorkbookInfo() : NULL),
is_mandatory_(is_mandatory)
{
}
//BinReaderProcessor::BinReaderProcessor(CFStreamCacheReader& reader, const bool is_mandatory)
//BinReaderProcessor::BinReaderProcessor(StreamCacheReader& reader, const bool is_mandatory)
//: reader_(reader),
// BinProcessor(reader.getGlobalWorkbookInfo()),
// is_mandatory_(is_mandatory)
@ -130,6 +130,9 @@ const bool BinReaderProcessor::mandatory(BaseObject& object)
// object_copy is necessary in case we haven't found the desired record and have to put it to the queue
const bool BinReaderProcessor::readChild(BaseObject& object, const bool is_mandatory)
{
if (!reader_)
return false;
bool ret_val = false;
try
{
@ -170,7 +173,10 @@ const bool BinReaderProcessor::readChild(BaseObject& object, const bool is_manda
// Check if the next read record would be of desired type
const bool BinReaderProcessor::checkNextRecord(const CFRecordType::TypeId desirable_type, const size_t num_records_to_check)
{
return reader_.checkNextRecord(desirable_type, num_records_to_check);
if (!reader_)
return false;
return reader_->checkNextRecord(desirable_type, num_records_to_check);
}
@ -178,7 +184,10 @@ const bool BinReaderProcessor::checkNextRecord(const CFRecordType::TypeId desira
// In the case of stream end returns false
const bool BinReaderProcessor::getNextSubstreamType(unsigned short& type)
{
CFRecordPtr record = reader_.touchTheNextRecord();
if (!reader_)
return false;
CFRecordPtr record = reader_->touchTheNextRecord();
if(!record)
{
return false; // EOF
@ -189,7 +198,7 @@ const bool BinReaderProcessor::getNextSubstreamType(unsigned short& type)
while(rt_Blank == record->getTypeId())
{
SkipRecord();
record = reader_.touchTheNextRecord();
record = reader_->touchTheNextRecord();
if(!record)
{
return false; // EOF
@ -211,7 +220,10 @@ const bool BinReaderProcessor::getNextSubstreamType(unsigned short& type)
// Check the next record type
const CFRecordType::TypeId BinReaderProcessor::getNextRecordType()
{
CFRecordPtr record = reader_.touchTheNextRecord();
if (!reader_)
return rt_NONE;
CFRecordPtr record = reader_->touchTheNextRecord();
if(!record)
{
return rt_NONE; // EOF
@ -220,11 +232,13 @@ const CFRecordType::TypeId BinReaderProcessor::getNextRecordType()
}
void BinReaderProcessor::SeekToEOF()
{
reader_.SeekToEOF();
if (reader_)
reader_->SeekToEOF();
}
void BinReaderProcessor::SkipRecord()
{
reader_.SkipRecord();
if (reader_)
reader_->SkipRecord();
}

View File

@ -96,7 +96,7 @@ protected:
class BinReaderProcessor : public BinProcessor
{
public:
BinReaderProcessor(CFStreamCacheReader& reader, BaseObject* parent, const bool is_mandatory);
BinReaderProcessor(StreamCacheReaderPtr reader, BaseObject* parent, const bool is_mandatory);
virtual const bool optional (BaseObject& object);
virtual const bool mandatory (BaseObject& object);
@ -112,7 +112,7 @@ public:
private:
const bool readChild(BaseObject& object, const bool is_mandatory);
CFStreamCacheReader& reader_;
StreamCacheReaderPtr reader_;
BaseObjectPtrList wanted_objects;
bool is_mandatory_;
};

View File

@ -47,7 +47,7 @@ CompositeObject::~CompositeObject()
}
const bool CompositeObject::read(CFStreamCacheReader& reader, BaseObject* parent, const bool is_mandatory)
const bool CompositeObject::read(StreamCacheReaderPtr reader, BaseObject* parent, const bool is_mandatory)
{
BinReaderProcessor reader_proc(reader, this, is_mandatory);
if(loadContentRead(reader_proc))
@ -69,7 +69,7 @@ const bool CompositeObject::loadContentRead(BinReaderProcessor& proc)
const bool ABNFParenthesis::read(CFStreamCacheReader& reader, BaseObject* parent, const bool is_mandatory)
const bool ABNFParenthesis::read(StreamCacheReaderPtr reader, BaseObject* parent, const bool is_mandatory)
{
BinReaderProcessor reader_proc(reader, parent, is_mandatory);
bool res = loadContentRead(reader_proc);

View File

@ -37,22 +37,15 @@
namespace XLS
{;
class CFStreamCacheReader;
class StreamCacheReader;
// Logical representation of composite objects
//
// Another new function is to buffer objects, that had to be read but was absent in the bin stream.
// The buffered records shall be checked for existence later.
// This feature is specially for files saved in OpenOffice Calc those don't conform to the Microsoft specification
// Call them "wanted objects"
//
class CompositeObject : public BaseObject
{
public:
CompositeObject();
~CompositeObject();
virtual const bool read (CFStreamCacheReader& reader, BaseObject* parent, const bool mandatory); // Read self and children
virtual const bool read (StreamCacheReaderPtr reader, BaseObject* parent, const bool mandatory); // Read self and children
virtual const bool loadContent (BinProcessor& proc) = 0;
virtual const bool loadContentRead (BinReaderProcessor& proc);
@ -67,7 +60,7 @@ class ABNFParenthesis : public CompositeObject
public:
ABNFParenthesis(){};
virtual const bool read(CFStreamCacheReader& reader, BaseObject* parent, const bool is_mandatory);
virtual const bool read(StreamCacheReaderPtr reader, BaseObject* parent, const bool is_mandatory);
static const ElementType type = typeABNFParenthesis;

View File

@ -36,7 +36,7 @@
namespace XLS
{;
class CFStreamCacheReader;
class StreamCacheReader;
class BOF;
class GlobalsSubstream;

View File

@ -174,7 +174,7 @@ XlsConverter::XlsConverter(const std::wstring & xlsFileName, const std::wstring
xls_global_info->password = password;
xls_global_info->tempDirectory = tempPath;
XLS::CFStreamCacheReader stream_reader(xls_file->getWorkbookStream(), xls_global_info);
XLS::StreamCacheReaderPtr stream_reader(new XLS::CFStreamCacheReader(xls_file->getWorkbookStream(), xls_global_info));
xls_document = boost::shared_ptr<XLS::WorkbookStreamObject>(new XLS::WorkbookStreamObject(workbook_code_page));
@ -199,7 +199,7 @@ XlsConverter::XlsConverter(const std::wstring & xlsFileName, const std::wstring
if (!pivot_cache_stream) continue;
//if (pivot_cache_stream->getStreamSize() < 1) continue;
XLS::CFStreamCacheReader pivot_cache_reader(pivot_cache_stream, xls_global_info);
XLS::StreamCacheReaderPtr pivot_cache_reader(new XLS::CFStreamCacheReader(pivot_cache_stream, xls_global_info));
XLS::BaseObjectPtr pivot_cache = boost::shared_ptr<XLS::PIVOTCACHE>(new XLS::PIVOTCACHE());