Rogue Wave banner
Previous fileTop of documentContentsIndexNext file

8.2 Member Functions

The class RWFileManager adds four additional member functions to those of class RWFile. They are:

  1. RWoffset allocate(RWspace s); Allocate s bytes of storage in the file, returning the offset to the start of the allocation.

  2. void deallocate(RWoffset t); Deallocate (free) the storage space starting at offset t. This space must have been previously allocated by the function allocate():

  3. RWOffset endData(); Return the offset to the last data in the file.

  4. RWoffset start(); Return the offset from the start of the file to the first space ever allocated by RWFileManager, or return RWNIL[7] if no space has been allocated, which implies that this is a new file.

The statement:

RWoffset a = F.allocate(sizeof(double)); 

uses F of RWFileManager to allocate the space required to store an object with the size of a double, and returns the offset to that space. To write the object to the disk file, you should seek to the allocated location and use Write(). It is an error to read or write to an unallocated location in the file.

It is your responsibility to maintain a record of the offsets necessary to read the stored object. To help you do this, the first allocation ever made by an RWFileManager is considered special and can be returned by member function start() at any time. The RWFileManager will not allow you to deallocate it. This first block will typically hold information necessary to read the remaining data, perhaps the offset of a root node, or the head of a linked-list.

The following example shows the use of class RWFileManager to construct a linked-list of ints on disk. The source code is included in the toolexam subdirectory as fmgrsave.cpp and fmgrrtrv.cpp.

When using this example, you must type a carriage return after the last item you want to insert in order to guarantee that it will be added to the list. This is because different compilers handle the occurrence of an EOF on the cin stream differently.

#include <rw/filemgr.h>                                      // 1
#include <rw/rstream.h>

struct DiskNode {                                            // 2
  int       data;                                            // 3
  Rwoffset  nextNode;                                        // 4
};

main(){
   RWFileManager fm("linklist.dat");                         // 5

   // Allocate space for offset to start of the linked list:
   fm.allocate(sizeof(RWoffset));                            // 6
   // Allocate space for the first link:
   RWoffset thisNode = fm.allocate(sizeof(DiskNode));        // 7

   fm.SeekTo(fm.start());                                    // 8
   fm.Write(thisNode);                                       // 9

   DiskNode n;
   int temp;
   RWoffset lastNode;
   cout << "Input a series of integers, ";
   cout << "then EOF to end:\n";

   while (cin >> temp) {                                    // 10
     n.data = temp;
     n.nextNode = fm.allocate(sizeof(DiskNode));            // 11
     fm.SeekTo(thisNode);                                   // 12
     fm.Write(n.data);                                      // 13
     fm.Write(n.nextNode);
     lastNode = thisNode;                                   // 14
     thisNode = n.nextNode;
   }

   fm.deallocate(n.nextNode);                               // 15
   n.nextNode = RWNIL;                                      // 16
   fm.SeekTo(lastNode);
   fm.Write(n.data);                                             
   fm.Write(n.nextNode);                                         
   return 0;
}                                                           // 17

Here's a line-by-line description of the program:

//1Include the declarations for the class RWFileManager.
//2Struct DiskNode is a link in the linked-list. It contains:
//3the data (an int), and:
//4the offset to the next link. RWoffset is typically typedef'd to a long int.
//5This is the constructor for an RWFileManager. It will create a new file, called linklist.dat.
//6Allocate space on the file to store the offset to the first link. This first allocation is considered special and will be saved by the RWFileManager. It can be retrieved at any time by using the member function start().
//7Allocate space to store the first link. The member function allocate() returns the offset to this space. Since each DiskNode needs the offset to the next DiskNode, space for the next link must be allocated before the current link is written.
//8Seek to the position to write the offset to the first link. Note that the offset to this position is returned by the member function start(). Note also that fm has access to public member functions of class RWFile, since class RWFileManager is derived from class RWFile.
//9Write the offset to the first link.
//10A loop to read integers and store them in a linked-list.
//11Allocate space for the next link, storing the offset to it in the nextNode field of this link.
//12Seek to the proper offset to store this link
//13Write this link.
//14Since we allocate the next link before we write the current link, the final link in the list will have an offset to an allocated block that is not used. It must be handled as a special case.
//15First, deallocate the final unused block.
//16Next, reassign the offset of the final link to be RWNIL. When the list is read, this will indicate the end of the linked list. Finally, rewrite the final link with the correct information.
//17The destructor for class RWFileManager, which closes the file, will be called here.

Having created the linked-list on disk, how might you read it? Here is a program that reads the list and prints the stored integer field:

#include <rw/filemgr.h>
#include <rw/rstream.h>

struct DiskNode {
  int       data;
  Rwoffset  nextNode;
};

main(){
   RWFileManager fm("linklist.dat");                         // 1

   fm.SeekTo(fm.start());                                    // 2
   RWoffset next;
   fm.Read(next);                                            // 3

   DiskNode n;
   while (next != RWNIL) {                                   // 4
     fm.SeekTo(next);                                        // 5
     fm.Read(n.data);                                        // 6
     fm.Read(n.nextNode);
     cout << n.data << "\n";                                 // 7
     next = n.nextNode;                                      // 8
   }
   return 0;
}                                                            // 9

And this is a line-by-line description of the program:

//1The RWFileManager has been constructed with an old File.
//2The member function start() returns the offset to the first space ever allocated in the file. In this case, that space will contain an offset to the start of the linked-list.
//3Read the offset to the first link.
//4A loop to read through the linked-list and print each entry.
//5Seek to the next link.
//6Read the next link.
//7Print the integer.
//8Get the offset to the next link.
//9The destructor for class RWFileManager, which closes the file, will be called here.


Previous fileTop of documentContentsIndexNext file
©Copyright 1999, Rogue Wave Software, Inc.
Send mail to report errors or comment on the documentation.