Attribute_RT.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_RT_h_ 00042 #define _Attribute_RT_h_ 00043 00044 #include <stdint.h> 00045 00046 #include "util/generic_endianess.h" 00047 00048 #include "mw/attributes/detail/AttributeElementHeader.h" 00049 #include "mw/attributes/access/AttributeHeader_RT.h" 00050 00051 namespace famouso { 00052 namespace mw { 00053 namespace attributes { 00054 namespace access { 00055 00072 class Attribute_RT : public AttributeHeader_RT { 00073 protected: 00074 Attribute_RT() { 00075 // Visibility 00076 } 00077 00078 // TODO: Think about the usage of CaseSelector<>::select_rt() for 00079 // getting and setting the attribute's value or even for all 00080 // case specific implementations of attribute runtime access 00081 00082 public: 00094 template <typename ValueType> 00095 const ValueType getValue() const { 00096 // The result (in big endian order first, it will be converted when 00097 // it is returned) 00098 ValueType res; 00099 00100 const uint8_t* const data = reinterpret_cast<const uint8_t* const>(this); 00101 00102 const elemHeader_t* const header = asElementHeader(); 00103 00104 if ((header->isHighDensity()) && (!header->lengthValueSwitch)) { 00105 // We have a HD-attribute with its value encoded as a part of the header 00106 00107 if (header->extension) { 00108 if (sizeof(ValueType) == 1) { 00109 // If the value type has only one byte, the two remaining bits 00110 // of the header byte are zero, since all 8 bits of the value 00111 // fit the extended byte 00112 // (Implicit conversion: data[1] -> uint8_t -> static_cast -> ValueType) 00113 res = static_cast<ValueType>(data[1]); 00114 } else { 00115 // In all other cases the 10 bits of the 2-byte-header must be used 00116 const uint16_t tmp = *(reinterpret_cast<const uint16_t* const>(data)); 00117 00118 // Adjust endianess and mask out the upper 6 header meta-bits 00119 res = (famouso::util::ntoh(tmp) & 0x3FF); 00120 } 00121 } else { 00122 res = static_cast<ValueType> (data[0] & 0x3); 00123 } 00124 } else { 00125 // Initialize the result to zeros 00126 res = ValueType(); 00127 00128 // Pointer to the attribute value 00129 const uint8_t* valPtr; 00130 00131 // Number of bytes to copy from the val-array 00132 uint16_t length; 00133 00134 const uint16_t lengthMask = ((header->isHighDensity()) ? 0x3FF : 0x7FF); 00135 const uint8_t valueOffset = ((header->isHighDensity()) ? 1 : 2); 00136 00137 // Read the length in big-endian order 00138 if (header->extension) { 00139 length = *(reinterpret_cast<const uint16_t*>(data)); 00140 length = (ntohs(length) & lengthMask); 00141 valPtr = &data[valueOffset + 1]; 00142 } else { 00143 // Expand the single byte to a 16 bit value and only apply the 00144 // high byte of the mask (0x3) 00145 length = static_cast<uint16_t>(data[0] & 0x3); 00146 valPtr = &data[valueOffset]; 00147 } 00148 00149 // Interpret the result as a byte array to copy every single byte 00150 uint8_t* resPtr = reinterpret_cast<uint8_t* const>(&res) + 00151 sizeof(ValueType) - 1; 00152 // Set the value pointer to the last byte of the value 00153 valPtr += (length - 1); 00154 00155 while (length-- > 0) { 00156 *resPtr-- = *valPtr--; 00157 } 00158 00159 res = famouso::util::ntoh(res); 00160 } 00161 00162 return (res); 00163 } 00164 00184 template <typename ValueType> 00185 const bool setValue(const ValueType newValue) { 00186 uint8_t* const data = reinterpret_cast<uint8_t* const>(this); 00187 00188 // Determine the bit count of the value to set 00189 const uint16_t newBitCount = getBitCount(newValue); 00190 00191 elemHeader_t* const header = asElementHeader(); 00192 00193 if ((header->isHighDensity()) && (!header->lengthValueSwitch)) { 00194 if (header->extension) { 00195 // 10 bits at max are allowed in this case 00196 if (newBitCount > 10) 00197 return (false); 00198 00199 if (sizeof(ValueType) == 1) { 00200 // If the given value has only one byte, the 2 bits of the header 00201 // must be cleared and the extended byte is set to the given value 00202 00203 header->valueOrLength = 0x0; 00204 00205 data[1] = static_cast<uint8_t>(newValue); 00206 } else { 00207 // This case can never be reached by a negative value (it would have 00208 // taken 16 bits, which is not allowed here) 00209 00210 // Convert the given value to big endian order 00211 const ValueType bigEndian = famouso::util::hton(newValue); 00212 00213 // In all other cases the lower 10 bits of the given value must be 00214 // copied into the binary representation 00215 // Retrieve a pointer and move it to the last byte of the value 00216 const uint8_t* const tmp = reinterpret_cast<const uint8_t* const>(&bigEndian) + 00217 sizeof(ValueType) - 1; 00218 00219 // Copy the lowest 2 bits of the header 00220 header->valueOrLength = (*(tmp - 1) & 0x3); 00221 // Copy into the extended byte 00222 data[1] = *tmp; 00223 } 00224 } else { 00225 // Only 2 bits at max are allowed here 00226 if (newBitCount > 2) 00227 return (false); 00228 00229 // This case can never be reached by a negative value (it takes 8 bits at least) 00230 // so it is legal to simply mask the lowest 2 bits 00231 00232 // Simply write the lowest 3 bits to the header 00233 header->valueOrLength = (newValue & 0x3); 00234 } 00235 } else { 00236 // Determine the byte count needed by the new value (this is necessary since 00237 // we only write whole bytes if the VOL flag isn't set) 00238 const uint16_t newByteCount = bitCountToByteCount(newBitCount); 00239 00240 // The pointer where to start copying the bytes of the new value 00241 // (depends on the extension flag) 00242 uint8_t* targetPtr; 00243 // The length read 00244 // TODO: Use AttributeHeader_RT.getLength() here 00245 uint16_t length; 00246 00247 const uint8_t valueOffset = ((header->isHighDensity()) ? 1 : 2); 00248 00249 // Read the length in big-endian order 00250 if (header->extension) { 00251 length = *(reinterpret_cast<const uint16_t*>(data)); 00252 length = (ntohs(length) & ((header->isHighDensity()) ? 0x3FF : 0x7FF)); 00253 targetPtr = &data[valueOffset + 1]; 00254 } else { 00255 // Expand the single byte to a 16 bit value and only apply the 00256 // high byte of the mask (0x3) 00257 length = static_cast<uint16_t>(data[0] & 0x3); 00258 targetPtr = &data[valueOffset]; 00259 } 00260 00261 // Check if the new byte count does not violate the old one 00262 if (newByteCount > length) return (false); 00263 00264 // Convert the given value to big endian order 00265 const ValueType bigEndian = famouso::util::hton(newValue); 00266 // Get a pointer to the big endian representation 00267 const uint8_t* const newValPtr = 00268 reinterpret_cast<const uint8_t*>(&bigEndian) + (sizeof(ValueType) - length); 00269 00270 // Copy the value (we even copy the possible zero bytes of the new value to 00271 // zero out the bytes not needed, the length must not be decreased since 00272 // it would make iterating over the byte sequence impossible) 00273 for (uint16_t i = 0; i < length; ++i) { 00274 targetPtr[i] = newValPtr[i]; 00275 } 00276 } 00277 00278 return (true); 00279 } 00280 00287 uint16_t length() const { 00288 // The sum of the header size (which eventually includes an encoded 00289 // attribute value) and the encoded length is the overall size of 00290 // the attribute 00291 return (headerLength() + valueLength()); 00292 } 00293 00294 }; 00295 00296 } // end namespace access 00297 } // end namespace attributes 00298 } // end namespace mw 00299 } // end namespace famouso 00300 00301 #endif // _Attribute_h_