• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

okteta

  • sources
  • kde-4.12
  • kdesdk
  • okteta
  • kasten
  • controllers
  • view
  • structures
allprimitivetypes.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Okteta Kasten module, made within the KDE community.
3  *
4  * Copyright 2010 Alex Richardson <alex.richardson@gmx.de>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) version 3, or any
10  * later version accepted by the membership of KDE e.V. (or its
11  * successor approved by the membership of KDE e.V.), which shall
12  * act as a proxy defined in Section 6 of version 3 of the license.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "allprimitivetypes.h"
24 #include "compiletimeassert.h"
25 #include "datatypes/primitive/primitivedatainformation.h"
26 
27 #include <abstractbytearraymodel.h>
28 
29 
30 compile_time_assert(sizeof(double) == 8);
31 compile_time_assert(sizeof(float) == 4);
32 compile_time_assert(sizeof(AllPrimitiveTypes) == 8);
33 
34 
35 //FIXME this code really needs unit tests!
36 //TODO optimised methods for *bitOffset == 0 && bitCount % 8 == 0
37 
38 bool AllPrimitiveTypes::writeBits(quint8 bitCount, AllPrimitiveTypes newValue,
39  Okteta::AbstractByteArrayModel* out, QSysInfo::Endian byteOrder, Okteta::Address address,
40  BitCount64 bitsRemaining, quint8* const bitOffset)
41 {
42  Q_ASSERT(*bitOffset < 8);
43  Q_ASSERT(bitCount <= 64);
44  if (bitsRemaining < bitCount)
45  {
46  _ulong.value = 0;
47  *bitOffset = 0;
48  return false;
49  }
50  //set if not
51  if (_ulong.value != newValue._ulong.value)
52  _ulong.value = newValue._ulong.value;
53 
54  if (bitCount % 8 == 0 && *bitOffset == 0)
55  {
56  //only writing full bytes
57  writeFullBytes(bitCount / 8, newValue, out, byteOrder, address);
58  }
59  else
60  {
61  if (byteOrder == QSysInfo::LittleEndian)
62  {
63  writeDataLittleEndian(bitCount, newValue, out, address, *bitOffset);
64  }
65  else if (byteOrder == QSysInfo::BigEndian)
66  {
67  writeDataBigEndian(bitCount, newValue, out, address, *bitOffset);
68  }
69  else
70  {
71  Q_ASSERT(false);
72  return false;
73  }
74  *bitOffset = (*bitOffset + bitCount) % 8;
75  }
76  return true;
77 }
78 
79 bool AllPrimitiveTypes::readBits(quint8 bitCount, const Okteta::AbstractByteArrayModel* input,
80  QSysInfo::Endian byteOrder, Okteta::Address address, BitCount64 bitsRemaining,
81  quint8* const bitOffset)
82 {
83  Q_ASSERT(bitCount <= 64);
84  Q_ASSERT(*bitOffset < 8);
85  if (bitsRemaining < bitCount)
86  {
87  _ulong.value = 0;
88  *bitOffset = 0;
89  return false;
90  }
91  //set to zero before reading
92  _ulong.value = 0;
93  if (bitCount % 8 == 0 && *bitOffset == 0)
94  {
95  //only reading full bytes
96  readFullBytes(bitCount / 8, input, byteOrder, address);
97  }
98  else
99  {
100  if (byteOrder == QSysInfo::LittleEndian)
101  {
102  readDataLittleEndian(bitCount, input, address, *bitOffset);
103  }
104  else if (byteOrder == QSysInfo::BigEndian)
105  {
106  readDataBigEndian(bitCount, input, address, *bitOffset);
107  }
108  else
109  {
110  Q_ASSERT(false);
111  return false;
112  }
113  *bitOffset = (*bitOffset + bitCount) % 8;
114  }
115  return true;
116 }
117 
118 void AllPrimitiveTypes::readDataLittleEndian(quint8 bitCount,
119  const Okteta::AbstractByteArrayModel* input, Okteta::Address address, quint8 bo)
120 {
121  if (bitCount <= (unsigned) (8 - bo))
122  {
123  //fits completely
124  const quint8 lowerMask = 0xff << bo; //all lower bits are 0
125  const quint8 higherMask = 0xff >> (8 - (bo + bitCount)); // all higher bits are 0
126  const quint8 completeMask = lowerMask & higherMask; //region in the middle
127  const quint8 readByte = input->byte(address);
128  const quint8 maskedByte = readByte & completeMask;
129  _ubyte.value = maskedByte >> bo;
130  }
131  else
132  {
133  const quint8 firstByteMask = 0xff << bo;
134  const quint8 firstByte = input->byte(address);
135  const quint8 firstByteMasked = firstByte & firstByteMask;
136  _ubyte.value = firstByteMasked >> bo;
137  //if spans more than this one byte continue
138  for (uint i = 8; i < bitCount + bo; i += 8)
139  {
140  quint8 readVal = input->byte(address + (i / 8));
141  if (bitCount + bo < i + 8)
142  {
143  //this is last byte needed, possibly cut off top values
144  const quint8 missingBits = (bitCount + bo) % 8;
145  const quint8 mask = (1 << missingBits) - 1;
146  readVal &= mask; //mask the top few bits
147  }
148  //otherwise we need full byte -> nothing to do
149  //needs cast since otherwise compiler decides to use 32 bit int and top 32 bits get lost
150  const quint64 shiftedVal = (quint64) readVal << i;
151  _ulong.value |= shiftedVal >> bo; //move to correct byte
152  }
153  }
154 }
155 
156 void AllPrimitiveTypes::readDataBigEndian(quint8 bitCount,
157  const Okteta::AbstractByteArrayModel* input, Okteta::Address address, quint8 bo)
158 {
159  if (bitCount <= (unsigned) (8 - bo))
160  {
161  const quint8 lowerMask = 0xff << (8 - (bo + bitCount));
162  const quint8 higherMask = 0xff >> bo;
163  const quint8 completeMask = lowerMask & higherMask;
164  //completeMask maskes the value -> negate it to clear all the bytes
165  const quint8 readByte = input->byte(address);
166  const quint8 maskedByte = readByte & completeMask;
167  _ubyte.value = maskedByte >> (8 - (bo + bitCount));
168  }
169  else
170  {
171  const quint8 firstByteMask = 0xff >> bo;
172  const quint8 firstByte = input->byte(address);
173  //needs quint64 since otherwise compiler decides to use 32 bit int when shifting and top 32 bits get lost
174  const quint64 firstByteMasked = firstByte & firstByteMask;
175  const quint64 firstByteShifted = firstByteMasked << (bo + bitCount - 8);
176  _ulong.value = firstByteShifted;
177  //if spans more than this one byte continue
178  for (uint i = 8; i < bitCount + bo; i += 8)
179  {
180  quint8 readVal = input->byte(address + (i / 8));
181  if (bitCount + bo < i + 8)
182  {
183  //this is last byte needed, possibly cut off lower values
184  const quint8 missingBits = (bo + bitCount) % 8;
185  const quint8 mask = 0xff << (8 - missingBits);
186  const quint8 maskedVal = readVal & mask; //cut off lower bits
187  const quint8 shiftedVal = maskedVal >> (8 - missingBits);
188  _ulong.value |= shiftedVal;
189  }
190  else
191  {
192  //otherwise we need full byte -> nothing to do
193  //needs cast since otherwise compiler decides to use 32 bit int and top 32 bits get lost
194  const quint64 shiftedVal = (quint64) readVal << ((bo + bitCount)
195  - (8 + i)); //move to correct byte
196  _ulong.value |= shiftedVal;
197  }
198  }
199  }
200 }
201 
202 void AllPrimitiveTypes::writeDataLittleEndian(quint8 bitCount,
203  AllPrimitiveTypes newValue, Okteta::AbstractByteArrayModel *out,
204  Okteta::Address address, quint8 bo) const
205 {
206  if (bitCount <= (unsigned) (8 - bo))
207  {
208  //fits completely
209  const quint8 lowerMask = (1 << bo) - 1; //all lower bits are 1
210  const quint8 higherMask = 0xff << (bo + bitCount); // all higher bits are 1
211  const quint8 completeMask = lowerMask | higherMask; //region in the middle is 0
212  const quint8 readByte = out->byte(address);
213  const quint8 maskedByte = readByte & completeMask;
214  const quint8 addedVal = newValue._ubyte.value << bo;
215  const quint8 newVal = maskedByte | addedVal;
216  out->setByte(address, newVal);
217  }
218  else
219  {
220  const quint8 firstByteMask = (1 << bo) - 1;
221  const quint8 firstByte = out->byte(address);
222  const quint8 firstByteMasked = firstByte & firstByteMask;
223  const quint8 firstAddedVal = (newValue._ubyte.value << bo);
224  const quint8 firstByteWithValAdded = firstByteMasked | firstAddedVal;
225  out->setByte(address, firstByteWithValAdded);
226  //if spans more than this one byte continue
227  for (uint i = 8; i < bitCount + bo; i += 8)
228  {
229  const quint8 currentByte = newValue._ulong.value >> (i - bo);
230  if (bitCount + bo < i + 8)
231  {
232  const quint8 readVal = out->byte(address + (i / 8));
233  //this is last byte needed, possibly cut off bottom
234  const quint8 missingBits = (bitCount + bo) % 8;
235  const quint8 mask = 0xff << missingBits;
236  const quint8 readValMasked = readVal & mask; //remove the bottom values
237  const quint8 resultingVal = readValMasked | currentByte;
238  out->setByte(address + (i / 8), resultingVal);
239  }
240  else
241  {
242  //otherwise we need full byte -> nothing to do
243  out->setByte(address + (i / 8), currentByte);
244  }
245  }
246  }
247 }
248 
249 void AllPrimitiveTypes::writeDataBigEndian(quint8 bitCount,
250  AllPrimitiveTypes newValue, Okteta::AbstractByteArrayModel *out,
251  Okteta::Address address, quint8 bo) const
252 {
253  if (bitCount <= (unsigned) (8 - bo))
254  {
255  //fits completely
256  const quint8 lowerMask = 0xff >> (bo + bitCount); //all lower bits are 1
257  const quint8 higherMask = 0xff << (8 - bo); // all higher bits are 1
258  const quint8 completeMask = lowerMask | higherMask; //region in the middle is 0
259  const quint8 readByte = out->byte(address);
260  const quint8 maskedByte = readByte & completeMask;
261  const quint8 addedVal = newValue._ubyte.value << (8 - bo - 1); //move to missing area
262  const quint8 maskedByteWithValueAdded = maskedByte | addedVal;
263  out->setByte(address, maskedByteWithValueAdded);
264  }
265  else
266  {
267  quint8 missingBits = (bitCount + bo) % 8;
268  missingBits = (missingBits == 0 ? 8 : missingBits);
269  const quint8 lastAddress = address + ((bo + bitCount) / 8) - (missingBits
270  > 0 ? 0 : 1);
271  const quint8 lastByte = out->byte(lastAddress);
272  const quint8 lastByteMask = (1 << missingBits) - 1;
273  const quint8 lastByteMasked = lastByte & lastByteMask; //remove the top values
274  const quint8 lastByteAddedVal = newValue._ubyte.value << (8 - missingBits);
275  const quint8 lastByteWithValAdded = lastByteMasked | lastByteAddedVal;
276  out->setByte(lastAddress, lastByteWithValAdded);
277  for (int currAddress = lastAddress - 1; currAddress >= address; currAddress--)
278  {
279  const quint8 currentByte = out->byte(currAddress);
280  if (currAddress == address)
281  {
282  //last byte to read
283  const quint8 firstByteMask = 0xff << (8 - bo);
284  const quint8 firstByteMasked = currentByte & firstByteMask;
285  const quint8 highestByte = newValue._ulong.value
286  >> (bo + bitCount - 8);
287  const quint8 firstByteWithValAdded = firstByteMasked | highestByte;
288  out->setByte(address, firstByteWithValAdded);
289  }
290  else
291  {
292  const int bytesNotToShift = 1 + (lastAddress - address)
293  - (lastAddress - currAddress);
294  const quint8 thisByteShifted = newValue._ulong.value >> (bo + bitCount
295  - (8 * bytesNotToShift));
296  out->setByte(currAddress, thisByteShifted);
297  }
298  }
299  }
300 }
301 
302 void AllPrimitiveTypes::readFullBytes(quint8 byteCount, const Okteta::AbstractByteArrayModel* input,
303  QSysInfo::Endian byteOrder, Okteta::Address address)
304 {
305  Q_ASSERT(byteCount <= 8);
306  //always use unsigned value
307  for (int i = 0; i < byteCount; i++)
308  {
309  int index = (byteOrder == QSysInfo::LittleEndian) ? i
310  : ((byteCount - 1) - i);
311  Okteta::Byte readByte = input->byte(address + i);
312  allBytes[index] = readByte;
313  }
314 }
315 
316 void AllPrimitiveTypes::writeFullBytes(quint8 byteCount, AllPrimitiveTypes newValue,
317  Okteta::AbstractByteArrayModel* out, QSysInfo::Endian byteOrder, Okteta::Address address)
318 {
319  Q_ASSERT(byteCount <= 8);
320  for (int i = 0; i < byteCount; ++i)
321  {
322  int index = (byteOrder == QSysInfo::LittleEndian) ? i
323  : ((byteCount - 1) - i);
324  out->setByte(address + i, newValue.allBytes[index]);
325  }
326 }
Okteta::Address
qint32 Address
Definition: address.h:34
Okteta::AbstractByteArrayModel
could it be useful to hide the data access behind an iterator? * class KDataBufferIterator { public: ...
Definition: abstractbytearraymodel.h:79
abstractbytearraymodel.h
AllPrimitiveTypes::readBits
bool readBits(quint8 bitCount, const Okteta::AbstractByteArrayModel *input, QSysInfo::Endian byteOrder, Okteta::Address address, BitCount64 bitsRemaining, quint8 *const bitOffset)
Reads given number of bits from input and sets value of this union to the new value.
Definition: allprimitivetypes.cpp:79
BitCount64
quint64 BitCount64
Definition: datainformationbase.h:42
EndianIndependentBase::value
T value
Definition: allprimitivetypes.h:54
Okteta::Byte
unsigned char Byte
Definition: byte.h:29
compile_time_assert
compile_time_assert(sizeof(double)==8)
BigEndian
Definition: endianness.h:33
AllPrimitiveTypes::allBytes
qint8 allBytes[8]
Definition: allprimitivetypes.h:84
Okteta::AbstractByteArrayModel::setByte
virtual void setByte(Address offset, Byte byte)=0
sets a single byte if the offset is not valid the behaviour is undefined
Okteta::AbstractByteArrayModel::byte
virtual Byte byte(Address offset) const =0
locates working range The idea behind is to tell buffer which range will be requested in the followin...
AllPrimitiveTypes
This union holds the value of one primitive datatype.
Definition: allprimitivetypes.h:70
allprimitivetypes.h
LittleEndian
Definition: endianness.h:32
AllPrimitiveTypes::writeBits
bool writeBits(quint8 bitCount, AllPrimitiveTypes newValue, Okteta::AbstractByteArrayModel *out, QSysInfo::Endian byteOrder, Okteta::Address address, BitCount64 bitsRemaining, quint8 *const bitOffset)
Writes given number of bits to out.
Definition: allprimitivetypes.cpp:38
primitivedatainformation.h
compiletimeassert.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:04:06 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

okteta

Skip menu "okteta"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • okteta
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal