// // brainfuck.hpp // // Created by Joshua Moerman on 05/22/11. // Copyright 2011 Vadovas. All rights reserved. // #include #include #include /** T is the memory-type (normally bytes aka char) OutputIterator is where to write (normally cout) */ namespace brainfuck_details { // recursive funtion (from http://www.xs4all.nl/~weegen/eelis/geordi/) but templated template void b(char * c, InputIterator& in, T * & p, OutputIterator out){ for(; *c && *c != ']'; ++c) { switch(*c){ case '>' : ++p; break; case '<' : --p; break; case '+' : ++*p; break; case '-' : --*p; break; case '.' : *out++ = *p; break; case ',' : *p = *in++; break; case '[' : for(++c; *p;) b(c, in, p, out); for(int d = 0; *c!=']' || d--; ++c) if(*c == '[') d++; break; } } } // normally we want a comma between values template std::ostream_iterator default_ostream_iterator(std::ostream& os = std::cout){ return std::ostream_iterator(os, ", "); } // except for char's template <> std::ostream_iterator default_ostream_iterator(std::ostream& os){ return std::ostream_iterator(os); } } // Would be better if we used a smarter iterator for p... it is of fixed size now :( template > void brainfuck(std::string prg, std::basic_string inp = std::basic_string(), OutputIterator it = brainfuck_details::default_ostream_iterator()) { char * c = new char[prg.length() + 1]; std::copy(prg.begin(), prg.end(), c); T * i = new T[inp.length() + 1]; std::copy(inp.begin(), inp.end(), i); T * p = new T[512]; std::fill_n(p, 512, T(0)); brainfuck_details::b(c,i,p,it); } // we can't put a default on the InputIterator, because that would be ambigious template , typename OutputIterator = std::ostream_iterator> void brainfuck(std::string prg, InputIterator inp, OutputIterator it = brainfuck_details::default_ostream_iterator()) { char * c = new char[prg.length() + 1]; std::copy(prg.begin(), prg.end(), c); T * p = new T[512]; std::fill_n(p, 512, T(0)); brainfuck_details::b(c,inp,p,it); }