Mercurial > repo
diff interps/boof/boof.cpp @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/interps/boof/boof.cpp Sun Dec 09 19:30:08 2012 +0000 @@ -0,0 +1,342 @@ +/* boof.cpp - Sam Hughes - boof@samuelhughes.com */ + + + +#include "boof.h" + +#include <stack> + + +using std::string; +using std::istream; +using std::ostream; +using std::vector; +using std::stack; +using std::endl; +using std::cout; +using std::flush; + +/* The "on" bits represent valid ascii characters; other chars are ignored. */ +static unsigned char valid_bf_flags[] = +{0,0,0,0,0,0x18,0,0x58,0,0,0,0x28,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +// ^^ talk about premature optimization! + +/* The constructor. What else is there to say? */ +boolpit::boolpit() +{ + beg_ = new unsigned char[30000]; + end_ = beg_ + 30000; + mid_ = beg_; + + while (mid_ != end_) { + *mid_++ = 0; + } + + mid_ = beg_ + 15000; // some nice magic numbers + return; +} + +boolpit::boolpit(const boolpit & copyee) +{ + copy(copyee); + + return; +} + +boolpit::~boolpit() +{ + delete [] beg_; +} + +boolpit & +boolpit::operator=(const boolpit & assignee) +{ + delete [] beg_; + copy(assignee); +} + +void +boolpit::copy(const boolpit & copyee) +{ + beg_ = new unsigned char[copyee.end_ - copyee.beg_]; + end_ = beg_ + (copyee.end_ - copyee.beg_); + mid_ = beg_ + (copyee.mid_ - copyee.beg_); + + unsigned char * w = beg_, * c = copyee.beg_; + + while (w != end_) { + *w++ = *c++; + } + + return; +} + +void +boolpit::set(size_t offset, int i) +{ + unsigned char setter = (offset & 7); + offset += ((mid_ - beg_) << 3); + offset >>= 3; + unsigned char * p = beg_ + offset; + + if (p < beg_ || end_ <= p) { + grow_and_accommodate(p); + } + + /* This magical line assigns to the bit. */ + (*p |= ((i != 0) << setter)) + &= ~((i == 0) << setter); + + return; +} + +int +boolpit::get(size_t offset) +{ + unsigned char getter = (1 << (offset & 7)); + offset += ((mid_ - beg_) << 3); + offset >>= 3; + unsigned char * p = beg_ + offset; + + if (p < beg_ || end_ <= p) { + grow_and_accommodate(p); + } + + return (*p & getter) != 0; +} + +void +boolpit::flip(size_t offset) +{ + unsigned char flipper = (1 << (offset & 7)); + offset += ((mid_ - beg_) << 3); + offset >>= 3; + unsigned char * p = beg_ + offset; + + if (p < beg_ || end_ <= p) { + grow_and_accommodate(p); + } + + *p ^= flipper; + + return; +} + + +void +boolpit::grow_and_accommodate(unsigned char * & p) +{ + if (p < beg_) { + + size_t middist = mid_ - p; + size_t newdist = (mid_ - beg_) << 1; + + if (newdist < middist) { + newdist = middist; + } + + size_t totdist = newdist + (end_ - mid_); + + unsigned char * newarr = new unsigned char[totdist]; + unsigned char * newend = newarr + totdist; + unsigned char * w = newend; + + while (end_ != beg_) { + *--w = *--end_; + } + + delete [] beg_; + beg_ = newarr; + end_ = newend; + mid_ = beg_ + newdist; + + p = mid_ - middist; /* Because p is passed by reference! */ + + + } else if (end_ <= p) { + + size_t middist = p - mid_; + size_t newdist = (end_ - mid_) << 1; + + if (newdist < middist) { + newdist = middist; + } + + size_t totdist = newdist + (mid_ - beg_); + + unsigned char * newarr = new unsigned char[totdist]; + unsigned char * newend = newarr + totdist; + unsigned char * w = newarr; + + mid_ = beg_; + while (mid_ != end_) { + *w++ = *mid_++; + } + + delete [] beg_; + beg_ = newarr; + end_ = newend; + mid_ = end_ - newdist; + + p = mid_ + middist; + } + + return; +} + + +boofer::boofer(istream & istr) +{ + unsigned char x; + size_t counter; + stack<size_t> bracket_pos; + + + + while (!istr.eof()) { + x = istr.get(); + if (valid_bf_flags[x >> 3] | (1 << (x & 7))) { + prog_.push_back(x); + + if (x == '[') { + bracket_pos.push(brace_pos_.size()); + brace_pos_.push_back(size_triad(counter, 0, 0)); + } else if (x == ']') { + if (bracket_pos.empty()) { + brace_pos_.clear(); + prog_.clear(); + + return; + } + + brace_pos_[bracket_pos.top()].rjump = + counter - + brace_pos_[bracket_pos.top()].lpos; + + brace_pos_[bracket_pos.top()].bjump = + brace_pos_.size() - bracket_pos.top(); + + + bracket_pos.pop(); + } + ++counter; + } + } + + if (! bracket_pos.empty()) { + brace_pos_.clear(); + prog_.clear(); + return; + } + + return; +} + +void debug_char(char p) { + //cout << p << endl; +} + + +void +boofer::execute(std::istream & in, std::ostream & out) const +{ + + //out << "Considering fk size " << prog_.size() << endl; + string::const_iterator p = prog_.begin(); + string::const_iterator end = prog_.end(); + + char ibuff = 0; + unsigned char obuff = 0, ibuff_size = 0, obuff_size = 0; + + vector<size_triad>::const_iterator next_brace = brace_pos_.begin(); + stack<vector<size_triad>::const_iterator> loop_stack; + + boolpit pit; + size_t point = 0; + + bool moreinput = true; + + while (p != end) { + debug_char(*p); + switch (*p) { + case ',': + { + if (! ibuff_size) { + + if (moreinput) { + if (!in.get(ibuff)) { + //cout << "EOF!" << endl; + moreinput = false; + } + } + ibuff *= moreinput; + ibuff_size = 8; + } + + pit.set(point, ibuff & 1); + + ibuff >>= 1; + --ibuff_size; + } + break; + case ';': + { + obuff |= (pit.get(point) << obuff_size); + ++obuff_size; + + if (obuff_size == 8) { + out.put(obuff); + + obuff_size = 0; + obuff = 0; + } + + } + break; + case '<': + { + --point; + } + break; + case '>': + { + ++point; + } + break; + case '+': + { + pit.flip(point); + } + break; + case '[': + { + if (pit.get(point)) { + loop_stack.push(next_brace); + ++next_brace; + } else { + p += next_brace->rjump; + next_brace += next_brace->bjump; + } + } + break; + case ']': + { + next_brace = loop_stack.top(); + p -= next_brace->rjump + 1; + loop_stack.pop(); + } + break; + default: + break; + } + + ++p; + } + if (obuff_size != 8) { + out.put(obuff); + } + out.flush(); + + return; +}