AttributeBlob_impl.h

Go to the documentation of this file.
00001 // $Id: AttributeBlob_impl.h 165 2006-05-29 16:39:53Z bingmann $
00002 
00003 #ifndef VGS_AttributeBlob_Impl_H
00004 #define VGS_AttributeBlob_Impl_H
00005 
00006 #include "AttributeBlob.h"
00007 
00008 namespace VGServer {
00009 
00015 
00016 template <typename AllocPolicy>
00017 inline void TpAttributeBlob<AllocPolicy>::getAnyType(unsigned int i, AnyType &v) const
00018 {
00019     switch(v.getType())
00020     {
00021     case ATTRTYPE_INVALID: assert(0); return;
00022 
00023     case ATTRTYPE_BOOL:
00024         // this is a special case: bit values are stored within the default
00025         // bitfield, so the index i alone is insufficient to fetch the boolean
00026         // value. getBool must be used directly.
00027         assert(0);
00028         return;
00029 
00030     case ATTRTYPE_CHAR:
00031         v.setInteger(get<char>(i));
00032         return;
00033 
00034     case ATTRTYPE_SHORT:
00035         v.setInteger(get<short>(i));
00036         return;
00037 
00038     case ATTRTYPE_INTEGER:
00039         v.setInteger(get<int>(i));
00040         return;
00041 
00042     case ATTRTYPE_LONG:
00043         v.setLong(get<long long>(i));
00044         return;
00045 
00046     case ATTRTYPE_BYTE:
00047         v.setInteger(get<unsigned char>(i));
00048         return;
00049 
00050     case ATTRTYPE_WORD:
00051         v.setInteger(get<unsigned short>(i));
00052         return;
00053 
00054     case ATTRTYPE_DWORD:
00055         v.setInteger(get<unsigned int>(i));
00056         return;
00057 
00058     case ATTRTYPE_QWORD:
00059         v.setLong(get<unsigned long long>(i));
00060         return;
00061 
00062     case ATTRTYPE_FLOAT:
00063         v.setDouble(get<float>(i));
00064         return;
00065 
00066     case ATTRTYPE_DOUBLE:
00067         v.setDouble(get<double>(i));
00068         return;
00069 
00070     case ATTRTYPE_STRING:
00071         v.setString(getString(i));
00072         return;
00073 
00074     case ATTRTYPE_LONGSTRING:
00075         v.setString(getLongstring(i));
00076         return;
00077 
00078     }
00079     assert(0);
00080 }
00081 
00083 template <typename AllocPolicy>
00084 inline void TpAttributeBlob<AllocPolicy>::putAnyType(unsigned int i, const AnyType &v)
00085 {
00086     switch(v.getType())
00087     {
00088     case ATTRTYPE_INVALID: assert(0); return;
00089 
00090     case ATTRTYPE_BOOL:
00091         // this is a special case: bit values are stored within the
00092         // default. putBool must be used directly.
00093         assert(0);
00094         return;
00095 
00096     case ATTRTYPE_CHAR:
00097         put<char>(i, v.getInteger());
00098         return;
00099 
00100     case ATTRTYPE_SHORT:
00101         put<short>(i, v.getInteger());
00102         return;
00103 
00104     case ATTRTYPE_INTEGER:
00105         put<int>(i, v.getInteger());
00106         return;
00107 
00108     case ATTRTYPE_LONG:
00109         put<long long>(i, v.getLong());
00110         return;
00111 
00112     case ATTRTYPE_BYTE:
00113         put<unsigned char>(i, v.getUnsignedInteger());
00114         return;
00115 
00116     case ATTRTYPE_WORD:
00117         put<unsigned short>(i, v.getUnsignedInteger());
00118         return;
00119 
00120     case ATTRTYPE_DWORD:
00121         put<unsigned int>(i, v.getUnsignedInteger());
00122         return;
00123 
00124     case ATTRTYPE_QWORD:
00125         put<unsigned long long>(i, v.getUnsignedLong());
00126         return;
00127 
00128     case ATTRTYPE_FLOAT:
00129         put<float>(i, static_cast<float>(v.getDouble()));
00130         return;
00131 
00132     case ATTRTYPE_DOUBLE:
00133         put<double>(i, v.getDouble());
00134         return;
00135 
00136     case ATTRTYPE_STRING:
00137         putString(i, v.getString());
00138         return;
00139 
00140     case ATTRTYPE_LONGSTRING:
00141         putLongstring(i, v.getString());
00142         return;
00143 
00144     }
00145     assert(0);
00146 }
00147 
00149 template <typename AllocPolicy>
00150 inline unsigned int TpAttributeBlob<AllocPolicy>::getAttrChainLength(unsigned int i, const AttributePropertiesList &attrlist) const
00151 {
00152     unsigned int p = i + attrlist.defbytes;
00153 
00154     for(unsigned int ai = 0; ai < attrlist.size(); ai++)
00155     {
00156         if (attrlist[ai].varying)
00157         {
00158             assert(attrlist[ai].isFixedLength());
00159             p += attrlist[ai].getTypeLength();
00160         }
00161         else
00162         {
00163             assert(attrlist.defbits > attrlist[ai].defbitnum);
00164             if (getBool(i, attrlist[ai].defbitnum))
00165             {
00166                 // if the default bit is set, then no space is used in the
00167                 // attribute array
00168             }
00169             else
00170             {
00171                 switch(attrlist[ai].getType())
00172                 {
00173                 default: assert(0); break;
00174 
00175                 CASE_FIXED_LENGTH:
00176                     // easy case
00177                     p += attrlist[ai].getTypeLength();
00178                     break;
00179 
00180                     // if this is a string or long string: we have to fetch the
00181                     // string's length from the attribute blob.
00182                 case ATTRTYPE_STRING:
00183                     p += get<unsigned char>(p);
00184                     break;
00185 
00186                 case ATTRTYPE_LONGSTRING:
00187                     p += get<unsigned int>(p);
00188                     break;
00189                 }
00190             }
00191         }
00192     }
00193 
00194     return p - i;
00195 }
00196 
00198 template <typename AllocPolicy>
00199 inline AnyType TpAttributeBlob<AllocPolicy>::getAttrChainValue(unsigned int chidx, unsigned int attrid, const AttributePropertiesList &attrlist) const
00200 {
00201     if (attrlist.size() < attrid) throw AttributeIdException();
00202 
00203     // alias for this attribute's properties
00204     const AttributeProperties &ap = attrlist[attrid];
00205 
00206     // create correctly typed return object
00207     class AnyType value(ap.getType());
00208 
00209     if (ap.lookup >= 0) // use the direct lookup index
00210     {
00211         // retrieve the typed value
00212         getAnyType(chidx + ap.lookup, value);
00213         return value;
00214     }
00215 
00216     // if it is a boolean type, the value is stored in the default bitfield
00217     if (ap.getType() == ATTRTYPE_BOOL)
00218     {
00219         value.setInteger( getBool(chidx, ap.defbitnum) );
00220         return value;
00221     }
00222 
00223     // check if the default bit is cleared: then return the default attribute
00224     // value.
00225     if (getBool(chidx, ap.defbitnum))
00226     {
00227         value = ap;
00228         return value;
00229     }
00230 
00231     // otherwise we have to iterate over the attribute values to find the
00232     // correct offset.
00233     unsigned int idx = chidx + attrlist.defbytes;
00234 
00235     for(unsigned int _i = 0; _i < attrid; _i++)
00236     {
00237         const AttributeProperties &aiter = attrlist[_i];
00238 
00239         // attributes marked as varying are always in the blob
00240         if (aiter.varying)
00241         {
00242             assert(aiter.isFixedLength());
00243             idx += aiter.getTypeLength();
00244         }
00245         else
00246         {
00247             if (getBool(chidx, aiter.defbitnum))
00248             {
00249                 // if the default bit is set, then no space is used in the
00250                 // attribute array
00251             }
00252             else
00253             {
00254                 switch(aiter.getType())
00255                 {
00256                 default: assert(0); break;
00257 
00258                 CASE_FIXED_LENGTH:
00259                     // easy case
00260                     idx += aiter.getTypeLength();
00261                     break;
00262                         
00263                 // this is a string or long string: we have to fetch the
00264                 // string's length from the attribute blob.
00265                 case ATTRTYPE_STRING:
00266                     idx += get<unsigned char>(idx);
00267                     break;
00268 
00269                 case ATTRTYPE_LONGSTRING:
00270                     idx += get<unsigned int>(idx);
00271                     break;
00272                 }
00273 
00274             }
00275         }
00276     }
00277 
00278     // well if everything worked right, then idx is now the offset
00279     getAnyType(idx, value);
00280     return value;
00281 }
00282 
00283 template <typename AllocPolicy>
00284 inline bool TpAttributeBlob<AllocPolicy>::putAttrChainValue(const AttributePropertiesList &attrlist,
00285                                                             unsigned int attrid, const AnyType &value)
00286 {
00287     if (attrid >= attrlist.size()) throw AttributeIdException();
00288 
00289     if (value.getType() != attrlist[attrid].getType())
00290     {
00291         // convert input value to attribute type, this could throw a
00292         // ConversionException.
00293         AnyType conv = value;
00294         conv.convertType(attrlist[attrid].getType());
00295         
00296         return putAttrChainValue(attrlist, attrid, conv);
00297     }
00298 
00299     // alias for the attribute properties
00300     const AttributeProperties &attrprop = attrlist[attrid];
00301 
00302     // easy case: the value is a boolean, so it is in the default bitfield.
00303     if (value.getType() == ATTRTYPE_BOOL)
00304     {
00305         putBool(0, attrprop.defbitnum, value.getInteger() != 0);
00306         return true;
00307     }
00308     
00309     // another fast and easy case: direct lookup attributes
00310     if (attrprop.lookup >= 0)
00311     {
00312         assert(attrprop.isFixedLength());
00313 
00314         // overwrite value at a direct lookup
00315         putAnyType(attrprop.lookup, value);
00316         return true;
00317     }
00318 
00319     // stupid case in which the default bit is set and the new value is also
00320     // the default value. Thus this is a noop.
00321     if (getBool(0, attrprop.defbitnum) and value == attrprop)
00322         return true;
00323 
00324     // else we have to run through the default bitfield to find the
00325     // right place.
00326     unsigned int p = attrlist.defbytes;
00327 
00328     for(unsigned int ai = 0; ai < attrid; ai++)
00329     {
00330         if (attrlist[ai].varying)
00331         {
00332             assert(attrlist[ai].isFixedLength());
00333             p += attrlist[ai].getTypeLength();
00334         }
00335         else
00336         {
00337             if (getBool(0, attrlist[ai].defbitnum))
00338             {
00339                 // if the default bit is set, then no space is used in the
00340                 // attribute array
00341             }
00342             else
00343             {
00344                 switch(attrlist[ai].getType())
00345                 {
00346                 default: assert(0); break;
00347 
00348                 CASE_FIXED_LENGTH:
00349                     // easy case
00350                     p += attrlist[ai].getTypeLength();
00351                     break;
00352 
00353                 // if this is a string or long string: we have to fetch the
00354                 // string's length from the attribute blob.
00355                 case ATTRTYPE_STRING:
00356                     p += get<unsigned char>(p);
00357                     break;
00358 
00359                 case ATTRTYPE_LONGSTRING:
00360                     p += get<unsigned int>(p);
00361                     break;
00362                 }
00363             }
00364         }
00365     }
00366 
00367     // p should now be the index of the attribute value, if it's default bit is
00368     // cleared.
00369 
00370     assert(not attrprop.varying);
00371 
00372     if (getBool(0, attrprop.defbitnum))
00373     {
00374         if (value == attrprop)
00375         {
00376             // no need for action: setting default value which is already set
00377             assert(0); // assert because this should have been handled above.
00378         }
00379         else
00380         {
00381             // default bit of our attribute is set, so we have to make room in the
00382             // blob for it's new value.
00383         
00384             putBool(0, attrprop.defbitnum, false);
00385 
00386             // same procedure for fixed sized and variable sized attributes, the
00387             // work is done by AnyType::getValueLength.
00388 
00389             move(p, p + value.getValueLength(), size() - p);
00390 
00391             putAnyType(p, value);
00392         }
00393     }
00394     else
00395     {
00396         // the default bit was cleared, so the attribute already has a
00397         // non-default value.
00398 
00399         if (value != attrprop)
00400         {
00401             // the new value is not the default value.
00402 
00403             switch(value.getType())
00404             {
00405             default: assert(0); break;
00406 
00407             CASE_FIXED_LENGTH:
00408             {
00409                 // simply overwrite fixed size values
00410                 putAnyType(p, value);
00411                 break;
00412             }
00413 
00414             // for variable sized attributes, we must move the following
00415             // attribute values.
00416 
00417             case ATTRTYPE_STRING:
00418             {
00419                 unsigned char oldlen = sizeof(unsigned char) + get<unsigned char>(p);
00420 
00421                 if (oldlen < value.getValueLength() or oldlen > value.getValueLength())
00422                 {
00423                     // make more room by moving trailing attribute values.
00424                     move(p + oldlen, p + value.getValueLength(),
00425                          size() - (p + oldlen));
00426                 }
00427 
00428                 // now the space fits exactly
00429                 putAnyType(p, value);
00430                 break;
00431             }
00432 
00433             case ATTRTYPE_LONGSTRING:
00434             {
00435                 unsigned int oldlen = sizeof(unsigned int) + get<unsigned int>(p);
00436 
00437                 if (oldlen < value.getValueLength() or oldlen > value.getValueLength())
00438                 {
00439                     // make more room by moving trailing attribute values.
00440                     move(p + oldlen, p + value.getValueLength(),
00441                          size() - (p + oldlen));
00442                 }
00443 
00444                 // now the space fits exactly
00445                 putAnyType(p, value);
00446                 break;
00447             }
00448             }
00449         }
00450         else
00451         {
00452             // new value is the default value, so we set the default bit and
00453             // erase any used memory.
00454             
00455             putBool(0, attrprop.defbitnum, true);
00456             
00457             // calculate the length to splice from the attribute value blob
00458             unsigned int len = 0;
00459 
00460             switch(value.getType())
00461             {
00462             default: assert(0); break;
00463 
00464             CASE_FIXED_LENGTH:
00465                 len = attrprop.getTypeLength();
00466                 break;
00467 
00468             // for variable sized attributes, we must check the length value in
00469             // the array
00470             case ATTRTYPE_STRING:
00471                 len = get<unsigned char>(p);
00472                 break;
00473 
00474             case ATTRTYPE_LONGSTRING:
00475                 len = get<unsigned int>(p);
00476                 break;
00477             }
00478 
00479             move(p + len, p, size() - (p + len));
00480         }
00481     }
00482     return true;
00483 }
00484 
00485 } // namespace VGServer
00486 
00487 #endif // VGS_AttributeBlob_Impl_H
00488 
00489 

Generated on Wed Sep 27 14:34:00 2006 for VGServer by  doxygen 1.4.7