1119610Sache/******************************************************************************* 2119610Sache * $Revision: 1.2 $ 3119610Sache * $Date: 2001/09/11 06:19:36 $ 4119610Sache * $Author: vyzo $ 5119610Sache * 6119610Sache * Contents: A streambuf which uses the GNU readline library for line I/O 7119610Sache * (c) 2001 by Dimitris Vyzovitis [vyzo@media.mit.edu] 8119610Sache * 9119610Sache * This program is free software; you can redistribute it and/or modify 10119610Sache * it under the terms of the GNU General Public License as published by 11119610Sache * the Free Software Foundation; either version 2 of the License, or 12119610Sache * (at your option) any later version. 13119610Sache * 14119610Sache * This program is distributed in the hope that it will be useful, 15119610Sache * but WITHOUT ANY WARRANTY; without even the implied warranty of 16119610Sache * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17119610Sache * General Public License for more details. 18119610Sache * 19119610Sache * You should have received a copy of the GNU General Public 20119610Sache * License along with this program; if not, write to the Free 21119610Sache * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 22119610Sache * MA 02111-1307 USA 23119610Sache * 24119610Sache ******************************************************************************/ 25119610Sache 26119610Sache#ifndef _READLINEBUF_H_ 27119610Sache#define _READLINEBUF_H_ 28119610Sache 29119610Sache#include <iostream> 30119610Sache#include <cstring> 31119610Sache#include <cassert> 32119610Sache#include <cstdlib> 33119610Sache#include <cstdio> 34119610Sache 35119610Sache#include <readline/readline.h> 36119610Sache#include <readline/history.h> 37119610Sache 38119610Sache#if (defined __GNUC__) && (__GNUC__ < 3) 39119610Sache#include <streambuf.h> 40119610Sache#else 41119610Sache#include <streambuf> 42119610Sacheusing std::streamsize; 43119610Sacheusing std::streambuf; 44119610Sache#endif 45119610Sache 46119610Sacheclass readlinebuf : public streambuf { 47119610Sachepublic: 48119610Sache#if (defined __GNUC__) && (__GNUC__ < 3) 49119610Sache typedef char char_type; 50119610Sache typedef int int_type; 51119610Sache typedef streampos pos_type; 52119610Sache typedef streamoff off_type; 53119610Sache#endif 54119610Sache static const int_type eof = EOF; // this is -1 55119610Sache static const int_type not_eof = 0; 56119610Sache 57119610Sacheprivate: 58119610Sache const char* prompt_; 59119610Sache bool history_; 60119610Sache char* line_; 61119610Sache int low_; 62119610Sache int high_; 63119610Sache 64119610Sacheprotected: 65119610Sache 66119610Sache virtual int_type showmanyc() const { return high_ - low_; } 67119610Sache 68119610Sache virtual streamsize xsgetn( char_type* buf, streamsize n ) { 69119610Sache int rd = n > (high_ - low_)? (high_ - low_) : n; 70119610Sache memcpy( buf, line_, rd ); 71119610Sache low_ += rd; 72119610Sache 73119610Sache if ( rd < n ) { 74119610Sache low_ = high_ = 0; 75119610Sache free( line_ ); // free( NULL ) is a noop 76119610Sache line_ = readline( prompt_ ); 77119610Sache if ( line_ ) { 78119610Sache high_ = strlen( line_ ); 79119610Sache if ( history_ && high_ ) add_history( line_ ); 80119610Sache rd += xsgetn( buf + rd, n - rd ); 81119610Sache } 82119610Sache } 83119610Sache 84119610Sache return rd; 85119610Sache } 86119610Sache 87119610Sache virtual int_type underflow() { 88119610Sache if ( high_ == low_ ) { 89119610Sache low_ = high_ = 0; 90119610Sache free( line_ ); // free( NULL ) is a noop 91119610Sache line_ = readline( prompt_ ); 92119610Sache if ( line_ ) { 93119610Sache high_ = strlen( line_ ); 94119610Sache if ( history_ && high_ ) add_history( line_ ); 95119610Sache } 96119610Sache } 97119610Sache 98119610Sache if ( low_ < high_ ) return line_[low_]; 99119610Sache else return eof; 100119610Sache } 101119610Sache 102119610Sache virtual int_type uflow() { 103119610Sache int_type c = underflow(); 104119610Sache if ( c != eof ) ++low_; 105119610Sache return c; 106119610Sache } 107119610Sache 108119610Sache virtual int_type pbackfail( int_type c = eof ) { 109119610Sache if ( low_ > 0 ) --low_; 110119610Sache else if ( c != eof ) { 111119610Sache if ( high_ > 0 ) { 112119610Sache char* nl = (char*)realloc( line_, high_ + 1 ); 113119610Sache if ( nl ) { 114119610Sache line_ = (char*)memcpy( nl + 1, line_, high_ ); 115119610Sache high_ += 1; 116119610Sache line_[0] = char( c ); 117119610Sache } else return eof; 118119610Sache } else { 119119610Sache assert( !line_ ); 120119610Sache line_ = (char*)malloc( sizeof( char ) ); 121119610Sache *line_ = char( c ); 122119610Sache high_ = 1; 123119610Sache } 124119610Sache } else return eof; 125119610Sache 126119610Sache return not_eof; 127119610Sache } 128119610Sache 129119610Sachepublic: 130119610Sache readlinebuf( const char* prompt = NULL, bool history = true ) 131119610Sache : prompt_( prompt ), history_( history ), 132119610Sache line_( NULL ), low_( 0 ), high_( 0 ) { 133119610Sache setbuf( 0, 0 ); 134119610Sache } 135119610Sache 136119610Sache 137119610Sache}; 138119610Sache 139119610Sache#endif 140