blob: 2c7e7c929df3229ba9159ea12e980eac931cb73d [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
2//
3// This file is part of GNU C++ uCommon.
4//
5// GNU uCommon C++ is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published
7// by the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GNU uCommon C++ is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17
18#include <ucommon-config.h>
19#include <ucommon/export.h>
20#include <ucommon/bitmap.h>
21#include <stdlib.h>
22#ifdef HAVE_UNISTD_H
23#include <unistd.h>
24#endif
25
26using namespace UCOMMON_NAMESPACE;
27
28bitmap::bitmap(size_t count)
29{
30 size_t mem = count / 8;
31 size = count;
32 bus = BMALLOC;
33
34 if(count % 8)
35 ++mem;
36
37 addr.a = ::malloc(mem);
38 clear();
39}
40
41bitmap::bitmap(void *ptr, size_t count, bus_t access)
42{
43 assert(ptr != NULL);
44 assert(access >= BMIN && access <= BMAX);
45 addr.a = ptr;
46 bus = access;
47}
48
49bitmap::~bitmap()
50{
51 if(bus == BMALLOC && addr.b)
52 ::free(addr.b);
53 addr.b = NULL;
54}
55
56unsigned bitmap::memsize(void) const
57{
58 switch(bus) {
59 case B64:
60 return 64;
61 case B32:
62 return 32;
63 case B16:
64 return 16;
65 default:
66 return 8;
67 }
68}
69
70void bitmap::set(size_t offset, bool bit)
71{
72 unsigned bs = memsize();
73 size_t pos = offset / bs;
74 unsigned rem = offset % bs;
75 uint64_t b64;
76 uint32_t b32;
77 uint16_t b16;
78 uint8_t b8;
79
80 if(offset >= size)
81 return;
82
83 switch(bus) {
84 case B64:
85 b64 = ((uint64_t)(1))<<rem;
86 if(bit)
87 addr.d[pos] |= b64;
88 else
89 addr.d[pos] &= ~b64;
90 break;
91 case B32:
92 b32 = 1<<rem;
93 if(bit)
94 addr.l[pos] |= b32;
95 else
96 addr.l[pos] &= ~b32;
97 break;
98 case B16:
99 b16 = 1<<rem;
100 if(bit)
101 addr.w[pos] |= b16;
102 else
103 addr.w[pos] &= ~b16;
104 break;
105 default:
106 b8 = 1<<rem;
107 if(bit)
108 addr.b[pos] |= b8;
109 else
110 addr.b[pos] &= ~b8;
111 break;
112 }
113}
114
115bool bitmap::get(size_t offset) const
116{
117 unsigned bs = memsize();
118 size_t pos = offset / bs;
119 unsigned rem = offset % bs;
120
121 if(offset >= size)
122 return false;
123
124 switch(bus) {
125#if !defined(_MSC_VER) || _MSC_VER >= 1400
126 case B64:
127 return (addr.d[pos] & 1ll<<rem) > 0;
128#endif
129 case B32:
130 return (addr.l[pos] & 1l<<rem) > 0;
131 case B16:
132 return (addr.w[pos] & 1<<rem) > 0;
133 default:
134 return (addr.b[pos] & 1<<rem) > 0;
135 }
136}
137
138void bitmap::clear(void)
139{
140 unsigned bs = memsize();
141
142 if(size % bs)
143 ++size;
144
145 while(size--) {
146 switch(bus) {
147#if !defined(_MSC_VER) || _MSC_VER >= 1400
148 case B64:
149 *(addr.d++) = 0ll;
150 break;
151#endif
152 case B32:
153 *(addr.l++) = 0l;
154 break;
155 case B16:
156 *(addr.w++) = 0;
157 break;
158 default:
159 *(addr.b++) = 0;
160 }
161 }
162}