Documentation & Examples
Reason contains many classes that you would see in other frameworks like Java or .Net as well as many that you wouldn't.
It also includes a comprehensive object hierarchy with its own form of run time type inference. Notably absent are
inbuilt C++ rtti and exception handling. This is deliberate and by design as it makes the framework faster and more
portable.
Classes are separated into major namespaces like System, Structure, Network, and Language. In addition each major namespace
has several sub namespaces sometimes by classification like Storage and sometimes by the name of a standard like Xml.
Every effort has been made to make these namespaces as obvious and intuitive as possible.
Fundamentals
Object is an abstract base class which defines several methods such as Print(), Compare(), Equals() and
Hash(). It is used as the base class for many of Reason's built in types, such as String, Path, and Url.
All Object's are inherently compatible with the collection classes within Reason and are often also used
as the polymorphic base types in many of the components.
Unlike many frameworks, Reason features many classes for string handling. This is in
recognition of the fact that there are many ways in which strings can be used.
Each type of string is a specialisation or a means of explicit optimisation.
For example Reason has a class for substrings and another one for strings used to create
other strings, or superstrings.
But you don't have to worry about them if you don't want too, String has everything you need
inlcuding a variety of methods for comparing and modifying strings.
 |
 |
 |
 |
String string;
string = "hello world";
/* Substring is used for partial strings. It acts as a reference to
memory used by another string. */
Substring substring;
substring = string.Substring(string.IndexOf(" "));
substring.Trim();
/* Superstring is used for temporary strings, it reduces memory when copying
and is the default class used for the + operator. */
Superstring superstring;
superstring = Superstring("hello") +" "+ Superstring("world");
/* Path is used for strings which have components. They allow strings to be split and their
components to be modified whilst updating the string as a whole. Path's are the basis for
many classes in Reason such as Url's, File's, and Folder's. */
Path path = string;
path.Split(" ");
path[0].Uppercase();
path[1].Replace("WORLD");
|
 |
 |
 |
 |
Strings also have methods for checking and converting between types. For example you might want
to extract a floating point or integer number from a string.
 |
 |
 |
 |
String string("3.14159");
// Conver the string to an integer 3
int i = string.Integer();
// Convert the string to a flaoting point 3.14159
double d = string.Float();
// Convert a string to a hexadecimal number 255
long l = String("FF").Hex();
if (string.IsAlphanumeric() || String("CC").IsHex())
{
// ...
}
|
 |
 |
 |
 |
All strings are also Sequence's, so they can be easily used in any circumstance where the Sequence class is supported.
Sequence simply represents a sequence of bytes.
 |
 |
 |
 |
