#ifndef _NSRVOL_ // -*-c++-*-
#define _NSRVOL_

//----------------------------------------------------------------------
//  nsrVol.h
//   Descriptors for part 3 of ISO/IEC 13346
//
//      Unpublished Confidential Information of Hewlett-Packard
//      Company. Do not disclose.  Copyright (c) Hewlett-Packard
//      Company 1995. All rights reserved
// 
// The contents of this software are proprietary and confidential to
// the Hewlett- Packard Company, and are limited in distribution to
// those with a direct need to know.  Individuals having access to
// this software are responsible for maintaining the confidentiality
// of the content and for keeping the software secure when not in use.
// Transfer to any party is strictly forbidden other than as expressly
// permitted in writing by Hewlett-Packard Company.  Unauthorized
// transfer to or possession by any unauthorized party may be a
// criminal offense.
//
//                  RESTRICTED RIGHTS LEGEND
//
//      Use,  duplication,  or disclosure by the U. S. Government is
//      subject to restrictions as set forth in subparagraph (c) (1)
//      (ii) in the Rights in Technical Data and Computer Software
//      clause in DFARS 252.227-7013 or any other successor clause.
//
//                      HEWLETT-PACKARD COMPANY
//                      3000 Hanover St.
//                      Palo Alto, CA  94304 U.S.A.
//
//      Rights for non-DOD U.S. Government Departments and Agencies
//      are as set forth in FAR 52.227-19 (c) (1,2) or any other
//      successor clause.
//
//  CLASSES:
//   TaggedDescriptor
//   SearchDescriptor
//   ADTable
//   ImplementUseVolumeDesc
//   OSTAVolumeDesc
//   AnchorVolumeDesc
//   PVDFlags
//   PrimaryVolumeDesc
//   PartitionHdrDesc
//   PDFlags
//   PartitionDesc
//   PartitionMap
//   PartMapTable
//   LogicalVolumeDesc
//   UnallocatedSpaceDesc
//   TerminatingDesc
//   FileSetDesc
//   Uint32Table
//   Int32Table
//   LogicalVolumeIntegrityDesc
//  
//----------------------------------------------------------------------
//
// $Source: /projects/HMS/nsr/udfCore/descr/nsrVol.h,v $
// $Revision: 1.35 $    $Author: hmgr $
// $State: Exp $        $Locker:  $
// $Date: 96/05/23 09:20:32 $

// NOTES for the Future:
//
// OSTA objects could be derived from ISO objects. ISO objects could
// be called base objects, but this should be done differently:
//
// Files: These should be split into
//   ISOChar.[hC]    (Dchars, Dstring, ??)
//   ISONum.[hC]     (the simple numeric field types)
//   ISOComplex.[hC] (the compound fields)
//   ISORecog.[hC]   (same as now)
//   ISOVol.[hC]     (same as now)
//   ISOFile.[hC]    (same as now)
//
// Then, the OSTA versions should be implemented. These are the ones
// that are used.
//
// ISO objects do not allow any but protected access to their members.
// ISO objects leave unused Byte fields OPEN.
//
// OSTA objects provide methods for all data members.
// OSTA objects impose meaning on Byte fields left OPEN. (add unique
//              fields). 
// OSTA objects include descriptors as well as Fields.
//
// In short, I need to do the following:
//
// 1. Make base classes (ISOxxxx).
//    - make sure data members and constructors are all private.
// 2. Derive OSTA classes (xxxx).
//    - ensure proper OSTA field treatment.
//
// ADTable could supply the method by which extent lists are assigned
// into it and retrieved from it. The code could be moved there.
//
// FOR NOW,
//  Most descriptors are OSTA-specific. Implementation use volume
//  descriptor may need collapsing.

// FILE: nsrVol.[hC]
//
// Class: TaggedDescriptor
//
// Descriptors have in common the structure of a DescriptorTag at
// location 0. This tag must be translated toISO() AFTER all the other
// fields have been, and should be translated fromISO() BEFORE all the
// other fields. In addition, TaggedDescriptors have a length which
// must be set before the tag is toISO()ed, because it dictates how
// the CRC is calculated. This length is recorded in the tag field.
//
// Specific descriptors inherit from the TaggedDescriptor class, and
// must override the protected bodyToISO() and bodyFromISO() methods,
// in which they translate all their fields to and from ISO except for
// the DescriptorTag. All the specific descriptors are translated via
// the inherited toISO() and fromISO() methods.
// 
// All descriptors ALSO contain an error object. This holds any
// information about errors encountered inside the methods. It is
// intended to be checked by the user(s) of the descriptors to see if
// anything is wrong. For this reason, the descriptor class provides
// an operator which casts to a boolean. It returns true if an error
// has occurred in the execution of any of the methods of a
// descriptor. Also, the error object is available via the error()
// method.
//
// The tag type comparisons are performed inside the TaggedDescriptor
// class. If the disk image found in fromISO() does not match, an
// ETagType error is generated. This test is avoided by instantiating
// a TaggedDescriptor of type tag_Unknown.
//
// Concerns include the use of the descriptorTag fields for holding
// what is looked for, as well as what is found, and making sure that
// this is easy to use for searching. An issue here is that the error
// may not be cleared. Thus, in order to use this for searching, the
// fromISOBlind() method should be used. Does this make sense, or does
// this give rise to some strange combinations of uses alongside the
// other fromISO() method, which requires a location parameter? If
// blind is used, why does the non-blind method support the unknown
// type?
//
// This can be addressed by inheriting from this a searchDescriptor
// class, which does everything appropriately, (and clears out
// errors), or by removing the tag_Unknown stuff out of the fromISO()
// method which this contains.

class TaggedDescriptor {

protected:

    DescriptorTag tag;
    Error err;
    
public:

    TaggedDescriptor ( TagType t = tag_Unknown, UINT16 len = 0 ) ;
    virtual ~TaggedDescriptor();

    Error error() const ;

    void descLen(UINT32 len);
    UINT32 descLen() const {
        return (tag.crcLen() + tag.field.len());
    }
    
    TagType type() const { return tag.tagIdentifier(); }

    void clear() ;
    void toISO( BYTE_PTR rbp, UINT32 loc ) ;
    void fromISOBlind( CONST_BYTE_PTR rbp ) ;
    void fromISO( CONST_BYTE_PTR rbp, UINT32 loc ) ;
    void fromISO( const ByteArray &ba, const UINT32 offs, const UINT32 loc ) ;
#ifdef NSR_VERIFY
    Error verifyISO( CONST_BYTE_PTR rbp, UINT32 loc );
#endif

protected:

    virtual Error bodyError() const { return Error(error_None); }
#ifdef NSR_VERIFY
    virtual Error bodyVerifyISO( CONST_BYTE_PTR rbp ) {
        return Error(error_None);
    }
#endif
    virtual void  bodyClear() {}
    virtual void  bodyInit() {}
    virtual void  bodyToISO( BYTE_PTR rbp ) {}
    virtual void  bodyFromISO( CONST_BYTE_PTR rbp ) {}
};

// Class: SearchDescriptor
//
// SearchDescriptor is a generic descriptor which is useful for
// searching through the disk looking for tagged descriptors. It is
// just like any other descriptor, except that it has no fields (apart
// from the DescriptorTag), and it does not care what type of
// descriptor it finds when a fromISO() is performed. It still checks
// for CRC and tag location errors, but cannot set the
// error_Bad_tag_descriptor_type error.

class SearchDescriptor : public TaggedDescriptor {

public:

    SearchDescriptor() {}

    void fromISOBlind( CONST_BYTE_PTR rbp ) ; // No error checking.
    void fromISOMyopic( CONST_BYTE_PTR rbp ) ; // checks for many errors, but not location
    void fromISO( CONST_BYTE_PTR rbp, UINT32 loc ) ; // full tag error checking
    void toISO( BYTE_PTR rbp, UINT32 loc ) {}
    
protected:
#ifdef NSR_VERIFY
    Error bodyVerifyISO( CONST_BYTE_PTR rbp ) {
        return Error(error_None);
    }
#endif
    Error bodyError() const { return Error(error_None); }
    void bodyClear() ;
    void bodyInit() {}
    void bodyToISO( BYTE_PTR rbp ) {}
    void bodyFromISO( CONST_BYTE_PTR rbp ) {}
    
        // This descriptor has no body, so no bodyToISO() or
        // bodyFromISO() methods are needed. 
};

//----------------------------------------------------------------------
// ENUM: ADType
//
//  Types of Allocation Descriptors
//
// DEFINITIONS:
//  
//  ad_Short        Short    (see ISO 4/14.14.1)
//  ad_Long         Long     (see ISO 4/14.14.2)
//  ad_Extended     Extended (see ISO 4/14.14.3)
//  ad_Embedded     No ADs; Embedded Data in their place
//                  (see ISO 4/14.6.8 bits 0-2)
//  ad_Unknown      Error condition. For internal use only.
//
// ABUSES:
//  NEVER set the ADType to ad_Unknown
//
//----------------------------------------------------------------------
enum ADType {
    ad_Short    =  0,
    ad_Long     =  1,
    ad_Extended =  2,
    ad_Embedded =  3,
    ad_Unknown  = -1
};

#ifdef _INCL_SSOBJS_
//----------------------------------------------------------------------
// ENUM: ADTableStopCondition
//
//  Specifies the stop condition for the last logical AD in this
//  table.
//
//  For example, the ADTable may have 10 entries, but the second
//  entry is a terminating AD (an ad with an extent length of zero).
//  In this case, the logical stop condition is ad_Terminating.
//  Likewise, a stop may be an ad_Continuation reference to an AED.
//  
//  If there are no stop conditions (ad_Nonstop), then all ADs in
//  this ADTable refer to extents in a logical chain.
//
// DEFINITIONS:
//  
//  ad_Nonstop       There are no logical stop conditions in the table.
//  ad_Terminating   We logically stop on a terminating AD.
//  ad_Continuation  We logically stop on a reference to an AED.
//
// ABUSES:
//
//----------------------------------------------------------------------
enum ADTableStopCondition {
    ad_Nonstop      = 0,
    ad_Terminating  = 1,
    ad_Continuation = 2
};
#endif  //  _INCL_SSOBJS_

//----------------------------------------------------------------------
// Class: ADTable     --DVM
//
//  This is a Field which holds a variable number of ADs or embedded data.
//
//  EmbeddedData is treated just like one-byte AllocationDescriptors -
//  i.e., numADs() returns number of bytes, lenAD() returns one, etc.
// 
// PUBLIC METHODS:
//  adType()        - returns the type of ADs held
//  numADs()        - returns the number of ADs held
//  maxADs()        - returns the maximum ADs given type and len.
//  shortADp()      - returns a pointer to short ADs.
//  longADp()       - returns a pointer to long ADs.
//  extendedADp()   - returns a pointer to extended ADs.
//  embeddedDatap() - returns a pointer to the embedded data.
//  error()         - returns the error state.
//  clear()         - Clears all entries in table. Does not free them.
//  fitToLen()      - Resizes to fit supplied byte length and ADType.
//                    NOTE: also clears all entries/embeddedData bytes.
//  fitEnts()       - Resizes to fit supplied number of ADs.
//  toISO()         - Boilerplate
//  fromISO()       - Boilerplate
//
// USAGE NOTES:
//  When adType() is ad_Embedded, fitEnts() will do nothing, and
//  numADs() will return Zero. 
// 
//----------------------------------------------------------------------
// COLLABORATORS:  
//  ShortAllocDesc
//  LongAllocDesc
//  ExtendedAllocDesc
//  SmallByteArray
//
// IMPLEMENTATION NOTES:
//  Could not properly swallow ADs without introducing inheritance at
//  their level (polymorphism). Tried to do the best we could with
//  this, however. NOTE that THIS is the reason that the ADs need
//  default constructors (we're newing C-style arrays of them).
//
//----------------------------------------------------------------------

class ADTable {

public:
    FieldInfo field;
private:

    ADType             adType_       ;
    UINT16             numADs_       ;
    ShortAllocDesc    *shortADp_     ;
    LongAllocDesc     *longADp_      ;
    ExtendedAllocDesc *extendADp_    ;
    SmallByteArray     embeddedData_ ;
    
protected:

    void freeADs() {
        delete [] shortADp_;  shortADp_  = NULL;
        delete [] longADp_;   longADp_   = NULL;
        delete [] extendADp_; extendADp_ = NULL;
    }

    void allocADs( UINT16 n, ADType at ) ;
public:
    ADTable( UINT16 o, UINT16 numADs, ADType at ) ;
    virtual ~ADTable();

    ADType adType() const { return adType_; }
    UINT16 numADs() const { return numADs_; }
    UINT16 maxADs( UINT16 lenADs, ADType at ) const ;

    ShortAllocDesc    *shortADp()     const { return shortADp_     ; }
    LongAllocDesc     *longADp()      const { return longADp_      ; }
    ExtendedAllocDesc *extendADp()    const { return extendADp_    ; }
    BYTE_PTR           embeddedDatap()      { return (BYTE_PTR)embeddedData_ ; }

#ifdef _INCL_SSOBJS_
    ADTableStopCondition appendToLogExtentList(Partition* partitionp, 
                                               LogExtentList& logExtentList, 
                                               UINT64 maxInfoLen, 
                                               UINT32& currentIndex, 
                                               Error& err) const;

    UINT32 fromLogExtentList(const LogExtentList& logExtentList, UINT32& currentListIndex, 
                             UINT32 beginADTableIndex, Error& err);

    // Set the AD at this index to be a continuation reference to the
    //   extent passed in.
    void setContinuationLogExtent(const LogExtent& extent, UINT32 adTableIndex, Error& err);

    // Populates the extent passed in with a continuation AD only if there
    //   is a continuation AD already in the AD table (this will be the
    //   last logical AD in the ADTable).
    void getContinuationLogExtent(Partition* partitionp, LogExtent& extent, 
                                  UINT32 adTableIndex, Error& err) const;
    // Force this entry to be a terminating AD entry in this ADTable
    //   list of ADs.  This means the extent will have a length of zero.
    void setTerminator(UINT32 adTableIndex, Error& err);

protected:
    void setContinued_(UINT32 adTableIndex, Error& err);
    Boolean isContinued_(UINT32 adTableIndex, Error& err) const;

    UINT64 getExtentLength_(UINT32 adTableIndex, Error& err) const;

    // Populate the exent passed in with the AD at the index specified.
    void toLogExtent_(Partition* partitionp, LogExtent& extent, 
                      UINT32 adTableIndex, Error& err) const;

    // Populate the AD at the index referenced with the extent passed in.
    void fromLogExtent_(const LogExtent& extent, UINT32 adTableIndex, Error& err);

public:
#endif   // #ifdef _INCL_SSOBJS_  

    void dump(CONST_CHAR_PTR  message) const;

#ifdef NSR_VERIFY
    Boolean operator != ( const ADTable & obj ) const ;
#endif

    Error error() const ;
    void clear() ;
    void fitToLen( UINT16 len, ADType at ) ;
    void fitToLen( UINT16 len ) ; // same allocDescType.
    void fitEnts( UINT16 ne, ADType at );
    void toISO( BYTE_PTR rbp ) ;
    void fromISO( CONST_BYTE_PTR rbp ) ;

};

// Class: ImplementUseVolumeDesc
//
// This is the representation of the implementation use volume
// descriptor. It is a standard volume descriptor in every respect,
// except that it has a large area devoted to implementation use.

class ImplementUseVolumeDesc : public TaggedDescriptor {

    static UINT8 descVersion_ ;

public:

    Uint32    volDescSeqNo ;
    ImplRegID implementID  ;
    Bytes     implementUse ;

    ImplementUseVolumeDesc() ;

#ifdef NSR_VERIFY
    Boolean operator != ( const ImplementUseVolumeDesc & obj ) const ;
#endif

protected:

#ifdef NSR_VERIFY
    Error bodyVerifyISO( CONST_BYTE_PTR rbp ) ;
#endif
    Error bodyError() const { return Error(error_None); };
    void bodyClear() ;
    void bodyInit() ;
    void bodyToISO( BYTE_PTR bp ) ;
    void bodyFromISO( CONST_BYTE_PTR bp ) ;
};

// Class: OSTAVolumeDesc
//
// This is the representation of the OSTA-defined implementation use
// volume descriptor. See OSTA 2.2.8 for its definition.

class OSTAVolumeDesc : public TaggedDescriptor {

    static UINT8  descVersion_ ;
    
public:

    Uint32        volDescSeqNo       ;
    OSTARegID     OSTAImplID         ;
    CharSpec      descCharSet        ;
    Dstring       logicalVolumeID    ;
    Dstring       logicalVolumeInfo1 ;
    Dstring       logicalVolumeInfo2 ;
    Dstring       logicalVolumeInfo3 ;
    ImplRegID     implementID        ;
    Bytes         implementUse       ;

    static String UDFLVInfoID ;

    OSTAVolumeDesc() ;

#ifdef NSR_VERIFY
    Boolean operator != ( const OSTAVolumeDesc & obj ) const ;
#endif

#ifdef NSR_VERIFY
    Error bodyVerifyISO( CONST_BYTE_PTR rbp ) ;
#endif
    Error bodyError() const;
    void  bodyClear() ;
    void  bodyInit() ;
    void  bodyToISO( BYTE_PTR bp ) ;
    void  bodyFromISO( CONST_BYTE_PTR bp ) ;
};

class AnchorVolumeDesc : public TaggedDescriptor {

public:

    ExtentDesc    mainVolDescSeqExt ;
    ExtentDesc    resvVolDescSeqExt ;
    ZeroBytes     reserved          ;

    AnchorVolumeDesc() ;

#ifdef NSR_VERIFY
    Boolean operator != ( const AnchorVolumeDesc & obj ) const ;
#endif

protected:

#ifdef NSR_VERIFY
    Error bodyVerifyISO( CONST_BYTE_PTR rbp ) ;
#endif
    Error bodyError() const ;
    void bodyClear() ;
    void bodyToISO( BYTE_PTR rbp ) ;
    void bodyFromISO( CONST_BYTE_PTR rbp ) ;
    
};

class PVDFlags {

public:
    FieldInfo field;
private:

public:

    Bit16   commonVolSetIdent;
    Ubits16 reserved;

    PVDFlags( UINT16 o ) ;
#ifdef NSR_VERIFY
    Boolean operator != ( const PVDFlags & obj ) const ;
#endif
    void clear() ;
    void toISO( BYTE_PTR rbp ) ;
    void fromISO( CONST_BYTE_PTR rbp ) ;

};

class PrimaryVolumeDesc : public TaggedDescriptor {

    static UINT8  descVersion_ ;

public:

    Uint32        volDescSeqNo     ; // used (=1)
    Uint32        priVolDescNo     ; // used (=0)
    Dstring       volumeIdentifier ; // used
    Uint16        volumeSeqNo      ; // used
    Uint16        maxVolumeSeqNo   ; // (=0) [maxVolSeqNo]
    Uint16        interchgLvl      ; // OSTA MV (=3)
    Uint16        maxInterchgLvl   ; // OSTA MV (=3)
    Uint32        charSetList      ; // OSTA (=0)
    Uint32        maxCharSetList   ; // OSTA (=0)
    Dstring       volumeSetID      ; // used
    CharSpec      descCharSet      ; // (=0)
    CharSpec      explCharSet      ; // (=0)
    ExtentDesc    volAbstract      ; // (=0,0)
    ExtentDesc    volCopyright     ; // (=0,0)
    RegID         applicationID    ; // (=0)
    TimeStamp     recordDateTime   ; // (=now)
    ImplRegID     implementID      ; // (same as all)
    ZeroBytes     implementUse     ; // (=0)
    Uint32        preVolDescSeqLoc ; // (=0)
    PVDFlags      flags            ; // (=1)
    ZeroBytes     reserved         ; // (=0)

    PrimaryVolumeDesc() ;

#ifdef NSR_VERIFY
    Boolean operator != ( const PrimaryVolumeDesc & obj ) const ;
#endif

protected:

#ifdef NSR_VERIFY
    Error bodyVerifyISO( CONST_BYTE_PTR rbp ) ;
#endif
    Error bodyError() const ;
    void bodyClear() ;
    void bodyInit() ;
    void bodyToISO( BYTE_PTR bp) ;
    void bodyFromISO( CONST_BYTE_PTR bp ) ;

};

class PartitionHdrDesc {

public:
    FieldInfo field;

    ShortAllocDesc unallocSpaceTable  ;
    ShortAllocDesc unallocSpaceBitmap ;
    ShortAllocDesc partIntegrityTable ;
    ShortAllocDesc freedSpaceTable    ;
    ShortAllocDesc freedSpaceBitmap   ;
    ZeroBytes      reserved           ;

    PartitionHdrDesc(UINT16 o) ;
#ifdef NSR_VERIFY
    Boolean operator != ( const PartitionHdrDesc & obj ) const ;
#endif
    void clear() ;
    void toISO( BYTE_PTR rbp ) ;
    void fromISO( CONST_BYTE_PTR rbp ) ;

};

class PDFlags {

public:
    FieldInfo field;
private:

public:

    Bit16   allocation ;
    Ubits16 reserved   ;

    PDFlags( UINT16 o ) ;
#ifdef NSR_VERIFY
    Boolean operator != ( const PDFlags & obj ) const ;
#endif
    void clear() ;
    void toISO( BYTE_PTR rbp ) ;
    void fromISO( CONST_BYTE_PTR rbp ) ;

};

enum AccessType {
    Unspecified  = 0,
    ReadOnly     = 1,
    WriteOnce    = 2,
    Rewritable   = 3,
    Overwritable = 4
};

class PartitionDesc : public TaggedDescriptor {

    static UINT8     descVersion_ ;

public:

    Uint32           volDescSeqNo      ;
    PDFlags          partitionFlags    ;
    Uint16           partitionNo       ;
    RegID            partitionContents ;
    PartitionHdrDesc partitionHdrDesc  ;
    Uint32           accessType        ;
    Uint32           partStartLoc      ;
    Uint32           partLength        ;
    ImplRegID        implementID       ;
    Bytes            implementUse      ;
    ZeroBytes        reserved          ;     

    PartitionDesc() ;

#ifdef NSR_VERIFY
    Boolean operator != ( const PartitionDesc & obj ) const ;
#endif

protected:

#ifdef NSR_VERIFY
    Error bodyVerifyISO( CONST_BYTE_PTR rbp ) ;
#endif
    Error bodyError() const ;
    void bodyClear() ;
    void bodyInit() ;
    void bodyToISO( BYTE_PTR rbp ) ;
    void bodyFromISO( CONST_BYTE_PTR rbp ) ;

};

class PartitionMap {

public:
    FieldInfo field;
private:

    void init() ;
    
public:

    Uint8       partitionMapType   ;
    Uint8       partitionMapLength ;
    Uint16      volumeSeqNo        ;
    Uint16      partitionNo        ;

    PartitionMap(UINT16 o = 0);

#ifdef NSR_VERIFY
    Boolean operator != ( const PartitionMap & obj ) const ;
#endif

    void clear() ;
    void toISO( BYTE_PTR rbp ) ;
    void fromISO( CONST_BYTE_PTR rbp ) ;

};

class PartMapTable {

public:
    FieldInfo field;
private:

    PartitionMap nullEntry;

    UINT16 numEnts;

public:

    PartitionMap *entry;
    
protected:

    void freeEnts() { delete [] entry; entry = NULL; }
    void allocEnts( UINT16 ne ) ;

public:
    
    PartMapTable( UINT16 o, UINT16 ne ) ;
    virtual ~PartMapTable();

    UINT16 num_ents() const { return numEnts; }

    PartitionMap &operator[]( UINT16 i) ;
    const PartitionMap &operator[]( UINT16 i) const ;
#ifdef NSR_VERIFY
    Boolean operator != ( const PartMapTable & obj ) const ;
#endif
    Error error() const ;
    void clear() ;
    void fitEnts( UINT16 ne ) ;
    void toISO( BYTE_PTR rbp ) ;
    void fromISO( CONST_BYTE_PTR rbp ) ;

};

class LogicalVolumeDesc : public TaggedDescriptor {

    static UINT8  descVersion_ ;

public:

    Uint32        volDescSeqNo       ;
    CharSpec      descCharSet        ;
    Dstring       logicalVolumeID    ;
    Uint32        logicalBlockSize   ;
    DomainRegID   domainID           ;
    LongAllocDesc fileSetDesc        ;
    Uint32        mapTableLength     ;
    Uint32        noPartMaps         ;
    ImplRegID     implementID        ;
    Bytes         implementUse       ;
    ExtentDesc    integritySeqExtent ;
    PartMapTable  partitionMapTable  ;

    LogicalVolumeDesc( UINT32 n = 1 ) ; 

    WriteProtectType writeProtect() { return domainID.writeProtect(); }
    void writeProtect(WriteProtectType wpt) { domainID.writeProtect(wpt); }

#ifdef NSR_VERIFY
    Boolean operator != ( const LogicalVolumeDesc & obj ) const ;
#endif

protected:

#ifdef NSR_VERIFY
    Error bodyVerifyISO( CONST_BYTE_PTR rbp ) ;
#endif
    Error bodyError() const ;
    void bodyClear() ;
    void bodyInit() ;
    void bodyToISO( BYTE_PTR rbp ) ;
    void bodyFromISO( CONST_BYTE_PTR rbp ) ;

};

// ISSUE: USDs do NOT properly read in extentDescriptors.
//        Instead, it ONLY writes out a USD with an empty
//        extentDescriptor Table. Another field must be added here in
//        order to provide access to them. (not counting another
//        class, ExtentDescTable...)

// WARNING: DO NOT READ AND THEN WRITE USDs

class UnallocatedSpaceDesc : public TaggedDescriptor {

public:

    Uint32    volDescSeqNo   ;
    Uint32    numAllocDescs  ;

    UnallocatedSpaceDesc() ;

#ifdef NSR_VERIFY
    Boolean operator != ( const UnallocatedSpaceDesc & obj ) const ;
#endif

protected:

#ifdef NSR_VERIFY
    Error bodyVerifyISO( CONST_BYTE_PTR rbp ) ;
#endif
    Error bodyError() const ;
    void bodyClear() ;
    void bodyToISO( BYTE_PTR rbp ) ;
    void bodyFromISO( CONST_BYTE_PTR rbp ) ;

};

class TerminatingDesc : public TaggedDescriptor {

public:

    ZeroBytes   reserved;

    TerminatingDesc() ;

protected:
    
#ifdef NSR_VERIFY
    Error bodyVerifyISO( CONST_BYTE_PTR rbp ) {
        return Error(error_None);
    }
#endif

    Error bodyError() const {
        return Error(error_None);
    }

    void bodyClear() {
        reserved .clear();
    }

    void bodyToISO( BYTE_PTR rbp ) {
        reserved .toISO( rbp );
    }

    void bodyFromISO( CONST_BYTE_PTR rbp ) {
        reserved .fromISO( rbp );
    }

};

class FileSetDesc : public TaggedDescriptor {

public:

    TimeStamp     recordDateTime         ;
    Uint16        interchgLevel          ;    
    Uint16        maxInterchgLevel       ; 
    Uint32        charSetList            ;      
    Uint32        maxCharSetList         ;   
    Uint32        fileSetNo              ;
    Uint32        fileSetDescNo          ;
    CharSpec      logicalVolumeIDCharSet ;
    Dstring       logicalVolumeID        ;
    CharSpec      fileSetCharSet         ;
    Dstring       fileSetID              ;
    Dstring       copyrightFileID        ;
    Dstring       abstractFileID         ;
    LongAllocDesc rootDirICB             ;
    DomainRegID   domainID               ;
    LongAllocDesc nextExtent             ;
    ZeroBytes     reserved               ;

    FileSetDesc() ;

    WriteProtectType writeProtect() { return domainID.writeProtect(); }
    void writeProtect(WriteProtectType wpt) { domainID.writeProtect(wpt); }

#ifdef NSR_VERIFY
    Boolean operator != ( const FileSetDesc & obj ) const ;
#endif

protected:

#ifdef NSR_VERIFY
    Error bodyVerifyISO( CONST_BYTE_PTR rbp ) ;
#endif
    Error bodyError() const ;
    void bodyClear() ;
    void bodyInit() ;
    void bodyToISO( BYTE_PTR rbp ) ;
    void bodyFromISO( CONST_BYTE_PTR rbp ) ;

};

class Uint32Table {

public:
    FieldInfo field;
private:

    Uint32 nullEntry;

    UINT16 numEnts;

public:

    Uint32 *entry;
    
protected:

    void freeEnts() {
        delete [] entry;
        entry = NULL;
    }
    void allocEnts( UINT16 ne ) ;

public:
    
    Uint32Table( UINT16 o, UINT16 ne ) ;
    virtual ~Uint32Table() ;

    UINT16 num_ents() const { return numEnts; }

    Uint32 &operator[]( UINT16 i) ;
    const Uint32 &operator[]( UINT16 i) const ;
#ifdef NSR_VERIFY
    Boolean operator != ( const Uint32Table & obj ) const ;
#endif
    Error error() const ;
    void clear() ;
    void fitEnts( UINT16 ne ) ;
    void toISO( BYTE_PTR rbp ) ;
    void fromISO( CONST_BYTE_PTR rbp ) ;
};

class Int32Table {

public:
    FieldInfo field;
private:

    Int32 nullEntry;

    UINT16 numEnts;

public:

    Int32 *entry;
    
protected:

    void freeEnts() {
        delete [] entry;
        entry = NULL;
    }
    void allocEnts( UINT16 ne ) ;

public:
    
    Int32Table( UINT16 o, UINT16 ne ) ;
    virtual ~Int32Table() ;

    UINT16 num_ents() const { return numEnts; }

    Int32 &operator[]( UINT16 i) ;
    const Int32 &operator[]( UINT16 i) const ;
#ifdef NSR_VERIFY
    Boolean operator != ( const Int32Table & obj ) const ;
#endif
    Error error() const ;
    void clear() ;
    void fitEnts( UINT16 ne ) ;
    void toISO( BYTE_PTR rbp ) ;
    void fromISO( CONST_BYTE_PTR rbp ) ;
};

// this enum specifies important locations
// for volume structures. It is ok to have
// non-unique values.
enum locations {

    // 1024 byte sector locations
    LOC_VRS_1024   = 32,
                                // 38-32 = 6 sectors for VolRecogSeq
    LOC_MVDS_1024  = 38,
                                // 56-38 = 18 sectors for main vds
    LOC_RVDS_1024  = 56,
                                // 74-56 = 18 sectors for reserve vds
    LOC_LVID_1024  = 74,   

    // 512 byte sector locations
    LOC_VRS_512    = 64,
                                // 76-64   = 12 sectors for VolRecogSeq
    LOC_MVDS_512   = 76,
                                // 100-76  = 24 sectors for main vds
    LOC_RVDS_512   = 100,
                                // 124-100 = 24 sectors for reserve vds
    LOC_LVID_512   = 124,

