//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / OVOPS++
//
//File: frame.h
//
//Version: $Revision: 1.22 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/11/25 15:00:16 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Authors:
//      Pasi Nummisalo
//      Timo Pärnänen
//      Juhana Räsänen
//	Vesa-Matti Puro
//	Sami Raatikainen
//
//Description:
//	(pfFrame is a wrapper class to OVOPS Frame class.)
//      Rewritten by JR, pfFrame is now independent of OVOPS and
//      has an own container class (FrameContainer) that is
//      reference-counting and copy-on-write.
//      This is a container class for pfFrame. Has reference counting,
//      so that frames can share containers and implement copy on write.
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//      
//Licence:
//     
//
//History:
//
// 

#ifndef __PF_FRAME_H__
#define __PF_FRAME_H__

#include <typeinfo>
#include <string>
#include "pf/types.h"
#include "pf/exception.h"

class pfFrame
{
    private:

    class FrameContainer
    {
        public:
            FrameContainer(pfUlong dataSize_);
            FrameContainer(const pfByte *data_,
                             pfUlong length_,
                             pfUlong dataSize_ = 0);
            FrameContainer(const FrameContainer &other_);
            virtual ~FrameContainer(void);

            pfUlong length(void) const;
            pfUlong getDataSize(void) const;
            void putFirst(pfByte byte_);
            void putFirst(const pfByte *byte_, pfUlong length_);
            pfByte getFirst(void);
            void putLast(pfByte byte_);
            void putLast(const pfByte *byte_, pfUlong length_);
            pfByte getLast(void);
            pfByte read(pfUlong offset_) const;
            void write(pfByte value_, pfUlong offset_);
            void clear(void);
            void incRefCount(void);
            void decRefCount(void);
            int getRefCount(void) const;
            void copyData(pfByte *destination_) const;
        
        private:
            static const pfUlong MAX_GROWTH = 16384;
            void expandBuffer(pfUlong minimumGrowth_ = 0);
        
            // These functions implement the private memory management routines
            static pfByte *allocateFrameData(pfUlong dataSize_);
            static void freeFrameData(pfByte *data_, pfUlong dataSize_);
        
            pfByte *_data;
            int _referenceCount;
            pfUlong _beginPointer;
            pfUlong _endPointer;
            pfUlong _dataSize;
    };

    public:
        static const pfUlong DEFAULT_DATASIZE = 16384;
        explicit pfFrame(pfUlong dataSize_ = DEFAULT_DATASIZE);
        pfFrame(pfByte *data_, pfUlong length_, pfUlong dataSize_ = 0);
        pfFrame(const pfFrame &other_);
        virtual ~pfFrame(void);
        
        const pfFrame &operator =(const pfFrame &other_);
        pfUlong length(void) const;
        pfUlong getDataSize(void) const;

        pfUlong toInteger(void) const
            throw (pfBadValue);
        void fromInteger(const pfUlong value_);

        string toString(void) const;
        void fromString(const string &octetstring_);
        void useBinary(void);
        void useHex(void);

        void putFirst(pfByte byte_);
        void putFirst16bit(pfUlong value_);
        void putFirst24bit(pfUlong value_);
        void putFirst32bit(pfUlong value_);
        void putFirst(const pfByte *byte_, pfUlong length_);
        pfByte getFirst(void);
        pfUlong getFirst16bit(void);
        pfUlong getFirst24bit(void);
        pfUlong getFirst32bit(void);
        
        void putLast(pfByte byte_);
        void putLast16bit(pfUlong value_);
        void putLast24bit(pfUlong value_);
        void putLast32bit(pfUlong value_);
        void putLast(const pfByte *byte_, pfUlong length_);
        pfByte getLast(void);
        pfUlong getLast16bit(void);
        pfUlong getLast24bit(void);
        pfUlong getLast32bit(void);
        
        pfByte read(pfUlong offset_) const;
        pfUlong read16bit(pfUlong offset_) const;
        pfUlong read24bit(pfUlong offset_) const;
        pfUlong read32bit(pfUlong offset_) const;

        void write(pfByte value_, pfUlong offset_);
        pfFrame getSubFrame(pfUlong start_, pfUlong length_) const;
        
        void setData(const pfByte *data_, pfUlong length_);
        void copyData(pfByte *destination_) const;
        void clear(void);
        void destroy(void);

    private:
        void fromBit (const string &bitstring_);
        string toBit(void) const;
        void fromHex (const string &hexstring_);
        string toHex(void) const;

        void copyIfNecessary(void);
        void giveUpFrameContainer(void);
        FrameContainer *_container;
        bool _useBinary;
};

#endif // __PF_FRAME_H__

