Commit e0777e74 by Maarten L. Hekkelman

minor updates

parent cf465134
...@@ -686,7 +686,7 @@ class Row ...@@ -686,7 +686,7 @@ class Row
} }
template<typename... Ts, size_t N> template<typename... Ts, size_t N>
std::tuple<Ts...> get(char const * const (&columns)[N]) std::tuple<Ts...> get(char const * const (&columns)[N]) const
{ {
static_assert(sizeof...(Ts) == N, "Number of columns should be equal to number of types to return"); static_assert(sizeof...(Ts) == N, "Number of columns should be equal to number of types to return");
...@@ -1087,7 +1087,7 @@ template<typename T> ...@@ -1087,7 +1087,7 @@ template<typename T>
Condition operator==(const Key& key, const T& v) Condition operator==(const Key& key, const T& v)
{ {
std::ostringstream s; std::ostringstream s;
s << "== " << v; s << " == " << v;
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase) return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return r[tag].template compare<T>(v, icase) == 0; }, s.str())); { return r[tag].template compare<T>(v, icase) == 0; }, s.str()));
...@@ -1123,7 +1123,7 @@ template<typename T> ...@@ -1123,7 +1123,7 @@ template<typename T>
Condition operator>(const Key& key, const T& v) Condition operator>(const Key& key, const T& v)
{ {
std::ostringstream s; std::ostringstream s;
s << ">" << v; s << " > " << v;
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase) return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return r[tag].template compare<T>(v, icase) > 0; }, s.str())); { return r[tag].template compare<T>(v, icase) > 0; }, s.str()));
...@@ -1133,7 +1133,7 @@ template<typename T> ...@@ -1133,7 +1133,7 @@ template<typename T>
Condition operator>=(const Key& key, const T& v) Condition operator>=(const Key& key, const T& v)
{ {
std::ostringstream s; std::ostringstream s;
s << ">=" << v; s << " >= " << v;
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase) return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return r[tag].template compare<T>(v, icase) >= 0; }, s.str())); { return r[tag].template compare<T>(v, icase) >= 0; }, s.str()));
...@@ -1143,7 +1143,7 @@ template<typename T> ...@@ -1143,7 +1143,7 @@ template<typename T>
Condition operator<(const Key& key, const T& v) Condition operator<(const Key& key, const T& v)
{ {
std::ostringstream s; std::ostringstream s;
s << "<" << v; s << " < " << v;
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase) return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return r[tag].template compare<T>(v, icase) < 0; }, s.str())); { return r[tag].template compare<T>(v, icase) < 0; }, s.str()));
...@@ -1153,7 +1153,7 @@ template<typename T> ...@@ -1153,7 +1153,7 @@ template<typename T>
Condition operator<=(const Key& key, const T& v) Condition operator<=(const Key& key, const T& v)
{ {
std::ostringstream s; std::ostringstream s;
s << "<=" << v; s << " <= " << v;
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase) return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return r[tag].template compare<T>(v, icase) <= 0; }, s.str())); { return r[tag].template compare<T>(v, icase) <= 0; }, s.str()));
...@@ -1824,6 +1824,12 @@ class Category ...@@ -1824,6 +1824,12 @@ class Category
RowSet getChildren(Row r, Category& childCat); RowSet getChildren(Row r, Category& childCat);
RowSet getChildren(Row r, const char* childCat); RowSet getChildren(Row r, const char* childCat);
RowSet getParents(Row r, Category& parentCat);
RowSet getParents(Row r, const char* parentCat);
RowSet getLinked(Row r, Category& cat);
RowSet getLinked(Row r, const char* cat);
bool isValid(); bool isValid();
void validateLinks() const; void validateLinks() const;
...@@ -1904,7 +1910,13 @@ class File ...@@ -1904,7 +1910,13 @@ class File
bool isValid(); bool isValid();
void validateLinks() const; void validateLinks() const;
Datablock& firstDatablock() { return *mHead; } Datablock& firstDatablock()
{
if (mHead == nullptr)
throw std::runtime_error("No datablocks in file");
return *mHead;
}
void append(Datablock* e); void append(Datablock* e);
Datablock* get(const std::string& name) const; Datablock* get(const std::string& name) const;
......
...@@ -340,6 +340,16 @@ double CosinusAngle(const PointF<F>& p1, const PointF<F>& p2, const PointF<F>& p ...@@ -340,6 +340,16 @@ double CosinusAngle(const PointF<F>& p1, const PointF<F>& p2, const PointF<F>& p
return result; return result;
} }
template<typename F>
auto DistancePointToLine(const PointF<F> &l1, const PointF<F> &l2, const PointF<F> &p)
{
auto line = l2 - l1;
auto p_to_l1 = p - l1;
auto p_to_l2 = p - l2;
auto cross = CrossProduct(p_to_l1, p_to_l2);
return cross.length() / line.length();
}
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// For e.g. simulated annealing, returns a new point that is moved in // For e.g. simulated annealing, returns a new point that is moved in
// a random direction with a distance randomly chosen from a normal // a random direction with a distance randomly chosen from a normal
......
...@@ -1904,6 +1904,55 @@ RowSet Category::getChildren(Row r, Category& childCat) ...@@ -1904,6 +1904,55 @@ RowSet Category::getChildren(Row r, Category& childCat)
return result; return result;
} }
RowSet Category::getParents(Row r, const char* parentCat)
{
return getParents(r, mDb[parentCat]);
}
RowSet Category::getParents(Row r, Category& parentCat)
{
assert(mValidator != nullptr);
assert(mCatValidator != nullptr);
RowSet result(parentCat);
for (auto& link: mValidator->getLinksForChild(mName))
{
if (link->mParentCategory != parentCat.mName)
continue;
Condition cond;
for (size_t ix = 0; ix < link->mChildKeys.size(); ++ix)
{
const char* value = r[link->mChildKeys[ix]].c_str();
cond = std::move(cond) && (Key(link->mParentKeys[ix]) == value);
}
auto parents = parentCat.find(std::move(cond));
result.insert(result.end(), parents.begin(), parents.end());
}
// remove duplicates
result.make_unique();
return result;
}
RowSet Category::getLinked(Row r, const char* cat)
{
return getLinked(r, mDb[cat]);
}
RowSet Category::getLinked(Row r, Category& cat)
{
RowSet result = getChildren(r, cat);
if (result.empty())
result = getParents(r, cat);
return result;
}
bool Category::isValid() bool Category::isValid()
{ {
bool result = true; bool result = true;
...@@ -2582,7 +2631,7 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked) ...@@ -2582,7 +2631,7 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
} }
} }
if (cif::VERBOSE >= 2) if (cif::VERBOSE > 2)
{ {
std::cerr << "Parent: " << linked->mParentCategory << " Child: " << linked->mChildCategory << std::endl std::cerr << "Parent: " << linked->mParentCategory << " Child: " << linked->mChildCategory << std::endl
<< cond << std::endl; << cond << std::endl;
......
...@@ -28,25 +28,25 @@ ...@@ -28,25 +28,25 @@
#include "Config.hpp" #include "Config.hpp"
#endif #endif
#include <tuple>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <atomic> #include <atomic>
#include <mutex> #include <chrono>
#include <thread> #include <cmath>
#include <cstdio>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <iomanip>
#include <iostream>
#include <map> #include <map>
#include <chrono> #include <mutex>
#include <regex> #include <regex>
#include <iomanip> #include <thread>
#include <tuple>
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define TERM_WIDTH 80 #define TERM_WIDTH 80
#else #else
#include <termios.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <termios.h>
#endif #endif
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
...@@ -74,13 +74,13 @@ std::string get_version_nr() ...@@ -74,13 +74,13 @@ std::string get_version_nr()
#if __has_include("revision.hpp") #if __has_include("revision.hpp")
#include "revision.hpp" #include "revision.hpp"
#else #else
const char* kRevision = ""; const char *kRevision = "";
#endif #endif
struct membuf : public std::streambuf struct membuf : public std::streambuf
{ {
membuf(char* data, size_t length) { this->setg(data, data, data + length); } membuf(char *data, size_t length) { this->setg(data, data, data + length); }
} buffer(const_cast<char*>(kRevision), sizeof(kRevision)); } buffer(const_cast<char *>(kRevision), sizeof(kRevision));
std::istream is(&buffer); std::istream is(&buffer);
...@@ -110,28 +110,27 @@ const char* kRevision = ""; ...@@ -110,28 +110,27 @@ const char* kRevision = "";
// This really makes a difference, having our own tolower routines // This really makes a difference, having our own tolower routines
const uint8_t kCharToLowerMap[256] = const uint8_t kCharToLowerMap[256] =
{ {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff};
};
// -------------------------------------------------------------------- // --------------------------------------------------------------------
bool iequals(const std::string& a, const std::string& b) bool iequals(const std::string &a, const std::string &b)
{ {
bool result = a.length() == b.length(); bool result = a.length() == b.length();
for (auto ai = a.begin(), bi = b.begin(); result and ai != a.end() and bi != b.end(); ++ai, ++bi) for (auto ai = a.begin(), bi = b.begin(); result and ai != a.end() and bi != b.end(); ++ai, ++bi)
...@@ -139,7 +138,7 @@ bool iequals(const std::string& a, const std::string& b) ...@@ -139,7 +138,7 @@ bool iequals(const std::string& a, const std::string& b)
return result; return result;
} }
bool iequals(const char* a, const char* b) bool iequals(const char *a, const char *b)
{ {
bool result = true; bool result = true;
for (; result and *a and *b; ++a, ++b) for (; result and *a and *b; ++a, ++b)
...@@ -148,11 +147,11 @@ bool iequals(const char* a, const char* b) ...@@ -148,11 +147,11 @@ bool iequals(const char* a, const char* b)
return result and *a == *b; return result and *a == *b;
} }
int icompare(const std::string& a, const std::string& b) int icompare(const std::string &a, const std::string &b)
{ {
int d = 0; int d = 0;
auto ai = a.begin(), bi = b.begin(); auto ai = a.begin(), bi = b.begin();
for (; d == 0 and ai != a.end() and bi != b.end(); ++ai, ++bi) for (; d == 0 and ai != a.end() and bi != b.end(); ++ai, ++bi)
d = tolower(*ai) - tolower(*bi); d = tolower(*ai) - tolower(*bi);
...@@ -163,14 +162,14 @@ int icompare(const std::string& a, const std::string& b) ...@@ -163,14 +162,14 @@ int icompare(const std::string& a, const std::string& b)
else if (bi != b.end()) else if (bi != b.end())
d = -1; d = -1;
} }
return d; return d;
} }
int icompare(const char* a, const char* b) int icompare(const char *a, const char *b)
{ {
int d = 0; int d = 0;
for (; d == 0 and *a != 0 and *b != 0; ++a, ++b) for (; d == 0 and *a != 0 and *b != 0; ++a, ++b)
d = tolower(*a) - tolower(*b); d = tolower(*a) - tolower(*b);
...@@ -181,27 +180,27 @@ int icompare(const char* a, const char* b) ...@@ -181,27 +180,27 @@ int icompare(const char* a, const char* b)
else if (*b != 0) else if (*b != 0)
d = -1; d = -1;
} }
return d; return d;
} }
void toLower(std::string& s) void toLower(std::string &s)
{ {
for (auto& c: s) for (auto &c : s)
c = tolower(c); c = tolower(c);
} }
std::string toLowerCopy(const std::string& s) std::string toLowerCopy(const std::string &s)
{ {
std::string result(s); std::string result(s);
for (auto& c: result) for (auto &c : result)
c = tolower(c); c = tolower(c);
return result; return result;
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
std::tuple<std::string,std::string> splitTagName(const std::string& tag) std::tuple<std::string, std::string> splitTagName(const std::string &tag)
{ {
if (tag.empty()) if (tag.empty())
throw std::runtime_error("empty tag"); throw std::runtime_error("empty tag");
...@@ -211,10 +210,9 @@ std::tuple<std::string,std::string> splitTagName(const std::string& tag) ...@@ -211,10 +210,9 @@ std::tuple<std::string,std::string> splitTagName(const std::string& tag)
auto s = tag.find('.'); auto s = tag.find('.');
if (s == std::string::npos) if (s == std::string::npos)
throw std::runtime_error("tag does not contain dot"); throw std::runtime_error("tag does not contain dot");
return std::tuple<std::string,std::string>{ return std::tuple<std::string, std::string>{
tag.substr(1, s - 1), tag.substr(s + 1) tag.substr(1, s - 1), tag.substr(s + 1)};
}; }
}
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Simplified line breaking code taken from a decent text editor. // Simplified line breaking code taken from a decent text editor.
...@@ -263,85 +261,84 @@ enum LineBreakClass ...@@ -263,85 +261,84 @@ enum LineBreakClass
}; };
const LineBreakClass kASCII_LBTable[128] = const LineBreakClass kASCII_LBTable[128] =
{ {
kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark,
kLBC_CombiningMark, kLBC_BreakAfter, kLBC_LineFeed, kLBC_MandatoryBreak, kLBC_MandatoryBreak, kLBC_CarriageReturn, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_BreakAfter, kLBC_LineFeed, kLBC_MandatoryBreak, kLBC_MandatoryBreak, kLBC_CarriageReturn, kLBC_CombiningMark, kLBC_CombiningMark,
kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark,
kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark,
kLBC_Space, kLBC_Exlamation, kLBC_Quotation, kLBC_Alphabetic, kLBC_PrefixNumeric, kLBC_PostfixNumeric, kLBC_Alphabetic, kLBC_Quotation, kLBC_Space, kLBC_Exlamation, kLBC_Quotation, kLBC_Alphabetic, kLBC_PrefixNumeric, kLBC_PostfixNumeric, kLBC_Alphabetic, kLBC_Quotation,
kLBC_OpenPunctuation, kLBC_CloseParenthesis, kLBC_Alphabetic, kLBC_PrefixNumeric, kLBC_OpenPunctuation, kLBC_CloseParenthesis, kLBC_Alphabetic, kLBC_PrefixNumeric,
// comma treated differently here, it is not a numeric separator in PDB // comma treated differently here, it is not a numeric separator in PDB
kLBC_SymbolAllowingBreakAfter/* kLBC_InfixNumericSeparator */, kLBC_SymbolAllowingBreakAfter /* kLBC_InfixNumericSeparator */,
kLBC_Hyphen, kLBC_InfixNumericSeparator, kLBC_SymbolAllowingBreakAfter, kLBC_Hyphen, kLBC_InfixNumericSeparator, kLBC_SymbolAllowingBreakAfter,
kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric,
kLBC_Numeric, kLBC_Numeric, kLBC_InfixNumericSeparator, kLBC_InfixNumericSeparator, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Exlamation, kLBC_Numeric, kLBC_Numeric, kLBC_InfixNumericSeparator, kLBC_InfixNumericSeparator, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Exlamation,
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_OpenPunctuation, kLBC_PrefixNumeric, kLBC_CloseParenthesis, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_OpenPunctuation, kLBC_PrefixNumeric, kLBC_CloseParenthesis, kLBC_Alphabetic, kLBC_Alphabetic,
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_OpenPunctuation, kLBC_BreakAfter, kLBC_ClosePunctuation, kLBC_Alphabetic, kLBC_CombiningMark kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_OpenPunctuation, kLBC_BreakAfter, kLBC_ClosePunctuation, kLBC_Alphabetic, kLBC_CombiningMark};
};
std::string::const_iterator nextLineBreak(std::string::const_iterator text, std::string::const_iterator end) std::string::const_iterator nextLineBreak(std::string::const_iterator text, std::string::const_iterator end)
{ {
if (text == end) if (text == end)
return text; return text;
enum breakAction enum breakAction
{ {
DBK = 0, // direct break (blank in table) DBK = 0, // direct break (blank in table)
IBK, // indirect break (% in table) IBK, // indirect break (% in table)
PBK, // prohibited break (^ in table) PBK, // prohibited break (^ in table)
CIB, // combining indirect break CIB, // combining indirect break
CPB // combining prohibited break CPB // combining prohibited break
}; };
const breakAction brkTable[27][27] = { const breakAction brkTable[27][27] = {
// OP CL CP QU GL NS EX SY IS PR PO NU AL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT // OP CL CP QU GL NS EX SY IS PR PO NU AL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT
/* OP */ { PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, CPB, PBK, PBK, PBK, PBK, PBK, PBK }, /* OP */ {PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, CPB, PBK, PBK, PBK, PBK, PBK, PBK},
/* CL */ { DBK, PBK, PBK, IBK, IBK, PBK, PBK, PBK, PBK, IBK, IBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* CL */ {DBK, PBK, PBK, IBK, IBK, PBK, PBK, PBK, PBK, IBK, IBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* CP */ { DBK, PBK, PBK, IBK, IBK, PBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* CP */ {DBK, PBK, PBK, IBK, IBK, PBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* QU */ { PBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK }, /* QU */ {PBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK},
/* GL */ { IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK }, /* GL */ {IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK},
/* NS */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* NS */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* EX */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* EX */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* SY */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* SY */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* IS */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* IS */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* PR */ { IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, IBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK }, /* PR */ {IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, IBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK},
/* PO */ { IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* PO */ {IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* NU */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* NU */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* AL */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* AL */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* ID */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* ID */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* IN */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* IN */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* HY */ { DBK, PBK, PBK, IBK, DBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* HY */ {DBK, PBK, PBK, IBK, DBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* BA */ { DBK, PBK, PBK, IBK, DBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* BA */ {DBK, PBK, PBK, IBK, DBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* BB */ { IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK }, /* BB */ {IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK},
/* B2 */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, PBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* B2 */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, PBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* ZW */ { DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK }, /* ZW */ {DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK},
/* CM */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK }, /* CM */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
/* WJ */ { IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK }, /* WJ */ {IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK},
/* H2 */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, IBK, IBK }, /* H2 */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, IBK, IBK},
/* H3 */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, IBK }, /* H3 */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, IBK},
/* JL */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, DBK }, /* JL */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, DBK},
/* JV */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, IBK, IBK }, /* JV */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, IBK, IBK},
/* JT */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, IBK }, /* JT */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, IBK},
}; };
uint8_t ch = static_cast<uint8_t>(*text); uint8_t ch = static_cast<uint8_t>(*text);
LineBreakClass cls; LineBreakClass cls;
if (ch == '\n') if (ch == '\n')
cls = kLBC_MandatoryBreak; cls = kLBC_MandatoryBreak;
else if (ch < 128) else if (ch < 128)
{ {
cls = kASCII_LBTable[ch]; cls = kASCII_LBTable[ch];
if (cls > kLBC_MandatoryBreak and cls != kLBC_Space) // duh... if (cls > kLBC_MandatoryBreak and cls != kLBC_Space) // duh...
cls = kLBC_Alphabetic; cls = kLBC_Alphabetic;
} }
else else
...@@ -355,9 +352,9 @@ std::string::const_iterator nextLineBreak(std::string::const_iterator text, std: ...@@ -355,9 +352,9 @@ std::string::const_iterator nextLineBreak(std::string::const_iterator text, std:
while (++text != end and cls != kLBC_MandatoryBreak) while (++text != end and cls != kLBC_MandatoryBreak)
{ {
ch = *text; ch = *text;
LineBreakClass lcls = ncls; LineBreakClass lcls = ncls;
if (ch == '\n') if (ch == '\n')
{ {
++text; ++text;
...@@ -365,42 +362,42 @@ std::string::const_iterator nextLineBreak(std::string::const_iterator text, std: ...@@ -365,42 +362,42 @@ std::string::const_iterator nextLineBreak(std::string::const_iterator text, std:
} }
ncls = kASCII_LBTable[ch]; ncls = kASCII_LBTable[ch];
if (ncls == kLBC_Space) if (ncls == kLBC_Space)
continue; continue;
breakAction brk = brkTable[cls][ncls]; breakAction brk = brkTable[cls][ncls];
if (brk == DBK or (brk == IBK and lcls == kLBC_Space)) if (brk == DBK or (brk == IBK and lcls == kLBC_Space))
break; break;
cls = ncls; cls = ncls;
} }
return text; return text;
} }
std::vector<std::string> wrapLine(const std::string& text, unsigned int width) std::vector<std::string> wrapLine(const std::string &text, unsigned int width)
{ {
std::vector<std::string> result; std::vector<std::string> result;
std::vector<size_t> offsets = { 0 }; std::vector<size_t> offsets = {0};
auto b = text.begin(); auto b = text.begin();
while (b != text.end()) while (b != text.end())
{ {
auto e = nextLineBreak(b, text.end()); auto e = nextLineBreak(b, text.end());
offsets.push_back(e - text.begin()); offsets.push_back(e - text.begin());
b = e; b = e;
} }
size_t count = offsets.size() - 1; size_t count = offsets.size() - 1;
std::vector<size_t> minima(count + 1, 1000000); std::vector<size_t> minima(count + 1, 1000000);
minima[0] = 0; minima[0] = 0;
std::vector<size_t> breaks(count + 1, 0); std::vector<size_t> breaks(count + 1, 0);
for (size_t i = 0; i < count; ++i) for (size_t i = 0; i < count; ++i)
{ {
size_t j = i + 1; size_t j = i + 1;
...@@ -415,7 +412,7 @@ std::vector<std::string> wrapLine(const std::string& text, unsigned int width) ...@@ -415,7 +412,7 @@ std::vector<std::string> wrapLine(const std::string& text, unsigned int width)
--w; --w;
size_t cost = minima[i]; size_t cost = minima[i];
if (j < count) // last line may be shorter if (j < count) // last line may be shorter
cost += (width - w) * (width - w); cost += (width - w) * (width - w);
if (cost < minima[j]) if (cost < minima[j])
...@@ -427,34 +424,34 @@ std::vector<std::string> wrapLine(const std::string& text, unsigned int width) ...@@ -427,34 +424,34 @@ std::vector<std::string> wrapLine(const std::string& text, unsigned int width)
++j; ++j;
} }
} }
size_t j = count; size_t j = count;
while (j > 0) while (j > 0)
{ {
size_t i = breaks[j]; size_t i = breaks[j];
result.push_back(text.substr(offsets[i], offsets[j] - offsets[i])); result.push_back(text.substr(offsets[i], offsets[j] - offsets[i]));
j = i; j = i;
} }
reverse(result.begin(), result.end()); reverse(result.begin(), result.end());
return result; return result;
} }
std::vector<std::string> wordWrap(const std::string& text, unsigned int width) std::vector<std::string> wordWrap(const std::string &text, unsigned int width)
{ {
std::vector<std::string> paragraphs; std::vector<std::string> paragraphs;
ba::split(paragraphs, text, ba::is_any_of("\n")); ba::split(paragraphs, text, ba::is_any_of("\n"));
std::vector<std::string> result; std::vector<std::string> result;
for (auto& p: paragraphs) for (auto &p : paragraphs)
{ {
if (p.empty()) if (p.empty())
{ {
result.push_back(""); result.push_back("");
continue; continue;
} }
auto lines = wrapLine(p, width); auto lines = wrapLine(p, width);
result.insert(result.end(), lines.begin(), lines.end()); result.insert(result.end(), lines.begin(), lines.end());
} }
...@@ -467,8 +464,8 @@ std::vector<std::string> wordWrap(const std::string& text, unsigned int width) ...@@ -467,8 +464,8 @@ std::vector<std::string> wordWrap(const std::string& text, unsigned int width)
#ifdef _MSC_VER #ifdef _MSC_VER
} }
#include <Windows.h> #include <Windows.h>
#include <wincon.h>
#include <libloaderapi.h> #include <libloaderapi.h>
#include <wincon.h>
namespace cif namespace cif
{ {
...@@ -494,15 +491,15 @@ std::string GetExecutablePath() ...@@ -494,15 +491,15 @@ std::string GetExecutablePath()
#else #else
uint32_t get_terminal_width() uint32_t get_terminal_width()
{ {
uint32_t result = 80; uint32_t result = 80;
if (isatty(STDOUT_FILENO)) if (isatty(STDOUT_FILENO))
{ {
struct winsize w; struct winsize w;
ioctl(0, TIOCGWINSZ, &w); ioctl(0, TIOCGWINSZ, &w);
result = w.ws_col; result = w.ws_col;
} }
return result; return result;
} }
std::string get_executable_path() std::string get_executable_path()
...@@ -512,7 +509,7 @@ std::string get_executable_path() ...@@ -512,7 +509,7 @@ std::string get_executable_path()
char path[PATH_MAX] = ""; char path[PATH_MAX] = "";
if (readlink("/proc/self/exe", path, sizeof(path)) == -1) if (readlink("/proc/self/exe", path, sizeof(path)) == -1)
throw std::runtime_error("could not get exe path "s + strerror(errno)); throw std::runtime_error("could not get exe path "s + strerror(errno));
return { path }; return {path};
} }
#endif #endif
...@@ -521,37 +518,42 @@ std::string get_executable_path() ...@@ -521,37 +518,42 @@ std::string get_executable_path()
struct ProgressImpl struct ProgressImpl
{ {
ProgressImpl(int64_t inMax, const std::string& inAction) ProgressImpl(int64_t inMax, const std::string &inAction)
: mMax(inMax), mConsumed(0), mAction(inAction), mMessage(inAction) : mMax(inMax)
, mThread(std::bind(&ProgressImpl::Run, this)) {} , mConsumed(0)
, mAction(inAction)
, mMessage(inAction)
, mThread(std::bind(&ProgressImpl::Run, this))
{
}
void Run(); void Run();
void Stop() void Stop()
{ {
mStop = true; mStop = true;
if (mThread.joinable()) if (mThread.joinable())
mThread.join(); mThread.join();
} }
void PrintProgress(); void PrintProgress();
void PrintDone(); void PrintDone();
int64_t mMax; int64_t mMax;
std::atomic<int64_t>mConsumed; std::atomic<int64_t> mConsumed;
int64_t mLastConsumed = 0; int64_t mLastConsumed = 0;
int mSpinnerIndex = 0; int mSpinnerIndex = 0;
std::string mAction, mMessage; std::string mAction, mMessage;
std::mutex mMutex; std::mutex mMutex;
std::thread mThread; std::thread mThread;
std::chrono::time_point<std::chrono::system_clock> std::chrono::time_point<std::chrono::system_clock>
mStart = std::chrono::system_clock::now(); mStart = std::chrono::system_clock::now();
bool mStop = false; bool mStop = false;
}; };
void ProgressImpl::Run() void ProgressImpl::Run()
{ {
bool printedAny = false; bool printedAny = false;
try try
{ {
for (;;) for (;;)
...@@ -559,7 +561,7 @@ void ProgressImpl::Run() ...@@ -559,7 +561,7 @@ void ProgressImpl::Run()
std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::unique_lock lock(mMutex); std::unique_lock lock(mMutex);
if (mStop or mConsumed == mMax) if (mStop or mConsumed == mMax)
break; break;
...@@ -570,43 +572,44 @@ void ProgressImpl::Run() ...@@ -570,43 +572,44 @@ void ProgressImpl::Run()
PrintProgress(); PrintProgress();
printedAny = true; printedAny = true;
} }
} }
catch (...) {} catch (...)
{
}
if (printedAny) if (printedAny)
PrintDone(); PrintDone();
} }
void ProgressImpl::PrintProgress() void ProgressImpl::PrintProgress()
{ {
// const char* kBlocks[] = { // const char* kBlocks[] = {
// " ", // 0 // " ", // 0
// u8"\u258F", // 1 // u8"\u258F", // 1
// u8"\u258E", // 2 // u8"\u258E", // 2
// u8"\u258D", // 3 // u8"\u258D", // 3
// u8"\u258C", // 4 // u8"\u258C", // 4
// u8"\u258B", // 5 // u8"\u258B", // 5
// u8"\u258A", // 6 // u8"\u258A", // 6
// u8"\u2589", // 7 // u8"\u2589", // 7
// u8"\u2588", // 8 // u8"\u2588", // 8
// }; // };
const char* kBlocks[] = { const char *kBlocks[] = {
" ", // 0 " ", // 0
" ", // 1 " ", // 1
" ", // 2 " ", // 2
"-", // 3 "-", // 3
"-", // 4 "-", // 4
"-", // 5 "-", // 5
"=", // 6 "=", // 6
"=", // 7 "=", // 7
"=", // 8 "=", // 8
}; };
uint32_t width = get_terminal_width(); uint32_t width = get_terminal_width();
std::string msg; std::string msg;
msg.reserve(width + 1); msg.reserve(width + 1);
if (mMessage.length() <= 20) if (mMessage.length() <= 20)
...@@ -617,16 +620,16 @@ void ProgressImpl::PrintProgress() ...@@ -617,16 +620,16 @@ void ProgressImpl::PrintProgress()
} }
else else
msg = mMessage.substr(0, 17) + "..."; msg = mMessage.substr(0, 17) + "...";
msg += " |"; msg += " |";
int64_t consumed = mConsumed; int64_t consumed = mConsumed;
float progress = static_cast<float>(consumed) / mMax; float progress = static_cast<float>(consumed) / mMax;
int pi = static_cast<int>(std::ceil(progress * 33 * 8)); int pi = static_cast<int>(std::ceil(progress * 33 * 8));
// int tw = width - 28; // int tw = width - 28;
// int twd = static_cast<int>(tw * progress + 0.5f); // int twd = static_cast<int>(tw * progress + 0.5f);
// msg.append(twd, '='); // msg.append(twd, '=');
// msg.append(tw - twd, ' '); // msg.append(tw - twd, ' ');
for (int i = 0; i < 33; ++i) for (int i = 0; i < 33; ++i)
{ {
...@@ -641,27 +644,27 @@ void ProgressImpl::PrintProgress() ...@@ -641,27 +644,27 @@ void ProgressImpl::PrintProgress()
msg.append("| "); msg.append("| ");
// const char kSpinner[] = { '|', '/', '-', '\\' }; // const char kSpinner[] = { '|', '/', '-', '\\' };
const char kSpinner[] = { ' ', '.', 'o', 'O', '0', 'O', 'o', '.' }; const char kSpinner[] = {' ', '.', 'o', 'O', '0', 'O', 'o', '.'};
const size_t kSpinnerCount = sizeof(kSpinner); const size_t kSpinnerCount = sizeof(kSpinner);
if (mLastConsumed < consumed) if (mLastConsumed < consumed)
{ {
mLastConsumed = consumed; mLastConsumed = consumed;
mSpinnerIndex = (mSpinnerIndex + 1) % kSpinnerCount; mSpinnerIndex = (mSpinnerIndex + 1) % kSpinnerCount;
} }
const char spinner[2] = { kSpinner[mSpinnerIndex], 0 }; const char spinner[2] = {kSpinner[mSpinnerIndex], 0};
msg.append(spinner); msg.append(spinner);
// int perc = static_cast<int>(100 * progress); // int perc = static_cast<int>(100 * progress);
// if (perc < 100) // if (perc < 100)
// msg += ' '; // msg += ' ';
// if (perc < 10) // if (perc < 10)
// msg += ' '; // msg += ' ';
// msg += to_string(perc); // msg += to_string(perc);
// msg += '%'; // msg += '%';
std::cout << '\r' << msg; std::cout << '\r' << msg;
std::cout.flush(); std::cout.flush();
} }
...@@ -669,38 +672,38 @@ void ProgressImpl::PrintProgress() ...@@ -669,38 +672,38 @@ void ProgressImpl::PrintProgress()
namespace namespace
{ {
std::ostream& operator<<(std::ostream& os, const std::chrono::duration<double>& t) std::ostream &operator<<(std::ostream &os, const std::chrono::duration<double> &t)
{
uint64_t s = static_cast<uint64_t>(std::trunc(t.count()));
if (s > 24 * 60 * 60)
{ {
uint32_t days = s / (24 * 60 * 60); uint64_t s = static_cast<uint64_t>(std::trunc(t.count()));
os << days << "d "; if (s > 24 * 60 * 60)
s %= 24 * 60 * 60; {
} uint32_t days = s / (24 * 60 * 60);
os << days << "d ";
if (s > 60 * 60) s %= 24 * 60 * 60;
{ }
uint32_t hours = s / (60 * 60);
os << hours << "h ";
s %= 60 * 60;
}
if (s > 60)
{
uint32_t minutes = s / 60;
os << minutes << "m ";
s %= 60;
}
double ss = s + 1e-6 * (t.count() - s);
os << std::fixed << std::setprecision(1) << ss << 's';
return os; if (s > 60 * 60)
} {
uint32_t hours = s / (60 * 60);
os << hours << "h ";
s %= 60 * 60;
}
} if (s > 60)
{
uint32_t minutes = s / 60;
os << minutes << "m ";
s %= 60;
}
double ss = s + 1e-6 * (t.count() - s);
os << std::fixed << std::setprecision(1) << ss << 's';
return os;
}
} // namespace
void ProgressImpl::PrintDone() void ProgressImpl::PrintDone()
{ {
...@@ -714,11 +717,11 @@ void ProgressImpl::PrintDone() ...@@ -714,11 +717,11 @@ void ProgressImpl::PrintDone()
if (msg.length() < width) if (msg.length() < width)
msg += std::string(width - msg.length(), ' '); msg += std::string(width - msg.length(), ' ');
std::cout << '\r' << msg << std::endl; std::cout << '\r' << msg << std::endl;
} }
Progress::Progress(int64_t inMax, const std::string& inAction) Progress::Progress(int64_t inMax, const std::string &inAction)
: mImpl(nullptr) : mImpl(nullptr)
{ {
if (isatty(STDOUT_FILENO)) if (isatty(STDOUT_FILENO))
...@@ -732,10 +735,10 @@ Progress::~Progress() ...@@ -732,10 +735,10 @@ Progress::~Progress()
delete mImpl; delete mImpl;
} }
void Progress::consumed(int64_t inConsumed) void Progress::consumed(int64_t inConsumed)
{ {
if (mImpl != nullptr and if (mImpl != nullptr and
(mImpl->mConsumed += inConsumed) >= mImpl->mMax) (mImpl->mConsumed += inConsumed) >= mImpl->mMax)
{ {
mImpl->Stop(); mImpl->Stop();
...@@ -744,14 +747,14 @@ void Progress::consumed(int64_t inConsumed) ...@@ -744,14 +747,14 @@ void Progress::consumed(int64_t inConsumed)
void Progress::progress(int64_t inProgress) void Progress::progress(int64_t inProgress)
{ {
if (mImpl != nullptr and if (mImpl != nullptr and
(mImpl->mConsumed = inProgress) >= mImpl->mMax) (mImpl->mConsumed = inProgress) >= mImpl->mMax)
{ {
mImpl->Stop(); mImpl->Stop();
} }
} }
void Progress::message(const std::string& inMessage) void Progress::message(const std::string &inMessage)
{ {
if (mImpl != nullptr) if (mImpl != nullptr)
{ {
...@@ -760,7 +763,7 @@ void Progress::message(const std::string& inMessage) ...@@ -760,7 +763,7 @@ void Progress::message(const std::string& inMessage)
} }
} }
} } // namespace cif
#if USE_RSRC #if USE_RSRC
...@@ -774,16 +777,16 @@ void Progress::message(const std::string& inMessage) ...@@ -774,16 +777,16 @@ void Progress::message(const std::string& inMessage)
namespace mrsrc namespace mrsrc
{ {
/// \brief Internal data structure as generated by mrc /// \brief Internal data structure as generated by mrc
struct rsrc_imp struct rsrc_imp
{ {
unsigned int m_next; unsigned int m_next;
unsigned int m_child; unsigned int m_child;
unsigned int m_name; unsigned int m_name;
unsigned int m_size; unsigned int m_size;
unsigned int m_data; unsigned int m_data;
}; };
} } // namespace mrsrc
extern const __attribute__((weak)) mrsrc::rsrc_imp gResourceIndex[]; extern const __attribute__((weak)) mrsrc::rsrc_imp gResourceIndex[];
extern const __attribute__((weak)) char gResourceData[]; extern const __attribute__((weak)) char gResourceData[];
...@@ -791,384 +794,386 @@ extern const __attribute__((weak)) char gResourceName[]; ...@@ -791,384 +794,386 @@ extern const __attribute__((weak)) char gResourceName[];
namespace mrsrc namespace mrsrc
{ {
class rsrc_data class rsrc_data
{
public:
static rsrc_data &instance()
{ {
public: static rsrc_data s_instance;
static rsrc_data& instance() return s_instance;
{ }
static rsrc_data s_instance;
return s_instance;
}
const rsrc_imp* index() const { return m_index; } const rsrc_imp *index() const { return m_index; }
const char* data(unsigned int offset) const const char *data(unsigned int offset) const
{ {
return m_data + offset; return m_data + offset;
} }
const char* name(unsigned int offset) const
{
return m_name + offset;
}
private: const char *name(unsigned int offset) const
{
return m_name + offset;
}
rsrc_data() private:
rsrc_data()
{
if (gResourceIndex and gResourceIndex and gResourceName)
{ {
if (gResourceIndex and gResourceIndex and gResourceName) m_index = gResourceIndex;
{ m_data = gResourceData;
m_index = gResourceIndex; m_name = gResourceName;
m_data = gResourceData;
m_name = gResourceName;
}
} }
}
rsrc_imp m_dummy = {}; rsrc_imp m_dummy = {};
const rsrc_imp* m_index = &m_dummy; const rsrc_imp *m_index = &m_dummy;
const char* m_data = ""; const char *m_data = "";
const char* m_name = ""; const char *m_name = "";
}; };
/// \brief Class mrsrc::rsrc contains a pointer to the data in the
/// resource, as well as offering an iterator interface to its
/// children.
/// \brief Class mrsrc::rsrc contains a pointer to the data in the class rsrc
/// resource, as well as offering an iterator interface to its {
/// children. public:
rsrc()
: m_impl(rsrc_data::instance().index())
{
}
class rsrc rsrc(const rsrc &other)
: m_impl(other.m_impl)
{ {
public: }
rsrc() : m_impl(rsrc_data::instance().index()) {} rsrc &operator=(const rsrc &other)
{
m_impl = other.m_impl;
return *this;
}
rsrc(const rsrc& other) rsrc(std::filesystem::path path);
: m_impl(other.m_impl) {}
rsrc& operator=(const rsrc& other) std::string name() const { return rsrc_data::instance().name(m_impl->m_name); }
{
m_impl = other.m_impl;
return *this;
}
rsrc(std::filesystem::path path); const char *data() const { return rsrc_data::instance().data(m_impl->m_data); }
std::string name() const { return rsrc_data::instance().name(m_impl->m_name); } unsigned long size() const { return m_impl->m_size; }
const char* data() const { return rsrc_data::instance().data(m_impl->m_data); } explicit operator bool() const { return m_impl != NULL and m_impl->m_size > 0; }
unsigned long size() const { return m_impl->m_size; } template <typename RSRC>
class iterator_t
{
public:
using iterator_category = std::input_iterator_tag;
using value_type = RSRC;
using difference_type = std::ptrdiff_t;
using pointer = value_type *;
using reference = value_type &;
iterator_t(const rsrc_imp *cur)
: m_cur(cur)
{
}
explicit operator bool() const { return m_impl != NULL and m_impl->m_size > 0; } iterator_t(const iterator_t &i)
: m_cur(i.m_cur)
{
}
template<typename RSRC> iterator_t &operator=(const iterator_t &i)
class iterator_t
{ {
public: m_cur = i.m_cur;
return *this;
}
using iterator_category = std::input_iterator_tag; reference operator*() { return m_cur; }
using value_type = RSRC; pointer operator->() { return &m_cur; }
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
iterator_t(const rsrc_imp* cur) iterator_t &operator++()
: m_cur(cur) {} {
if (m_cur.m_impl->m_next)
m_cur.m_impl = rsrc_data::instance().index() + m_cur.m_impl->m_next;
else
m_cur.m_impl = nullptr;
return *this;
}
iterator_t(const iterator_t& i) iterator_t operator++(int)
: m_cur(i.m_cur) {
{ auto tmp(*this);
} this->operator++();
return tmp;
iterator_t& operator=(const iterator_t& i) }
{
m_cur = i.m_cur;
return *this;
}
reference operator*() { return m_cur; } bool operator==(const iterator_t &rhs) const { return m_cur.m_impl == rhs.m_cur.m_impl; }
pointer operator->() { return& m_cur; } bool operator!=(const iterator_t &rhs) const { return m_cur.m_impl != rhs.m_cur.m_impl; }
iterator_t& operator++() private:
{ value_type m_cur;
if (m_cur.m_impl->m_next) };
m_cur.m_impl = rsrc_data::instance().index() + m_cur.m_impl->m_next;
else
m_cur.m_impl = nullptr;
return *this;
}
iterator_t operator++(int) using iterator = iterator_t<rsrc>;
{
auto tmp(*this);
this->operator++();
return tmp;
}
bool operator==(const iterator_t& rhs) const { return m_cur.m_impl == rhs.m_cur.m_impl; } iterator begin() const
bool operator!=(const iterator_t& rhs) const { return m_cur.m_impl != rhs.m_cur.m_impl; } {
const rsrc_imp *impl = nullptr;
if (m_impl and m_impl->m_child)
impl = rsrc_data::instance().index() + m_impl->m_child;
return iterator(impl);
}
private: iterator end() const
value_type m_cur; {
}; return iterator(nullptr);
}
using iterator = iterator_t<rsrc>; private:
rsrc(const rsrc_imp *imp)
: m_impl(imp)
{
}
iterator begin() const const rsrc_imp *m_impl;
{ };
const rsrc_imp* impl = nullptr;
if (m_impl and m_impl->m_child)
impl = rsrc_data::instance().index() + m_impl->m_child;
return iterator(impl);
}
iterator end() const inline rsrc::rsrc(std::filesystem::path p)
{ {
return iterator(nullptr); m_impl = rsrc_data::instance().index();
}
private: // using std::filesytem::path would have been natural here of course...
rsrc(const rsrc_imp* imp)
: m_impl(imp) {}
const rsrc_imp *m_impl; auto pb = p.begin();
}; auto pe = p.end();
inline rsrc::rsrc(std::filesystem::path p) while (m_impl != nullptr and pb != pe)
{ {
m_impl = rsrc_data::instance().index(); auto name = *pb++;
// using std::filesytem::path would have been natural here of course... const rsrc_imp *impl = nullptr;
for (rsrc child : *this)
auto pb = p.begin();
auto pe = p.end();
while (m_impl != nullptr and pb != pe)
{ {
auto name = *pb++; if (child.name() == name)
const rsrc_imp* impl = nullptr;
for (rsrc child: *this)
{ {
if (child.name() == name) impl = child.m_impl;
{ break;
impl = child.m_impl;
break;
}
} }
m_impl = impl;
} }
if (pb != pe) // not found m_impl = impl;
m_impl = nullptr;
} }
// -------------------------------------------------------------------- if (pb != pe) // not found
m_impl = nullptr;
template<typename CharT, typename Traits> }
class basic_streambuf : public std::basic_streambuf<CharT, Traits>
{
public:
typedef CharT char_type; // --------------------------------------------------------------------
typedef Traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
/// \brief constructor taking a \a path to the resource in memory template <typename CharT, typename Traits>
basic_streambuf(const std::string& path) class basic_streambuf : public std::basic_streambuf<CharT, Traits>
: m_rsrc(path) {
{ public:
init(); typedef CharT char_type;
} typedef Traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
/// \brief constructor taking a \a path to the resource in memory
basic_streambuf(const std::string &path)
: m_rsrc(path)
{
init();
}
/// \brief constructor taking a \a rsrc /// \brief constructor taking a \a rsrc
basic_streambuf(const rsrc& rsrc) basic_streambuf(const rsrc &rsrc)
: m_rsrc(rsrc) : m_rsrc(rsrc)
{ {
init(); init();
} }
basic_streambuf(const basic_streambuf&) = delete; basic_streambuf(const basic_streambuf &) = delete;
basic_streambuf(basic_streambuf&& rhs) basic_streambuf(basic_streambuf &&rhs)
: basic_streambuf(rhs.m_rsrc) : basic_streambuf(rhs.m_rsrc)
{ {
} }
basic_streambuf& operator=(const basic_streambuf&) = delete; basic_streambuf &operator=(const basic_streambuf &) = delete;
basic_streambuf& operator=(basic_streambuf&& rhs) basic_streambuf &operator=(basic_streambuf &&rhs)
{ {
swap(rhs); swap(rhs);
return *this; return *this;
} }
void swap(basic_streambuf& rhs) void swap(basic_streambuf &rhs)
{ {
std::swap(m_begin, rhs.m_begin); std::swap(m_begin, rhs.m_begin);
std::swap(m_end, rhs.m_end); std::swap(m_end, rhs.m_end);
std::swap(m_current, rhs.m_current); std::swap(m_current, rhs.m_current);
} }
private: private:
void init()
{
m_begin = reinterpret_cast<const char_type *>(m_rsrc.data());
m_end = reinterpret_cast<const char_type *>(m_rsrc.data() + m_rsrc.size());
m_current = m_begin;
}
void init() int_type underflow()
{ {
m_begin = reinterpret_cast<const char_type*>(m_rsrc.data()); if (m_current == m_end)
m_end = reinterpret_cast<const char_type*>(m_rsrc.data() + m_rsrc.size()); return traits_type::eof();
m_current = m_begin;
}
int_type underflow() return traits_type::to_int_type(*m_current);
{ }
if (m_current == m_end)
return traits_type::eof();
return traits_type::to_int_type(*m_current); int_type uflow()
} {
if (m_current == m_end)
return traits_type::eof();
int_type uflow() return traits_type::to_int_type(*m_current++);
{ }
if (m_current == m_end)
return traits_type::eof();
return traits_type::to_int_type(*m_current++); int_type pbackfail(int_type ch)
} {
if (m_current == m_begin or (ch != traits_type::eof() and ch != m_current[-1]))
return traits_type::eof();
int_type pbackfail(int_type ch) return traits_type::to_int_type(*--m_current);
{ }
if (m_current == m_begin or (ch != traits_type::eof() and ch != m_current[-1]))
return traits_type::eof();
return traits_type::to_int_type(*--m_current); std::streamsize showmanyc()
} {
assert(std::less_equal<const char *>()(m_current, m_end));
return m_end - m_current;
}
std::streamsize showmanyc() pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which)
{
switch (dir)
{ {
assert(std::less_equal<const char*>()(m_current, m_end)); case std::ios_base::beg:
return m_end - m_current; m_current = m_begin + off;
} break;
pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) case std::ios_base::end:
{ m_current = m_end + off;
switch (dir) break;
{
case std::ios_base::beg:
m_current = m_begin + off;
break;
case std::ios_base::end:
m_current = m_end + off;
break;
case std::ios_base::cur:
m_current += off;
break;
default:
break;
}
if (m_current < m_begin) case std::ios_base::cur:
m_current = m_begin; m_current += off;
break;
if (m_current > m_end)
m_current = m_end;
return m_current - m_begin; default:
break;
} }
pos_type seekpos(pos_type pos, std::ios_base::openmode which) if (m_current < m_begin)
{ m_current = m_begin;
m_current = m_begin + pos;
if (m_current < m_begin) if (m_current > m_end)
m_current = m_begin; m_current = m_end;
if (m_current > m_end)
m_current = m_end;
return m_current - m_begin; return m_current - m_begin;
} }
private: pos_type seekpos(pos_type pos, std::ios_base::openmode which)
rsrc m_rsrc; {
const char_type* m_begin; m_current = m_begin + pos;
const char_type* m_end;
const char_type* m_current;
};
using streambuf = basic_streambuf<char, std::char_traits<char>>; if (m_current < m_begin)
m_current = m_begin;
// -------------------------------------------------------------------- if (m_current > m_end)
// class mrsrc::istream m_current = m_end;
template<typename CharT, typename Traits> return m_current - m_begin;
class basic_istream : public std::basic_istream<CharT, Traits> }
{
public:
typedef CharT char_type;
typedef Traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
private: private:
rsrc m_rsrc;
const char_type *m_begin;
const char_type *m_end;
const char_type *m_current;
};
using __streambuf_type = basic_streambuf<CharT, Traits>; using streambuf = basic_streambuf<char, std::char_traits<char>>;
using __istream_type = std::basic_istream<CharT, Traits>;
__streambuf_type m_buffer; // --------------------------------------------------------------------
// class mrsrc::istream
public:
basic_istream(const std::string& path) template <typename CharT, typename Traits>
: __istream_type(&m_buffer) class basic_istream : public std::basic_istream<CharT, Traits>
, m_buffer(path) {
{ public:
this->init(&m_buffer); typedef CharT char_type;
} typedef Traits traits_type;
typedef typename traits_type::int_type int_type;
basic_istream(rsrc& resource) typedef typename traits_type::pos_type pos_type;
: __istream_type(&m_buffer) typedef typename traits_type::off_type off_type;
, m_buffer(resource)\
{ private:
this->init(&m_buffer); using __streambuf_type = basic_streambuf<CharT, Traits>;
} using __istream_type = std::basic_istream<CharT, Traits>;
basic_istream(const basic_istream&) = delete; __streambuf_type m_buffer;
public:
basic_istream(const std::string &path)
: __istream_type(&m_buffer)
, m_buffer(path)
{
this->init(&m_buffer);
}
basic_istream(basic_istream&& rhs) basic_istream(rsrc &resource)
: __istream_type(std::move(rhs)) : __istream_type(&m_buffer)
, m_buffer(std::move(rhs.m_buffer)) , m_buffer(resource)
{ {
__istream_type::set_rdbuf(&m_buffer); this->init(&m_buffer);
} }
basic_istream& operator=(const basic_istream& ) = delete; basic_istream(const basic_istream &) = delete;
basic_istream& operator=(basic_istream&& rhs) basic_istream(basic_istream &&rhs)
{ : __istream_type(std::move(rhs))
__istream_type::operator=(std::move(rhs)); , m_buffer(std::move(rhs.m_buffer))
m_buffer = std::move(rhs.m_buffer); {
return *this; __istream_type::set_rdbuf(&m_buffer);
} }
void swap(basic_istream& rhs) basic_istream &operator=(const basic_istream &) = delete;
{
__istream_type::swap(rhs);
m_buffer.swap(rhs.m_buffer);
}
__streambuf_type* rdbuf() const basic_istream &operator=(basic_istream &&rhs)
{ {
return const_cast<__streambuf_type*>(&m_buffer); __istream_type::operator=(std::move(rhs));
} m_buffer = std::move(rhs.m_buffer);
}; return *this;
}
using istream = basic_istream<char, std::char_traits<char>>; void swap(basic_istream &rhs)
} {
__istream_type::swap(rhs);
m_buffer.swap(rhs.m_buffer);
}
__streambuf_type *rdbuf() const
{
return const_cast<__streambuf_type *>(&m_buffer);
}
};
using istream = basic_istream<char, std::char_traits<char>>;
} // namespace mrsrc
#endif #endif
...@@ -1188,7 +1193,7 @@ std::unique_ptr<std::istream> loadResource(std::filesystem::path name) ...@@ -1188,7 +1193,7 @@ std::unique_ptr<std::istream> loadResource(std::filesystem::path name)
#if defined(CACHE_DIR) and defined(DATA_DIR) #if defined(CACHE_DIR) and defined(DATA_DIR)
if (not fs::exists(p)) if (not fs::exists(p))
{ {
for (const char* dir: { CACHE_DIR, DATA_DIR }) for (const char *dir : {CACHE_DIR, DATA_DIR})
{ {
auto p2 = fs::path(dir) / p; auto p2 = fs::path(dir) / p;
if (fs::exists(p2)) if (fs::exists(p2))
...@@ -1219,4 +1224,4 @@ std::unique_ptr<std::istream> loadResource(std::filesystem::path name) ...@@ -1219,4 +1224,4 @@ std::unique_ptr<std::istream> loadResource(std::filesystem::path name)
return result; return result;
} }
} } // namespace cif
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