String string;
// All strings classes are sequences, but sequence is abstract
string.Allocate(255);
string.Append("hello");
/* Sequence defines the two member variables which all string classes share, these
are Data and Size */
// String::Length() checks for null, strlen() just crashes
memcpy(string.Data+string.Size-1," world",String::Length("world");
string.Terminate();
/* Notice that if you want to you can treat a string as a C string and do
all kinds of nasty pointer things to them */
bool is = string.Is("hello world");
|
 |
 |
 |
 |
Strings of all types can be printed using the Print() method which is inherited from Object. If a
Substring calls Print() then the substring is copied to a threadsafe circular printing buffer before
returning a pointer. A String just returns the pointer to its Data member.
Rather than just basic time and date support Reason contains a comprehensive set of classes for
dealing with presentation and converting between times and time formats.
All times used in Reason are local time only. Reason deliberately does not make any attempt to
automatically adjust for daylight savings time or apply timezone information.
Other frameworks and even the standard C library make assumptions about times which programmers
use which are often wrong. You don't want times from a Sql database which mean something in the
local timezone of the database to be converted to the local timezone of your computer without
knowing about it.
Likewise, if the time or date is changed whilst your application is running, you dont want your
times within the application to be affected by this change. Reason ensures that no timezone
information can corrupt its representations.
The date and time classes include Calendar, Time, Epoch, and Interval. Most classes can be freely
converted form one form to another.
Time represents an integer time as used by most operating systems. It is the number of seconds since
a particular moment in time, or epoch. For example, unix represents time as the number of seconds since
January 1st 1970.
 |
 |
 |
 |
// The time now
Time now;
// Todays calendar date
Calendar today(now);
// Yesterdays calendar date
Calendar yesterday(today - Time::SecondsPerDay);
// Days between 1970 and yesterday
int days = yesterday.Days("1/1/1970");
|
 |
 |
 |
 |
Calendar can be used to parse almost any time format possible and will resolve inconsistencies between U.S. and
other date formats. European/Australiasian date formats are the assumed standard.
 |
 |
 |
 |
// Parse the time and date
String string = "Thursday April 21, @04:32PM";
Calendar calendar(string);
if (calendar.Day == 21 && calendar.Hour == 16 && calendar.Minute == 32)
{
// ...
}
// These formats will also work
calendar.Construct("21 Apr 2005 20:56");
calendar.Construct("April 21, 2005: 5:06 PM EDT");
calendar.Construct("20 Apr 2005");
calendar.Construct("15:25:14 04/21/2005");
calendar.Construct("15:25:14");
// Or if you wanted to parse a time from a piece of text
String text = ", and 21:00 ambitious documentary";
Calendar calendar;
int index=0;
while (!calendar.Construct(text.Substring(index)))
{
index = text.IndexOf(index+1," ");
if (index == -1) break;
}
|
 |
 |
 |
 |
The Epoch class can be used to model a moment in time with a number of ticks at a given scale. This is used
for converting between time formats used both within and between operating systems. For example Windows has
a different concept for file time than it does for system time.
 |
 |
 |
 |
/* These two epochs represent standard unix time and windows system time
versus windows file time */
Epoch posix("01 Jan 1970 00:00:00");
Epoch windows("01 Jan 1601, 00:00:00",0,10000000);
double elapsed = posix - windows;
long long ticks = elapsed*windows.Scale;
if (ticks == 116444736000000000LL)
{
// ...
}
|
 |
 |
 |
 |
The Interval class is used to represent a period of time. Since time is not scalar, when you subtract two times
what you end up with is an interval. It supports a full range of integer additions and subtractions with overloaded
operators like + and -.
 |
 |
 |
 |
// Compare two dates
Calendar after("2/2/2000");
Calendar before("1/1/1000");
bool less = before < after;
|
 |
 |
 |
 |
Also available are Date, Day, Week, Month, and Year classes which can be used for presentation and for extracting
specific information from a Time or a Calendar.
All filesystem operations in Reason are represented by the Filesystem class which encapsulates the notion
of a filesystem path and contains basic methods like Status() and Exists() as well as members like Properties
which allow you to query filesystem information.
Both the File class and the Folder class inherit from Filsystem. File provides methods for reading from and
writing too al kinds of files as well as operations like Rename(), Seek(), and Truncate().
 |
 |
 |
 |
// Open and read from a file
File file("readme.txt");
String string;
/* There is no need to open a file before use, calling the read
method will always attempt to open the file as readable. If the file does not exist
it will be created automatically */
file.Read(string);
/* But if we want to write to the file now we must close it or reopen it as writable */
file.Close();
file.Write("hello world");
/* Of course, we could always open the file for both reading and writing */
file.Open(File::OPTIONS_OPEN_TEXT_MUTABLE);
/* Seek to the end of the file, the first parameter specifies the position and
the second parameter specifies the origin. Origins are start < 0, current == 0, finish > 0 */
file.Seek(0,1);
file.Construct("example.txt");
if (file.Exists() && Time(file.Properties.Modified) < Time() - Time::SecondsPerHour)
{
file.Delete();
}
else
{
file.Create();
}
|
 |
 |
 |
 |
File's also inherit from two interfaces, Reader, and Writer which make them compatible with
all stream operations.
Folder allows manipulatin and iteration over files and folders, as well as creation and deletion of files and folders.
 |
 |
 |
 |
// Open a folder and list its contents
Folder folder("/home");
folder.List();
// Now we can iterate through the files or folders
for (folder.Files.MoveFirst(); folder.Files.Has(); folder.Files.MoveNext())
{
/* The name is a pointer to a Path component,
File and Folder both inherit from Path */
String name = *folder.Files().Name
name.Uppercase();
folder.Files().Name->Replace(name);
folder.Files().Construct();
folder.Files().Create();
}
// And we can sort them before iteration
int order = Orderable::ORDER_DESCENDING;
folder.Folders.Sort(order);
// Creating sub folders or files is easy
folder.CreateFile("new.txt");
folder.CreateFolder("admin");
|
 |
 |
 |
 |
No feature defines a framework more than collections, and Reason is no exception.
Reason contains all of the usual collection classes as generic C++ templates and also
a number of classes which have been specialised for use with Object's.
The primary difference between the collections offered by Reason and those by other
C++ frameworks is that the template classes in Reason are simple to use and easy to
understand. In fact they are on par, if not better than those available in .Net or Java.
 |
 |
 |
 |
/* Create an array of integers, this uses the overloaded , operator to assign
a list of values */
Array<int> array = 1,2,3,4,5;
// Create a list of strings and sort them
List<String> list;
list.Append("a");
list.Append("d");
list.Append("c");
list.Append("b");
list.Append(String((char)'d' + array[0]));
list.Sort(Orderable::ORDER_DESCENDING);
// Create a set of pointers, and then destroy them
Set<Object*> set;
set.Insert(new String("five"));
set.Insert(new Number(5));
Number * number = new Number(5);
if (!set.Insert(number)
{
delete number;
}
// No memory leaks here...
set.Destroy();
|
 |
 |
 |
 |
C++ template code can be incredibly complicated, most implementations of STL are a
testament to this. The Reason template classes are not only readable, they are reliable
and 100% cross platform, just like the rest of the framework.
They are also extremely flexible and fast, one of the side effects of simplicity.
The collection classes contain a number of useful concepts which you will notice extend
throughout the Reason namespaces. One such concept is the idea that collections manage
the lifecycle of the objects which they contain.
If a collection contains pointers, you have the option of reclaiming all the memory using
a simple call to Destroy(). Likewise most collections have both a Delete() and a Remove()
method.
 |
 |
 |
 |
/* As well as ordered sets and maps, there are unordered sets and maps, as well
as multimaps and multisets */
Hashtable<int> table;
table.Insert(1);
table.Insert(2);
table.Insert(3);
table.Select(1);
Map<Object *,String> map(Comparable::COMPARE_GENERAL);
map.Insert(new Number(10),"z");
map.Insert(new Number(5),"a");
Number number(5);
map.Insert(&number,"b");
/* because the insertion above will fail, we can safely destroy all of the keys. All
maps let you destroy either the keys or the values or both */
map.DestroyKeys();
/* The multimap will allow duplicate keys, that is of course what makes it a multi-map. When
the values are not pointers calling destroy on them should do nothing */
Multimap<Object *,String> multi(Comparable::COMPARE_INSTANCE);
multi.Insert(new Number(10),"z");
multi.Insert(new Number(5),"a");
multi.Insert(new Number(5),"b");
multi.Insert(new Number(5),"c");
multi.DestroyKeys();
multi.DestroyValues();
|
 |
 |
 |
 |
Another concept is that things which can be compared can be compared in a number of different
ways. Classes which inherit from Object like String, or Folder can be compared using generic,
precise, or instance comparisons.
This is because sometimes when you have a collection of String pointers you want to compare them
in a case insenstive way, whilst others you may want to compare as case sensitive. Or perhaps you
actually just want to compare the pointers themselves.
Reason does not force the user to construct custom compare functions or functors unless they really
want to. It comes in built with the flexibility to allow a wide range of polymorphic comparisons.
The collections also use naming conventions familiar to anyone who has ever used a database. Most
classes support methods like Insert(), Update(), Select(), and Delete().
You can safely inherit from Reason's collection classes. They have been designed with this in mind,
unlike STL which explicitly forbids inheritance.
Of course, no modern software framework is complete without iterators. Reason uses a combination
of metaphores in its iterator design, it is part STL like pointer and part Java or .Net like class.
I like to think its the best of both. Iterator's in Reason are used as classes but iterate over the
Iterable interface using classes called Iterands and Iterations.
 |
 |
 |
 |
/* Whenever we insert something into a map we get an iterand which tells us if the
insertion was succesful. The iterand wraps whatever internal storage type is used in the collection */
Hashmap<int,String> hashmap;
hashmap.Insert(1,"a");
Iterand< Mapped<int,String> > iterand;
iterand = hashmap.Insert(2,"b");
if (iterand)
{
hashmap.Remove(1);
}
/* You don't have to use this verbose description of the iterator types. Every
collection defines typedefs of their iterator types, but i prefer to see what im iterating. Note that a map is
really just a set of Mapped items, its a very thin wrapper. Mapped is very similar to Pair in concept and
behaviour */
Iterator< Mapped<int,String> > iterator;
iterator = hashmap.Iterate();
for(iterator.MoveFirst();iterator.Has();iterator.MoveNext())
{
int i = iterator().Key();
String string = iterator().Value();
}
|
 |
 |
 |
 |
Iterand is a smart pointer like class which provides a generic interface to all types which can be
iterated. It is also the return type for most collection methods. It provides a common way to
iterate and return complex types, pointers, and primitive types whilst still being able to check
for success or failure.
Iteration's are classes used by the abstract collection types to hold state about the Iterator which
is currently being used. They provide a mechanism for Iterator's to be invalidated during iteration
and also a way for multiple Iterators to be iterating a collection at the same time.
One of the major advantages of the appraoch to iteration that Reason uses, over say STL, is that Iterator's
are types in their own right. So you can define a function which takes an Iterator<int>
and it does not matter wether that iterator came from a List or an Array. Likewise all collections which use
the Mapped class use the same iterator interface, so Map, Set, Hashset, and Hashmap all have the same iterator.
Bjarn Stroustrup once defined C++ templates as being parametric polymorphism. But that doesn't mean they can't
also be object oriented.
Reasons templates are object oriented, and so are its iterators.
Streams are an important part of any modern software framework as they provide a mechanism for processing data.
Unlike other C++ frameworks, and even the standard C++ library. Streams in Reason have nothing to do with the
<< and >> operators.
 |
 |
 |
 |
/* Stream itself is an abstract class so we must create an instance of some
other class which implements it */
String write = "This String will be written to the StringStream.";
String read;
StringStream stringStream;
stringStream.Write(write);
bool is = stringStream.Is(write);
bool size = stringStream.Size == write.Size;
bool position = stringStream.Position == write.Size;
int size = String::Length("StringStream.");
stringStream.Seek(stringStream.Position-size);
|
 |
 |
 |
 |
Information which is transmitted across a network can be processed as it arrives using a Stream, allowing for better use
of local resources and asynchronous operation. In addition Stream's can be used for processing data which is too large to fit in memory.
Stream's can also be used as buffers for increasing network performance or reading efficiently from a file.
The StreamBuffer class can turn any Stream into a buffered stream.
All Stream's in Reason can be either absolute, or relative streams. This means that they either support Seek() and
therefore random acces, like a file. Or they are sequential and do not support Seek() like a network socket.
The Stream class inherits from the Reader and Writer interfaces. So by definition all streams in Reason are
potentially mutable. To find out wether a Stream is both readable and writable you should call the IsReadable()
and IsWritable() methods.
There are inbuilt streams for strings, files, text, sockets, compression, checksums, encoding, serialisation, and encryption.
The classes are StringStream, FileStream, TextStream, TextFileStream, SocketStream, GzipStream, RawStream, DeflateStream,
ChecksumStream, CodecStream, PrimitiveStream, and HashStream.
Several of the stream classes also contain adapters for mapping between existing classes and the Stream class. For example, if you have
a Stream which you want to behave as a File, you can pass it through the FileStream::FileAdapter class.
If you have a File which you want to use as a Stream you can use the FileStream::StreamAdapter class, though most of the time that
wont be ncessessary since File inherits from the same Reader/Writer interfaces as Stream. Likewise if you have a String which you
want to use as a Stream you can use the String::StreamAdapter.
Components
Parsing is fundamental to everything that Reason does.
Having a well thought out and consistent approach to parsing is one of the things which makes Reason so simple to understand
and maintainable.
 |
 |
 |
 |
/* Parse tab or comma delimited data from a file and store it in a table structure */
FileStream stream("data.csv");
List< Array<String> > table;
/* Parser requires an instance of Scanner. There are two default implementations
of the Scanner interface, StringScanner and StreamScanner. But you can just use the
wrappers */
StreamParser parser(stream);
int row=0;
/* Parser has an internal substring called token which you mark at the start of
a sequence of bytes and trap at the end. When parsing String's you can also mark and
trap any number of user supplied substrings by passing them as an argument.
Basically the mark just sets the Data, and the trap sets the Size. A substring of size 0 will
evaluate false with the IsEmpty() method.*/
parser.Mark();
while(!parser.Eof())
{
if (parser.IsAny("\t,"))
{
parser.Trap();
table[row].Append(parser.Token);
parser.Skip();
parser.Mark();
}
else
if (parser.IsNewLine())
{
parser.Trap();
table[row].Append(parser.Token);
parser.SkipNewLine();
parser.Mark();
++row;
table.Append(Array<String>());
}
else
{
parser.Next();
}
}
parser.Trap();
if (!parser.Token.IsEmpty())
{
table[row].Append(parser.Token);
}
|
 |
 |
 |
 |
All of the protocols and standards implemented in Reason use the Parser class. There are numerous highly
customisable hand crafted recursive descent parsers for things form Url's to the Javascript language.
The Parser is guaranteed to only look ahead in a Stream as far as has been necessary to meet the requirements of the
interface. Likewise it will only buffer as much of the Stream as is necessary to maintain its internal token.
For instance the Is(5,"hello") method will look ahead exactly 5+String::Length("hello"), so you can safely use the Parser for processing
things like HTTP responses during keep-alive connections.
The parser also supports the notion of state, its base class, called Scanner, provides everything that is needed to load and store
state on String's and absolute Stream's. Relative Stream's by necesity can only store a limited amount of state, namely whatever
is in the buffer.
Reason contains complete implementations of XML 1.0, and XPath 1.0/2.0 including a validating
parser with full DTD support.
 |
 |
 |
 |
/* The xml document and similar classes all support three methods of creation, Load(),
Download(), and Create(). */
XmlDocument document;
document.Load("shopping.xml");
XmlPathNavigator navigator(&document);
navigator.Select("//cheese");
for (navigator.MoveFirst();navigator.Has();navigator.MoveNext())
{
XmlObject * object = navigator();
}
|
 |
 |
 |
 |
The XPath implementation is second to none and heavily optimised for speed and extendability. Whilst the XML
parser is as forgiving or as sctrict as you require. It can easily parse and repair invalid HTML using information
from the schema.
Reason includes a generic database api with support for both MySQL and SqLite databases.
All database operations are completely thread safe. The classes include support for prepared statements, recordsets
and records, as well as transactions.
Statments can be executed using printf style format specifiers using the Execute() method on the SqlDatabase class.
There are overloads which provide support for SqlRecordset's and SqlRecord's to be returned from an Execute() call.
 |
 |
 |
 |
/* You can share a sql driver between multiple databases, it doesnt really matter
unless you want to customise behaviour of the driver or track connections */
MySql mysql;
SqlRecordset recordset;
SqlDatabase database(&mysql);
database.Open("test",
"user",
"pass",
"localhost"
,3306);
database.Execute(recordset,"select * from test");
int count = recordset.Count;
if (recordset.Fields[0].Is("name"))
{
String string = recordset(0,0);
}
datatbase.Execute("drop table garbage");
|
 |
 |
 |
 |
All SQL which is executed through the variable arguments version of the database Execute() method
is automatically checked for SQL injection attacks. All quotes and special characters are escaped.
This means that a large number of potential vulnerabilities are avoided. Of course you should still
use prepared statements for maximum safety.
If you wish to pass in a string which has been externally sanitised, or if you just want to play hacker,
you can always use the version of the database Execute() method which takes a Sequence.
 |
 |
 |
 |
/* SqLite is super cool. You can create local filesystem databases, temporary
databases, and in memory databases. Notice that both SqLite and MySql use the same set of database
classes and interfaces */
SqLite sqlite;
SqlRecord record;
// Lets create an in memory temporary database
SqlDatabase memorydb(&sqlite);
memorydb.Open(SqLite::Memory);
// Insert some records
memorydb.Execute("create table hashes(url varchar(200),hash varchar(32))");
memorydb.Execute("insert into hashes values('http://cnn.com/index.html','9CD0D01540E3E01')");
memorydb.Execute("insert into hashes values('http://cnn.com/privacy.html','BA365969B17906')");
// Now lets iterate it one record at a time
if (memorydb.Execute(record,"select * from hashes"))
{
do
{
String hash = record[2];
}
while(record.Step());
}
|
 |
 |
 |
 |
Reason also includes helper classes like SqlTime and SqlFormatter which are designed to aid
in construction and processing of SQL queries.
Advanced
Networking is embedded in many of the components in Reason. Classes like Url and XmlDocument all allow you
to download things from any standard internet url.
Its very simple, just call the Download() method, and in the case of Url, supply a String where you wish the
content to be placed.
 |
 |
 |
 |
// Download something and save it to disk
String string;
Url url("http://pics.obra.se/Yarly.jpg");
url.Download(string);
File("/tmp/" + url.Filename()).Write(string);
// Download an xml document
XmlDocument document;
document.Download("http://www.digg.com/rss/index.xml");
/* You can nest calls to navigator like this, of course its usually more efficient
to write a direct path expression like //item/title */
XmlPathNavigator navigator;
navigator.Select(&document,"//item");
for(navigator.MoveFirst();navigator.Has();navigator.MoveNext())
{
String title;
XmlPathNavigator item(navigator());
if (item.Select("title"))
title = item()->Token;
}
|
 |
 |
 |
 |
But if you want to do something a little more serious, you can use the low level TCP/IP classes like Address
and Socket to build just about any kind of networking functionality you need.
Socket supports both synchronous and asycnhronous operation through the same class, so you can make use of
blocking or non blocking behaviour on all platforms.
 |
 |
 |
 |
// Resolve the local hostname
char * host = SocketLibrary::ResolveHostname();
// Resolve the local address
unsigned long addr = SocketLibrary::ResolveAddress();
/* Create a socket on port 80 and bind to that address and you have an instant web server */
Address local(addr,80);
Socket server;
server.Bind(local);
server.Listen();
Address remote; Socket client;
while(server.Accept(client,remote))
{
String buffer;
buffer.Allocate(1024);
if ((buffer.Size=client.Read(buffer.Data,buffer.Allocated)) > 0
&& buffer.StartsWith("GET "))
{
buffer.Format("HTTP/1.x 200 Ok\r\nConnection: close
\r\n\r\n<html><body>Welcome %s</body></html>
\r\n\r\n",remote.Ip());
client.Send(buffer.Data,buffer.Size);
}
client.Close();
}
|
 |
 |
 |
 |
If you want to use non blocking sockets you can either change the Socket mode using the Mode() method
or supply the mode in the constructor.
The following example illustrates how this can be used to create an efficient non blocking connection
handler.
The Connection class provides a convinient way of managing Address's and Socket's.
 |
 |
 |
 |
// A simple non blocking io socket server.
List<Connection*> connections;
Socket listener(Socket::SOCKET_MODE_ASYNCHRONOUS);
/* You might want to bind to a specific addres, or all available addresses */
listener.Bind(Address(Address::ADDRESS_TYPE_ANY,8080));
// listener.Bind(Address(SocketLibrary::ResolveAddress(),8080));
listener.Listen();
Connection * connection = new Connection(Socket::SOCKET_MODE_ASYNCHRONOUS);
Time future;
future += 10; // 10 seconds from now
do
{
if(listener.Accept(connection->Socket,connection->Address))
{
connections.Append(connection);
connection = new Connection(Socket::SOCKET_MODE_ASYNCHRONOUS);
}
for(int i=0;i<connections.Length();++i)
{
String string;
string.Allocate(1024);
int read = connections[i]->Socket.Read(string.Data,string.Allocated);
if (read == 0 && !connections[i]->Socket.IsReadable())
connections.DeleteAt(i);
else
string.Size = read;
}
// Wait 100 milliseconds between accepting connections
Thread::Sleep(100);
}
while(Time() < future);
delete connection;
connections.Destroy();
|
 |
 |
 |
 |
There are also classes for working with common protocols like HTTP. You can use HttpClient or HttpServer
along with HttpRequest and HttpResponse to construct your own web server or client. Reason is ideal for developing
and deploying simple XML based web services.
There is also a HttpManager class along with an HttpService class for building simple servlet style HTTP request
processing components.