Listing 3: An example of Handle class use with a String class


#include <stdio.h>
#include <string.h>
#include <iostream.h>
#include <vbtools/handle.h>

class _String 
{
   public:

   typedef int      Size;
   typedef char* Address;

       ~_String () { delete _text; } 
        _String () : _text(0), _size(0) {}
        _String (Address, Size =0);
   Address text () { return _text; }
   Size    size () { return _size; }
   void    text (Address, Size);

//   private:

   Address _text;
   Size    _size;
};

_String::_String(Address addr, Size sz) : _text(0), _size(0)
{
   text(addr, sz ? sz : addr ? strlen(addr) : 0);   
}

void
_String::text(Address addr, Size size)
{
   delete _text;
   _text = (Address) memcpy(new char[_size = size], addr, size);
}

// String instances are of 'void*' size. Easy to pass around.
// _String resources are handled automatically.

typedef Handle<_String> String;

HandleError string_is_empty;
HandleError string_too_long;

String
foo(String input)
{
   String s;

   if (!input->size()) 
   {
      String err = String::error(string_is_empty);

      // A value can be set to error instance as well.

      err->text("Usage: foo argument.\n");
      return err;
   }
   if (4 < input->size()) return s.error(string_too_long);

   s->text("Changed");

   return s;
}

int 
main(int argc, char** argv)
{
   String  input(1 < argc ? argv[1] : (char*) 0);
   String   orig = input;
   String output = foo(input);

   if (output.is_error())
   {
      if (output.get_error() == string_is_empty)
      {
         // A value and an error condition can be 
         // passed at the same time.

         cout << output->text() << endl; 
      }
      else if (output.get_error() == string_too_long)
      {
         cout << "Argument is too long.\n";
      }
   }
   else
   {
      cout << orig-> text() << endl; // argv[1] printed.
      cout << input->text() << endl; // "Changed" printed.
   }
}

//End of File