1878f3ea558ded9f662b1ad9dcd0684394eddc9c
[swifty.git] / src / libswift_udp / bin.cpp
1 /*
2  *  bin.cpp
3  *  swift
4  *
5  *  Created by Victor Grishchenko on 10/10/09.
6  *  Reimplemented by Alexander G. Pronchenkov on 05/05/10
7  *
8  *  Copyright 2010 Delft University of Technology. All rights reserved.
9  *
10  */
11
12 #include "bin.h"
13 #include <ostream>
14
15
16 const bin_t bin_t::NONE(8 * sizeof(bin_t::uint_t), 0);
17 const bin_t bin_t::ALL(8 * sizeof(bin_t::uint_t) - 1, 0);
18
19
20 /* Methods */
21
22 /**
23  * Gets the layer value of a bin
24  */
25 int bin_t::layer(void) const
26 {
27     if (is_none()) {
28         return -1;
29     }
30
31     int r = 0;
32
33 #ifdef _MSC_VER
34 #  pragma warning (push)
35 #  pragma warning (disable:4146)
36 #endif
37     register uint_t tail;
38     tail = v_ + 1;
39     tail = tail & (-tail);
40 #ifdef _MSC_VER
41 #  pragma warning (pop)
42 #endif
43
44     if (tail > 0x80000000U) {
45         r = 32;
46         tail >>= 16;    // FIXME: hide warning
47         tail >>= 16;
48     }
49
50     // courtesy of Sean Eron Anderson
51     // http://graphics.stanford.edu/~seander/bithacks.html
52     static const char DeBRUIJN[32] = { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 };
53
54     return r + DeBRUIJN[ 0x1f & ((tail * 0x077CB531U) >> 27) ];
55 }
56
57 /* String operations */
58
59 namespace {
60
61 char* append(char* buf, int x)
62 {
63     char* l = buf;
64     char* r = buf;
65
66     if (x < 0) {
67         *r++ = '-';
68         x = -x;
69     }
70
71     do {
72         *r++ = '0' + x % 10;
73         x /= 10;
74     } while (x);
75
76     char* e = r--;
77
78     while (l < r) {
79         const char t = *l;
80         *l++ = *r;
81         *r-- = t;
82     }
83
84     *e = '\0';
85
86     return e;
87 }
88
89 char* append(char* buf, bin_t::uint_t x)
90 {
91     char* l = buf;
92     char* r = buf;
93
94     do {
95         *r++ = '0' + x % 10;
96         x /= 10;
97     } while (x);
98
99     char* e = r--;
100
101     while (l < r) {
102         const char t = *l;
103         *l++ = *r;
104         *r-- = t;
105     }
106
107     *e = '\0';
108
109     return e;
110 }
111
112 char* append(char* buf, const char* s)
113 {
114     char* e = buf;
115
116     while (*s) {
117         *e++ = *s++;
118     }
119
120     *e = '\0';
121
122     return e;
123 }
124
125 char* append(char* buf, char c)
126 {
127     char* e = buf;
128
129     *e++ = c;
130     *e = '\0';
131
132     return e;
133 }
134
135 } /* namespace */
136
137
138 /**
139  * Get the standard-form of this bin, e.g. "(2,1)".
140  * (buffer should have enough of space)
141  */
142 const char* bin_t::str(char* buf) const
143 {
144     char* e = buf;
145
146     if (is_all()) {
147         e = append(e, "(ALL)");
148     } else if (is_none()) {
149         e = append(e, "(NONE)");
150     } else {
151         e = append(e, '(');
152         e = append(e, layer());
153         e = append(e, ',');
154         e = append(e, layer_offset());
155         e = append(e, ')');
156     }
157
158     return buf;
159 }
160
161
162 /**
163  * Output operator
164  */
165 std::ostream & operator << (std::ostream & ostream, const bin_t & bin)
166 {
167     char bin_name_buf[64];
168     return ostream << bin.str(bin_name_buf);
169 }