Blame src/buffer.h

Packit 8f70b4
/*
Packit 8f70b4
 * lftp - file transfer program
Packit 8f70b4
 *
Packit 8f70b4
 * Copyright (c) 1996-2012 by Alexander V. Lukyanov (lav@yars.free.net)
Packit 8f70b4
 *
Packit 8f70b4
 * This program is free software; you can redistribute it and/or modify
Packit 8f70b4
 * it under the terms of the GNU General Public License as published by
Packit 8f70b4
 * the Free Software Foundation; either version 3 of the License, or
Packit 8f70b4
 * (at your option) any later version.
Packit 8f70b4
 *
Packit 8f70b4
 * This program is distributed in the hope that it will be useful,
Packit 8f70b4
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8f70b4
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8f70b4
 * GNU General Public License for more details.
Packit 8f70b4
 *
Packit 8f70b4
 * You should have received a copy of the GNU General Public License
Packit 8f70b4
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 8f70b4
 */
Packit 8f70b4
Packit 8f70b4
#ifndef BUFFER_H
Packit 8f70b4
#define BUFFER_H
Packit 8f70b4
Packit 8f70b4
#include "SMTask.h"
Packit 8f70b4
#include "Filter.h"
Packit 8f70b4
#include "Timer.h"
Packit 8f70b4
#include "fg.h"
Packit 8f70b4
#include "xstring.h"
Packit 8f70b4
#include "Speedometer.h"
Packit 8f70b4
Packit 8f70b4
#include <stdarg.h>
Packit 8f70b4
Packit 8f70b4
#ifdef HAVE_ICONV
Packit 8f70b4
CDECL_BEGIN
Packit 8f70b4
# include <iconv.h>
Packit 8f70b4
CDECL_END
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
class Buffer
Packit 8f70b4
{
Packit 8f70b4
protected:
Packit 8f70b4
   xstring error_text;
Packit 8f70b4
   int  saved_errno;
Packit 8f70b4
   bool error_fatal;
Packit 8f70b4
Packit 8f70b4
   xstring buffer;
Packit 8f70b4
   int buffer_ptr;
Packit 8f70b4
   bool eof;	  // no reads possible (except from mem buffer)
Packit 8f70b4
   bool broken;	  // no writes possible
Packit 8f70b4
Packit 8f70b4
   bool save;  // save skipped data
Packit 8f70b4
   int save_max;
Packit 8f70b4
Packit 8f70b4
   off_t pos;
Packit 8f70b4
Packit 8f70b4
   Ref<Speedometer> rate;
Packit 8f70b4
   void RateAdd(int n);
Packit 8f70b4
Packit 8f70b4
   void Allocate(int size);
Packit 8f70b4
Packit 8f70b4
   void SaveMaxCheck(int addsize);
Packit 8f70b4
Packit 8f70b4
public:
Packit 8f70b4
   bool Error() const { return error_text!=0; }
Packit 8f70b4
   bool ErrorFatal() const { return error_fatal; }
Packit 8f70b4
   void SetError(const char *e,bool fatal=false);
Packit 8f70b4
   void SetErrorCached(const char *e);
Packit 8f70b4
   const char *ErrorText() const { return error_text; }
Packit 8f70b4
   int Size() const { return buffer.length()-buffer_ptr; }
Packit 8f70b4
   bool Eof() const { return eof; }
Packit 8f70b4
   bool Broken() const { return broken; }
Packit 8f70b4
Packit 8f70b4
   const char *Get() const;
Packit 8f70b4
   void Get(const char **buf,int *size) const;
Packit 8f70b4
   void Skip(int len); // Get(); consume; Skip()
Packit 8f70b4
   void UnSkip(int len); // this only works if there were no Put's.
Packit 8f70b4
   void Append(const char *buf,int size);
Packit 8f70b4
   void Append(const xstring& s) { Append(s.get(),s.length()); }
Packit 8f70b4
   void Put(const char *buf,int size);
Packit 8f70b4
   void Put(const char *buf) { Put(buf,strlen(buf)); }
Packit 8f70b4
   void Put(const xstring &s) { Put(s.get(),s.length()); }
Packit 8f70b4
   void Put(char c) { Put(&c,1); }
Packit 8f70b4
   void Format(const char *f,...) PRINTF_LIKE(2,3);
Packit 8f70b4
   void vFormat(const char *f, va_list v);
Packit 8f70b4
   void PutEOF() { eof=true; }
Packit 8f70b4
   char *GetSpace(int size) {
Packit 8f70b4
      Allocate(size);
Packit 8f70b4
      return buffer.get_non_const()+buffer.length();
Packit 8f70b4
   }
Packit 8f70b4
   void SpaceAdd(int size) {
Packit 8f70b4
      buffer.set_length(buffer.length()+size);
Packit 8f70b4
   }
Packit 8f70b4
   void Prepend(const char *buf,int size);
Packit 8f70b4
   void Prepend(const char *buf) { Prepend(buf,strlen(buf)); }
Packit 8f70b4
   int MoveDataHere(Buffer *o,int len);
Packit 8f70b4
   template<class BUF> int MoveDataHere(const Ref<BUF>& o,int len) { return MoveDataHere(o.get_non_const(),len); }
Packit 8f70b4
   template<class BUF> int MoveDataHere(const SMTaskRef<BUF>& o,int len) { return MoveDataHere(o.get_non_const(),len); }
Packit 8f70b4
Packit 8f70b4
   unsigned long long UnpackUINT64BE(int offset=0) const;
Packit 8f70b4
   unsigned UnpackUINT32BE(int offset=0) const;
Packit 8f70b4
   unsigned UnpackUINT16BE(int offset=0) const;
Packit 8f70b4
   unsigned UnpackUINT8(int offset=0) const;
Packit 8f70b4
   void PackUINT64BE(unsigned long long data);
Packit 8f70b4
   void PackUINT32BE(unsigned data);
Packit 8f70b4
   void PackUINT16BE(unsigned data);
Packit 8f70b4
   void PackUINT8(unsigned data);
Packit 8f70b4
Packit 8f70b4
   long long UnpackINT64BE(int offset=0) const;
Packit 8f70b4
   int UnpackINT32BE(int offset=0) const;
Packit 8f70b4
   int UnpackINT16BE(int offset=0) const;
Packit 8f70b4
   int UnpackINT8(int offset=0) const;
Packit 8f70b4
   void PackINT64BE(long long data);
Packit 8f70b4
   void PackINT32BE(int data);
Packit 8f70b4
   void PackINT16BE(int data);
Packit 8f70b4
   void PackINT8(int data);
Packit 8f70b4
Packit 8f70b4
   // useful for cache.
Packit 8f70b4
   void Save(int m) { save=true; save_max=m; }
Packit 8f70b4
   bool IsSaving() const { return save; }
Packit 8f70b4
   void GetSaved(const char **buf,int *size) const;
Packit 8f70b4
   void SaveRollback(off_t p);
Packit 8f70b4
Packit 8f70b4
   void SetPos(off_t p) { pos=p; }
Packit 8f70b4
   off_t GetPos() const { return pos; }
Packit 8f70b4
Packit 8f70b4
   void SetSpeedometer(Speedometer *s) { rate=s; }
Packit 8f70b4
   const char *GetRateStrS();
Packit 8f70b4
Packit 8f70b4
   void Empty();
Packit 8f70b4
Packit 8f70b4
   Buffer();
Packit 8f70b4
   ~Buffer();
Packit 8f70b4
Packit 8f70b4
   const char *Dump() const;
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
class DataTranslator : public Buffer
Packit 8f70b4
{
Packit 8f70b4
public:
Packit 8f70b4
   virtual void PutTranslated(Buffer *dst,const char *buf,int size)=0;
Packit 8f70b4
   virtual void ResetTranslation() { Empty(); }
Packit 8f70b4
   virtual ~DataTranslator() {}
Packit 8f70b4
Packit 8f70b4
   // same as PutTranslated, but does not advance pos.
Packit 8f70b4
   void AppendTranslated(Buffer *dst,const char *buf,int size);
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
#ifdef HAVE_ICONV
Packit 8f70b4
class DataRecoder : public DataTranslator
Packit 8f70b4
{
Packit 8f70b4
   iconv_t backend_translate;
Packit 8f70b4
public:
Packit 8f70b4
   void PutTranslated(Buffer *dst,const char *buf,int size);
Packit 8f70b4
   void ResetTranslation();
Packit 8f70b4
   DataRecoder(const char *from_code,const char *to_code,bool translit=true);
Packit 8f70b4
   ~DataRecoder();
Packit 8f70b4
};
Packit 8f70b4
#endif //HAVE_ICONV
Packit 8f70b4
Packit 8f70b4
class DirectedBuffer : public Buffer
Packit 8f70b4
{
Packit 8f70b4
public:
Packit 8f70b4
   enum dir_t { GET, PUT };
Packit 8f70b4
Packit 8f70b4
protected:
Packit 8f70b4
   Ref<DataTranslator> translator;
Packit 8f70b4
   dir_t mode;
Packit 8f70b4
   void EmbraceNewData(int len);
Packit 8f70b4
Packit 8f70b4
public:
Packit 8f70b4
   DirectedBuffer(dir_t m) : mode(m) {}
Packit 8f70b4
   void SetTranslator(DataTranslator *t);
Packit 8f70b4
   const Ref<DataTranslator>& GetTranslator() const { return translator; }
Packit 8f70b4
   void SetTranslation(const char *be_encoding,bool translit=true)
Packit 8f70b4
#ifdef HAVE_ICONV
Packit 8f70b4
      ;
Packit 8f70b4
#else
Packit 8f70b4
      {}
Packit 8f70b4
#endif //HAVE_ICONV
Packit 8f70b4
   void PutTranslated(const char *buf,int size);
Packit 8f70b4
   void PutTranslated(const char *buf) { PutTranslated(buf,strlen(buf)); }
Packit 8f70b4
   void PutTranslated(const xstring& s) { PutTranslated(s.get(),s.length()); }
Packit 8f70b4
   void ResetTranslation();
Packit 8f70b4
   void PutRaw(const char *buf,int size) { Buffer::Put(buf,size); }
Packit 8f70b4
   void PutRaw(const char *buf) { Buffer::Put(buf); }
Packit 8f70b4
   void Put(const char *buf,int size);
Packit 8f70b4
   void Put(const char *buf) { Put(buf,strlen(buf)); }
Packit 8f70b4
   void PutEOF(); // set eof, flush translator
Packit 8f70b4
   int MoveDataHere(Buffer *o,int len);
Packit 8f70b4
   template<class BUF> int MoveDataHere(const SMTaskRef<BUF>& o,int len) { return MoveDataHere(o.get_non_const(),len); }
Packit 8f70b4
   dir_t GetDirection() { return mode; }
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
class IOBuffer : public DirectedBuffer, public SMTask
Packit 8f70b4
{
Packit 8f70b4
protected:
Packit 8f70b4
   // low-level for derived classes
Packit 8f70b4
   virtual int Get_LL(int size) { return 0; }
Packit 8f70b4
   virtual int Put_LL(const char *buf,int size) { return 0; }
Packit 8f70b4
   virtual int PutEOF_LL() { return 0; }
Packit 8f70b4
Packit 8f70b4
   Time event_time; // used to detect timeouts
Packit 8f70b4
   int max_buf;
Packit 8f70b4
   int get_size;
Packit 8f70b4
   int TuneGetSize(int res);
Packit 8f70b4
Packit 8f70b4
   enum {
Packit 8f70b4
      GET_BUFSIZE=0x10000,
Packit 8f70b4
      PUT_LL_MIN=0x2000,
Packit 8f70b4
   };
Packit 8f70b4
Packit 8f70b4
   virtual ~IOBuffer();
Packit 8f70b4
Packit 8f70b4
public:
Packit 8f70b4
   IOBuffer(dir_t m);
Packit 8f70b4
   virtual const Time& EventTime()
Packit 8f70b4
      {
Packit 8f70b4
	 if(IsSuspended())
Packit 8f70b4
	    return now;
Packit 8f70b4
	 return event_time;
Packit 8f70b4
      }
Packit 8f70b4
   virtual bool Done()
Packit 8f70b4
      {
Packit 8f70b4
	 return(broken || Error() || (eof && (mode==GET || Size()==0)));
Packit 8f70b4
      }
Packit 8f70b4
   virtual int Do();
Packit 8f70b4
Packit 8f70b4
   virtual FgData *GetFgData(bool) { return 0; }
Packit 8f70b4
   virtual const char *Status() { return ""; }
Packit 8f70b4
   virtual int Buffered() { return Size(); }
Packit 8f70b4
   virtual bool TranslationEOF() const { return translator?translator->Eof():false; }
Packit 8f70b4
Packit 8f70b4
   // Put method with Put_LL shortcut
Packit 8f70b4
   void Put(const char *,int);
Packit 8f70b4
   void Put(const char *buf);
Packit 8f70b4
   void Put(const xstring &s) { Put(s.get(),s.length()); }
Packit 8f70b4
   void Put(char c) { Put(&c,1); }
Packit 8f70b4
   // anchor to PutEOF_LL
Packit 8f70b4
   void PutEOF() { DirectedBuffer::PutEOF(); PutEOF_LL(); }
Packit 8f70b4
Packit 8f70b4
   void SetMaxBuffered(int m) { max_buf=m; }
Packit 8f70b4
   bool IsFull() { return Size()+(translator?translator->Size():0) >= max_buf; }
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
class IOBufferStacked : public IOBuffer
Packit 8f70b4
{
Packit 8f70b4
   SMTaskRef<IOBuffer> down;
Packit 8f70b4
Packit 8f70b4
   int Get_LL(int size);
Packit 8f70b4
   int Put_LL(const char *buf,int size);
Packit 8f70b4
Packit 8f70b4
   void SuspendInternal();
Packit 8f70b4
   void ResumeInternal();
Packit 8f70b4
Packit 8f70b4
public:
Packit 8f70b4
   IOBufferStacked(IOBuffer *b) : IOBuffer(b->GetDirection()), down(b) {}
Packit 8f70b4
   bool TranslationEOF() const { return down->TranslationEOF()||IOBuffer::TranslationEOF(); }
Packit 8f70b4
   void PrepareToDie() { down=0; }
Packit 8f70b4
   const Time& EventTime() { return down->EventTime(); }
Packit 8f70b4
   int Do();
Packit 8f70b4
   bool Done();
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
class IOBufferFDStream : public IOBuffer
Packit 8f70b4
{
Packit 8f70b4
   Ref<FDStream> my_stream;
Packit 8f70b4
   const Ref<FDStream>& stream;
Packit 8f70b4
   Ref<Timer> put_ll_timer;
Packit 8f70b4
Packit 8f70b4
   int Get_LL(int size);
Packit 8f70b4
   int Put_LL(const char *buf,int size);
Packit 8f70b4
Packit 8f70b4
public:
Packit 8f70b4
   IOBufferFDStream(FDStream *o,dir_t m)
Packit 8f70b4
      : IOBuffer(m), my_stream(o), stream(my_stream) {}
Packit 8f70b4
   IOBufferFDStream(const Ref<FDStream>& o,dir_t m)
Packit 8f70b4
      : IOBuffer(m), stream(o) {}
Packit 8f70b4
   IOBufferFDStream(FDStream *o,dir_t m,Timer *t)
Packit 8f70b4
      : IOBuffer(m), my_stream(o), stream(my_stream), put_ll_timer(t) {}
Packit 8f70b4
   IOBufferFDStream(const Ref<FDStream>& o,dir_t m,Timer *t)
Packit 8f70b4
      : IOBuffer(m), stream(o), put_ll_timer(t) {}
Packit 8f70b4
   ~IOBufferFDStream();
Packit 8f70b4
   bool Done();
Packit 8f70b4
   FgData *GetFgData(bool fg);
Packit 8f70b4
   const char *Status() { return stream->status; }
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
#include <FileAccess.h>
Packit 8f70b4
Packit 8f70b4
class IOBufferFileAccess : public IOBuffer
Packit 8f70b4
{
Packit 8f70b4
   const FileAccessRef& session;
Packit 8f70b4
   FileAccessRef session_ref;
Packit 8f70b4
Packit 8f70b4
   int Get_LL(int size);
Packit 8f70b4
Packit 8f70b4
   void SuspendInternal();
Packit 8f70b4
   void ResumeInternal();
Packit 8f70b4
Packit 8f70b4
public:
Packit 8f70b4
   IOBufferFileAccess(const FileAccessRef& i) : IOBuffer(GET), session(i) {}
Packit 8f70b4
   IOBufferFileAccess(FileAccess *fa) : IOBuffer(GET), session(session_ref), session_ref(fa) {}
Packit 8f70b4
   ~IOBufferFileAccess() {
Packit 8f70b4
      // we don't want to delete the session
Packit 8f70b4
      (void)session_ref.borrow();
Packit 8f70b4
   }
Packit 8f70b4
Packit 8f70b4
   const char *Status();
Packit 8f70b4
};
Packit 8f70b4
Packit 8f70b4
#endif // BUFFER_H