Contents
Resources

Overview

The resource classes provide a unified approach to specifying, sourcing and obtaining resource streams via URIs.

There are two groups of classes defined in the Balau::Resource namespace:

URIs specify resources and provide functionality specific to each URI type. Resources are a convenient way of obtaining read and (for certain resource types) write streams on the resources specified by the URIs.

Quick start

#include <Balau/Resource/*.hpp>

URIs

URI classes each specify a different type of URI. All URI classes are derived from the common Uri base class. The currently available URI classes are:

The Http and Https URI classes derive from the abstract Url class.

URI classes may be used as stack based objects or on the heap in standard pointer containers.

			// Stack based URI objects.
			File file { "text.txt" };
			Http wiki { "http://wikipedia.org" };

			// Heap based URI objects.
			auto src1 = std::unique_ptr<URI>(new File("text.txt"));
			auto src2 = std::unique_ptr<URI>(new Https("https://en.wikipedia.org/wiki/B"));
		

Heap based URI objects allow different types of URI to provide abstract functionality, such as providing resources.

Resources

Each URI class is accompanied by two or four resource classes. The abstract resource classes are:

The first pair of abstract resource classes provide byte based resource reading and writing.

The second pair of abstract resource classes provide UTF-8 to UTF-32 resource reading and UTF-32 to UTF-8 resource writing. These resource types allow reading from UTF-8 streams and consuming in UTF-32, and producing in UTF-32 and writing as UTF-8.

Resource objects must be obtained from URIs, either in heap based, abstract form contained within std::unique_ptr containers, or in stack based, concrete form directly from concrete URI types.

			// An abstract URI.
			std::unique_ptr<URI> uri = getUri();

			// Get an abstract byte read resource from the URI.
			std::unique_ptr<ByteReadResource> readResource = uri->byteReadResource();
		

Once a read / write resource has been obtained from a URI, the input / output stream (UTF-8 or UTF-32) may be obtained by calling readStream or writeStream.

			// Get an input stream from the resource.
			std::istream & stream = readResource->readStream();
		

URI classes

There are two ways to use the URI classes. The first way is to use instances of the URI classes directly as stack based objects. Balau components make extensive use of URI classes in this way, predominantly the File class. Each URI class provides an API that is specialised for URIs of the type provided by the class. For example, the File class provides the usual file manipulation functions such as checking for file existence and type, delete the file, etc.

The second way to use the URI classes is on the heap inside a pointer container. Some Balau components accept a std::unique_ptr<Uri> argument, allowing any type of URI to be supplied.

The most useful use cases for supplying std::unique_ptr<Uri> arguments to a component is:

The methods in the base Uri class that obtain read and write resources are as follows.

			///
			/// Get a byte read resource for the URI.
			///
			/// This will throw a NotImplementedException if the URI does not support reading.

			///
			public: virtual std::unique_ptr<ByteReadResource> byteReadResource() = 0;

			///
			/// Get a UTF-8 to UTF-32 read resource for the URI.
			///
			/// This will throw a NotImplementedException if the URI does not support reading.
			///
			public: virtual std::unique_ptr<Utf8To32ReadResource> utf8To32ReadResource() = 0;

			///
			/// Get a byte write resource for the URI.
			///
			/// This will throw a NotImplementedException if the URI does not support writing.
			///
			public: virtual std::unique_ptr<ByteWriteResource> byteWriteResource() = 0;

			///
			/// Get a UTF-32 to UTF-8 write resource for the URI.
			///
			/// This will throw a NotImplementedException if the URI does not support writing.
			///
			public: virtual std::unique_ptr<Utf32To8WriteResource> utf32To8WriteResource() = 0;
		

In order to determine whether a URI supports reading and writing, the canReadFrom and canWriteTo methods can be called.

			///
			/// Can data be read from the URI via a read resource.
			///
			public: virtual bool canReadFrom() const = 0;

			///
			/// Can data be written to the URI via a write resource.
			///
			public: virtual bool canWriteTo() const = 0;
		

The method in the base Uri class that obtains a recursive iterator is as follows.

			///
			/// Get a recursive iterator.
			///
			/// This will throw a NotImplementedException if the URI does not have a recursive iterator.
			///
			public: virtual std::unique_ptr<RecursiveUriIterator> recursiveIterator() = 0;
		

In order to determine whether a URI supports recursive iteration, the isRecursivelyIterable method can be called.

			///
			/// Does the URI have a recursive iterator (e.g. file and zip archive URIs).
			///
			public: virtual bool isRecursivelyIterable() const = 0;
		

Resource classes

As discussed in the previous section, the abstract resource classes are:

Byte based ByteReadResource and ByteWriteResource derived resources provide input and output streams that read/write as bytes. These can be used for any byte oriented purpose, including UTF-8 strings.

Unicode based Utf8To32ReadResource and Utf32To8WriteResource derived resources provide input and output streams that provide an internal format of char32_t, despite reading or writing the external resource data as a UTF-8 byte stream. These can be used when a stream of Unicode characters needs to be read or written.

Each concrete URI type provides at least one set of read or write resource classes. Some URI classes provide both sets of resource classes.

Recursive iterators

In addition to the resource readers and writers, some of the URI classes provide recursive iterators. These iterators supply a stream of new URIs, either of the same URI type (in the case of the File URI), or a different type (ZipFile). Resource readers/writers may be obtained from each of the URIs obtained during iteration.

The two types of recursive iterator currently defined in the library allow iteration over:

As the recursive iterators may be obtained from a pointer of type Uri, components may be written that consume input and/or output streams for sets of resources on the local file system or from within zip archives.

Custom resources

As the Uri and resource readers/writers are abstract classes, custom URIs and associated resources may be created easily and used within components that consume abstract resources. In order to do this, the Uri class should be implemented, along with associated implementations of ByteReadResource / Utf8To32ReadResource if the resource may be read, and ByteWriteResource / Utf32To8WriteResource if the resource may be written.