An Overlay-based
Virtual Network Substrate
SpoVNet

source: source/ariba/utility/serialization/DataUtilities.hpp @ 3690

Last change on this file since 3690 was 3690, checked in by mies, 14 years ago

Merged 20090512-mies-connectors changes r3472:r3689 into trunk.

File size: 10.6 KB
Line 
1// [License]
2// The Ariba-Underlay Copyright
3//
4// Copyright (c) 2008-2009, Institute of Telematics, UniversitÀt Karlsruhe (TH)
5//
6// Institute of Telematics
7// UniversitÀt Karlsruhe (TH)
8// Zirkel 2, 76128 Karlsruhe
9// Germany
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
22// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
25// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33// The views and conclusions contained in the software and documentation
34// are those of the authors and should not be interpreted as representing
35// official policies, either expressed or implied, of the Institute of
36// Telematics.
37// [License]
38
39/* This file implements some common bit operations for unsigned integer types
40 * and arrays. There are two different approaches in indexing bits inside arrays
41 * and integrals:
42 *
43 * In simple integer types the least significant bit (LSB) is identified by index zero.
44 * A length is specified from the LSB to the MSB. On the other hand, there is an
45 * inverted form of this representation. In this case, the MSB is identfied by index
46 * zero and the length identifies a range from the MSB to the LSB.
47 *
48 *                   Normal                      Inverted
49 *             MSB            LSB           MSB            LSB
50 *              v              v             v              v
51 *             +----------------+           +----------------+
52 *             | uint16_t       |           | uint16_t       |
53 *             +----------------+           +----------------+
54 *              ^              ^             ^              ^
55 *     Index   15              0             0              15
56 *     Length          |<------+             +----->|
57 *
58 * Inside arrays the inverted form is used. Therefore an index of zero identifies the
59 * MSB of the first word in the array.
60 *
61 * TODO: TBC
62 */
63#ifndef DATAUTILITIES_HPP_
64#define DATAUTILITIES_HPP_
65
66#include "../internal/Utilities.hpp"
67
68#include <boost/cstdint.hpp>
69
70#include <memory>
71#include <string>
72
73/**
74 * TODO: Doc
75 */
76template<typename X> finline
77static X bitblk(size_t index, size_t length, bool value, if_uint(X)) {
78        if (index == 0 && length >= sizeof(X) * 8) return value ? ~0 : 0;
79        X x = ((((X) 1) << length) - 1) << index;
80        return value ? x : ~x;
81}
82
83/**
84 * TODO: Doc
85 */
86template<typename X, bool value> finline
87static X bitblk(size_t index, size_t length, if_uint(X)) {
88        return bitblk<X> (index, length, value);
89}
90
91/**
92 * TODO: Doc
93 */
94template<typename X, bool value> finline
95static X bitblk(size_t length, if_uint(X)) {
96        if (length >= sizeof(X) * 8) return value ? ~0 : 0;
97        return value ? (((X) 1 << length) - 1) : ~(((X) 1 << length) - 1);
98}
99
100/**
101 * This method copies bits from one integral to another
102 */
103template<typename X, typename Y> finline
104static Y bitcpy(X src, size_t srcIdx, Y dst, size_t dstIdx, size_t len =
105                sizeof(X) * 8, bool srcInvert = false, bool dstInvert = false,
106                if_uint(X),if_uint (Y) ) {
107        if (srcInvert) srcIdx = sizeof(X) * 8 - srcIdx - len;
108        if (dstInvert) dstIdx = sizeof(Y) * 8 - dstIdx - len;
109        Y value = ((Y) (src >> srcIdx)) << dstIdx;
110        Y mask = bitblk<Y, 0> (dstIdx, len);
111        return (dst & mask) | (value & ~mask);
112}
113
114/**
115 * This method copies bits from an array to another of the same
116 * integral type.
117 */
118template<typename X> finline
119static void bitcpy(X* src, size_t srcIdx, X* dst, size_t dstIdx, size_t len) {
120
121        // word width
122        const size_t w = sizeof(X) * 8;
123
124        // calculate indexes
125        size_t dwp = dstIdx % w, swp = srcIdx % w;
126        size_t idwp = w - dwp, iswp = w - swp;
127        dst += dstIdx / w;
128        src += srcIdx / w;
129
130        // check direct copy
131        if (dwp == 0 && swp == 0 && len % w == 0) {
132                memcpy(dst, src, len / 8);
133                return;
134        }
135
136        // check if first word only is affected
137        if ((dwp + len) <= w) {
138                X fw = (src[0] << swp) | (src[1] >> iswp);
139                *dst = bitcpy(fw, 0, *dst, dwp, len, true, true);
140                return;
141        }
142
143        // set first word
144        if (idwp != 0) {
145                X fw = (src[0] << swp) | (src[1] >> iswp);
146                *dst = (*dst & ~(((X) 1 << idwp) - 1)) | (fw >> dwp);
147
148                // recalculate indexes & lengths
149                dst++;
150                src++;
151                len -= idwp;
152                swp = (swp + idwp) % w;
153                iswp = w - swp;
154        }
155
156        X a, b;
157
158        // copy whole words
159        if (swp == 0) {
160                size_t numWords = len / w;
161                // use memory copy
162                memcpy(dst, src, numWords * sizeof(X));
163                src += numWords;
164                dst += numWords;
165                len = len % w;
166                a = src[0], b = src[1];
167        } else {
168                // use shifted copy
169                a = src[0], b = src[1];
170                while (len >= w) {
171                        *dst = (a << swp) | (b >> iswp);
172                        dst++;
173                        src++;
174                        len -= w;
175                        a = b;
176                        b = *src;
177                }
178        }
179
180        // set last word
181        X lw = (a << swp) | (b >> iswp), lm = (((X) 1 << (w - len)) - 1);
182        *dst = (*dst & lm) | (lw & ~lm);
183}
184
185/**
186 * array -> integral
187 */
188template<typename X, typename Y> finline
189static void bitcpy(X* src, size_t srcIdx, Y& dst, size_t dstIdx, size_t len =
190                sizeof(Y) * 8, if_uint(Y),if_uint (X) ) {
191
192        // word width
193                const size_t w = sizeof(X) * 8;
194
195                // calculate indexes
196                size_t swp = srcIdx % w, iswp = w - swp;
197                src += srcIdx / w;
198
199                // mask off bits
200                dst &= bitblk<Y,0>(dstIdx,len);
201
202                // copy whole words
203                X a = src[0], b = src[1];
204                Y value = 0;
205                src++;
206                while (len >= w) {
207                        X x = (a << swp) | (b >> iswp);
208                        value <<= w;
209                        value |= x;
210                        src++;
211                        len -= w;
212                        a = b; b = *src;
213                }
214
215                // copy leftover
216                if ( len> 0 ) {
217                        value <<= len;
218                        value |= (((a << swp) | (b >> iswp)) >> (w - len)) & ((1 << len)-1);
219                }
220
221                // set value
222                dst |= (value << dstIdx);
223        }
224
225/**
226 * TODO: Doc
227 */
228// word -> array
229template<typename X> finline
230static void bitcpy(X src, size_t srcIdx, X* dst, size_t dstIdx, size_t len =
231                sizeof(X) * 8, bool srcInvert = false, if_uint(X)) {
232
233        // check inversion
234        if (srcInvert) srcIdx = sizeof(X) * 8 - srcIdx - len;
235
236        // word width
237        const size_t w = sizeof(X) * 8;
238
239        // calculate indexes
240        size_t dwp = dstIdx % w;
241        dst += dstIdx / w;
242
243        // copy directly
244        if (dwp == 0 && srcIdx == 0 && len == w) {
245                *dst = src;
246        } else
247
248        // copy non-overlapping word
249        if ((dwp + len) <= w) {
250                *dst = bitcpy(src, srcIdx, *dst, dwp, len, false, true);
251
252                // copy overlapping word
253        } else {
254                size_t idwp = w - dwp;
255                src >>= srcIdx;
256                X mask1 = ~((1 << idwp) - 1);
257                dst[0] = (dst[0] & mask1) | ((src >> (len - idwp)) & ~mask1);
258                X mask2 = (1 << (w - len + idwp)) - 1;
259                dst[1] = (dst[1] & mask2) | ((src << (w - len + idwp)) & ~mask2);
260        }
261}
262
263/**
264 * TODO: Doc
265 */
266// integral -> array
267template<typename Y, typename X> finline
268static void bitcpy(Y src, size_t srcIdx, X* dst, size_t dstIdx, size_t len =
269                sizeof(Y) * 8, bool srcInvert = false, if_uint(X),if_uint (Y) ) {
270
271        if (sizeof(Y) <= sizeof(X)) {
272                // check inversion
273                if (srcInvert)
274                srcIdx = sizeof(Y) * 8 - srcIdx - len + (sizeof(X)-sizeof(Y))*8;
275                bitcpy((X)src,srcIdx,dst,dstIdx,len,false);
276        } else {
277                // check inversion
278                if (srcInvert) srcIdx = sizeof(Y) * 8 - srcIdx - len;
279                src >>= srcIdx;
280
281                const size_t dw = sizeof(X)*8;
282                while (len >= dw) {
283                        X word = (X)(src >> (len-dw));
284                        bitcpy(word,0,dst,dstIdx,dw);
285                        dstIdx += dw;
286                        len -= dw;
287                }
288                X word = (X)src;
289                bitcpy(word,0,dst,dstIdx,len);
290        }
291}
292
293/**
294 * TODO: Doc
295 */
296template<typename T, typename X> finline
297static T bitget(X* src, size_t idx, size_t len = sizeof(T) * 8, if_uint(X),if_uint (T) ) {
298        T x = 0;
299        bitcpy(src, idx, x, 0, len );
300        return x;
301}
302
303/**
304 * TODO: Doc
305 */
306template<typename T, typename X> finline
307static T bitget(X src, size_t idx, size_t len = sizeof(T) * 8, if_uint(X),if_uint (T) ) {
308        T x = 0;
309        bitcpy(src, idx, x, 0, len );
310        return x;
311}
312
313/**
314 * TODO: Doc
315 */
316template<typename X> finline
317static bool bitget(X* src, size_t index, if_uint(X)) {
318        uint8_t x = 0;
319        bitcpy(src, index, x, 0, 1);
320        return x != 0;
321}
322
323/**
324 * TODO: Doc
325 */
326template<typename X> finline
327static bool bitget(X src, size_t index, if_uint(X)) {
328        uint8_t x = 0;
329        x = bitcpy(src, index, x, 0, 1);
330        return x != 0;
331}
332
333/**
334 * TODO: Doc
335 */
336template<typename T, typename X> finline
337static void bitset(T src, X* dst, size_t index, if_uint(X),if_uint (T) ) {
338        bitcpy(src,0,dst,index);
339}
340
341/**
342 * TODO: Doc
343 */
344template<typename X> finline
345static void bitset(bool src, X* dst, size_t index, if_uint(X) ) {
346        bitcpy(src != 0, 0, dst, index, 1);
347}
348
349/**
350 * TODO: Doc
351 */
352template<typename X> finline
353static X bitset(bool src, X dst, size_t index, if_uint(X)) {
354        return bitcpy(src != 0, 0, dst, index, 1);
355}
356
357/**
358 * TODO: Doc
359 */
360template<typename X> finline
361static X bitrev(X src, if_uint(X) ) {
362        const size_t width = sizeof(X) * 8;
363        X dst = 0;
364        for (size_t i = 0; i < width; i++)
365                dst = bitset(bitget(src, i), dst, width - i - 1);
366        return dst;
367}
368
369/**
370 * TODO: Doc
371 */
372template<typename X> finline
373static void bitrev(X* src, size_t len, if_uint(X) ) {
374        for (size_t i = 0; i < len / 2; i++) {
375                bool b0 = bitget(src, i);
376                bool b1 = bitget(src, len - i - 1);
377                bitset(b1, src, i);
378                bitset(b0, src, len - i - 1);
379        }
380}
381
382/**
383 * TODO: Doc
384 */
385template<typename X> finline
386static X switch_endian(X src, if_uint(X) ) {
387        if (sizeof(X) == 1) return src;
388        X ret = 0;
389        for (size_t i = 0; i < sizeof(X); i++) {
390                ret <<= 8;
391                ret |= src & 0xFF;
392                src >>= 8;
393        }
394        return ret;
395}
396
397/**
398 * TODO: Doc
399 */
400template<typename X> finline
401static std::string bitstr(X src, int log2base = 4, if_uint(X)) {
402        const size_t word_width = sizeof(src) * 8;
403        const char digit[37] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
404
405        std::string str;
406        for (int i = word_width - log2base, j = 0; i >= 0; i -= log2base, j++)
407                str.append(1, digit[(src >> i) & ((1 << log2base) - 1)]);
408        return str;
409}
410
411/**
412 * TODO: Doc
413 */
414template<typename X> finline
415static std::string bitstr(X* src, size_t len, int log2base = 4, bool dot =
416                false, if_uint(X)) {
417        std::string str;
418        for (size_t i = 0; i < len / 8 / sizeof(X); i++) {
419                if (i != 0 && dot) str.append(".");
420                str.append(bitstr(src[i], log2base));
421        }
422        return str;
423}
424
425#endif /* DATAUTILITIES_HPP_ */
Note: See TracBrowser for help on using the repository browser.