JX Application Framework
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | Protected Member Functions | Friends | List of all members
JFileArray Class Reference

#include <JFileArray.h>

Inheritance diagram for JFileArray:
[legend]

Classes

class  FileAlreadyOpen
 
class  FileNotWritable
 
class  ItemChanged
 
class  ItemInserted
 
class  ItemMoved
 
class  ItemRemoved
 
class  ItemsSwapped
 
class  NotEmbeddedFile
 
class  WrongSignature
 

Public Types

enum  CreateAction {
  kFailIfOpen ,
  kIgnoreIfOpen ,
  kDeleteIfOpen ,
  kTryWaitUntilCanOpen ,
  kDeleteIfWaitTimeout
}
 
enum  { kUnsignedLongLength = 4 }
 

Public Member Functions

 ~JFileArray () override
 
const JStringGetFileName () const
 
JFileVersion GetVersion () const
 
void SetVersion (const JFileVersion newVersion)
 
void GetItem (const JFAIndex &index, std::string *data) const
 
void GetItem (const JFAID &id, std::string *data) const
 
void SetItem (const JFAIndex &index, const JString &data)
 
void SetItem (const JFAID &id, const JString &data)
 
void InsertItemAtIndex (const JFAIndex &index, const JString &data)
 
void PrependItem (const JString &data)
 
void AppendItem (const JString &data)
 
void SetItem (const JFAIndex &index, std::ostringstream &dataStream)
 
void SetItem (const JFAID &id, std::ostringstream &dataStream)
 
void InsertItemAtIndex (const JFAIndex &index, std::ostringstream &dataStream)
 
void PrependItem (std::ostringstream &dataStream)
 
void AppendItem (std::ostringstream &dataStream)
 
void RemoveItem (const JFAIndex &index)
 
void RemoveItem (const JFAID &id)
 
void MoveItemToIndex (const JFAIndex &currentIndex, const JFAIndex &newIndex)
 
void SwapItems (const JFAIndex &index1, const JFAIndex &index2)
 
bool IndexToID (const JFAIndex &index, JFAID *id) const
 
bool IDToIndex (const JFAID &id, JFAIndex *index) const
 
bool IndexValid (const JFAIndex &index) const
 
bool IDValid (const JFAID &id) const
 
bool WillFlushChanges () const
 
void ShouldFlushChanges (const bool write)
 
void FlushChanges ()
 
- Public Member Functions inherited from JCollection
 JCollection ()
 
 JCollection (const JCollection &source)
 
 ~JCollection () override
 
JCollectionoperator= (const JCollection &source)
 
JSize GetItemCount () const
 
bool IsEmpty () const
 
bool IndexValid (const JIndex index) const
 
JIndex GetIndexFromEnd (const JIndex index) const
 
JString ToString () const override
 
- Public Member Functions inherited from JBroadcaster
 JBroadcaster ()
 
virtual ~JBroadcaster ()
 
JBroadcasteroperator= (const JBroadcaster &source)
 
bool HasSenders () const
 
JSize GetSenderCount () const
 
bool HasRecipients () const
 
JSize GetRecipientCount () const
 
template<class T >
void ListenTo (const JBroadcaster *sender, const std::function< void(const T &)> &f)
 

Static Public Member Functions

static JError Create (const JString &fileName, const JUtf8Byte *fileSignature, JFileArray **obj, const CreateAction action=kFailIfOpen)
 
static JError OKToCreateBase (const JString &fileName, const JUtf8Byte *fileSignature, const CreateAction action=kFailIfOpen)
 
static JError Create (JFileArray *theEnclosingFile, const JFAID &enclosureItemID, JFileArray **obj)
 
static JError OKToCreateEmbedded (JFileArray *theEnclosingFile, const JFAID &enclosureItemID)
 

Static Public Attributes

static const JFileVersion kInitialVersion = 0
 
static const JUtf8BytekItemInserted = "ItemInserted::JFileArray"
 
static const JUtf8BytekItemRemoved = "ItemRemoved::JFileArray"
 
static const JUtf8BytekItemMoved = "ItemMoved::JFileArray"
 
static const JUtf8BytekItemsSwapped = "ItemsSwapped::JFileArray"
 
static const JUtf8BytekItemChanged = "ItemChanged::JFileArray"
 
