Mercurial > repo
view interps/boof/boof.cpp @ 9554:23f43464694e
<Zarutian> le/rn Frams\xc3\xb3knarflokkurinn/A, now defunct, political party in Iceland. Like its sister party Sj\xc3\xa1lfst\xc3\xa6\xc3\xb0isflokkurinn it is named by the antonym of what it is. (The name means the Progressive Party but they have nearly always been highly regressive). Think dumb Hill-Billies in ill fitting suits and you get their constiuents.
author | HackBot |
---|---|
date | Sun, 30 Oct 2016 14:33:24 +0000 |
parents | 859f9b4339e6 |
children |
line wrap: on
line source
/* 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; }