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