xdrbuf.h

Go to the documentation of this file.
00001 /*
00002  * xdrbuf.h
00003  *
00004  * Copyright (c) 2008,2009 Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Wrapper API to create and read/write XDR buffers for interprocess/network
00032  * communication.
00033  */
00034 
00035 #ifndef WAVEPACKET_XDRBUF_H__
00036 #define WAVEPACKET_XDRBUF_H__
00037 
00038 
00039 // includes --------------------------------------------------------------------
00040 #include "common/common.h"
00041 #include "threadsafe/smart_ptr.h"
00042 
00043 
00044 namespace xdrbuf {
00045 
00046 // doxygen block
00047 
00048 ////////////////////////////////////////////////////////////////////////////////
00049 ///
00050 /// \ingroup networking
00051 /// \defgroup xdrbuf XDR Buffer APIs
00052 ///
00053 /// \n
00054 /// Objects and APIs to help manage XDR streams.  XDR is used to ensure that
00055 /// data can be passed between hosts on a network transparently, even if the
00056 /// hardware uses different byte ordering (little- vs big-endian).
00057 ///
00058 /// For information on XDR, see
00059 /// http://en.wikipedia.org/wiki/External_Data_Representation , or, on Unix
00060 /// systems, type "man xdr".
00061 ///
00062 /// \b Update: Actually, this library no longer depends on XDR!  I found that
00063 /// XDR has very poor support on Windows at least.  So I dropped it.  Wire
00064 /// encoding is handled by the basic socket methods htonl(), ntohl(), etc.
00065 ///
00066 /// The fact that this library no longer uses XDR doesn't impact callers: they
00067 /// were already insulated.  But it does mean that "xdrbuf" is already a
00068 /// legacy name...  For now, I'll keep referring to "XDR streams" to describe
00069 /// the series of bytes sent and received across the network.
00070 ///
00071 ///\n
00072 /// What this library attempts to do is add a simple, self-describing layer
00073 /// on top of basic XDR streams.
00074 ///
00075 /// The organizing unit is called a "packlet", because it is a small packet of
00076 /// data.  You can think of packlets as something like XML tags.  Packlets can
00077 /// contain simple data (like leaf XML nodes), or they can contain other
00078 /// packlets (parent XML nodes).
00079 ///
00080 /// XML tags are fairly feature-rich, but packlets are designed to be very
00081 /// simple and small.  A packlet header is only 2 bytes, which keeps overhead
00082 /// down.
00083 ///
00084 /// Use the xdrbuf::Output object to construct XDR streams containing packlets.
00085 /// If you use that interface, you are guaranteed a well-formed packlet stream.
00086 ///
00087 /// Once you receive an XDR stream (created with the xdrbuf::Output interface),
00088 /// use the xdrbuf::Input object to decode it.  The Input object will use the
00089 /// encoded packlet information to verify that access to the raw XDR stream is
00090 /// syntactically correct.
00091 ///
00092 ////////////////////////////////////////////////////////////////////////////////
00093 /*@{*/
00094 
00095 
00096 /// these are the types of data supported by packlets
00097 enum ePackletType {
00098         ePacklet_Reserved       = 0,    ///< don't use this
00099         ePacklet_ParentBegin    = 1,    ///< packlet contains other packlets
00100         ePacklet_ParentEnd      = 2,    ///< end of parent packlet
00101         ePacklet_String         = 3,    ///< packlet contains a single string
00102         ePacklet_Floats         = 4,    ///< packlet contains list of floats
00103         ePacklet_Int32s         = 5,    ///< packlet contains list of int32s
00104 
00105         // must be last!
00106         ePacklet_Invalid        = 8
00107 };
00108 
00109 
00110 
00111 /// A name is a single character.
00112 /// valid names are 'a' - 'z', '$', '*', '?', '!', '='
00113 bool isValidPackletName(IN char a);
00114 
00115 
00116 
00117 /// A PackletHeader describes a given packlet (what sort of data it is,
00118 ///     and how much data is there).
00119 class PackletHeader {
00120 public:
00121         // xdrbuf::PackletHeader class methods ---------------------------------
00122 
00123         /// return the (single-character) name for this packlet
00124         char getName(void) const throw();
00125 
00126         /// return the datatype contained in this packlet
00127         ePackletType getType(void) const throw();
00128 
00129         /// return count (count, \e not size!) , based on packlet type
00130         ///  - \b String: returns length of string (NOT counting null-terminator)
00131         ///  - \b Floats: returns count of floats
00132         ///  - \b Int32s:  returns count of longs
00133         int getDataCount(void) const throw();
00134 
00135 protected:
00136         PackletHeader(void) throw();
00137         void setData(IN word_t d) { m_data = d; }
00138 
00139         word_t          m_data;
00140 };
00141 
00142 
00143 
00144 
00145 /// class for writing data to the network
00146 class Output {
00147 public:
00148         // virtual destructor --------------------------------------------------
00149         virtual ~Output(void) throw();
00150 
00151         // xdrbuf::Output class interface methods ------------------------------
00152         virtual void clear(void) = 0;
00153         virtual int getRemainingBytes(void) const throw() = 0;
00154 
00155         /// create (open) a parent packlet in the stream
00156         virtual void openPacklet(IN char name) = 0;
00157 
00158         /// close an open (parent) packlet
00159         virtual void closePacklet(IN char name) = 0;
00160 
00161         /// add a string packlet to the stream
00162         virtual void addStringPacklet(IN char name,
00163                                 IN const char * s,
00164                                 IN int length) = 0;
00165 
00166         /// add a float packlet (array of floats) to the stream
00167         virtual void addFloatPacklet(IN char name,
00168                                 IN const float * data,
00169                                 IN int nFloats) = 0;
00170 
00171         /// add an int32 packlet (array of int32_t's) to the stream
00172         virtual void addInt32Packlet(IN char name,
00173                                 IN const int32_t * data,
00174                                 IN int nInts) = 0;
00175 
00176         /// retrieve raw data from buffer (called after all streaming is done)
00177         virtual const byte_t * getData(void) throw() = 0;
00178         virtual int getDataBytes(void) const throw() = 0;
00179 
00180         // static factory methods ----------------------------------------------
00181         static smart_ptr<Output> create(IN int bytes);
00182 };
00183 
00184 
00185 
00186 /// class for reading data from the network
00187 class Input {
00188 public:
00189         // virtual destructor --------------------------------------------------
00190         virtual ~Input(void) throw();
00191 
00192         // xdrbuf::Input class interface methods -------------------------------
00193 
00194         /// provide stream reading object with the raw data to use.  \b WARNING:
00195         ///  the Input class does not make a copy of the input buffer!  The
00196         ///  caller needs to ensure that the input buffer lives as long as the
00197         ///  Input object.
00198         virtual void reset(IN const byte_t * stream,
00199                                 IN int bytes) = 0;
00200 
00201         /// have we read all data?
00202         virtual bool endOfStream(void) = 0;
00203 
00204         /// retrieves the next packlet header (fails if not at a packlet header)
00205         virtual PackletHeader getNextPackletHeader(void) = 0;
00206 
00207         /// read int32s (fails if you didn't just read an Int32 packlet header)
00208         virtual void readInt32s(OUT int32_t * buffer,
00209                                 IN int count) = 0;
00210 
00211         /// read floats (fails if you didn't just read a float packlet header)
00212         virtual void readFloats(OUT float * buffer,
00213                                 IN int count) = 0;
00214 
00215         /// read strings (fails if you didn't just read a string packlet header)
00216         virtual void readString(OUT char * buffer,
00217                                 IN int length) = 0;
00218 
00219         // static factory methods ----------------------------------------------
00220         static smart_ptr<Input> create(void);
00221 };
00222 
00223 
00224 
00225 };      // xdrbuf namespace
00226 
00227 /*@}*/  // end of documentation block
00228 
00229 #endif  // WAVEPACKET_XDRBUF_H__
00230