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

//----------------------------------------------------------------------
//  nsrFile.h
//   Descriptors related to part 4 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:
//    SpaceBitmapDesc
//    SpaceBitmapMap
//    PagedSpaceBitmapMap
//    ICBFlags
//    ICBTag
//    FilePerms
//    FileEntry
//    AllocExtentDesc
//    IndirectEntry
//    TerminalEntry
//    FileCharacteristics
//    FileIdentifierDesc
//    UnallocatedSpaceEntry
//    PathComponent
//  
//----------------------------------------------------------------------
// $Source: /projects/HMS/nsr/udfCore/descr/nsrFile.h,v $
// $Revision: 1.32 $    $Author: hmgr $
// $State: Exp $        $Locker:  $
// $Date: 96/05/21 09:48:51 $

//----------------------------------------------------------------------
// CLASS: SpaceBitmapDesc     --DVM
//
//  The Space Bitmap Descriptor
//
//  This supports only the 24-byte header for the Space Bitmap
//
// PUBLIC DATA MEMBERS:
//  DescriptorTag   tag       Same as all other TaggedDescriptors
//  UINT32          numBits   The number of bits
//  UINT32          numBits   The number of bytes
//
// PUBLIC METHODS:
//  SAME AS ALL TaggedDescriptors:
//  Error error()     - returns error if in error state.
//  void descLen()    - returns length of the descriptor
//  void clear()      - sets state to same as when instantiated
//  void toISO()      - Translates to ISO form in supplied buffer
//  void fromISO()    - Translates from ISO form in supplied buffer
//  Error verifyISO() - Compares object with ISO form in buffer
// USAGE NOTES:
//  - CRC is NOT calculated over the entire bitmap, but rather only
//    over the header (i.e., over the structure defined here).
//  - descLen() is ALWAYS 24 bytes !!! On read, too?
// 
//----------------------------------------------------------------------
// COLLABORATORS:  
//  Derived from TaggedDescriptor
//
// PRIVATE METHODS:
//  Boolean operator!=()
//  Error bodyVerifyISO()
//  Error bodyError()
//  void bodyClear()
//  void bodyInit()
//  void bodyToISO()
//  void bodyFromISO()
//
// IMPLEMENTATION NOTES:
//  !!! How does Bitmap handle ISO forms with longer DescLengths?
//  Does this enforce the rule about numBytes fitting numBits?
//  Does it hide numBytes altogether?
//
//----------------------------------------------------------------------

class SpaceBitmapDesc : public TaggedDescriptor {

    Uint32 numBits_  ;
    Uint32 numBytes_ ;

public:

    SpaceBitmapDesc( UINT32 nb = 0 ) ;

    void numBits(UINT32 nb) {
        numBits_  = nb;
        bodyInit();
    }
        
    UINT32 numBits(void)  const { return numBits_  ; }
    UINT32 numBytes(void) const { return numBytes_ ; }
    
#ifdef NSR_VERIFY
    Boolean operator != ( const SpaceBitmapDesc & 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 rbp ) ;
    void bodyFromISO( CONST_BYTE_PTR rbp ) ;
} ;

//----------------------------------------------------------------------
// CLASS: SpaceBitmapMap     --DVM
//
//  This maps the logical concept of a bitmap to its physical
//  representation.
//
//  This supports the concept of a bitmap as having a space of bits,
//  each with its own bit address. It provides block numbers, byte
//  offsets into a block, and bit masks, so that individual bits may
//  be accessed and modified. It is a "helper" class, and NOT a
//  container class, like the rest of the descriptor-level objects. It
//  has NO to/fromISO(), but holds state obtained at construction from
//  the SpaceBitmapDesc.
//
//  It is intended for the user to first use the SpaceBitmapDesc to
//  identify and find the size of a bitmap, but then, that the bitmap
//  may be read into a ByteArray (potentially a page at a time). This
//  class, then, is intended to provide all of the information about
//  where that bit resides on the disk and in the ByteArray.
//
// PUBLIC METHODS:
//  SpaceBitmapMap()       - Constructor which requires a
//                           SpaceBitmapDesc, the block number where
//                           it is located in the partition, and the
//                           block size of the medium.
//  blockSize()            - Returns the logical block size of the
//                           partition (specified in the
//                           constructor).
//  startBlock()           - Returns the logical block address of the
//                           first block of the bitmap (specified in
//                           the constructor).
//  startByteOffset()      - Returns the byte offset to the start of
//                           the actual bitmap data (accounts for the
//                           header image).
//  blockStartByteOffset() - Returns the byte offset to the start of
//                           the actual bitmap data in the specified
//                           block (value is zero except for the first
//                           block).
//  numBits()              - Returns the number of bits in the bitmap
//                           data. 
//  bitComponent()         - Static function that returns only the bit
//                           residue in the final byte of a given bit
//                           offset.
//  byteComponent()        - Static function that returns the number
//                           of COMPLETE bytes represented by a given
//                           bit offset.
//  bitNumber()            - Static function that translates a byte
//                           offset into a bit offset.
//  bitNumber()            - Static function that translates a byte
//                           offset and bit residue into a single bit
//                           offset.
//  maskBit()              - Static function that generates a mask
//                           byte to extract a specified bit.
//  maskBits()             - Static function that generates a mask
//                           byte to extract a specified range of bits.
//  blockAbsToRel()        - Converts a logical block number to a block
//                           offset relative to the start of the bitmap.
//  blockRelToAbs()        - Converts a block number relative to the
//                           start of the bitmap to an absolute
//                           logical block number.
//  maxExtentBlocks()      - Returns the maximum number of blocks a
//                           logical extent may contain.
//  bytesToBlocks()        - Returns the number of logical blocks
//                           needed to contain the specified number of
//                           bytes. 
//  blocksToBytes()        - Returns the total number of bytes
//                           represented by the specified number of
//                           logical blocks.
//  blockNum()             - Returns the relative offset to the block
//                           containing the specified bit address.
//  blockBitOffset()       - Returns the residule bit offset within a
//                           logical block of a specified bit address.
//  blockBitAddr()         - Returns the bit address of a specified
//                           bit offset within a specified block.
//
// USAGE NOTES:
//
//  This is to be used AFTER using the SpaceBitmapDesc, in order to
//  access individual bits in the SpaceBitmap. It merely provides
//  information about where bits are located, and leaves the task of
//  reading and writing individual pages of the bitmap up to the user.
//
//  It supports arbitrary-sized paging of bitmaps, by supporting an
//  optional BlockNum in the byteOffset() method.
//
//  Once it is constructed, the SpaceBitmapDesc passed in may be
//  destroyed, since this object contains neither a pointer nor a
//  reference to it, but rather extracts all the information it needs
//  at that time.
//
//  NOTE that the first block of the SpaceBitmap contains the
//  SpaceBitmapDesc (at its beginning). Also NOTE that this class
//  takes that descriptor's presence into account, so that it will
//  NEVER return values allowing the SpaceBitmapDesc to be
//  modified. Therefore, if only the addresses returned by this class
//  are used for modifying bits, the first block in the bitmap area
//  may be read/modified/written with no risk to the SpaceBitmapDesc
//  becoming corrupted. Thus, the user may view this as presenting the
//  entire SpaceBitmap area as ONLY a bitmap which may be easily paged
//  in and out to disk.
//
//----------------------------------------------------------------------
// COLLABORATORS:
//  SpaceBitmapDesc
//
// PRIVATE METHODS:
//  NONE
//
// IMPLEMENTATION NOTES:
//
//  The methods are ALL kept inline, so that this is as fast as
//  possible.  These functions represent the rudimentary translations
//  used to address and manipulate data in the bitmap.  No range
//  checking or error trapping is provided.
//
//  Future versions may feature methods which support multiple-bit
//  access to bitmap information.
//
//----------------------------------------------------------------------
class SpaceBitmapMap {

    UINT16 blockSize_;
    UINT32 startBlock_;
    UINT32 startByteOffset_;
    UINT32 numBits_;

public:

    SpaceBitmapMap(const SpaceBitmapDesc& clDesc,
                   UINT32 nStartBlock,
                   UINT16 nBlockSize):
            blockSize_       (nBlockSize),
            startBlock_      (nStartBlock),
            startByteOffset_ (clDesc.descLen()),
            numBits_         (clDesc.numBits())
    {}

    UINT16 blockSize() const
    { return blockSize_; }

    UINT32 startBlock() const
    { return startBlock_; }

    UINT32 startByteOffset() const
    { return startByteOffset_; }

    UINT32 blockStartByteOffset(UINT32 nBlock) const
    { return (nBlock ? 0 : startByteOffset_); }

    UINT32 numBits() const
    { return numBits_; }

    static UINT32 bitComponent(UINT32 nBit)
    { return (nBit & 0x07); }

    static UINT32 byteComponent(UINT32 nBit)
    { return (nBit >> 3); }

    static UINT32 bitNumber(UINT32 nByte)
    { return (nByte << 3); }

    static UINT32 bitNumber(UINT32 nByte, UINT32 nBit)
    { return (bitNumber(nByte) + nBit); }

    static BYTE maskBit(UINT32 nBit)
    { return (1 << nBit); }

    static BYTE maskBits(UINT32 nStartBit, UINT32 nEndBit)
    { return (0xff << nStartBit) ^ (0xff << nEndBit); }

    UINT32 blockAbsToRel(UINT32 nBlock) const
    { return (nBlock - startBlock_); }

    UINT32 blockRelToAbs(UINT32 nBlock) const
    { return (nBlock + startBlock_); }

    UINT32 maxExtentBlocks() const {
        return ((MAX_UINT32 >> 2) / blockSize_);
    }

    UINT32 bytesToBlocks(UINT64 nBytes) const {
        return UINT32((nBytes + UINT64(blockSize_ - 1)) /
                      UINT64(blockSize_));
    }

    UINT64 blocksToBytes(UINT32 nBlocks) const {
        return UINT64(nBlocks) * UINT64(blockSize_);
    }

    UINT32 blockNum(UINT32 nBitAddr) const {
        return (byteComponent(nBitAddr) + startByteOffset_) /
            blockSize_;
    } 

    UINT32 blockBitOffset(UINT32 nBitAddr) const {
        UINT32 nTemp = (byteComponent(nBitAddr) + startByteOffset_);
        if (nTemp < blockSize_)
            nTemp -= startByteOffset_;
        else
            nTemp %= blockSize_;
        return (bitNumber(nTemp) + bitComponent(nBitAddr));
    }

    UINT32 blockBitAddr(UINT32 nBlock, UINT32 nOffset) const {
        return (nBlock * blockSize_ -
                bitNumber(nBlock ? startByteOffset_ : 0) + nOffset);
    }
};

//----------------------------------------------------------------------
// CLASS: PagedSpaceBitmapMap     --GKG
//
//  This maps the logical concept of a paged bitmap implementation
//  to its physical representation.
//
//  This class is derived from the SpaceBitmapMap, and is intended to
//  augment its functionality by providing translations to facilitate
//  bit addressing within the "paged" bitmap mechanism used by the
//  BitmapSpaceResource class.  These translations are specifically
//  adapted to this particular implementation, and are thus somewhat
//  less generic. It is a "helper" class, and NOT a container class,
//  like the rest of the descriptor-level objects. It has NO to/fromISO(),
//  but holds state obtained at construction from the SpaceBitmapDesc.
//
//  It is intended for the user to first use the SpaceBitmapDesc to
//  identify and find the size of a bitmap page, but then, that the
//  bitmap page may be read into a ByteArray.  This class, then, is
//  intended to provide all of the information about where that bit
//  resides on the disk and in the ByteArray as it relates to the
//  paged implementation.
//
// PUBLIC METHODS:
//  PagedSpaceBitmapMap()  - Constructor which requires a
//                           SpaceBitmapDesc, the block number where
//                           it is located in the partition, and the
//                           block size of the medium.
//  pageSize()             - Returns the size (in bytes) of the pages
//                           into which the bitmap has been segmented.
//                           The actual size of the last page may be
//                           smaller than this value as it contains
//                           the residue. This value is always an even
//                           muliple of the logical blocks size.
//  numPages()             - Returns the number of pages into which
//                           the bitmap has been segmented.
//  blocksPerPage()        - Returns the number of logical blocks that
//                           fill the page size.
//  pageStartBlock()       - Returns the logical block number of the
//                           first block in the specified page.
//  pageAbsToRel()         - Converts a logical block number to a
//                           block offset relative to the start of the
//                           page.
//  pageRelToAbs()         - Converts a block number relative to the
//                           start of the page to an absolute logical
//                           block number.
//  pageStartByteOffset()  - Returns the offset (in bytes) to the
//                           beginning of the bitmap data withing the
//                           specified page. This value should be zero
//                           except when specifing page zero.
//  pageNum()              - Returns the page number of the page
//                           containing the specified bit address.
//  pageBitOffset()        - Returns the residule bit offset within a
//                           page of a specified bit address.
//  pageBitAddr()          - Returns the bit address of a specified
//                           bit offset within a specified page.
//  pageBitSize()          - Returns the size of the specified page in
//                           bits. The value is the same for all pages
//                           except possibly the last page (which may
//                           be smaller than the others).
//  pageByteSize()         - Returns the size of the specified page in
//                           bytes. The value except possibly the last
//                           page.
//  pageBlockSize()        - Returns the size of the specified page in
//                           logical blocks.  The value is the same
//                           for all pages except possibly the last
//                           page.
//  pageBitResidue()       - Returns the number of residule bits in
//                           the last byte of the specified page (can
//                           only be non-zero for the last page).
//  pageNumBits()          - Returns the number of bits in the
//                           specified page representing bitmap data.
//                           Excludes space used by the header
//                           (differentiating it from pageBitSize()).
//  pageOffsetToBufferPos()- Converts a bit address within a page into
//                           a bit offset within the page memory
//                           buffer.
//  bufferPosToPageOffset()- Converts a bit offset within the page
//                           memory buffer to a bit address within the
//                           page.
//  bufferBlockOffset()    - Returns the block offset within the page
//                           memory buffer of a given bit offset
//                           within a given page within a specified
//                           block.
//
// USAGE NOTES:
//
//  This is to be used AFTER using the SpaceBitmapDesc, in order to
//  access individual bits in the SpaceBitmap. It merely provides
//  information about where bits are located, and leaves the task of
//  reading and writing individual pages of the bitmap up to the user.
//
//  It supports arbitrary-sized paging of bitmaps, by supporting an
//  optional BlockNum in the byteOffset() method.
//
//  Once it is constructed, the SpaceBitmapDesc passed in may be
//  destroyed, since this object contains neither a pointer nor a
//  reference to it, but rather extracts all the information it needs
//  at that time.
//
//  NOTE that the first block of the SpaceBitmap contains the
//  SpaceBitmapDesc (at its beginning). Also NOTE that this class
//  takes that descriptor's presence into account, so that it will
//  NEVER return values allowing the SpaceBitmapDesc to be
//  modified. Therefore, if only the addresses returned by this class
//  are used for modifying bits, the first block in the bitmap area
//  may be read/modified/written with no risk to the SpaceBitmapDesc
//  becoming corrupted. Thus, the user may view this as presenting the
//  entire SpaceBitmap area as ONLY a bitmap which may be easily paged
//  in and out to disk.
//
//----------------------------------------------------------------------
// COLLABORATORS:
//  SpaceBitmapDesc
//
// PRIVATE METHODS:
//  NONE
//
// IMPLEMENTATION NOTES:
//
//  The methods are ALL kept inline, so that this is as fast as
//  possible.  These functions represent the rudimentary translations
//  used to address and manipulate data in the bitmap.  No range
//  checking or error trapping is provided.
//
//  Future versions may feature methods which support multiple-bit
//  access to bitmap information.
//
//----------------------------------------------------------------------
class PagedSpaceBitmapMap : public SpaceBitmapMap {

    enum
    {
        defaultPageSize         = 8192
    };

    UINT32 pageSize_;
    UINT32 numPages_;
    UINT32 blocksPerPage_;

public:

    PagedSpaceBitmapMap(const SpaceBitmapDesc& clDesc,
                        UINT32 nStartBlock,
                        UINT16 nBlockSize):
            SpaceBitmapMap(clDesc, nStartBlock, nBlockSize)
    {
        blocksPerPage_ = defaultPageSize / nBlockSize;
        pageSize_ = blocksPerPage_ * nBlockSize;
        numPages_ = (byteComponent(numBits()) + startByteOffset() +
                     pageSize_ - 1) / pageSize_; 
    }

    UINT32 pageSize() const
    { return pageSize_; }

    UINT32 numPages() const
    { return numPages_; }

    UINT32 blocksPerPage() const
    { return blocksPerPage_; }

    UINT32 pageStartBlock(UINT32 nPage) const
    { return (startBlock() + nPage * blocksPerPage_); }

    UINT32 pageAbsToRel(UINT32 nPage, UINT32 nBlock) const
    { return (nBlock - pageStartBlock(nPage)); }

    UINT32 pageRelToAbs(UINT32 nPage, UINT32 nBlock) const
    { return (nBlock + pageStartBlock(nPage)); }

    UINT32 pageStartByteOffset(UINT32 nPage) const
    { return (nPage ? 0 : startByteOffset()); }

    UINT32 pageNum(UINT32 nBitAddr) const
    { return (byteComponent(nBitAddr) + startByteOffset()) / pageSize_; }

    UINT32 pageBitOffset(UINT32 nBitAddr) const
    {
        UINT32 nTemp = (byteComponent(nBitAddr) + startByteOffset());
        if (nTemp < pageSize_)
            nTemp -= startByteOffset();
        else
            nTemp %= pageSize_;
        return (bitNumber(nTemp) + bitComponent(nBitAddr));
    }

    UINT32 pageBitAddr(UINT32 nPage, UINT32 nOffset) const {
        return (bitNumber(nPage * pageSize_ -
                          (nPage ? startByteOffset() : 0))
                + nOffset); } 

    UINT32 pageBitSize(UINT32 nPage) const {
        return (nPage == numPages_ - 1) ?
            (numBits() + bitNumber(startByteOffset())) % pageSize_ :
            bitNumber(pageSize_); } 

    UINT32 pageByteSize(UINT32 nPage) const {
        return (nPage == numPages_ - 1) ?
            (byteComponent(numBits() + 7) + startByteOffset()) %
            pageSize_ :
            pageSize_; }

    UINT32 pageBlockSize(UINT32 nPage) const
    { return (pageByteSize(nPage) + blockSize() - 1) / blockSize(); }

    UINT32 pageBitResidue(UINT32 nPage) const
    { return (nPage == numPages_ - 1) ? numBits() & 0x07 : 0; }

    UINT32 pageNumBits(UINT32 nPage) const
    {
        UINT32 nSize = bitNumber(pageByteSize(nPage) -
                                 pageStartByteOffset(nPage));
        if (pageBitResidue(nPage))
            nSize += pageBitResidue(nPage) - 8;
        return nSize;
    }

    UINT32 pageOffsetToBufferPos(UINT32 nPage, UINT32 nOffset) const
    { return (nOffset + bitNumber(pageStartByteOffset(nPage))); }

    UINT32 bufferPosToPageOffset(UINT32 nPage, UINT32 nPosition) const
    { return (nPosition - bitNumber(pageStartByteOffset(nPage))); }

    UINT32 bufferBlockOffset(UINT32 nPosition) const
    { return (byteComponent(nPosition) / blockSize()); }
};

class ICBFlags {

public:
    FieldInfo field;
private:

public:

    Ubits16 adType;
    Ubits16 miscCharacteristics; // All sorts of bits...
    Ubits16 reserved;

    ICBFlags( UINT16 o ) ;

private:

    void init() ;

public:

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

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

};

//----------------------------------------------------------------------
// ENUM: FileType
//
//  Describes the type of file for the Attributes class.
//
// DEFINITIONS:
//  file_Unspecified             
//  file_Directory                
//  file_Raw                    
//  file_SpecialBlockDevice    
//  file_SpecialCharacterDevice 
//  file_ExtendedAttributes   
//  file_Fifo                
//  file_Sock               
//  file_SymbolicLink      
//
// USES:
//  optional
//
// ABUSES:
//  optional
//
// NOTES:
//  optional
//
// NOTE:  The FileType enum was split out into ICBType enum
//   and FileType enum.  (This is because the ICB constructor
//   should only have values of the ICBType enum, whereas the
//   Attributes class should only allow users to set values
//   of the new FileType enum (not ICBType enum).
// NOTE:  Both new enums do not overlap in values, because the
//   values refer to the FileTypes specified in the standard
//   (Part 4, Page 20, Figure 17: FileTypes.)
//   may actually be s
//----------------------------------------------------------------------

enum ICBType {
    // These are types of entries.

    // If the ICBTag is instantiated with icb_FileEntry, the
    //   file type is unspecified (file_Unspecified).  This
    //   happens automatically, because both share the same enum
    //   value.
    icb_FileEntry              =  0,  
    icb_UnallocatedSpaceEntry  =  1,
    icb_PartIntegrityEntry     =  2,
    icb_IndirectEntry          =  3,
    icb_TerminalEntry          = 11

    // If the ICBTag is storing any of the FileType types, then
    //   it will report that it is merely an icb_FileEntry.
    // RECALL:  The ICBTag is storing all 8 bits, so it knows
    //   exactly what the type is (across these two enums).
    //   Likewise, the Attributes struct is packing the FileType
    //   into 4 bits, and knows exactly what the value is (across
    //   both enums).

};

enum FileType {

    // Default to file_Unspecified in Attributes struct.
    file_Unspecified            =  0,
    file_Directory              =  4,
    file_Raw                    =  5,
    file_SpecialBlockDevice     =  6,
    file_SpecialCharacterDevice =  7,
    file_ExtendedAttributes     =  8,
    file_Fifo                   =  9,
    file_Sock                   = 10,
    file_SymbolicLink           = 12,
    // Match for any value in the ICBType enum.
    // The Attributes struct will report one of these values
    //   when queried.  If the type is REALLY one of the ICBTypes, 
    //   then this is really an invalid file (and Attributes will
    //   report the following):
    // /
    file_InvalidFile            = -1
};

// NOTE:  The members of this class reflect the sizes and orders
//   that these items are mapped to the surface.  --CSB.
class ICBTag {

public:
    FieldInfo field;
private:

public:

    Uint32              priNoDirectEntries ;
    Uint16              strategyType       ;
    Uint16              strategyParm       ;
    Uint16              maxEntries         ;
    ZeroBytes           reserved           ;
protected:
    Uint8               fileType_          ;
public:
    LogicalBlockAddr    parentICB          ;
    ICBFlags            flags              ;

    // The constructor takes an ICBType, a more restrictive
    //   subset of the previous FileType (more accurate).
    ICBTag( UINT16 o, ICBType icbType, ADType at = ad_Short ) ;

    void adType(ADType at) { flags.adType = at; }
    ADType adType(void) const ;

    // icbType() and fileType() access the same field, but the former
    // is used directly, while the UINT8 version is used by the
    // Attributes class.
    void icbType(ICBType icbt) { fileType_ = (UINT8) icbt; }
    ICBType icbType(void) const;
    void fileType(UINT8 ft) { fileType_ = ft; }
    UINT8 fileType(void) const { return fileType_; }
        
private:

    void init() ;

public:    

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

class FilePerms {

public:
    FieldInfo field;
private:

public:
    
    Ubits32 all      ;
    Ubits32 reserved ;

    FilePerms( UINT16 o ) ;

private:

    void init() ;

public:

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

};

// CSB:  9-6-95  We removed isDirectory(), isExtAttr(), etc.
//   because the user should really go through the Attributes
//   class when processing this information.

class FileEntry : public TaggedDescriptor {

    static UINT8  descVersion_ ;

public:

    ICBTag        icbTag                ;
    Uint32        uid                   ;
    Uint32        gid                   ;                     
    FilePerms     permissions           ;              
    Uint16        fileLinkCount         ;
    Uint8         recordFormat          ;
    Uint8         recordDisplayAttr     ;
    Uint32        recordLength          ;
    Uint64        infoLength            ;
    Uint64        logicalBlocksRecorded ;                
    TimeStamp     accessTime            ;           
    TimeStamp     modifyTime            ;     
    TimeStamp     attributeTime         ;        
    Uint32        checkpoint            ;
    LongAllocDesc extendedAttrICB       ;
    ImplRegID     implementID           ;
    Uint64        uniqueID              ;
    Uint32        lenExtendedAttr       ;
    Uint32        lenAllocDesc          ;              
protected:        
    Bytes         extendedAttr_         ;
    ADTable       allocDescTable_       ;

private:
    void affixFloatingFields() ;
public:

    FileEntry( unsigned n = 1, ADType at = ad_Long ) ;

    UINT16 unusedBytes( UINT16 blockLen ) const ;
    UINT16 EAPadLen( UINT16 eaLen ) const { return eaLen % 4; }

    UINT16 getEALen( void ) { return extendedAttr_.field.len(); }
    Error setEALen( UINT16 blockLen, UINT16 eaLen ) ;
    BYTE_PTR embeddedEAp() { return (BYTE_PTR)extendedAttr_; }

    UINT16 numADTEnts()   const   { return allocDescTable_.numADs() ;}
    Error numADTEnts( UINT16 blockLen, UINT16 n ) ;
    Error numADTEnts( UINT16 blockLen, UINT16 n, ADType at ) ;

    UINT16 maxADTEnts( UINT16 blockLen ) const ;
    UINT16 maxADTEnts( UINT16 blockLen, ADType at ) const ;

    ShortAllocDesc    *shortADT()  { return allocDescTable_.shortADp()      ;}
    LongAllocDesc     *longADT()   { return allocDescTable_.longADp()       ;}  
    // ExtendedAllocDesc *extendADT() { return allocDescTable_.extendADp()     ;}
    BYTE_PTR       embeddedDatap() { return allocDescTable_.embeddedDatap() ;}

