readlinebuf.h revision 119610
196462Sru/******************************************************************************* 296462Sru * $Revision: 1.2 $ 396462Sru * $Date: 2001/09/11 06:19:36 $ 496462Sru * $Author: vyzo $ 596462Sru * 696462Sru * Contents: A streambuf which uses the GNU readline library for line I/O 7156813Sru * (c) 2001 by Dimitris Vyzovitis [vyzo@media.mit.edu] 8155264Sru * 996462Sru * This program is free software; you can redistribute it and/or modify 1096462Sru * it under the terms of the GNU General Public License as published by 1196668Sru * the Free Software Foundation; either version 2 of the License, or 1296462Sru * (at your option) any later version. 1396668Sru * 1496462Sru * This program is distributed in the hope that it will be useful, 1596462Sru * but WITHOUT ANY WARRANTY; without even the implied warranty of 1696462Sru * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1796668Sru * General Public License for more details. 1896462Sru * 1996668Sru * You should have received a copy of the GNU General Public 2096462Sru * License along with this program; if not, write to the Free 2196462Sru * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 2296462Sru * MA 02111-1307 USA 2396462Sru * 2496462Sru ******************************************************************************/ 2596462Sru 2696462Sru#ifndef _READLINEBUF_H_ 2796462Sru#define _READLINEBUF_H_ 2896462Sru 2996462Sru#include <iostream> 3096462Sru#include <cstring> 3196462Sru#include <cassert> 3296462Sru#include <cstdlib> 3396462Sru#include <cstdio> 3496462Sru 3596462Sru#include <readline/readline.h> 3696462Sru#include <readline/history.h> 3796462Sru 3896462Sru#if (defined __GNUC__) && (__GNUC__ < 3) 3996462Sru#include <streambuf.h> 4096462Sru#else 4196462Sru#include <streambuf> 4296668Sruusing std::streamsize; 4396462Sruusing std::streambuf; 4496462Sru#endif 4596462Sru 4696462Sruclass readlinebuf : public streambuf { 4796462Srupublic: 4896462Sru#if (defined __GNUC__) && (__GNUC__ < 3) 4996462Sru typedef char char_type; 5096462Sru typedef int int_type; 5196462Sru typedef streampos pos_type; 5296462Sru typedef streamoff off_type; 5396668Sru#endif 5496462Sru static const int_type eof = EOF; // this is -1 5596462Sru static const int_type not_eof = 0; 5696462Sru 5796462Sruprivate: 5896462Sru const char* prompt_; 5996462Sru bool history_; 6096462Sru char* line_; 6196462Sru int low_; 6296462Sru int high_; 6396462Sru 64144893Shartiprotected: 6596462Sru 6696462Sru virtual int_type showmanyc() const { return high_ - low_; } 6796462Sru 6896668Sru virtual streamsize xsgetn( char_type* buf, streamsize n ) { 6996462Sru int rd = n > (high_ - low_)? (high_ - low_) : n; 7096462Sru memcpy( buf, line_, rd ); 7196462Sru low_ += rd; 7296462Sru 7396462Sru if ( rd < n ) { 7496462Sru low_ = high_ = 0; 7596462Sru free( line_ ); // free( NULL ) is a noop 7696462Sru line_ = readline( prompt_ ); 7796462Sru if ( line_ ) { 7896462Sru high_ = strlen( line_ ); 79144893Sharti if ( history_ && high_ ) add_history( line_ ); 8096668Sru rd += xsgetn( buf + rd, n - rd ); 8196668Sru } 8299343Sru } 83155264Sru 84156813Sru return rd; 85 } 86 87 virtual int_type underflow() { 88 if ( high_ == low_ ) { 89 low_ = high_ = 0; 90 free( line_ ); // free( NULL ) is a noop 91 line_ = readline( prompt_ ); 92 if ( line_ ) { 93 high_ = strlen( line_ ); 94 if ( history_ && high_ ) add_history( line_ ); 95 } 96 } 97 98 if ( low_ < high_ ) return line_[low_]; 99 else return eof; 100 } 101 102 virtual int_type uflow() { 103 int_type c = underflow(); 104 if ( c != eof ) ++low_; 105 return c; 106 } 107 108 virtual int_type pbackfail( int_type c = eof ) { 109 if ( low_ > 0 ) --low_; 110 else if ( c != eof ) { 111 if ( high_ > 0 ) { 112 char* nl = (char*)realloc( line_, high_ + 1 ); 113 if ( nl ) { 114 line_ = (char*)memcpy( nl + 1, line_, high_ ); 115 high_ += 1; 116 line_[0] = char( c ); 117 } else return eof; 118 } else { 119 assert( !line_ ); 120 line_ = (char*)malloc( sizeof( char ) ); 121 *line_ = char( c ); 122 high_ = 1; 123 } 124 } else return eof; 125 126 return not_eof; 127 } 128 129public: 130 readlinebuf( const char* prompt = NULL, bool history = true ) 131 : prompt_( prompt ), history_( history ), 132 line_( NULL ), low_( 0 ), high_( 0 ) { 133 setbuf( 0, 0 ); 134 } 135 136 137}; 138 139#endif 140