/*
_____       _    _    Corso   Italia,  178
(_|__   .  (_   |_|_  56125           Pisa
(_|_) |)|(()_)()| |   tel.  +39  050 46380
  |   |               picosoft@picosoft.it

 Copyright (C) Picosoft s.r.l. 1995-2002

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
# ifndef blob_h
# define blob_h "$Id$"

# include "pstring.h"
# include "pbool.h"
# include "dberror.h"
extern "C" {
#include <stdlib.h>
#include <errno.h>
#include "picoblob.h"
}

class StmtRel;
class BlobField;

class BlobFile : public PObject
{
friend class BlobField;
   PCLASS(BlobFile, PObject)
   int pbfd;
   int pbErrno;
   PString dirName;
   PString fileName;
public:
   BlobFile (const PString &dName, const PString &fName) {
      pbfd = -1;
      pbErrno = 0;
      dirName = dName;
      fileName = fName;
   }
   ~BlobFile () {
      if (pbfd != 0)
         pBclose (pbfd);
   }
   Error bopen (int mode);
   Error bclose () {
      if (pbfd != -1)
         pBclose (pbfd);
      pbfd = -1;
      return SQL_SUCCESS;
   }
   Error erase();
   Error remove (unsigned long blkNum);
   Error rename(char *newName);
   int getErrno() { return pbErrno; }
private:
   unsigned long write (unsigned char *blob, unsigned long size);
   unsigned long read (unsigned long blkNum, unsigned char **blob);
   unsigned long rewrite (unsigned long blkNum, unsigned char *blob,
                                                 unsigned long size);
};

class BlobField : public PObject
{
friend class BlobFile;
   PCLASS(BlobField, PObject)
   unsigned char *inpBlob;
   unsigned char *outBlob;
   unsigned long inpBlobLen;
   unsigned long outBlobLen;
   unsigned long outBlkNum;
   unsigned long offset;
   BlobFile *bFile;
public:
   BlobField (BlobFile *f) {
      bFile = f;
      inpBlob = (unsigned char *) 0;
      outBlob = (unsigned char *) 0;
      inpBlobLen = 0L;
      outBlobLen = 0L;
      outBlkNum = 0L;
      offset = 0;
   }
   ~BlobField () {
      if (outBlob != (unsigned char *) 0) {
         free (outBlob);
      }
   }
   void operator=(BlobField &b) {
      if (b.bFile)
         bFile = b.bFile;
      inpBlob = b.inpBlob;
      inpBlobLen = b.inpBlobLen;
      if (b.outBlob != 0) {
         outBlob = b.outBlob;
         outBlobLen = b.outBlobLen;
         offset = b.offset;
         b.outBlob = 0L;
         b.outBlobLen = 0L;
         b.offset = 0L;
      }
      outBlkNum = b.outBlkNum;
   }
   void setFile (BlobFile *f) {
      bFile = f;
   }
   void setNull() {
      inpBlob = (unsigned char *) 0;
      if (outBlob != (unsigned char *) 0) {
         free (outBlob);
         outBlob = (unsigned char *) 0;
      }
      inpBlobLen = 0L;
      outBlobLen = 0L;
      offset = 0L;
   }
   PBool isNull() {
      if (inpBlobLen <= 0 && outBlobLen <= 0)
         return PTrue;
      else
         return PFalse;
   }
   Error write () {
      outBlkNum = bFile->write (inpBlob, inpBlobLen);
      if (bFile->pbErrno != 0)
         return SQL_ERROR;
      else
         return SQL_SUCCESS;
   }
   Error read (unsigned long blkNum) {
      setNull();
      outBlobLen = bFile->read (blkNum, &outBlob);
      if (bFile->pbErrno != 0)
         return SQL_ERROR;
      else {
         outBlkNum = blkNum;
         return SQL_SUCCESS;
      }
   }
   Error rewrite (unsigned long blkNum) {
      outBlkNum = bFile->rewrite (blkNum, inpBlob, inpBlobLen);
      if (bFile->pbErrno != 0)
         return SQL_ERROR;
      else
         return SQL_SUCCESS;
   }
   Error remove (unsigned long blkNum) {
      setNull();
      return bFile->remove (blkNum);
   }
   void setBlob (unsigned char *b, unsigned long len) {
      inpBlob = b;
      inpBlobLen = len;
   }
   unsigned char * getBlob () {
      return outBlob;
   }
   unsigned char * getBlobPiece (unsigned long dim) {
      unsigned char * Return = &outBlob[offset];
      offset += dim;
      if (offset > outBlobLen)
         offset = outBlobLen;
      return Return;
   }
   unsigned long getToRead() {
      return outBlobLen - offset;
   }
   unsigned long getBlobLen() {
      return outBlobLen;
   }
   unsigned long getBlkNum() {
      return outBlkNum;
   }
   int getErrno() {
      return bFile->pbErrno;
   }
   void setErrno(int err) {
      bFile->pbErrno = err;
   }
};
# endif
