Menu

Attribute.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2008-2010 Michael Schulze <mschulze@ivs.cs.uni-magdeburg.de>
00004  *                    2010 Marcus Foerster <MarcusFoerster1@gmx.de>
00005  * All rights reserved.
00006  *
00007  *    Redistribution and use in source and binary forms, with or without
00008  *    modification, are permitted provided that the following conditions
00009  *    are met:
00010  *
00011  *    * Redistributions of source code must retain the above copyright
00012  *      notice, this list of conditions and the following disclaimer.
00013  *
00014  *    * Redistributions in binary form must reproduce the above copyright
00015  *      notice, this list of conditions and the following disclaimer in
00016  *      the documentation and/or other materials provided with the
00017  *      distribution.
00018  *
00019  *    * Neither the name of the copyright holders nor the names of
00020  *      contributors may be used to endorse or promote products derived
00021  *      from this software without specific prior written permission.
00022  *
00023  *
00024  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00025  *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00026  *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00027  *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  *    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  *    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  *    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  *    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  *    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  *
00037  * $Id$
00038  *
00039  ******************************************************************************/
00040 
00041 #ifndef _Attribute_h_
00042 #define _Attribute_h_
00043 
00044 #include <stdint.h>
00045 
00046 #include "boost/mpl/integral_c.hpp"
00047 
00048 #include "util/endianness.h"
00049 #include "util/generic_endianess.h"
00050 
00051 #include "object/PlacementNew.h"
00052 
00053 #include "mw/attributes/access/Attribute_RT.h"
00054 
00055 #include "mw/attributes/detail/AttributeSize.h"
00056 #include "mw/attributes/detail/AttributeAsserts.h"
00057 #include "mw/attributes/detail/ValueOffset.h"
00058 #include "mw/attributes/detail/ValueByteCount.h"
00059 #include "mw/attributes/detail/AttributeHeader.h"
00060 #include "mw/attributes/detail/AttributeElementHeader.h"
00061 #include "mw/attributes/detail/SmallestValueType.h"
00062 #include "mw/attributes/tags/IntegralConstTag.h"
00063 #include "mw/attributes/tags/AttributeTag.h"
00064 
00065 #include "mw/attributes/detail/tags/TagSet.h"
00066 #include "mw/attributes/detail/tags/IsHighDensity.h"
00067 #include "mw/attributes/detail/tags/IsRequirable.h"
00068 #include "mw/attributes/detail/tags/HasLessThanRelation.h"
00069 
00070 #include "config/type_traits/ByteCount.h"
00071 
00072 #include "assert/staticerror.h"
00073 
00074 namespace famouso {
00075     namespace mw {
00076         namespace attributes {
00077 
00115             template <typename BaseType, typename CompareTag, typename ValueType,
00116                       ValueType Value, uint8_t ID, typename TagSet = detail::TagSet<> >
00117             class Attribute : public famouso::mw::attributes::access::Attribute_RT {
00118                 public:
00119                     // The boost tag type, declaring the attribute class to be an
00120                     //  integral constant
00121                     typedef boost::mpl::integral_c_tag tag;
00122 
00123                     typedef tags::attribute_tag type_tag;
00124                     typedef CompareTag          compare_tag;
00125                     typedef BaseType            base_type;
00126 
00127                     // The type of the attribute's value
00128                     typedef ValueType value_type;
00129 
00130                     // The static value of this attribute
00131                     static const ValueType value = Value;
00132 
00133                     // The comparator filter expression for this attribute class, determined from
00134                     //  the given tag set
00135                     typedef typename
00136                         detail::HasLessThanRelation::template get_comparator<TagSet>::type comparator;
00137 
00138                     // The ID (aka category for system attributes) of this attribute
00139                     static const uint8_t id = ID;
00140 
00141                     // Determines whether this attribute is a high density attribute
00142                     static const bool highDensity =
00143                             TagSet::template contains_tag<detail::IsHighDensity>::value;
00144 
00145                     // Determines whether this attribute can occur in a requirement
00146                     static const bool requirable =
00147                             TagSet::template contains_tag<detail::IsRequirable>::value;
00148 
00149                     // A struct implementing the stronger relation between attributes
00150                     //  (generally delegates to less-than-or-equal respective
00151                     //   greater-than-or-equal relations)
00152                     template <typename OtherAttr>
00153                     struct isStronger :
00154                         public comparator::template apply_compiletime<Attribute, OtherAttr> {
00155                         FAMOUSO_STATIC_ASSERT_ERROR(
00156                             requirable,
00157                             only_requirable_attributes_may_have_a_stronger_relation,
00158                             (Attribute));
00159                     };
00160 
00161                     // The data array contains the binary representation of
00162                     //  this attribute (header + value)
00163                     uint8_t data[detail::AttributeSize<Attribute>::value];
00164 
00165                 private:
00166                     // Static dummy typedefs
00167                     typedef typename detail::ValueTypeAssert<value_type>::dummy       valueTypeAssert;
00168                     typedef typename detail::IdBitCountAssert<highDensity, id>::dummy idBitCountAssert;
00169 
00170                 protected:
00171                     Attribute() {
00172                         // Initialize the member array "data" to the binary representation
00173                         //  of this attribute
00174 
00175                         // The complex initialization (i.e. copying the bytes into the array)
00176                         //  only applies if the value takes at least one bit (e.g. 0 does not)
00177                         if (BitCount<value_type, value>::value > 0) {
00178                             // We help the compiler by determining the smallest type needed to
00179                             //  represent the initial attribute value
00180                             typedef typename detail::SmallestValueType<
00181                                                       ValueType, value
00182                                                      >::type smallest_type;
00183 
00184                             // Get a big endian representation of the value
00185                             const smallest_type bigEndian = famouso::util::hton(static_cast<smallest_type>(value));
00186                             // Get a pointer to the value
00187                             const uint8_t* ptr = reinterpret_cast<const uint8_t*> (&bigEndian);
00188                             // Move the pointer to the last byte
00189                             ptr += sizeof(smallest_type) - 1;
00190 
00191                             // The index where we start writing the value (starts at the last
00192                             //  byte which will be written and will then be decremented)
00193                             uint8_t i = detail::AttributeSize<Attribute>::value-1;
00194 
00195                             // Copy as many bytes as either fit the range where the value is
00196                             //  supposed to be written or as the value itself has (as sizeof()
00197                             //  determines)
00198                             uint8_t j = detail::ValueByteCount<Attribute>::value;
00199                             do {
00200                                 data[i--] = *ptr--;
00201                             } while (--j != 0);
00202                         } else {
00203                             // If the value's representation does not need any bit we simply zero
00204                             //  out the member array, the header will overwrite everything needed
00205                             //
00206                             //  1. System attribute, non-extended value
00207                             //      -here the whole attribute only consists of one
00208                             //       byte, so zeroing the "last" (the only) byte is
00209                             //       sufficient
00210                             //  2. Non-system attribute, non-extended length (length = 0 in this case)
00211                             //      -Nothing more has to be done here, since the
00212                             //       header will assign (not OR) itself to the first
00213                             //       two bytes (0xFFFF+length-part and the ID-part)
00214                             if (highDensity) {
00215                                   data[0] = 0x00;
00216                             }
00217                         }
00218 
00219                         // Write the header
00220                         // (It is essential to do that now, since the algorithm above does
00221                         //  not care about a possibly pre-written header, but the header
00222                         //  writer itself cares for a value possibly already written)
00223                         new (&data[0]) detail::AttributeHeader<Attribute> ;
00224                     }
00225 
00226                 public:
00227                     const ValueType getValue() const {
00228                         return (Attribute_RT::getValue<ValueType>());
00229                     }
00230 
00231                     const bool setValue(const ValueType newValue) {
00232                         return (Attribute_RT::setValue<ValueType>(newValue));
00233                     }
00234 
00235             };
00236 
00237         } // end namespace attributes
00238     } // end namespace mw
00239 } // end namespace famouso
00240 
00241 #endif // _Attribute_h_