Skip to content

Instantly share code, notes, and snippets.

@DragonOsman
Last active November 22, 2017 20:28
Show Gist options
  • Save DragonOsman/90f7caae90c35c4c31a2d47d89ece9b0 to your computer and use it in GitHub Desktop.
Save DragonOsman/90f7caae90c35c4c31a2d47d89ece9b0 to your computer and use it in GitHub Desktop.
#include <algorithm>
#include <iostream>
#include <vector>
#include <list>
#include "Document.h"
std::istream &operator>>(std::istream &is, Document &d)
{
char ch = ' ';
for ( ; is.get(ch);)
{
d.line.back().push_back(ch); // add the character
}
if (ch == '\n')
{
d.line.push_back(Line{}); // add another line
}
if (d.line.back().size())
{
d.line.push_back(Line{}); // add final empty line
}
return is;
}
Document::Text_iterator &Document::Text_iterator::operator++()
{
++pos; // proceed to the next character
if (pos == (*ln).end())
{
++ln; // proceed to the next line
pos = (*ln).begin(); // bad if ln == line.end(); so make sure it isn't
}
return *this;
}
Document::Text_iterator Document::Text_iterator::operator++(int n)
{
auto ret = *this;
pos += n;
if (pos == (*ln).end())
{
++ln;
pos = (*ln).begin();
}
ret = *this;
return ret;
}
Document::Text_iterator Document::Text_iterator::find_txt(Document::Text_iterator first, Document::Text_iterator last, const std::string &s)
{
if (s.size() == 0)
{
return last;
}
char first_char = s[0];
while (true)
{
auto p = std::find(first, last, first_char);
if (p == last || match(p, last, s))
{
return p;
}
first = ++p;
}
}
bool Document::Text_iterator::match(Document::Text_iterator first, Document::Text_iterator last, const std::string &str)
{
if (str.empty())
{
return false;
}
for (char i = 0, j = *first; i < str.length(), j != *last; ++i, ++j)
{
if (i != j)
{
return false;
}
}
return true;
}
#ifndef DOCUMENT_H
#define DOCUMENT_H
#include <list>
#include <iostream>
#include <vector>
#include <iterator>
using Line = std::vector<char>;
struct Document
{
std::list<Line> line;
class Text_iterator : public std::iterator<std::bidirectional_iterator_tag, Line, Line, Line*, Line&>
// keep track of line and character position within a line
{
std::list<Line>::iterator ln;
Line::iterator pos;
public:
// start iterator at line ll's character position pp
Text_iterator(std::list<Line>::iterator ll, Line::iterator pp)
: ln{ ll }, pos{ pp } {}
char &operator*() { return *pos; }
Text_iterator &operator++();
Text_iterator operator++(int n);
bool operator==(const Text_iterator &other) { return ln == other.ln && pos == other.pos; }
bool operator!=(const Text_iterator &other) { return !(*this == other); }
Text_iterator find_txt(Text_iterator first, Text_iterator last, const std::string &s);
bool match(Text_iterator first, Text_iterator last, const std::string &str);
};
Document() { line.push_back(Line{}); }
Text_iterator begin() { return Text_iterator(line.begin(), (*line.begin()).begin()); }
Text_iterator end()
{
auto last = line.end();
--last; // we know know that the document is not empty
return Text_iterator(last, (*last).end());
}
};
std::istream &operator>>(std::istream &is, Document &d);
#endif
#include <iostream>
#include <fstream>
#include <list>
#include <vector>
#include "Document.h"
void print(Document &d);
void erase_line(Document &d, int n);
template<typename Iter>
void advance(Iter &p, int n);
int main()
{
std::string str{ "hello world" };
Document doc;
for (int i = 0; i < str.length(); ++i)
{
doc.line.back().push_back(str[i]);
}
Document::Text_iterator it = doc.begin();
auto matched = it.find_txt(it, doc.end(), "hello");
if (matched != doc.end())
{
std::cout << "Found\n";
}
}
void print(Document &d)
{
for (auto p : d)
{
std::cout << p;
}
}
void erase_line(Document &d, int n)
{
if (n < 0 || n >= d.line.size() - 1)
{
return;
}
auto p = d.line.begin();
advance(p, n);
d.line.erase(p);
}
template<typename Iter>
void advance(Iter &p, int n)
{
while (n > 0)
{
++p;
--n;
}
if (n < 0)
{
while (n < 0)
{
--p;
++n;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment