EnumBitArray.h

00001 /*  _________________________________________________________________________
00002  *
00003  *  UTILIB: A utility library for developing portable C++ codes.
00004  *  Copyright (c) 2001, Sandia National Laboratories.
00005  *  This software is distributed under the GNU Lesser General Public License.
00006  *  For more information, see the README file in the top UTILIB directory.
00007  *  _________________________________________________________________________
00008  */
00009 
00010 //
00011 // EnumBitArray.h
00012 //
00028 #ifndef __EnumBitArray
00029 #define __EnumBitArray
00030 
00031 #ifdef __GNUC__
00032 #pragma interface
00033 #endif
00034 
00035 #ifdef NON_ANSI
00036 #include <iostream.h>
00037 #else
00038 #include <iostream>
00039 using namespace std;
00040 #endif
00041 #ifndef ANSI_HDRS
00042 #include <math.h>
00043 #else
00044 #include <cmath>
00045 #endif
00046 #include "BitArrayBase.h"
00047 
00048 // I'm not sure that this would work if BYTESIZE != 8
00049 #define BYTESIZE 8      /* bits per char */
00050 
00063 #if !defined(EnumBitArraySanityChecking)
00064 #define EnumBitArraySanityChecking      1
00065 #endif
00066 
00067 
00068 template <class T>
00069 class UTILIB_API EnumBitArray : public BitArrayBase {
00070 
00071 public:
00072 
00074   EnumBitArray() : BitArrayBase() {}
00076   EnumBitArray(const size_type len, const size_type nbytes=0, char* d=(char*)0, 
00077                          const EnumDataOwned o=DataNotOwned)
00078                 {construct(len,
00079                         (nbytes==0 ?  (len+BYTESIZE-1)/(BYTESIZE/element_size())                                
00080                                    : nbytes), 
00081                         d,o); }
00083   EnumBitArray(const EnumBitArray& array)
00084                 : BitArrayBase(array) {}
00085 
00087   T operator()(const size_type idx) const;
00089   void put(const size_type idx, const T val);
00091   EnumBitArray<T>& operator=(const T value);
00092 
00094   int write(ostream& input) const;
00096   int read(istream& input);
00097 
00098 protected:
00099 
00101   int operator[](const size_type idx) const;
00103   void put(const size_type , const int ) {}
00105   int element_size() const
00106                 {return enum_count;}
00107 
00109   static int   enum_count;
00111   static char  enum_labels[];
00113   static T     enum_vals[];
00114 
00115 };
00116  
00117 
00118 template <class T>
00119 inline int EnumBitArray<T>::operator[](const size_type idx) const
00120 {
00121 #if (EnumBitArraySanityChecking==1)
00122 if (idx >= array_len)
00123    ErrAbort(errmsg("EnumBitArray<T>::operator() : iterator out of range. idx=%d len=%d",idx,array_len));
00124 #endif
00125 
00126 unsigned char X = Data[(2*idx)/BYTESIZE];
00127 size_type i = 2*idx;
00128 unsigned char val = (X & (char)(3 << (i & (BYTESIZE - 1))));
00129 val = val >> (i & (BYTESIZE - 1));
00130 
00131 return (int)val;
00132 }
00133  
00134 
00135 template <class T>
00136 inline T EnumBitArray<T>::operator()(const size_type idx) const
00137 { return (T) operator[](idx); }
00138  
00139 
00140 template <class T>
00141 inline void EnumBitArray<T>::put(const size_type idx, const T val)
00142 {
00143 #if (EnumBitArraySanityChecking==1)
00144 if (idx >= array_len)
00145    ErrAbort(errmsg("EnumBitArray<T>::put : iterator out of range. idx=%d len=%d",idx,array_len));
00146 #endif
00147 
00148 int tval = (int)val;
00149 unsigned char X = Data[(2*idx)/BYTESIZE];
00150 size_type i = 2*idx;
00151 unsigned char qwerty = (3 << (i & (BYTESIZE - 1)));
00152 unsigned char qwertydata = X & qwerty;
00153 X ^= qwertydata;
00154 X |= ((tval & 3) << (i & (BYTESIZE - 1)));
00155 Data[(2*idx)/BYTESIZE] = X;
00156 }
00157 
00158 
00159 //
00160 // This only works for element_size() <= 4 right now...
00161 //
00162 template <class T>
00163 int EnumBitArray<T>::read(istream& s)
00164 {
00165   size_type i;
00166   char c;
00167 
00168   if (Data) {// size is known
00169      for (i=0; i<array_len; i++) {
00170        s.get(c);
00171        while (s && ((c == ' ') || (c == '\t') || (c == '\n')))
00172          s.get(c);
00173        int j;
00174        for (j=0; j<element_size(); j++)
00175          if (c == enum_labels[j]) break;
00176        if (j<element_size())
00177           put(i,enum_vals[j]);
00178        else {
00179           ErrAbort(errmsg("TwoBitArray::read : Bad input value: %c.",c));
00180           break;
00181           }
00182        }
00183      }
00184 
00185   else                  // size and sparseity is not known
00186     ErrAbort( "TwoBitArray::read: size and sparseity not known" );
00187 
00188   return OK ;
00189 }
00190 
00191 
00192 
00193 template <class T>
00194 int EnumBitArray<T>::write(ostream& s) const
00195 {
00196 s << array_len << ": ";
00197 if (Data) {
00198    for (size_type i=0; i<array_len; i++)
00199      s << enum_labels[(int)(operator()(i))];
00200    }
00201 
00202 return OK ;
00203 }
00204 
00205 
00206 template <class T>
00207 EnumBitArray<T>& EnumBitArray<T>::operator=(const T val)
00208 {
00209 BitArrayBase::operator=((int)val);
00210 return *this;
00211 }
00212 
00213 #endif