161033Sdfr/******************************************************************************* 261033Sdfr * $Revision: 1.1.1.1 $ 361033Sdfr * $Date: 2004/05/10 18:48:43 $ 461033Sdfr * $Author: kettenis $ 561033Sdfr * 661033Sdfr * Contents: A streambuf which uses the GNU readline library for line I/O 761033Sdfr * (c) 2001 by Dimitris Vyzovitis [vyzo@media.mit.edu] 861033Sdfr * 961033Sdfr * This program is free software; you can redistribute it and/or modify 1061033Sdfr * it under the terms of the GNU General Public License as published by 1161033Sdfr * the Free Software Foundation; either version 2 of the License, or 1261033Sdfr * (at your option) any later version. 1361033Sdfr * 1461033Sdfr * This program is distributed in the hope that it will be useful, 1561033Sdfr * but WITHOUT ANY WARRANTY; without even the implied warranty of 1661033Sdfr * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1761033Sdfr * General Public License for more details. 1861033Sdfr * 1961033Sdfr * You should have received a copy of the GNU General Public 2061033Sdfr * License along with this program; if not, write to the Free 2161033Sdfr * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 2261033Sdfr * MA 02111-1307 USA 2361033Sdfr * 2461033Sdfr ******************************************************************************/ 2561033Sdfr 2661033Sdfr#ifndef _READLINEBUF_H_ 27116182Sobrien#define _READLINEBUF_H_ 28116182Sobrien 29116182Sobrien#include <iostream> 3061033Sdfr#include <cstring> 3185521Sjhb#include <cassert> 3265822Sjhb#include <cstdlib> 3385560Sjhb#include <cstdio> 3461033Sdfr 3585521Sjhb#include <readline/readline.h> 3661033Sdfr#include <readline/history.h> 3785521Sjhb 3885521Sjhb#if (defined __GNUC__) && (__GNUC__ < 3) 39119708Sken#include <streambuf.h> 40119708Sken#else 4161033Sdfr#include <streambuf> 4269774Sphkusing std::streamsize; 4361033Sdfrusing std::streambuf; 4461033Sdfr#endif 4561033Sdfr 4672238Sjhbclass readlinebuf : public streambuf { 47111528Sscottlpublic: 4885521Sjhb#if (defined __GNUC__) && (__GNUC__ < 3) 49119708Sken typedef char char_type; 5067551Sjhb typedef int int_type; 5161033Sdfr typedef streampos pos_type; 5261033Sdfr typedef streamoff off_type; 5361033Sdfr#endif 5461033Sdfr static const int_type eof = EOF; // this is -1 5561033Sdfr static const int_type not_eof = 0; 5661033Sdfr 5761033Sdfrprivate: 5885521Sjhb const char* prompt_; 5961033Sdfr bool history_; 6061033Sdfr char* line_; 6185521Sjhb int low_; 6285521Sjhb int high_; 6385521Sjhb 6485521Sjhbprotected: 6585521Sjhb 6685521Sjhb virtual int_type showmanyc() const { return high_ - low_; } 6793818Sjhb 6885521Sjhb virtual streamsize xsgetn( char_type* buf, streamsize n ) { 6985521Sjhb int rd = n > (high_ - low_)? (high_ - low_) : n; 7085521Sjhb memcpy( buf, line_, rd ); 7185521Sjhb low_ += rd; 7285521Sjhb 7361033Sdfr if ( rd < n ) { 7461033Sdfr low_ = high_ = 0; 7561033Sdfr free( line_ ); // free( NULL ) is a noop 7661033Sdfr line_ = readline( prompt_ ); 7761033Sdfr if ( line_ ) { 7861033Sdfr high_ = strlen( line_ ); 7985521Sjhb if ( history_ && high_ ) add_history( line_ ); 8061033Sdfr rd += xsgetn( buf + rd, n - rd ); 8161033Sdfr } 8285521Sjhb } 8361033Sdfr 8461033Sdfr return rd; 8561033Sdfr } 8661033Sdfr 8761033Sdfr virtual int_type underflow() { 8893818Sjhb if ( high_ == low_ ) { 8961033Sdfr low_ = high_ = 0; 9085521Sjhb free( line_ ); // free( NULL ) is a noop 9161033Sdfr line_ = readline( prompt_ ); 9285521Sjhb if ( line_ ) { 9361033Sdfr high_ = strlen( line_ ); 9461033Sdfr if ( history_ && high_ ) add_history( line_ ); 9561033Sdfr } 9661033Sdfr } 9761033Sdfr 9861033Sdfr if ( low_ < high_ ) return line_[low_]; 9961033Sdfr else return eof; 10085521Sjhb } 10185521Sjhb 102101153Sjhb virtual int_type uflow() { 10361033Sdfr int_type c = underflow(); 10485521Sjhb if ( c != eof ) ++low_; 10561033Sdfr return c; 10661033Sdfr } 10761033Sdfr 10885521Sjhb virtual int_type pbackfail( int_type c = eof ) { 10961033Sdfr if ( low_ > 0 ) --low_; 11085521Sjhb else if ( c != eof ) { 11161033Sdfr if ( high_ > 0 ) { 11285521Sjhb char* nl = (char*)realloc( line_, high_ + 1 ); 11361033Sdfr if ( nl ) { 11461033Sdfr line_ = (char*)memcpy( nl + 1, line_, high_ ); 11561033Sdfr high_ += 1; 11685521Sjhb line_[0] = char( c ); 11785521Sjhb } else return eof; 11885521Sjhb } else { 11961033Sdfr assert( !line_ ); 12061033Sdfr line_ = (char*)malloc( sizeof( char ) ); 12161033Sdfr *line_ = char( c ); 12261033Sdfr high_ = 1; 12361033Sdfr } 12485521Sjhb } else return eof; 12585521Sjhb 12685521Sjhb return not_eof; 12761033Sdfr } 12885521Sjhb 12961033Sdfrpublic: 13061033Sdfr readlinebuf( const char* prompt = NULL, bool history = true ) 13185521Sjhb : prompt_( prompt ), history_( history ), 13285521Sjhb line_( NULL ), low_( 0 ), high_( 0 ) { 13385521Sjhb setbuf( 0, 0 ); 13461033Sdfr } 13561033Sdfr 13661033Sdfr 13761033Sdfr}; 13861033Sdfr 13961033Sdfr#endif 14061033Sdfr