1 : /* GRAPHITE2 LICENSING
2 :
3 : Copyright 2010, SIL International
4 : All rights reserved.
5 :
6 : This library is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU Lesser General Public License as published
8 : by the Free Software Foundation; either version 2.1 of License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : Lesser General Public License for more details.
15 :
16 : You should also have received a copy of the GNU Lesser General Public
17 : License along with this library in the file named "LICENSE".
18 : If not, write to the Free Software Foundation, 51 Franklin Street,
19 : Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
20 : internet at http://www.fsf.org/licenses/lgpl.html.
21 :
22 : Alternatively, the contents of this file may be used under the terms of the
23 : Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
24 : License, as published by the Free Software Foundation, either version 2
25 : of the License or (at your option) any later version.
26 : */
27 : #pragma once
28 :
29 : #include "inc/Main.h"
30 :
31 : namespace graphite2 {
32 :
33 :
34 :
35 : class sparse
36 : {
37 : typedef unsigned long mask_t;
38 :
39 : static const unsigned char SIZEOF_CHUNK = (sizeof(mask_t) - sizeof(uint16))*8;
40 :
41 : struct chunk
42 : {
43 : mask_t mask:SIZEOF_CHUNK;
44 : uint16 offset;
45 : };
46 :
47 : public:
48 : typedef uint16 key;
49 : typedef uint16 value;
50 :
51 : template<typename I>
52 : sparse(I first, const I last);
53 : sparse() throw();
54 : ~sparse() throw();
55 :
56 : value operator [] (int k) const throw();
57 : operator bool () const throw();
58 :
59 : size_t capacity() const throw();
60 : size_t size() const throw();
61 :
62 : size_t _sizeof() const throw();
63 :
64 0 : CLASS_NEW_DELETE;
65 : private:
66 : union {
67 : chunk * map;
68 : value * values;
69 : } m_array;
70 : key m_nchunks;
71 : };
72 :
73 :
74 : inline
75 0 : sparse::sparse() throw() : m_nchunks(0)
76 : {
77 0 : m_array.map = 0;
78 0 : }
79 :
80 :
81 : template <typename I>
82 0 : sparse::sparse(I attr, const I last)
83 0 : : m_nchunks(0)
84 : {
85 : // Find the maximum extent of the key space.
86 0 : size_t n_values=0;
87 0 : for (I i = attr; i != last; ++i, ++n_values)
88 : {
89 0 : const key k = i->id / SIZEOF_CHUNK;
90 0 : if (k >= m_nchunks) m_nchunks = k+1;
91 : }
92 :
93 0 : m_array.values = grzeroalloc<value>((m_nchunks*sizeof(chunk) + sizeof(value)/2)/sizeof(value) + n_values*sizeof(value));
94 :
95 0 : if (m_array.values == 0 || m_nchunks == 0)
96 : {
97 0 : free(m_array.values); m_array.map=0;
98 0 : return;
99 : }
100 :
101 0 : chunk * ci = m_array.map;
102 0 : ci->offset = (m_nchunks*sizeof(chunk) + sizeof(value)-1)/sizeof(value);
103 0 : value * vi = m_array.values + ci->offset;
104 0 : for (; attr != last; ++attr, ++vi)
105 : {
106 0 : const typename I::value_type v = *attr;
107 0 : chunk * const ci_ = m_array.map + v.id/SIZEOF_CHUNK;
108 :
109 0 : if (ci != ci_)
110 : {
111 0 : ci = ci_;
112 0 : ci->offset = vi - m_array.values;
113 : }
114 :
115 0 : ci->mask |= 1UL << (SIZEOF_CHUNK - 1 - (v.id % SIZEOF_CHUNK));
116 0 : *vi = v.value;
117 : }
118 : }
119 :
120 :
121 : inline
122 0 : sparse::operator bool () const throw()
123 : {
124 0 : return m_array.map != 0;
125 : }
126 :
127 :
128 : inline
129 : size_t sparse::capacity() const throw()
130 : {
131 : return m_nchunks;
132 : }
133 :
134 :
135 : inline
136 : size_t sparse::_sizeof() const throw()
137 : {
138 : return sizeof(sparse) + size()*sizeof(value) + m_nchunks*sizeof(chunk);
139 : }
140 :
141 : } // namespace graphite2
|