Commit 1e47fa55 by Maarten L. Hekkelman

indexed CCD file

parent 1ae3cf7b
...@@ -96,6 +96,10 @@ inline bool isUnquotedString(const char* s) ...@@ -96,6 +96,10 @@ inline bool isUnquotedString(const char* s)
std::tuple<std::string,std::string> splitTagName(const std::string& tag); std::tuple<std::string,std::string> splitTagName(const std::string& tag);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
using DatablockIndex = std::map<std::string,std::size_t>;
// --------------------------------------------------------------------
// sac Parser, analogous to SAX Parser (simple api for xml) // sac Parser, analogous to SAX Parser (simple api for xml)
class SacParser class SacParser
...@@ -142,7 +146,10 @@ class SacParser ...@@ -142,7 +146,10 @@ class SacParser
CIFToken getNextToken(); CIFToken getNextToken();
void match(CIFToken token); void match(CIFToken token);
bool parseFile(const std::string& datablock); bool parseSingleDatablock(const std::string& datablock);
DatablockIndex indexDatablocks();
bool parseSingleDatablock(const std::string& datablock, const DatablockIndex &index);
void parseFile(); void parseFile();
void parseGlobal(); void parseGlobal();
...@@ -199,7 +206,7 @@ class SacParser ...@@ -199,7 +206,7 @@ class SacParser
class Parser : public SacParser class Parser : public SacParser
{ {
public: public:
Parser(std::istream& is, File& f); Parser(std::istream& is, File& f, bool init = true);
virtual void produceDatablock(const std::string& name); virtual void produceDatablock(const std::string& name);
virtual void produceCategory(const std::string& name); virtual void produceCategory(const std::string& name);
......
...@@ -3073,7 +3073,7 @@ void File::load(std::istream& is, const std::string& datablock) ...@@ -3073,7 +3073,7 @@ void File::load(std::istream& is, const std::string& datablock)
setValidator(nullptr); setValidator(nullptr);
Parser p(is, *this); Parser p(is, *this);
p.parseFile(datablock); p.parseSingleDatablock(datablock);
if (saved != nullptr) if (saved != nullptr)
{ {
......
...@@ -523,7 +523,104 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -523,7 +523,104 @@ SacParser::CIFToken SacParser::getNextToken()
return result; return result;
} }
bool SacParser::parseFile(const std::string& datablock) DatablockIndex SacParser::indexDatablocks()
{
DatablockIndex index;
// first locate the start, as fast as we can
auto &sb = *mData.rdbuf();
enum {
start, comment, string, string_quote, qstring, data, data_name
} state = start;
int quote = 0;
bool bol = true;
const char dblk[] = "data_";
std::string::size_type si = 0;
std::string datablock;
bool found = false;
while (sb.in_avail() > 0 and not found)
{
int ch = sb.sbumpc();
switch (state)
{
case start:
switch (ch)
{
case '#': state = comment; break;
case 'd':
case 'D':
state = data;
si = 1;
break;
case '\'':
case '"':
state = string;
quote = ch;
break;
case ';':
if (bol)
state = qstring;
break;
}
break;
case comment:
if (ch == '\n')
state = start;
break;
case string:
if (ch == quote)
state = string_quote;
break;
case string_quote:
if (std::isspace(ch))
state = start;
else
state = string;
break;
case qstring:
if (ch == ';' and bol)
state = start;
break;
case data:
if (dblk[si] == 0 and isNonBlank(ch))
{
datablock = { static_cast<char>(ch) };
state = data_name;
}
else if (dblk[si++] != ch)
state = start;
break;
case data_name:
if (isNonBlank(ch))
datablock.insert(datablock.end(), ch);
else if (isspace(ch))
{
if (not datablock.empty())
index[datablock] = mData.tellg();
state = start;
}
else
state = start;
break;
}
bol = (ch == '\n');
}
return index;
}
bool SacParser::parseSingleDatablock(const std::string& datablock)
{ {
// first locate the start, as fast as we can // first locate the start, as fast as we can
auto &sb = *mData.rdbuf(); auto &sb = *mData.rdbuf();
...@@ -607,6 +704,25 @@ bool SacParser::parseFile(const std::string& datablock) ...@@ -607,6 +704,25 @@ bool SacParser::parseFile(const std::string& datablock)
return found; return found;
} }
bool SacParser::parseSingleDatablock(const std::string& datablock, const DatablockIndex &index)
{
bool result = false;
auto i = index.find(datablock);
if (i != index.end())
{
mData.seekg(i->second);
produceDatablock(datablock);
mLookahead = getNextToken();
parseDataBlock();
result = true;
}
return result;
}
void SacParser::parseFile() void SacParser::parseFile()
{ {
while (mLookahead != eCIFTokenEOF) while (mLookahead != eCIFTokenEOF)
...@@ -728,8 +844,8 @@ void SacParser::parseSaveFrame() ...@@ -728,8 +844,8 @@ void SacParser::parseSaveFrame()
// -------------------------------------------------------------------- // --------------------------------------------------------------------
Parser::Parser(std::istream& is, File& f) Parser::Parser(std::istream& is, File& f, bool init)
: SacParser(is), mFile(f), mDataBlock(nullptr) : SacParser(is, init), mFile(f), mDataBlock(nullptr)
{ {
} }
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "cif++/CifUtils.hpp" #include "cif++/CifUtils.hpp"
#include "cif++/Compound.hpp" #include "cif++/Compound.hpp"
#include "cif++/Point.hpp" #include "cif++/Point.hpp"
#include "cif++/CifParser.hpp"
namespace ba = boost::algorithm; namespace ba = boost::algorithm;
namespace fs = std::filesystem; namespace fs = std::filesystem;
...@@ -455,6 +456,8 @@ class CCDCompoundFactoryImpl : public CompoundFactoryImpl ...@@ -455,6 +456,8 @@ class CCDCompoundFactoryImpl : public CompoundFactoryImpl
CCDCompoundFactoryImpl() {} CCDCompoundFactoryImpl() {}
Compound *create(std::string id) override; Compound *create(std::string id) override;
cif::DatablockIndex mIndex;
}; };
Compound *CCDCompoundFactoryImpl::create(std::string id) Compound *CCDCompoundFactoryImpl::create(std::string id)
...@@ -467,14 +470,34 @@ Compound *CCDCompoundFactoryImpl::create(std::string id) ...@@ -467,14 +470,34 @@ Compound *CCDCompoundFactoryImpl::create(std::string id)
if (not ccd) if (not ccd)
throw std::runtime_error("Could not locate the CCD components.cif file, please make sure the software is installed properly and/or use the update-dictionary-script to fetch the data."); throw std::runtime_error("Could not locate the CCD components.cif file, please make sure the software is installed properly and/or use the update-dictionary-script to fetch the data.");
cif::File file;
if (mIndex.empty())
{
if (cif::VERBOSE)
{
std::cout << "Creating component index " << "...";
std::cout.flush();
}
cif::Parser parser(*ccd, file, false);
mIndex = parser.indexDatablocks();
if (cif::VERBOSE)
std::cout << " done" << std::endl;
// reload the resource, perhaps this should be improved...
ccd = cif::loadResource("components.cif");
}
if (cif::VERBOSE) if (cif::VERBOSE)
{ {
std::cout << "Loading component " << id << "..."; std::cout << "Loading component " << id << "...";
std::cout.flush(); std::cout.flush();
} }
cif::File file; cif::Parser parser(*ccd, file, false);
file.load(*ccd, id); parser.parseSingleDatablock(id, mIndex);
if (cif::VERBOSE) if (cif::VERBOSE)
std::cout << " done" << std::endl; std::cout << " done" << std::endl;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment