EndianIndependentFile

 

Derived from: BufferedFile

Declared in: EndianIndependentFile.h

Library: none


Overview

BFile-derived class which adds a layer of abstraction and avoids having to worry about several issues:

- "endian-ness": When you create a EndianIndependentFile for read or write, the first thing it does is read or write a single byte flag to indicate the endianness of the file, and automatically converts to native byte order if necessary when reading as long as you use the ReadNumber and WriteNumber functions.

- size of numbers: If I'm going down a structure with lots of members, writing each member, I find it annoying to have to constantly check the type of each member, then call the appropriate sized byte swap if necessary and write the appropriate size manually. It is especially annoying when some members are not base types (for example, time_t is not a base type - you have to know or look up to find out that it is int64). ReadNumber and WriteNumber accept any size or type of data (integers, floats, etc) and treat it appropriately. Thus, to write an array time_t TimeArray[5]: MyFile->WriteNumber(TimeArray,sizeof(time_t),5)

- strings: How do you write a string? The length first, followed by the string, or omit the length and search for the null terminator when you read? The former adds extra size, while the latter is inefficient without buffering of the read data. EndianIndependentFile provides ReadString() and WriteString() to handle that for you. No big deal but it simplifies things and keeps code more readable.

- The last advantage is that it inherits from BufferedFile and buffers the data during read and write, so that you can conveniently read/write the small pieces at a time (one member at a time, for example) without costly repeated calls to the storage server. Just using BFile, you would need to manually fill a write buffer for the sake of efficiency and not call BFile::Read() or BFile::Write() too many times for small data elements. With buffering, it is just as efficient to write a byte or an int at a time. This saves the hassle by buffering output for you, allowing you to focus on the task at hand, namely writing your data one piece at a time while keeping your code simple and readable.

EndianIndependentFile still provides all of the functionality of a BFile: It now provides Read/Write access, random access, etc. All the regular BFile calls can be mixed with the EndianIndependentFile calls, although the BFile calls won't benefit from the buffering (they force the buffer to flush, and actually introduce inefficiency - use them carefully; in general try to stick to the EndianIndependentFile-specific calls.

 


Constructor and Destructor


EndianIndependentFile()

      EndianIndependentFile(const entry_ref* ref, uint32 openMode, int32 BufferSize = 4095)
      EndianIndependentFile(const BEntry* entry, uint32 openMode, int32 BufferSize = 4095)
      EndianIndependentFile(const char* path, uint32 openMode, int32 BufferSize = 4095)
      EndianIndependentFile(BDirectory* dir, const char* path, uint32 openMode, int32 BufferSize = 4095)

Creates a new virtual EndianIndependentFile object, initializes it according to the arguments, and sets InitCheck() to return the status of the initialization. If opening for read, sets the object's endianness to that recorded in the first byte of the file. If opening a new file for write, sets the object's endianness to that of the host system and writes one byte to the file to indicate the endianness.

See also: BufferedFile::BufferedFile()


~EndianIndependentFile()

      virtual ~EndianIndependentFile() 

Closes the object's file, frees its file descriptor, and destroys the object. Destroys the EndianIndependentFile, but DOES NOT write any buffered data, as a file error could occur without the opportunity to report the error. You must call FlushBuffer() before destroying the EndianIndependentFile in order to write any data in the write buffer.

See also: BufferedFile::~BufferedFile(), BufferedFile::FlushBuffer()


Member Functions


IsBigEndian(), IsNativeEndian()

 
      bool IsBigEndian()
      bool IsNativeEndian()
 

IsBigEndian() returns true if the file is in big endian format. IsNativeEndian() returns true if the file is in the native endianness format for the host system.


ReadRaw(), WriteRaw(), ReadString(), WriteString(), ReadNumber(), WriteNumber()

 
      int32 ReadRaw(void* Buffer, size_t BytesToRead)
      int32 WriteRaw(const void* Buffer, size_t BytesToWrite)
      status_t ReadString(char* Buffer, int32 BufferSize)
      status_t WriteString(const char* Buffer)
      int32 ReadNumber(void* Buffer, uint8 SizeOfData, int32 NumbersToRead = 1)
      int32 WriteNumber(void* Buffer, uint8 SizeOfData, int32 NumbersToWrite = 1)

 

Reads or writes the raw data, string, or number. The ReadNumber() and WriteNumber() pair read or write the number in the endianness appropriate for the file, as determined in the EndianIndependentFile constructor. The length of the number written may be 1,2,4, or 8 bytes.


By Brian Tietz

Copyright 2000

Bug reports (including documentation errors) and feature requests can be sent to briant@timelinevista.com.