forked from mirror/openmw-tes3mp
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
5.3 KiB
C++
192 lines
5.3 KiB
C++
#ifndef COMPONENTS_FILES_ESCAPE_HPP
|
|
#define COMPONENTS_FILES_ESCAPE_HPP
|
|
|
|
#include <queue>
|
|
|
|
#include <components/files/multidircollection.hpp>
|
|
|
|
#include <boost/iostreams/filtering_stream.hpp>
|
|
#include <boost/filesystem/path.hpp>
|
|
#include <boost/program_options.hpp>
|
|
|
|
/**
|
|
* \namespace Files
|
|
*/
|
|
namespace Files
|
|
{
|
|
/**
|
|
* \struct escape_hash_filter
|
|
*/
|
|
struct escape_hash_filter : public boost::iostreams::input_filter
|
|
{
|
|
static const int sEscape;
|
|
static const int sHashIdentifier;
|
|
static const int sEscapeIdentifier;
|
|
|
|
escape_hash_filter();
|
|
virtual ~escape_hash_filter();
|
|
|
|
template <typename Source> int get(Source & src);
|
|
|
|
private:
|
|
std::queue<int> mNext;
|
|
|
|
bool mSeenNonWhitespace;
|
|
bool mFinishLine;
|
|
};
|
|
|
|
template <typename Source>
|
|
int escape_hash_filter::get(Source & src)
|
|
{
|
|
if (mNext.empty())
|
|
{
|
|
int character = boost::iostreams::get(src);
|
|
if (character == boost::iostreams::WOULD_BLOCK)
|
|
{
|
|
mNext.push(character);
|
|
}
|
|
else if (character == EOF)
|
|
{
|
|
mSeenNonWhitespace = false;
|
|
mFinishLine = false;
|
|
mNext.push(character);
|
|
}
|
|
else if (character == '\n')
|
|
{
|
|
mSeenNonWhitespace = false;
|
|
mFinishLine = false;
|
|
mNext.push(character);
|
|
}
|
|
else if (mFinishLine)
|
|
{
|
|
mNext.push(character);
|
|
}
|
|
else if (character == '#')
|
|
{
|
|
if (mSeenNonWhitespace)
|
|
{
|
|
mNext.push(sEscape);
|
|
mNext.push(sHashIdentifier);
|
|
}
|
|
else
|
|
{
|
|
//it's fine being interpreted by Boost as a comment, and so is anything afterwards
|
|
mNext.push(character);
|
|
mFinishLine = true;
|
|
}
|
|
}
|
|
else if (character == sEscape)
|
|
{
|
|
mNext.push(sEscape);
|
|
mNext.push(sEscapeIdentifier);
|
|
}
|
|
else
|
|
{
|
|
mNext.push(character);
|
|
}
|
|
if (!mSeenNonWhitespace && !isspace(character))
|
|
mSeenNonWhitespace = true;
|
|
}
|
|
int retval = mNext.front();
|
|
mNext.pop();
|
|
return retval;
|
|
}
|
|
|
|
struct unescape_hash_filter : public boost::iostreams::input_filter
|
|
{
|
|
unescape_hash_filter();
|
|
virtual ~unescape_hash_filter();
|
|
|
|
template <typename Source> int get(Source & src);
|
|
|
|
private:
|
|
bool expectingIdentifier;
|
|
};
|
|
|
|
template <typename Source>
|
|
int unescape_hash_filter::get(Source & src)
|
|
{
|
|
int character;
|
|
if (!expectingIdentifier)
|
|
character = boost::iostreams::get(src);
|
|
else
|
|
{
|
|
character = escape_hash_filter::sEscape;
|
|
expectingIdentifier = false;
|
|
}
|
|
if (character == escape_hash_filter::sEscape)
|
|
{
|
|
int nextChar = boost::iostreams::get(src);
|
|
int intended;
|
|
if (nextChar == escape_hash_filter::sEscapeIdentifier)
|
|
intended = escape_hash_filter::sEscape;
|
|
else if (nextChar == escape_hash_filter::sHashIdentifier)
|
|
intended = '#';
|
|
else if (nextChar == boost::iostreams::WOULD_BLOCK)
|
|
{
|
|
expectingIdentifier = true;
|
|
intended = nextChar;
|
|
}
|
|
else
|
|
intended = '?';
|
|
return intended;
|
|
}
|
|
else
|
|
return character;
|
|
}
|
|
|
|
/**
|
|
* \class EscapeHashString
|
|
*/
|
|
class EscapeHashString
|
|
{
|
|
private:
|
|
std::string mData;
|
|
public:
|
|
static std::string processString(const std::string & str);
|
|
|
|
EscapeHashString();
|
|
EscapeHashString(const std::string & str);
|
|
EscapeHashString(const std::string & str, size_t pos, size_t len = std::string::npos);
|
|
EscapeHashString(const char * s);
|
|
EscapeHashString(const char * s, size_t n);
|
|
EscapeHashString(size_t n, char c);
|
|
template <class InputIterator>
|
|
EscapeHashString(InputIterator first, InputIterator last);
|
|
|
|
std::string toStdString() const;
|
|
|
|
friend std::ostream & operator<< (std::ostream & os, const EscapeHashString & eHS);
|
|
};
|
|
|
|
std::istream & operator>> (std::istream & is, EscapeHashString & eHS);
|
|
|
|
struct EscapeStringVector
|
|
{
|
|
std::vector<Files::EscapeHashString> mVector;
|
|
|
|
EscapeStringVector();
|
|
virtual ~EscapeStringVector();
|
|
|
|
std::vector<std::string> toStdStringVector() const;
|
|
};
|
|
|
|
//boost program options validation
|
|
|
|
void validate(boost::any &v, const std::vector<std::string> &tokens, Files::EscapeHashString * eHS, int a);
|
|
|
|
void validate(boost::any &v, const std::vector<std::string> &tokens, EscapeStringVector *, int);
|
|
|
|
struct EscapePath
|
|
{
|
|
boost::filesystem::path mPath;
|
|
|
|
static PathContainer toPathContainer(const std::vector<EscapePath> & escapePathContainer);
|
|
};
|
|
|
|
typedef std::vector<EscapePath> EscapePathContainer;
|
|
|
|
std::istream & operator>> (std::istream & istream, EscapePath & escapePath);
|
|
} /* namespace Files */
|
|
#endif /* COMPONENTS_FILES_ESCAPE_HPP */
|