    // other locations
    LOC_AVD1       = 256,
    LOC_PART_START = 257,
    LOC_USE        = 257,
    LOC_FILE_DATA_START_MIN = 300  
};

// for worm, may need indirect entries that point
// to a new extent that can be used for ICB/s. This
// enum defines how large that extent will be.
enum { incrementalICBs = 20 };

//----------------------------------------------------------------------
// ENUM: IntegrityType
//
//  Types of integrity which may be recorded and/or found on the
//  LogicalVolume.
//
// DEFINITIONS:
//  integ_Unknown  (read-only) invalid value recorded in descriptor.
//  integ_Open     Dirty.
//  integ_Closed   Clean.
//
// USES:
//  optional
//
// ABUSES:
//  optional
//
// NOTES:
//  optional
//
//----------------------------------------------------------------------
// Private comments go here - will not be extracted into HTML.
//----------------------------------------------------------------------
enum IntegrityType {
    integ_Unknown   =-1,
    integ_Open      = 0,
    integ_Closed    = 1
};

//----------------------------------------------------------------------
// ENUM: LVIDType
//
//  Specifies which type of LVID is to be written.
//
// DEFINITIONS:
//  lvid_WithICBTable Includes an ICBTable at end.
//  lvid_Simple       Does not include ICBTable.
//
// USES:
//  optional
//
// ABUSES:
//  optional
//
// NOTES:
//  Version with ICBTable should only be found on older HP Archive
//  Server disks. More recent products use an EA on the Root ICB.
//
//----------------------------------------------------------------------
// Private comments go here - will not be extracted into HTML.
//----------------------------------------------------------------------
enum LVIDType {
    lvid_WithICBTable = 0,
    lvid_Simple       = 1
};

//----------------------------------------------------------------------
// The LogicalVolumeIntegrityDesc supports two versions:
//
// Version 0 - has ICBTable at end
// Version 1 - Does not have ICBTable
//
// In order to select which one you will WRITE, simply modify the
// static variable:
//     NSR::LogicalVolumeIntegrityDesc::descVersion_
//
// NOTE that this DOES NOT AFFECT what is read -- the
// descriptorVersion is recorded in the descriptor itself, and it
// adapts to whatever it finds. NOTE ALSO that since no method is
// provided to SET the descVersion, it uses the default from the
// static above, OR the last type to be fromISO()ed, whichever is more
// recent. Essentially, the static dictates what gets filled in on a
// call to clear() and at construction.
// 
// The Boolean method hasICBTable() is provided for user convenience.

class LogicalVolumeIntegrityDesc : public TaggedDescriptor {

public:

    static UINT8   descVersion_ ; // Specifies which one to write.

    TimeStamp      recordDateTime      ;
    Uint32         integrityType_      ;
    ExtentDesc     nextIntegrityExtent ;
    Uint64         uniqueID            ;
    ZeroBytes      reserved            ;
    Uint32         numPartitions       ;
    Uint32         lenImplementUse     ;
    Uint32Table    freeSpaceTable      ;
    Uint32Table    sizeTable           ;
    ImplRegID      implementID         ;
    Uint32         numFiles            ;
    Uint32         numDirectories      ;
    Uint32         icbTableLength      ;
    ADTable        icbTable            ;

    LogicalVolumeIntegrityDesc( UINT32 n, UINT32 licbt = 1) ;
    Boolean hasICBTable() const {
        if ( implementID.descVersionNo() == lvid_WithICBTable )
            return True;
        else
            return False;
    }
    
    LongAllocDesc * icbTbl() { return ( icbTable.longADp() ); }
    UINT16 numEnts() const { return ( icbTable.numADs() ); }

#ifdef NSR_VERIFY
    Boolean operator != ( const LogicalVolumeIntegrityDesc & obj ) const ;
#endif

private:

    void affixFloatingFields() ;
    void affixImplUseFields() ;

public:

    IntegrityType integrityType(void) const;
    void integrityType(IntegrityType it) { integrityType_ = it; }
    
protected:

#ifdef NSR_VERIFY
    Error bodyVerifyISO( CONST_BYTE_PTR rbp ) ;
#endif
    Error bodyError() const ;
    void bodyClear() ;
    void bodyInit() ;
    void bodyToISO( BYTE_PTR rbp ) ;
    void bodyFromISO( CONST_BYTE_PTR rbp ) ;

};

#endif
