~ubuntu-branches/ubuntu/trusty/liblas/trusty-proposed

« back to all changes in this revision

Viewing changes to include/liblas/detail/binary.hpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2014-01-05 17:00:29 UTC
  • mfrom: (7.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20140105170029-ddtp0j63x5jvck2u
Tags: 1.7.0+dfsg-2
Fixed missing linking of system boost component.
(closes: #733282)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Code taken from Boost.Geometry
 
2
//
 
3
// Copyright Mateusz Loskot <mateusz@loskot.net> 2009
 
4
// Use, modification and distribution is subject to the Boost Software License,
 
5
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 
6
// http://www.boost.org/LICENSE_1_0.txt)
 
7
//
 
8
// Load/Store values from/to stream of bytes across different endianness.
 
9
//
 
10
// Original design of unrolled_byte_loops templates based on
 
11
// endian utility library from Boost C++ Libraries,
 
12
// source: boost/spirit/home/support/detail/integer/endian.hpp
 
13
// Copyright Darin Adler 2000
 
14
// Copyright Beman Dawes 2006, 2009
 
15
// Distributed under the Boost Software License, Version 1.0.
 
16
 
 
17
#ifndef LIBLAS_DETAIL_BINARY_HPP_INCLUDED
 
18
#define LIBLAS_DETAIL_BINARY_HPP_INCLUDED
 
19
 
 
20
#include <cassert>
 
21
#include <climits>
 
22
#include <cstring>
 
23
#include <cstddef>
 
24
#include <iterator>
 
25
 
 
26
#include <boost/config.hpp>
 
27
#include <boost/cstdint.hpp>
 
28
#include <boost/static_assert.hpp>
 
29
#include <boost/detail/endian.hpp>
 
30
#include <boost/type_traits/is_signed.hpp>
 
31
 
 
32
#if CHAR_BIT != 8
 
33
#error Platforms with CHAR_BIT != 8 are not supported
 
34
#endif
 
35
 
 
36
// TODO: mloskot - add static asserts to validate compile-time pre-conditions
 
37
 
 
38
namespace liblas {
 
39
 
 
40
namespace detail { namespace binary {
 
41
 
 
42
// Endianness tag used to indicate load/store directoin
 
43
 
 
44
struct big_endian_tag {};
 
45
struct little_endian_tag {};
 
46
 
 
47
#ifdef BOOST_BIG_ENDIAN
 
48
typedef big_endian_tag native_endian_tag;
 
49
#else
 
50
typedef little_endian_tag native_endian_tag;
 
51
#endif
 
52
 
 
53
// Unrolled loops for loading and storing streams of bytes.
 
54
 
 
55
template <typename T, std::size_t N, bool Sign = boost::is_signed<T>::value>
 
56
struct unrolled_byte_loops
 
57
{
 
58
    typedef unrolled_byte_loops<T, N - 1, Sign> next;
 
59
 
 
60
    template <typename Iterator>
 
61
    static T load_forward(Iterator& bytes)
 
62
    {
 
63
        T const value = *bytes;
 
64
        ++bytes;
 
65
        return value | (next::load_forward(bytes) << 8);
 
66
    }
 
67
 
 
68
    template <typename Iterator>
 
69
    static T load_backward(Iterator& bytes)
 
70
    {
 
71
        T const value = *(bytes - 1);
 
72
        --bytes;
 
73
        return value | (next::load_backward(bytes) << 8);
 
74
    }
 
75
 
 
76
    template <typename Iterator>
 
77
    static void store_forward(Iterator& bytes, T value)
 
78
    {
 
79
        *bytes = static_cast<char>(value);
 
80
        next::store_forward(++bytes, value >> 8);
 
81
    }
 
82
 
 
83
    template <typename Iterator>
 
84
    static void store_backward(Iterator& bytes, T value)
 
85
    {
 
86
        *(bytes - 1) = static_cast<char>(value);
 
87
        next::store_backward(--bytes, value >> 8);
 
88
    }
 
89
};
 
90
 
 
91
template <typename T>
 
92
struct unrolled_byte_loops<T, 1, false>
 
93
{
 
94
    template <typename Iterator>
 
95
    static T load_forward(Iterator& bytes)
 
96
    {
 
97
        return *bytes;
 
98
    }
 
99
 
 
100
    template <typename Iterator>
 
101
    static T load_backward(Iterator& bytes)
 
102
    {
 
103
        return *(bytes - 1);
 
104
    }
 
105
 
 
106
    template <typename Iterator>
 
107
    static void store_forward(Iterator& bytes, T value)
 
108
    {
 
109
        // typename Iterator::value_type
 
110
        *bytes = static_cast<char>(value);
 
111
    }
 
112
 
 
113
    template <typename Iterator>
 
114
    static void store_backward(Iterator& bytes, T value)
 
115
    {
 
116
        *(bytes - 1) = static_cast<char>(value);
 
117
    }
 
118
};
 
119
 
 
120
template <typename T>
 
121
struct unrolled_byte_loops<T, 1, true>
 
122
{
 
123
    template <typename Iterator>
 
124
    static T load_forward(Iterator& bytes)
 
125
    {
 
126
        return *reinterpret_cast<const signed char*>(&*bytes);
 
127
    }
 
128
 
 
129
    template <typename Iterator>
 
130
    static T load_backward(Iterator& bytes)
 
131
    {
 
132
        return *reinterpret_cast<const signed char*>(&*(bytes - 1));
 
133
    }
 
134
 
 
135
    template <typename Iterator>
 
136
    static void store_forward(Iterator& bytes, T value)
 
137
    {
 
138
        *bytes = static_cast<char>(value);
 
139
    }
 
140
 
 
141
    template <typename Iterator>
 
142
    static void store_backward(Iterator& bytes, T value)
 
143
    {
 
144
        *(bytes - 1) = static_cast<char>(value);
 
145
    }
 
146
};
 
147
 
 
148
// load/store operation dispatch
 
149
// E, E - source and target endianness is the same
 
150
// E1, E2 - source and target endianness is different (big-endian <-> little-endian)
 
151
 
 
152
template <typename T, std::size_t N, typename Iterator, typename E>
 
153
T load_dispatch(Iterator& bytes, E, E)
 
154
{
 
155
    return unrolled_byte_loops<T, N>::load_forward(bytes);
 
156
}
 
157
 
 
158
template <typename T, std::size_t N, typename Iterator, typename E1, typename E2>
 
159
T load_dispatch(Iterator& bytes, E1, E2)
 
160
{
 
161
    std::advance(bytes, N);
 
162
    return unrolled_byte_loops<T, N>::load_backward(bytes);
 
163
}
 
164
 
 
165
template <typename T, std::size_t N, typename Iterator, typename E>
 
166
void store_dispatch(Iterator& bytes, T value, E, E)
 
167
{
 
168
    return unrolled_byte_loops<T, N>::store_forward(bytes, value);
 
169
}
 
170
 
 
171
template <typename T, std::size_t N, typename Iterator, typename E1, typename E2>
 
172
void store_dispatch(Iterator& bytes, T value, E1, E2)
 
173
{
 
174
    std::advance(bytes, N);
 
175
    return unrolled_byte_loops<T, N>::store_backward(bytes, value);
 
176
}
 
177
 
 
178
// numeric value holder for load/store operation
 
179
 
 
180
template <typename T>
 
181
struct endian_value_base
 
182
{
 
183
    typedef T value_type;
 
184
    typedef native_endian_tag endian_type;
 
185
 
 
186
    endian_value_base() : value(T()) {}
 
187
    explicit endian_value_base(T value) : value(value) {}
 
188
 
 
189
    operator T() const
 
190
    {
 
191
        return value;
 
192
    }
 
193
 
 
194
protected:
 
195
    T value;
 
196
};
 
197
 
 
198
template <typename T, std::size_t N = sizeof(T)>
 
199
struct endian_value : public endian_value_base<T>
 
200
{
 
201
    typedef endian_value_base<T> base;
 
202
 
 
203
    endian_value() {}
 
204
    explicit endian_value(T value) : base(value) {}
 
205
 
 
206
    template <typename E, typename Iterator>
 
207
    void load(Iterator bytes)
 
208
    {
 
209
        base::value = load_dispatch<T, N>(bytes, typename base::endian_type(), E());
 
210
    }
 
211
 
 
212
    template <typename E, typename Iterator>
 
213
    void store(Iterator bytes)
 
214
    {
 
215
        store_dispatch<T, N>(bytes, base::value, typename base::endian_type(), E());
 
216
    }
 
217
};
 
218
 
 
219
template <>
 
220
struct endian_value<double, 8> : public endian_value_base<double>
 
221
{
 
222
    typedef endian_value_base<double> base;
 
223
 
 
224
    endian_value() {}
 
225
    explicit endian_value(double value) : base(value) {}
 
226
 
 
227
    template <typename E, typename Iterator>
 
228
    void load(Iterator bytes)
 
229
    {
 
230
        endian_value<boost::uint64_t, 8> raw;
 
231
        raw.load<E>(bytes);
 
232
 
 
233
        double& target_value = base::value;
 
234
        std::memcpy(&target_value, &raw, sizeof(double));
 
235
    }
 
236
 
 
237
    template <typename E, typename Iterator>
 
238
    void store(Iterator bytes)
 
239
    {
 
240
        boost::uint64_t raw;
 
241
        double const& source_value = base::value;
 
242
        std::memcpy(&raw, &source_value, sizeof(boost::uint64_t));
 
243
 
 
244
        store_dispatch
 
245
            <
 
246
            boost::uint64_t,
 
247
            sizeof(boost::uint64_t)
 
248
            >(bytes, raw, typename base::endian_type(), E());
 
249
    }
 
250
};
 
251
 
 
252
}} // namespace detail::binary
 
253
} // namespace liblas
 
254
 
 
255
#endif // LIBLAS_DETAIL_BINARY_HPP_INCLUDED