===========================================
Controlling the reading and writing process
===========================================

Overview
========

In addition to the high-level read/write functions which support reading from and writing to a disk file, the HOOPS/Stream Toolkit also supports writing and reading HOOPS Stream File information to and from a user-specified location. This is a powerful feature which enables the application developer to store the HOOPS Stream File information within a custom application specific file format (or any location) and retrieve it from the custom location, rather than use a separate HSF file. More importantly, the data can be incrementally streamed into the reading application's scene-graph. 

For example, many technical applications that also visualize 2D/3D information utilize a custom file format that contains application specific data. When the file is read in, the application then goes through a laborious process of recreating the 2D/3D information associated with the application data. By utilizing the HOOPS/Stream Toolkit, a developer could cache the scene-graph geometry in their own proprietary file format file by actually embedding the HSF information in their file. File load time and initial rendering is drastically reduced, the custom file format remains intact, and the highly compressed HSF information minimizes the increase of file size.
   
   
Controlling reading
===================

First review the section about :doc:`reading HSF files </prog_guide/base_stream/02_02_base_reading>`. To control the reading process, a piece of binary data that has been read from an HSF file is presented to the ``BStreamFileToolkit`` object for parsing and insertion into your custom data structures by calling the ``BStreamFileToolkit::ParseBuffer`` method. This method doesn't care where the data originated from, but simply reads the data from the buffer passed to it, and calls the Read and Execute methods of the opcode handler registered to handle the current opcode being processed. Therefore, if you want to access custom HSF objects, you will need to have first registered custom opcode handlers for the objects of interest (and implement the Execute methods to do something with the data.) 

The following code example demonstrates how data could be manually read from a local file and inserted into your custom data structures using ``BStreamFileToolkit::ParseBuffer``. A file is open and pieces of data are read from it using the ``BStreamFileToolkit`` wrapper functions for file opening and reading ( ``BStreamFileToolkit::OpenFile`` and ``BStreamFileToolkit::ReadBuffer`` ). Data is continually read and passed to ``BStreamFileToolkit::ParseBuffer`` until it returns ``#TK_Complete``, indicating that reading is complete, or until an error occurs. Example::

	void Read_Stream_File (char const * filename)  
	{ 
		auto	char		block[BUFFER_SIZE]; 
		auto	TK_Status	status = TK_Normal; 
		auto	int			amount;  

		BStreamFileToolkit * tk = new BStreamFileToolkit;  

		// our sample custom toolkit only cares about segment and shells 
		tk->SetOpcodeHandler (TKE_Open_Segment, new TK_My_Open_Segment);    
		tk->SetOpcodeHandler (TKE_Close_Segment, new TK_My_Close_Segment);    
		tk->SetOpcodeHandler (TKE_Shell, new TK_My_Shell);  

		if ((status = tk->OpenFile (filename)) != TK_Normal)    
			return status;  
		do 
		{ 
			if (tk->ReadBuffer (block, BUFFER_SIZE, amount) != TK_Normal) 
				break;  
			status = tk->ParseBuffer(block, amount);  
			
			if (status == TK_Error)    
			{ 
				// whatever...    
				break; 
			} 
		} while (status != TK_Complete);  

		tk->CloseFile ();  

		delete tk; 
	} 


Controlling writing
===================

Controlling writing using the base classes is already explained in the section on :doc:`writing HSF files </prog_guide/base_stream/02_01_base_writing>`. Since writing out an HSF file using the base classes must be done manually anyway (because the developer has to supply their own logic to traverse the graphics information and directly export HSF objects), exporting to a user-supplied/controlled buffer rather than a file is just a special case of the ``WriteObject`` function described in the example programs in that section. The only difference would be to omit the 'fwrite' call, and deal with the HSF data buffer directly. (Perhaps you wish to send the HSF data to another application, or export it to your own custom filetype, etc...)