static const JUtf8BytekFileNotWritable = "FileNotWritable::JFileArray"
 
static const JUtf8BytekFileAlreadyOpen = "FileAlreadyOpen::JFileArray"
 
static const JUtf8BytekWrongSignature = "WrongSignature::JFileArray"
 
static const JUtf8BytekNotEmbeddedFile = "NotEmbeddedFile::JFileArray"
 

Protected Member Functions

 JFileArray (const JString &fileName, const JUtf8Byte *fileSignature, const CreateAction action)
 
 JFileArray (JFileArray *theEnclosingFile, const JFAID &enclosureItemID)
 
JFileArrayIndexGetFileArrayIndex ()
 
- Protected Member Functions inherited from JCollection
void ItemAdded ()
 
void ItemRemoved ()
 
void SetItemCount (const JSize newItemCount)
 
- Protected Member Functions inherited from JBroadcaster
 JBroadcaster (const JBroadcaster &source)
 
void ListenTo (const JBroadcaster *sender)
 
void StopListening (const JBroadcaster *sender)
 
void ClearWhenGoingAway (const JBroadcaster *sender, void *pointerToMember)
 
void StopListening (const JBroadcaster *sender, const std::type_info &messageType)
 
template<class T >
void Send (JBroadcaster *recipient, const T &message)
 
template<class T >
void Broadcast (const T &message)
 
virtual void Receive (JBroadcaster *sender, const Message &message)
 
void SendWithFeedback (JBroadcaster *recipient, Message *message)
 
void BroadcastWithFeedback (Message *message)
 
virtual void ReceiveWithFeedback (JBroadcaster *sender, Message *message)
 
virtual void ReceiveGoingAway (JBroadcaster *sender)
 

Friends

class JFileArrayIndex
 

Detailed Description

                        The Array-in-a-File Class

An array implemented as a file.  All data is stored as text and is
transferred via stringstream objects. Each item can have an
arbitrary size.

A JFileArray can be embedded within other JFileArray by storing all the
embedded file's data inside one item of the enclosing file.
The single base file object is initialized with the file specifications.
An embedded file object is initialized with the file object that
contains it and the ID of the item that contains it.

The embedding can theoretically go on forever.  In practice, deep
embedding can be hard to keep track of.

    Embedded files must be opened after the base file and
    must be closed before the base file.

Storage details:

The first item is the file signature (arbitrary length).
The second item is the version.
The third item is the number of items in the array.
The fourth item is the offset into the file where the index starts.

Each item is preceded by its length.
(This makes it easier to recover the data directly from the file.)

The positions and id's of the items in the file are stored
at the end of the file.  This is handled by JFileArrayIndex.

Since both the data and index sections have to change size,
the index was placed at the end because it is usually
significantly smaller and only needs to be written out when
the file is closed.

sig  header      items (length+data)            index
+--+--+--+--+-------------------------------+-------------------+
|  |  |  |  | ++---++---+- - - -++---++---+   +-+-+- - - -+-+-+
|  |  |  |  | ||   ||   |       ||   ||   |   | | |       | | |
|  |  |  |  | ||   ||   |       ||   ||   |   | | |       | | |
|  |  |  |  | ++---++---+- - - -++---++---+   +-+-+- - - -+-+-+
+--+--+--+--+-------------------------------+-------------------+

Implementation details:

Only the base file opens the stream.  All embedded files simply get
a pointer to the stream so they can use it.

    This means that one should never rely on the position of
    the read or write mark unless the previous statement explicitly set it.

    Embedded files should not delete itsStream.

The file's header and index are read in when the file is opened and is
maintained in memory.  However, the header and index are also written
to the file whenever they change.  This provides safety in the event of
program and system crashes.  It also slows the program down, however.
One could use a flag to tell whether to always update the file or just
update it when it is closed.

    While the file is open, do not rely on the data in the header or
    index sections of the file.  Use the data members and itsFileIndex.
    The information in the space allocated for the header and index is
    undefined.

    While the file is open, space for the index is still maintained at
    the end of the file to avoid having to adjust the allocation when
    the index is written out.

