Commit 1e47fa55 by Maarten L. Hekkelman

indexed CCD file

parent 1ae3cf7b
......@@ -96,6 +96,10 @@ inline bool isUnquotedString(const char* s)
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)
class SacParser
......@@ -142,7 +146,10 @@ class SacParser
CIFToken getNextToken();
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 parseGlobal();
......@@ -199,7 +206,7 @@ class SacParser
class Parser : public SacParser
{
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 produceCategory(const std::string& name);
......
......@@ -3073,7 +3073,7 @@ void File::load(std::istream& is, const std::string& datablock)
setValidator(nullptr);
Parser p(is, *this);
p.parseFile(datablock);
p.parseSingleDatablock(datablock);
if (saved != nullptr)
{
......
......@@ -523,7 +523,104 @@ SacParser::CIFToken SacParser::getNextToken()
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
auto &sb = *mData.rdbuf();
......@@ -607,6 +704,25 @@ bool SacParser::parseFile(const std::string& datablock)
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()
{
while (mLookahead != eCIFTokenEOF)
......@@ -728,8 +844,8 @@ void SacParser::parseSaveFrame()
// --------------------------------------------------------------------
Parser::Parser(std::istream& is, File& f)
: SacParser(is), mFile(f), mDataBlock(nullptr)
Parser::Parser(std::istream& is, File& f, bool init)
: SacParser(is, init), mFile(f), mDataBlock(nullptr)
{
}
......
......@@ -42,6 +42,7 @@
#include "cif++/CifUtils.hpp"
#include "cif++/Compound.hpp"
#include "cif++/Point.hpp"
#include "cif++/CifParser.hpp"
namespace ba = boost::algorithm;
namespace fs = std::filesystem;
......@@ -455,6 +456,8 @@ class CCDCompoundFactoryImpl : public CompoundFactoryImpl
CCDCompoundFactoryImpl() {}
Compound *create(std::string id) override;
cif::DatablockIndex mIndex;
};
Compound *CCDCompoundFactoryImpl::create(std::string id)
......@@ -467,14 +470,34 @@ Compound *CCDCompoundFactoryImpl::create(std::string id)
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.");
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)
{
std::cout << "Loading component " << id << "...";
std::cout.flush();
}
cif::File file;
file.load(*ccd, id);
cif::Parser parser(*ccd, file, false);
parser.parseSingleDatablock(id, mIndex);
if (cif::VERBOSE)
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