Mercurial > repo
view interps/boof/boof.cpp @ 12518:2d8fe55c6e65 draft default tip
<int-e> learn The password of the month is release incident pilot.
author | HackEso <hackeso@esolangs.org> |
---|---|
date | Sun, 03 Nov 2024 00:31:02 +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; }