Since some information is only written out when the file is closed,
only one process at a time can open the disk file.  To guarantee this,
the high bit of the itemCount is set when the file is opened.
This does not conflict with other uses because one will run out of
RAM and disk space long before one needs the high bit in itemCount.
(If you're not out of space, switch to a real database system!)
If this bit is set, JFileArray::Create() will return false.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
Enumerator
kUnsignedLongLength 

◆ CreateAction

Enumerator
kFailIfOpen 
kIgnoreIfOpen 
kDeleteIfOpen 
kTryWaitUntilCanOpen 
kDeleteIfWaitTimeout 

Constructor & Destructor Documentation

◆ ~JFileArray()

JFileArray::~JFileArray ( )
override
All embedded files must be closed before calling this!

We could use a Message to notify the owners of embedded files that the files have been closed, but it is much easier and safer to simply write client code that closes the embedded files first.

◆ JFileArray() [1/2]

JFileArray::JFileArray ( const JString fileName,
const JUtf8Byte fileSignature,
const CreateAction  action 
)
protected

Initialize a JFileArray object as the base file. Since we are the base class, we create and open the std::fstream.

◆ JFileArray() [2/2]

JFileArray::JFileArray ( JFileArray theEnclosingFile,
const JFAID enclosureItemID 
)
protected

Initialize a JFileArray object as a nested part of the given JFileArray.

Member Function Documentation

◆ AppendItem() [1/2]

void JFileArray::AppendItem ( const JString data)
inline

◆ AppendItem() [2/2]

void JFileArray::AppendItem ( std::ostringstream &  dataStream)
inline

◆ Create() [1/2]

JError JFileArray::Create ( const JString fileName,
const JUtf8Byte fileSignature,
JFileArray **  obj,
const CreateAction  action = kFailIfOpen 
)
static

By forcing everyone to use this function, we avoid having to worry about errors within the class itself.

Derived classes must define their own constructor functions and check OKToCreateBase() before creating the object.

Be very careful when using kIgnoreIfOpen. If you always call ShouldFlushChanges(true) when you open the file, it should be safe to specify kIgnoreIfOpen, but only if JFileArray itself did not cause the crash.

kTryWaitUntilCanOpen does not guarantee that Create() will return true. If somebody else never closes the file, Create() will fail. This is safer than blocking forever.

The code for kTryWaitUntilCanOpen and kDeleteIfWaitTimeout suffers from a race condition. If it ever becomes a problem, it will need to use lockfile instead.

◆ Create() [2/2]

JError JFileArray::Create ( JFileArray theEnclosingFile,
const JFAID enclosureItemID,
JFileArray **  obj 
)
static

By forcing everyone to use this function, we avoid having to worry about errors within the class itself.

Derived classes must define their own constructor functions and check OKToCreateEmbedded() before creating the object.

◆ FlushChanges()

void JFileArray::FlushChanges ( )

Write out the header information and the file's index.

This is called automatically if ShouldFlushChanges(true) was called. You can optimize by calling ShouldFlushChanges(false) and then calling FlushChanges() after making a sequence of changes.

◆ GetFileArrayIndex()

JFileArrayIndex * JFileArray::GetFileArrayIndex ( )
inlineprotected

◆ GetFileName()

const JString & JFileArray::GetFileName ( ) const

Returns the name of the file on disk.

◆ GetItem() [1/2]

void JFileArray::GetItem ( const JFAID id,
std::string *  data 
) const

◆ GetItem() [2/2]

void JFileArray::GetItem ( const JFAIndex index,
std::string *  data 
) const

Fills the given string with a copy of the data for the specified item.

◆ GetVersion()

JFileVersion JFileArray::GetVersion ( ) const
inline

◆ IDToIndex()

bool JFileArray::IDToIndex ( const JFAID id,
JFAIndex index 
) const

Return the index of the item with the specified ID. Returns an invalid JFAIndex if there is no item with the specified ID.

This is not inline because JFileArrayIndex is forward declared.

◆ IDValid()

bool JFileArray::IDValid ( const JFAID id) const
inline

◆ IndexToID()

bool JFileArray::IndexToID ( const JFAIndex index,
JFAID id 
) const

Return the ID of the specified item.

This is not inline because JFileArrayIndex is forward declared.

◆ IndexValid()

bool JFileArray::IndexValid ( const JFAIndex index) const
inline

◆ InsertItemAtIndex() [1/2]

void JFileArray::InsertItemAtIndex ( const JFAIndex index,
const JString data 
)

◆ InsertItemAtIndex() [2/2]

void JFileArray::InsertItemAtIndex ( const JFAIndex index,
std::ostringstream &  dataStream 
)

Insert an item into the array at the specified index.

If index is any value greater than the current number of items, then the item is appended to the end of the array.

The actual data is appended to the data section of the file. The index entry for the item is inserted into the file's index at the specified index.

◆ MoveItemToIndex()

void JFileArray::MoveItemToIndex ( const JFAIndex currentIndex,
const JFAIndex newIndex 
)

Move the specified item to a different index in the file.

◆ OKToCreateBase()

JError JFileArray::OKToCreateBase ( const JString fileName,
const JUtf8Byte fileSignature,
const CreateAction  action = kFailIfOpen 
)
static

◆ OKToCreateEmbedded()

JError JFileArray::OKToCreateEmbedded ( JFileArray theEnclosingFile,
const JFAID enclosureItemID 
)
static

◆ PrependItem() [1/2]

void JFileArray::PrependItem ( const JString data)
inline

◆ PrependItem() [2/2]

void JFileArray::PrependItem ( std::ostringstream &  dataStream)
inline

◆ RemoveItem() [1/2]

void JFileArray::RemoveItem ( const JFAID id)

◆ RemoveItem() [2/2]

void JFileArray::RemoveItem ( const JFAIndex index)

Remove the specified item from the file.

If it is an embedded file, it must already be closed.

◆ SetItem() [1/4]

void JFileArray::SetItem ( const JFAID id,
const JString data 
)

◆ SetItem() [2/4]

void JFileArray::SetItem ( const JFAID id,
std::ostringstream &  dataStream 
)

◆ SetItem() [3/4]

void JFileArray::SetItem ( const JFAIndex index,
const JString data 
)

◆ SetItem() [4/4]

void JFileArray::SetItem ( const JFAIndex index,
std::ostringstream &  dataStream 
)

Write out the contents of the ostringstream to the specified item.

◆ SetVersion()

void JFileArray::SetVersion ( const JFileVersion  newVersion)
inline

◆ ShouldFlushChanges()

void JFileArray::ShouldFlushChanges ( const bool  write)
inline

◆ SwapItems()

void JFileArray::SwapItems ( const JFAIndex index1,
const JFAIndex index2 
)

Interchange the specified items in the file.

◆ WillFlushChanges()

bool JFileArray::WillFlushChanges ( ) const
inline

When this flag is set, the file's index will be written out after every change. The default is not to do this, since it slows us down dramatically. If you need to protect against data loss due to crashes, you should turn this option on.

Friends And Related Symbol Documentation

◆ JFileArrayIndex

friend class JFileArrayIndex
friend

Member Data Documentation

◆ kFileAlreadyOpen

const JUtf8Byte * JFileArray::kFileAlreadyOpen = "FileAlreadyOpen::JFileArray"
static

◆ kFileNotWritable

const JUtf8Byte * JFileArray::kFileNotWritable = "FileNotWritable::JFileArray"
static

◆ kInitialVersion

const JFileVersion JFileArray::kInitialVersion = 0
static

◆ kItemChanged

const JUtf8Byte * JFileArray::kItemChanged = "ItemChanged::JFileArray"
static

◆ kItemInserted

const JUtf8Byte * JFileArray::kItemInserted = "ItemInserted::JFileArray"
static

◆ kItemMoved

const JUtf8Byte * JFileArray::kItemMoved = "ItemMoved::JFileArray"
static

◆ kItemRemoved

const JUtf8Byte * JFileArray::kItemRemoved = "ItemRemoved::JFileArray"
static

◆ kItemsSwapped

const JUtf8Byte * JFileArray::kItemsSwapped = "ItemsSwapped::JFileArray"
static

◆ kNotEmbeddedFile

const JUtf8Byte * JFileArray::kNotEmbeddedFile = "NotEmbeddedFile::JFileArray"
static

◆ kWrongSignature

const JUtf8Byte * JFileArray::kWrongSignature = "WrongSignature::JFileArray"
static

The documentation for this class was generated from the following files: