00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 #ifndef W_OPAQUE_H
00031 #define W_OPAQUE_H
00032 
00033 #include "w_defines.h"
00034 
00035 
00036 
00037 #include <cctype>
00038 #include <cstring>
00039 
00040 #ifndef W_BASE_H
00041 #include <w_base.h>
00042 #endif
00043 
00044 template <int LEN> class opaque_quantity;
00045 template <int LEN> ostream &operator<<(ostream &o,
00046                        const opaque_quantity<LEN> &r);
00047 template <int LEN> bool operator==(const opaque_quantity<LEN> &l,
00048                    const opaque_quantity<LEN> &r);
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 template <int LEN> 
00062 class opaque_quantity 
00063 {
00064 
00065 private:
00066 
00067     uint4_t         _length;
00068     unsigned char _opaque[LEN];
00069 
00070     public:
00071     opaque_quantity() {
00072         (void) set_length(0);
00073 #ifdef ZERO_INIT
00074         memset(_opaque, '\0', LEN);
00075 #endif
00076     }
00077     opaque_quantity(const char* s)
00078     {
00079 #ifdef ZERO_INIT
00080         memset(_opaque, '\0', LEN);
00081 #endif
00082         *this = s;
00083     }
00084 
00085     friend bool
00086     operator== <LEN> (
00087         const opaque_quantity<LEN>    &l,
00088         const opaque_quantity<LEN>    &r); 
00089 
00090     friend ostream & 
00091     operator<< <LEN> (
00092         ostream &o, 
00093         const opaque_quantity<LEN>    &b);
00094 
00095     opaque_quantity<LEN>    &
00096     operator=(const opaque_quantity<LEN>    &r) 
00097     {
00098         (void) set_length(r.length());
00099         memcpy(_opaque,r._opaque,length());
00100         return *this;
00101     }
00102     opaque_quantity<LEN>    &
00103     operator=(const char* s)
00104     {
00105         w_assert9(strlen(s) <= LEN);
00106         (void) set_length(0);
00107         while ((_opaque[length()] = *s++))
00108             (void) set_length(length() + 1);
00109         return *this;
00110     }
00111     opaque_quantity<LEN>    &
00112     operator+=(const char* s)
00113     {
00114         w_assert9(strlen(s) + length() <= LEN);
00115         while ((_opaque[set_length(length() + 1)] = *s++))
00116             ;
00117         return *this;
00118     }
00119     opaque_quantity<LEN>    &
00120     operator-=(uint4_t len)
00121     {
00122         w_assert9(len <= length());
00123         (void) set_length(length() - len);
00124         return *this;
00125     }
00126     opaque_quantity<LEN>    &
00127     append(const void* data, uint4_t len)
00128     {
00129         w_assert9(len + length() <= LEN);
00130         memcpy((void*)&_opaque[length()], data, len);
00131         (void) set_length(length() + len);
00132         return *this;
00133     }
00134     opaque_quantity<LEN>    &
00135     zero()
00136     {
00137         (void) set_length(0);
00138         memset(_opaque, 0, LEN);
00139         return *this;
00140     }
00141     opaque_quantity<LEN>    &
00142     clear()
00143     {
00144         (void) set_length(0);
00145         return *this;
00146     }
00147     void *
00148     data_at_offset(unsigned i)  const
00149     {
00150         w_assert9(i < length());
00151         return (void*)&_opaque[i];
00152     }
00153     uint4_t          wholelength() const {
00154         return (sizeof(_length) + length());
00155     }
00156     uint4_t          set_length(uint4_t l) {
00157         if(is_aligned()) { 
00158             _length = l; 
00159         } else {
00160             char *m = (char *)&_length;
00161             memcpy(m, &l, sizeof(_length));
00162         }
00163         return l;
00164     }
00165     uint4_t          length() const {
00166         if(is_aligned()) return _length;
00167         else {
00168             uint4_t l;
00169             char *m = (char *)&_length;
00170             memcpy(&l, m, sizeof(_length));
00171             return l;
00172         }
00173     }
00174 
00175     void          ntoh()  {
00176         if(is_aligned()) {
00177             _length = w_base_t::w_ntohl(_length);
00178         } else {
00179             uint4_t         l = w_base_t::w_ntohl(length());
00180             char *m = (char *)&l;
00181             memcpy(&_length, m, sizeof(_length));
00182         }
00183     }
00184     void          hton()  {
00185         if(is_aligned()) {
00186             _length = w_base_t::w_htonl(_length);
00187         } else {
00188             uint4_t         l = w_base_t::w_htonl(length());
00189             char *m = (char *)&l;
00190             memcpy(&_length, m, sizeof(_length));
00191         }
00192     }
00193 
00194     
00195     bool          is_aligned() const  {
00196         return (((ptrdiff_t)(&_length) & (sizeof(_length) - 1)) == 0);
00197     }
00198 
00199     ostream        &print(ostream & o) const {
00200         o << "opaque[" << length() << "]" ;
00201 
00202         uint4_t print_length = length();
00203         if (print_length > LEN) {
00204             o << "[TRUNC TO LEN=" << LEN << "!!]";
00205             print_length = LEN;
00206         }
00207         o << '"';
00208         const unsigned char *cp = &_opaque[0];
00209         for (uint4_t i = 0; i < print_length; i++, cp++) {
00210             if (isprint(*cp))
00211                 o << *cp;
00212             else {
00213                 W_FORM(o)("\\x%02X", *cp); 
00214             }
00215         }
00216 
00217         return o << '"';
00218     }
00219 };
00220 
00221 
00222 template <int LEN>
00223 bool operator==(const opaque_quantity<LEN> &a,
00224     const opaque_quantity<LEN>    &b) 
00225 {
00226     return ((a.length()==b.length()) &&
00227         (memcmp(a._opaque,b._opaque,a.length())==0));
00228 }
00229 
00230 template <int LEN>
00231 ostream & 
00232 operator<<(ostream &o, const opaque_quantity<LEN>    &b) 
00233 {
00234     return b.print(o);
00235 }
00236 
00237 
00238 
00239 #endif