1 #ifndef COMPONENTS_FILES_ESCAPE_HPP 2 #define COMPONENTS_FILES_ESCAPE_HPP 3 4 #include <queue> 5 6 #include <components/files/multidircollection.hpp> 7 8 #include <boost/iostreams/filtering_stream.hpp> 9 #include <boost/filesystem/path.hpp> 10 #include <boost/program_options.hpp> 11 12 /** 13 * \namespace Files 14 */ 15 namespace Files 16 { 17 /** 18 * \struct escape_hash_filter 19 */ 20 struct escape_hash_filter : public boost::iostreams::input_filter 21 { 22 static const int sEscape; 23 static const int sHashIdentifier; 24 static const int sEscapeIdentifier; 25 26 escape_hash_filter(); 27 virtual ~escape_hash_filter(); 28 29 template <typename Source> int get(Source & src); 30 31 private: 32 std::queue<int> mNext; 33 34 bool mSeenNonWhitespace; 35 bool mFinishLine; 36 }; 37 38 template <typename Source> get(Source & src)39 int escape_hash_filter::get(Source & src) 40 { 41 if (mNext.empty()) 42 { 43 int character = boost::iostreams::get(src); 44 if (character == boost::iostreams::WOULD_BLOCK) 45 { 46 mNext.push(character); 47 } 48 else if (character == EOF) 49 { 50 mSeenNonWhitespace = false; 51 mFinishLine = false; 52 mNext.push(character); 53 } 54 else if (character == '\n') 55 { 56 mSeenNonWhitespace = false; 57 mFinishLine = false; 58 mNext.push(character); 59 } 60 else if (mFinishLine) 61 { 62 mNext.push(character); 63 } 64 else if (character == '#') 65 { 66 if (mSeenNonWhitespace) 67 { 68 mNext.push(sEscape); 69 mNext.push(sHashIdentifier); 70 } 71 else 72 { 73 //it's fine being interpreted by Boost as a comment, and so is anything afterwards 74 mNext.push(character); 75 mFinishLine = true; 76 } 77 } 78 else if (character == sEscape) 79 { 80 mNext.push(sEscape); 81 mNext.push(sEscapeIdentifier); 82 } 83 else 84 { 85 mNext.push(character); 86 } 87 if (!mSeenNonWhitespace && !isspace(character)) 88 mSeenNonWhitespace = true; 89 } 90 int retval = mNext.front(); 91 mNext.pop(); 92 return retval; 93 } 94 95 struct unescape_hash_filter : public boost::iostreams::input_filter 96 { 97 unescape_hash_filter(); 98 virtual ~unescape_hash_filter(); 99 100 template <typename Source> int get(Source & src); 101 102 private: 103 bool expectingIdentifier; 104 }; 105 106 template <typename Source> get(Source & src)107 int unescape_hash_filter::get(Source & src) 108 { 109 int character; 110 if (!expectingIdentifier) 111 character = boost::iostreams::get(src); 112 else 113 { 114 character = escape_hash_filter::sEscape; 115 expectingIdentifier = false; 116 } 117 if (character == escape_hash_filter::sEscape) 118 { 119 int nextChar = boost::iostreams::get(src); 120 int intended; 121 if (nextChar == escape_hash_filter::sEscapeIdentifier) 122 intended = escape_hash_filter::sEscape; 123 else if (nextChar == escape_hash_filter::sHashIdentifier) 124 intended = '#'; 125 else if (nextChar == boost::iostreams::WOULD_BLOCK) 126 { 127 expectingIdentifier = true; 128 intended = nextChar; 129 } 130 else 131 intended = '?'; 132 return intended; 133 } 134 else 135 return character; 136 } 137 138 /** 139 * \class EscapeHashString 140 */ 141 class EscapeHashString 142 { 143 private: 144 std::string mData; 145 public: 146 static std::string processString(const std::string & str); 147 148 EscapeHashString(); 149 EscapeHashString(const std::string & str); 150 EscapeHashString(const std::string & str, size_t pos, size_t len = std::string::npos); 151 EscapeHashString(const char * s); 152 EscapeHashString(const char * s, size_t n); 153 EscapeHashString(size_t n, char c); 154 template <class InputIterator> 155 EscapeHashString(InputIterator first, InputIterator last); 156 157 std::string toStdString() const; 158 159 friend std::ostream & operator<< (std::ostream & os, const EscapeHashString & eHS); 160 }; 161 162 std::istream & operator>> (std::istream & is, EscapeHashString & eHS); 163 164 struct EscapeStringVector 165 { 166 std::vector<Files::EscapeHashString> mVector; 167 168 EscapeStringVector(); 169 virtual ~EscapeStringVector(); 170 171 std::vector<std::string> toStdStringVector() const; 172 }; 173 174 //boost program options validation 175 176 void validate(boost::any &v, const std::vector<std::string> &tokens, Files::EscapeHashString * eHS, int a); 177 178 void validate(boost::any &v, const std::vector<std::string> &tokens, EscapeStringVector *, int); 179 180 struct EscapePath 181 { 182 boost::filesystem::path mPath; 183 184 static PathContainer toPathContainer(const std::vector<EscapePath> & escapePathContainer); 185 }; 186 187 typedef std::vector<EscapePath> EscapePathContainer; 188 189 std::istream & operator>> (std::istream & istream, EscapePath & escapePath); 190 } /* namespace Files */ 191 #endif /* COMPONENTS_FILES_ESCAPE_HPP */ 192