    // Deal with it directly with extreme care!
    ADTable & adTable()            { return allocDescTable_; } 

#ifdef NSR_VERIFY
    Boolean operator != ( const FileEntry & 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: AllocExtentDesc
//
// The AllocExtentDesc class is a composite field, allowing direct
// access to its constituent fields. It provides the simple field
// class methods, as well as a location() method, which sets the
// address field inside its descriptor tag to the supplied value.
//
// Its constructor accepts an optional length of allocation
// descriptors value.
//
// METHOD: AllocExtentDesc::AllocExtentDesc()
// METHOD: AllocExtentDesc::descLoc()
// METHOD: AllocExtentDesc::toISO()
// METHOD: AllocExtentDesc::fromISO()

class AllocExtentDesc : public TaggedDescriptor {

public:

    Uint32    prevAllocExtentLoc ;
    Uint32    lenAllocDesc       ;
protected:
    ADTable   allocDescTable_    ; // not part of descriptor

public:

    AllocExtentDesc( unsigned n = 1, ADType at = ad_Long ) ;

    UINT16 numADTEnts()   const   { return allocDescTable_.numADs() ;}

    Error numADTEnts( UINT16 blockLen, UINT16 n ) ;
    Error numADTEnts( UINT16 blockLen, UINT16 n, ADType at ) ;

    UINT16 maxADTEnts( UINT16 blockLen ) const ;
    UINT16 maxADTEnts( UINT16 blockLen, ADType at ) const ;
    
    ShortAllocDesc    *shortADT()  { return allocDescTable_.shortADp()      ;}
    LongAllocDesc     *longADT()   { return allocDescTable_.longADp()       ;}  
    // ExtendedAllocDesc *extendADT() { return allocDescTable_.extendADp()     ;}

    // Deal with it directly with extreme care!
    ADTable & adTable()            { return allocDescTable_; } 

    void dump(CONST_CHAR_PTR  message) const;

#ifdef NSR_VERIFY
    Boolean operator != ( const AllocExtentDesc & 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 IndirectEntry : public TaggedDescriptor {

public:

    ICBTag        icbTag      ;
    LongAllocDesc indirectICB ;

    IndirectEntry() ;
#ifdef NSR_VERIFY
    Boolean operator != ( const IndirectEntry & 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 TerminalEntry : public TaggedDescriptor{
 
public:

    ICBTag      icbTag;
 
    TerminalEntry() ;

#ifdef NSR_VERIFY
    Boolean operator != ( const TerminalEntry & 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 FileCharacteristics {

public:
    FieldInfo field;
private:

public:

    Bit8   hidden    ;
    Bit8   directory ;
    Bit8   deleted   ;
    Bit8   parent    ;
    Ubits8 reserved  ;

    FileCharacteristics( UINT16 o ) ;

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

    void clear() ;
    void toISO( BYTE_PTR rbp ) ;
    void fromISO( CONST_BYTE_PTR rbp ) ;
    
};
        
class FileIdentifierDesc : public TaggedDescriptor {

    static UINT8        descVersion_ ;
    static CharSetType  readCSType_  ;
    
public:

    Uint16              fileVersionNo       ;
    FileCharacteristics fileCharacteristics ;
    Uint8               lenFileID           ;
    LongAllocDesc       icbAddr             ;
    Uint16              implementLength     ;
    ImplRegID           implementID         ; // OSTA 2.3.4.1
    Bytes               implementUse        ;
protected:                      // use supplied methods
    Dchars              fileIdentifier      ;
    ZeroBytes           padding             ;
      
private:

    void affixFloatingFields() ;

public:
    
    static void readCSType(CharSetType cst) { readCSType_ = cst; }
    static CharSetType readCSType(void) { return readCSType_; }

    FileIdentifierDesc( const String &id = String("") ) ;

    void markDir() { fileCharacteristics.directory = 1; }
    void clearDir() { fileCharacteristics.directory = 0; }
    Boolean isDir() const {
        return fileCharacteristics.directory ? True : False;
    }

    void markDel() { fileCharacteristics.deleted = 1; }
    void clearDel() { fileCharacteristics.deleted = 0; }
    Boolean isDel() const {
        return fileCharacteristics.deleted ? True : False;
    }

    void markParent() { fileCharacteristics.parent = 1; }
    void clearParent() { fileCharacteristics.parent = 0; }
    Boolean isParent() const {
        return fileCharacteristics.parent ? True : False;
    }

    void markHidden() { fileCharacteristics.hidden = 1; }
    void clearHidden() { fileCharacteristics.hidden = 0; }
    Boolean isHidden() const {
        return fileCharacteristics.hidden ? True : False;
    }

    void fileID( const String &id ) ;
    String fileID() const { return (String) fileIdentifier; }

#ifdef NSR_VERIFY
    Boolean operator != ( const FileIdentifierDesc & 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 UnallocatedSpaceEntry : public TaggedDescriptor {

public:

    ICBTag    icbTag          ;
    Uint32    lenAllocDesc    ;
    ADTable   allocDescTable_ ;
    
public:

    UnallocatedSpaceEntry( UINT32 n ) ;

    ShortAllocDesc *shortADT()   const { return allocDescTable_.shortADp();}
    UINT16   numADTEnts() const { return allocDescTable_.numADs();  }
    Error    numADTEnts( UINT16 blockLen, UINT16 n ) ;
    UINT16   maxADTEnts( UINT16 blockLen ) const;

    ADTable &       adTable()    { return allocDescTable_;           } 

#ifdef NSR_VERIFY
    Boolean operator != ( const UnallocatedSpaceEntry & 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 ) ;

};

enum PathComponentType {

    pc_Reserved = 0,
    pc_FSRoot   = 1,
    pc_DirRoot  = 2,
    pc_Parent   = 3,
    pc_Same     = 4,
    pc_Name     = 5

};

class PathComponent {

    // First, data members which have no fields...
    Error               err         ;
    static CharSetType  readCSType_ ;
    
    // Now, for the fields.
    Uint8    componentType        ;
    Uint8    lenComponentID       ;
    Uint16   componentFileVersion ;
    Dchars   componentID          ;

    void init() ;
#ifdef NSR_VERIFY
    Error verifyISO( BYTE_PTR rbp ) ;
#endif
    
public:

    static void readCSType(CharSetType cst) { readCSType_ = cst; }
    static CharSetType readCSType(void) { return readCSType_; }
        
    PathComponent() ;

    PathComponent & operator=( const PathElement& pe ) ;
    operator PathElement() ;
    
    UINT16 descLen() {
        return componentID.field.after();
    }

    Error error() { return err; }

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

};
    
#endif

