2 * Copyright (c) 2009 Kov Chai <tchaikov@gmail.com>
4 * The contents of this file are subject to the terms of either the GNU Lesser
5 * General Public License Version 2.1 only ("LGPL") or the Common Development and
6 * Distribution License ("CDDL")(collectively, the "License"). You may not use this
7 * file except in compliance with the License. You can obtain a copy of the CDDL at
8 * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
9 * http://www.opensource.org/licenses/lgpl-license.php. See the License for the
10 * specific language governing permissions and limitations under the License. When
11 * distributing the software, include this License Header Notice in each file and
12 * include the full text of the License in the License file as well as the
15 * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
17 * For Covered Software in this distribution, this License shall be governed by the
18 * laws of the State of California (excluding conflict-of-law provisions).
19 * Any litigation relating to this License shall be subject to the jurisdiction of
20 * the Federal Courts of the Northern District of California and the state courts
21 * of the State of California, with venue lying in Santa Clara County, California.
25 * If you wish your version of this file to be governed by only the CDDL or only
26 * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
27 * include this software in this distribution under the [CDDL or LGPL Version 2.1]
28 * license." If you don't indicate a single choice of license, a recipient has the
29 * option to distribute your version of this file under either the CDDL or the LGPL
30 * Version 2.1, or to extend the choice of license to its licensees as provided
31 * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
32 * Version 2 license, then the option applies only if the new code is made subject
33 * to such option by the copyright holder.
37 * the layout of binary file
39 * - usingLogPr : uint32_t
40 * - slm.getLevelSize(0..N) : uint32_t * N
41 * - pr_table() : float * 1<<CThreadSlm::BITS_PR # padding with 0.0F
42 * - bow_table() : float * 1 <<CThreadSlm::BITS_BOW # padding with 0.0F
43 * - node[0][] : CThreadSlm::TNode * slm.getLevelSize(0)
44 * - node[1][] : CThreadSlm::TNode * slm.getLevelSize(1)
46 * - node[N-1][] : CThreadSlm::TNode * slm.getLevelSize(N-1)
47 * - leaf[N-1][] : CThreadSlm::TLeaf * slm.getLevelSize(N)
50 #include <arpa/inet.h>
51 #include <sys/types.h>
67 typedef CThreadSlm::TNode TNode;
68 typedef CThreadSlm::TLeaf TLeaf;
70 // byte order reversed CThreadSlm::TLeaf small-endian presentation on big-endian machine
71 // 5-bits padding before m_pr_lo so that m_pr_lo is 4-byte aligned
73 // would be easier if m_bon is 28 bits long
76 unsigned m_pr_lo : 14;
84 leaf_betole(const CThreadSlm::TLeaf& v)
86 // since the CThreadSlm::TLeaf `protects' its bits, we duplicated a `public' one
89 unsigned m_pr_lo : 14;
95 Leaf_BE be_leaf = change_byte_order(*(Leaf_BE*)(&v));
99 Leaf_LE_* le_leaf = (Leaf_LE_*)(&leaf);
100 le_leaf->m_wid = be_leaf.m_wid;
101 le_leaf->m_pr_lo = be_leaf.m_pr_lo;
102 le_leaf->m_bon = be_leaf.m_bon;
103 le_leaf->m_bol = be_leaf.m_bol;
104 le_leaf->m_pr_hi = be_leaf.m_pr_hi;
108 // byte order reversed little-endian presentation
109 // 5-bits padding at end of struct
111 unsigned padding : 5;
112 unsigned m_pr_hi : 2;
115 unsigned m_pr_lo : 14;
120 leaf_letobe(const TLeaf& v)
122 // since the TLeaf `protects' its bits, we duplicated a `public' one
124 unsigned m_pr_hi : 2;
127 unsigned m_pr_lo : 14;
132 Leaf_LE_ le_leaf = change_byte_order(*(Leaf_LE_*)(&v));
136 Leaf_BE_* be_leaf = (Leaf_BE_*)(&leaf);
137 be_leaf->m_wid = le_leaf.m_wid;
138 be_leaf->m_pr_lo = le_leaf.m_pr_lo;
139 be_leaf->m_bon = le_leaf.m_bon;
140 be_leaf->m_bol = le_leaf.m_bol;
141 be_leaf->m_pr_hi = le_leaf.m_pr_hi;
145 template<typename Type>
147 read_value(char*& buf, bool do_swap)
149 Type v = *(Type*)buf;
151 v = change_byte_order(v);
157 // change the byte order of all elements in the array in place
158 template<typename Type>
160 read_values(char*& buf, size_t len, bool do_swap)
162 Type* begin = (Type*)buf;
163 Type* end = begin + len;
166 for (Type* p = begin; p != end; ++p) {
167 *p = change_byte_order(*p);
175 typedef TLeaf (*convert_func_t)(const TLeaf&);
178 TLeaf* read_values<TLeaf
179 >(char*& buf, size_t len, bool do_swap)
181 TLeaf* begin = (TLeaf*)buf;
182 TLeaf* end = begin + len;
183 convert_func_t convert =
184 (CThreadSlmFile::getHostEndian() ==
185 BIG_ENDIAN) ? leaf_letobe : leaf_betole;
188 for (TLeaf* p = begin; p != end; ++p) {
196 template<typename Type>
198 write_value(FILE* fp, const Type& value, bool do_swap)
202 v = change_byte_order(v);
204 return fwrite(&v, sizeof(v), 1, fp) * sizeof(v);
207 template<typename Type>
209 write_values(FILE* fp, Type* const begin, size_t len, bool do_swap)
211 const Type* end = begin + len;
213 for (Type* p = begin; p != end; ++p) {
214 *p = change_byte_order(*p);
217 return fwrite(begin, sizeof(Type), end - begin, fp) * sizeof(Type);
221 size_t write_values<TLeaf
222 >(FILE* fp, TLeaf* const begin, size_t len, bool do_swap)
224 const TLeaf* end = begin + len;
225 convert_func_t convert =
226 (CThreadSlmFile::getHostEndian() ==
227 BIG_ENDIAN) ? leaf_betole : leaf_letobe;
229 for (TLeaf* p = begin; p != end; ++p) {
233 return fwrite(begin, sizeof(TLeaf), end - begin, fp) * sizeof(TLeaf);
236 CThreadSlmFile::CThreadSlmFile()
238 m_N(0), m_usingLogPr(0), m_levelSizes(NULL), m_prTable(NULL),
240 m_nnode(0), m_nodes(NULL), m_nleaf(0), m_leafs(NULL)
244 // TODO: may need consolidate this class with CThreadSlm
246 CThreadSlmFile::load(const char* fname)
248 assert(m_buf == NULL);
250 int fd = open(fname, O_RDONLY);
251 ssize_t len = lseek(fd, 0, SEEK_END);
252 lseek(fd, 0, SEEK_SET);
253 m_buf = new char[len];
254 if (read(fd, m_buf, len) != len) {
257 cerr << "Failed to read from " << fname << endl;
263 bool do_swap = (getEndian() != getHostEndian());
265 m_N = read_value<uint32_t>(buf, do_swap);
266 m_usingLogPr = read_value<uint32_t>(buf, do_swap);
268 m_levelSizes = read_values<uint32_t>(buf, m_N + 1, do_swap);
269 m_prTable = read_values<float>(buf, 1 << CThreadSlm::BITS_PR, do_swap);
270 m_bowTable = read_values<float>(buf, 1 << CThreadSlm::BITS_BOW, do_swap);
272 m_nnode = accumulate(m_levelSizes, m_levelSizes + m_N, 0);
273 m_nodes = read_values<TNode>(buf, m_nnode, do_swap);
274 m_nleaf = m_levelSizes[m_N];
275 m_leafs = read_values<TLeaf>(buf, m_nleaf, do_swap);
278 return(m_buf + len == buf);
282 CThreadSlmFile::save(const char* fname, int endian)
284 bool do_swap = (endian != getHostEndian());
285 FILE* fp = fopen(fname, "wb");
287 nwrite += write_value(fp, m_N, do_swap);
288 nwrite += write_value(fp, m_usingLogPr, do_swap);
289 nwrite += write_values(fp, m_levelSizes, m_N + 1, do_swap);
290 nwrite += write_values(fp, m_prTable, 1 << CThreadSlm::BITS_PR, do_swap);
291 nwrite += write_values(fp, m_bowTable, 1 << CThreadSlm::BITS_BOW, do_swap);
292 nwrite += write_values(fp, m_nodes, m_nnode, do_swap);
293 nwrite += write_values(fp, m_leafs, m_nleaf, do_swap);
299 CThreadSlmFile::size() const
304 CThreadSlmFile::~CThreadSlmFile()
311 CThreadSlmFile::getEndian() const
313 assert(m_buf != NULL);
314 // assuming the N of this lm is not larger than 0x0100 0000
315 return (*(uint8_t*)m_buf) == 0 ? BIG_ENDIAN : LITTLE_ENDIAN;
319 CThreadSlmFile::getHostEndian()
321 return htons(0x0001) == 0x0100 ? LITTLE_ENDIAN : BIG_ENDIAN;