Merge lp:~thomas-voss/location-service/generalize-glue-code-for-agps-operation into lp:location-service/15.04

Proposed by Thomas Voß
Status: Superseded
Proposed branch: lp:~thomas-voss/location-service/generalize-glue-code-for-agps-operation
Merge into: lp:location-service/15.04
Diff against target: 4046 lines (+3470/-62)
34 files modified
3rd-party/boost/core/scoped_enum.hpp (+192/-0)
3rd-party/boost/endian/arithmetic.hpp (+413/-0)
3rd-party/boost/endian/buffers.hpp (+515/-0)
3rd-party/boost/endian/conversion.hpp (+487/-0)
3rd-party/boost/endian/detail/config.hpp (+62/-0)
3rd-party/boost/endian/detail/cover_operators.hpp (+142/-0)
3rd-party/boost/endian/detail/disable_warnings.hpp (+33/-0)
3rd-party/boost/endian/detail/disable_warnings_pop.hpp (+12/-0)
3rd-party/boost/endian/detail/intrinsic.hpp (+64/-0)
3rd-party/boost/endian/detail/lightweight_test.hpp (+223/-0)
3rd-party/boost/endian/endian.hpp (+19/-0)
3rd-party/boost/endian/std_pair.hpp (+38/-0)
CMakeLists.txt (+3/-0)
include/location_service/com/ubuntu/location/connectivity/manager.h (+21/-0)
src/location_service/com/ubuntu/location/CMakeLists.txt (+8/-0)
src/location_service/com/ubuntu/location/connectivity/ofono.h (+115/-1)
src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp (+34/-2)
src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h (+5/-1)
src/location_service/com/ubuntu/location/providers/gps/CMakeLists.txt (+13/-10)
src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp (+120/-30)
src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h (+34/-5)
src/location_service/com/ubuntu/location/providers/gps/hardware_abstraction_layer.cpp (+30/-0)
src/location_service/com/ubuntu/location/providers/gps/hardware_abstraction_layer.h (+35/-4)
src/location_service/com/ubuntu/location/providers/gps/sntp_client.cpp (+210/-0)
src/location_service/com/ubuntu/location/providers/gps/sntp_client.h (+210/-0)
src/location_service/com/ubuntu/location/providers/gps/sntp_reference_time_source.cpp (+57/-0)
src/location_service/com/ubuntu/location/providers/gps/sntp_reference_time_source.h (+51/-0)
src/location_service/com/ubuntu/location/service/runtime.h (+1/-1)
src/location_service/com/ubuntu/location/service/runtime_tests.cpp (+1/-0)
src/location_service/com/ubuntu/location/time_since_boot.cpp (+140/-0)
src/location_service/com/ubuntu/location/time_since_boot.h (+35/-0)
tests/CMakeLists.txt (+1/-0)
tests/gps_provider_test.cpp (+42/-8)
tests/sntp_client_test.cpp (+104/-0)
To merge this branch: bzr merge lp:~thomas-voss/location-service/generalize-glue-code-for-agps-operation
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+288690@code.launchpad.net

This proposal has been superseded by a proposal from 2016-03-10.

Commit message

This is the first MP in a series to generalize AGPS behavior. Here, we wire up
incoming RIL-specific requests and respond to them by reaching out to our Ofono-based telephony stack.

Description of the change

This is the first MP in a series to generalize AGPS behavior. Here, we wire up
incoming RIL-specific requests and respond to them by reaching out to our Ofono-based telephony stack.

To post a comment you must log in.
230. By Thomas Voß

Log individual imsi/msisdn callback invocations.

231. By Thomas Voß

Extend runtime test cases to cover agps use cases.

232. By Thomas Voß

Clean up event connections after each trial.
Adjust terminal output.

Unmerged revisions

232. By Thomas Voß

Clean up event connections after each trial.
Adjust terminal output.

231. By Thomas Voß

Extend runtime test cases to cover agps use cases.

230. By Thomas Voß

Log individual imsi/msisdn callback invocations.

229. By Thomas Voß

Wire up ril request callbacks.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory '3rd-party'
=== added directory '3rd-party/boost'
=== added directory '3rd-party/boost/core'
=== added file '3rd-party/boost/core/scoped_enum.hpp'
--- 3rd-party/boost/core/scoped_enum.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/core/scoped_enum.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,192 @@
1// scoped_enum.hpp ---------------------------------------------------------//
2
3// Copyright Beman Dawes, 2009
4// Copyright (C) 2011-2012 Vicente J. Botet Escriba
5// Copyright (C) 2012 Anthony Williams
6
7// Distributed under the Boost Software License, Version 1.0.
8// See http://www.boost.org/LICENSE_1_0.txt
9
10#ifndef BOOST_CORE_SCOPED_ENUM_HPP
11#define BOOST_CORE_SCOPED_ENUM_HPP
12
13#include <boost/config.hpp>
14
15#ifdef BOOST_HAS_PRAGMA_ONCE
16#pragma once
17#endif
18
19namespace boost
20{
21
22#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
23
24 /**
25 * Meta-function to get the native enum type associated to an enum class or its emulation.
26 */
27 template <typename EnumType>
28 struct native_type
29 {
30 /**
31 * The member typedef type names the native enum type associated to the scoped enum,
32 * which is it self if the compiler supports scoped enums or EnumType::enum_type if it is an emulated scoped enum.
33 */
34 typedef typename EnumType::enum_type type;
35 };
36
37 /**
38 * Casts a scoped enum to its underlying type.
39 *
40 * This function is useful when working with scoped enum classes, which doens't implicitly convert to the underlying type.
41 * @param v A scoped enum.
42 * @returns The underlying type.
43 * @throws No-throws.
44 */
45 template <typename UnderlyingType, typename EnumType>
46 UnderlyingType underlying_cast(EnumType v)
47 {
48 return v.get_underlying_value_();
49 }
50
51 /**
52 * Casts a scoped enum to its native enum type.
53 *
54 * This function is useful to make programs portable when the scoped enum emulation can not be use where native enums can.
55 *
56 * EnumType the scoped enum type
57 *
58 * @param v A scoped enum.
59 * @returns The native enum value.
60 * @throws No-throws.
61 */
62 template <typename EnumType>
63 inline
64 typename EnumType::enum_type native_value(EnumType e)
65 {
66 return e.get_native_value_();
67 }
68
69#else // BOOST_NO_CXX11_SCOPED_ENUMS
70
71 template <typename EnumType>
72 struct native_type
73 {
74 typedef EnumType type;
75 };
76
77 template <typename UnderlyingType, typename EnumType>
78 UnderlyingType underlying_cast(EnumType v)
79 {
80 return static_cast<UnderlyingType>(v);
81 }
82
83 template <typename EnumType>
84 inline
85 EnumType native_value(EnumType e)
86 {
87 return e;
88 }
89
90#endif // BOOST_NO_CXX11_SCOPED_ENUMS
91}
92
93
94#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
95
96#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
97
98#define BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR \
99 explicit operator underlying_type() const BOOST_NOEXCEPT { return get_underlying_value_(); }
100
101#else
102
103#define BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR
104
105#endif
106
107/**
108 * Start a declaration of a scoped enum.
109 *
110 * @param EnumType The new scoped enum.
111 * @param UnderlyingType The underlying type.
112 */
113#define BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(EnumType, UnderlyingType) \
114 struct EnumType { \
115 typedef void is_boost_scoped_enum_tag; \
116 typedef UnderlyingType underlying_type; \
117 EnumType() BOOST_NOEXCEPT {} \
118 explicit EnumType(underlying_type v) BOOST_NOEXCEPT : v_(v) {} \
119 underlying_type get_underlying_value_() const BOOST_NOEXCEPT { return v_; } \
120 BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR \
121 private: \
122 underlying_type v_; \
123 typedef EnumType self_type; \
124 public: \
125 enum enum_type
126
127#define BOOST_SCOPED_ENUM_DECLARE_END2() \
128 enum_type get_native_value_() const BOOST_NOEXCEPT { return enum_type(v_); } \
129 friend bool operator ==(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==enum_type(rhs.v_); } \
130 friend bool operator ==(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==rhs; } \
131 friend bool operator ==(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs==enum_type(rhs.v_); } \
132 friend bool operator !=(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)!=enum_type(rhs.v_); } \
133 friend bool operator !=(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)!=rhs; } \
134 friend bool operator !=(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs!=enum_type(rhs.v_); } \
135 friend bool operator <(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<enum_type(rhs.v_); } \
136 friend bool operator <(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<rhs; } \
137 friend bool operator <(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs<enum_type(rhs.v_); } \
138 friend bool operator <=(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<=enum_type(rhs.v_); } \
139 friend bool operator <=(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<=rhs; } \
140 friend bool operator <=(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs<=enum_type(rhs.v_); } \
141 friend bool operator >(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>enum_type(rhs.v_); } \
142 friend bool operator >(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>rhs; } \
143 friend bool operator >(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs>enum_type(rhs.v_); } \
144 friend bool operator >=(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>=enum_type(rhs.v_); } \
145 friend bool operator >=(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>=rhs; } \
146 friend bool operator >=(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs>=enum_type(rhs.v_); } \
147 };
148
149#define BOOST_SCOPED_ENUM_DECLARE_END(EnumType) \
150 ; \
151 EnumType(enum_type v) BOOST_NOEXCEPT : v_(v) {} \
152 BOOST_SCOPED_ENUM_DECLARE_END2()
153
154/**
155 * Starts a declaration of a scoped enum with the default int underlying type.
156 *
157 * @param EnumType The new scoped enum.
158 */
159#define BOOST_SCOPED_ENUM_DECLARE_BEGIN(EnumType) \
160 BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(EnumType,int)
161
162/**
163 * Name of the native enum type.
164 *
165 * @param EnumType The new scoped enum.
166 */
167#define BOOST_SCOPED_ENUM_NATIVE(EnumType) EnumType::enum_type
168/**
169 * Forward declares an scoped enum.
170 *
171 * @param EnumType The scoped enum.
172 */
173#define BOOST_SCOPED_ENUM_FORWARD_DECLARE(EnumType) struct EnumType
174
175#else // BOOST_NO_CXX11_SCOPED_ENUMS
176
177#define BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(EnumType,UnderlyingType) enum class EnumType : UnderlyingType
178#define BOOST_SCOPED_ENUM_DECLARE_BEGIN(EnumType) enum class EnumType
179#define BOOST_SCOPED_ENUM_DECLARE_END2()
180#define BOOST_SCOPED_ENUM_DECLARE_END(EnumType) ;
181
182#define BOOST_SCOPED_ENUM_NATIVE(EnumType) EnumType
183#define BOOST_SCOPED_ENUM_FORWARD_DECLARE(EnumType) enum class EnumType
184
185#endif // BOOST_NO_CXX11_SCOPED_ENUMS
186
187// Deprecated macros
188#define BOOST_SCOPED_ENUM_START(name) BOOST_SCOPED_ENUM_DECLARE_BEGIN(name)
189#define BOOST_SCOPED_ENUM_END BOOST_SCOPED_ENUM_DECLARE_END2()
190#define BOOST_SCOPED_ENUM(name) BOOST_SCOPED_ENUM_NATIVE(name)
191
192#endif // BOOST_CORE_SCOPED_ENUM_HPP
0193
=== added directory '3rd-party/boost/endian'
=== added file '3rd-party/boost/endian/arithmetic.hpp'
--- 3rd-party/boost/endian/arithmetic.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/endian/arithmetic.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,413 @@
1// boost/endian/arithmetic.hpp -------------------------------------------------------//
2
3// (C) Copyright Darin Adler 2000
4// (C) Copyright Beman Dawes 2006, 2009, 2014
5
6// Distributed under the Boost Software License, Version 1.0.
7// See http://www.boost.org/LICENSE_1_0.txt
8
9// See library home page at http://www.boost.org/libs/endian
10
11//--------------------------------------------------------------------------------------//
12
13// Original design developed by Darin Adler based on classes developed by Mark
14// Borgerding. Four original class templates were combined into a single endian
15// class template by Beman Dawes, who also added the unrolled_byte_loops sign
16// partial specialization to correctly extend the sign when cover integer size
17// differs from endian representation size.
18
19// TODO: When a compiler supporting constexpr becomes available, try possible uses.
20
21#ifndef BOOST_ENDIAN_ARITHMETIC_HPP
22#define BOOST_ENDIAN_ARITHMETIC_HPP
23
24#if defined(_MSC_VER)
25# pragma warning(push)
26# pragma warning(disable:4365) // conversion ... signed/unsigned mismatch
27#endif
28
29#ifdef BOOST_ENDIAN_LOG
30# include <iostream>
31#endif
32
33#if defined(__BORLANDC__) || defined( __CODEGEARC__)
34# pragma pack(push, 1)
35#endif
36
37#include <boost/config.hpp>
38#include <boost/predef/detail/endian_compat.h>
39#include <boost/endian/conversion.hpp>
40#include <boost/endian/buffers.hpp>
41#define BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
42#include <boost/endian/detail/cover_operators.hpp>
43#undef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
44#include <boost/type_traits/is_signed.hpp>
45#include <boost/cstdint.hpp>
46#include <boost/static_assert.hpp>
47#include <boost/core/scoped_enum.hpp>
48#include <iosfwd>
49#include <climits>
50
51# if CHAR_BIT != 8
52# error Platforms with CHAR_BIT != 8 are not supported
53# endif
54
55# ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
56# define BOOST_ENDIAN_DEFAULT_CONSTRUCT {} // C++03
57# else
58# define BOOST_ENDIAN_DEFAULT_CONSTRUCT = default; // C++0x
59# endif
60
61# if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && defined(BOOST_ENDIAN_FORCE_PODNESS)
62# define BOOST_ENDIAN_NO_CTORS
63# endif
64
65# ifndef BOOST_ENDIAN_EXPLICIT_CTORS
66# define BOOST_ENDIAN_EXPLICIT_OPT
67# else
68# define BOOST_ENDIAN_EXPLICIT_OPT explicit
69# endif
70
71//---------------------------------- synopsis ----------------------------------------//
72
73namespace boost
74{
75namespace endian
76{
77
78 template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits,
79 BOOST_SCOPED_ENUM(align) A = align::no>
80 class endian_arithmetic;
81
82 // big endian signed integer aligned types
83 typedef endian_arithmetic<order::big, int8_t, 8, align::yes> big_int8_at;
84 typedef endian_arithmetic<order::big, int16_t, 16, align::yes> big_int16_at;
85 typedef endian_arithmetic<order::big, int32_t, 32, align::yes> big_int32_at;
86 typedef endian_arithmetic<order::big, int64_t, 64, align::yes> big_int64_at;
87
88 // big endian unsigned integer aligned types
89 typedef endian_arithmetic<order::big, uint8_t, 8, align::yes> big_uint8_at;
90 typedef endian_arithmetic<order::big, uint16_t, 16, align::yes> big_uint16_at;
91 typedef endian_arithmetic<order::big, uint32_t, 32, align::yes> big_uint32_at;
92 typedef endian_arithmetic<order::big, uint64_t, 64, align::yes> big_uint64_at;
93
94 // little endian signed integer aligned types
95 typedef endian_arithmetic<order::little, int8_t, 8, align::yes> little_int8_at;
96 typedef endian_arithmetic<order::little, int16_t, 16, align::yes> little_int16_at;
97 typedef endian_arithmetic<order::little, int32_t, 32, align::yes> little_int32_at;
98 typedef endian_arithmetic<order::little, int64_t, 64, align::yes> little_int64_at;
99
100 // little endian unsigned integer aligned types
101 typedef endian_arithmetic<order::little, uint8_t, 8, align::yes> little_uint8_at;
102 typedef endian_arithmetic<order::little, uint16_t, 16, align::yes> little_uint16_at;
103 typedef endian_arithmetic<order::little, uint32_t, 32, align::yes> little_uint32_at;
104 typedef endian_arithmetic<order::little, uint64_t, 64, align::yes> little_uint64_at;
105
106 // aligned native endian typedefs are not provided because
107 // <cstdint> types are superior for this use case
108
109 // big endian signed integer unaligned types
110 typedef endian_arithmetic<order::big, int_least8_t, 8> big_int8_t;
111 typedef endian_arithmetic<order::big, int_least16_t, 16> big_int16_t;
112 typedef endian_arithmetic<order::big, int_least32_t, 24> big_int24_t;
113 typedef endian_arithmetic<order::big, int_least32_t, 32> big_int32_t;
114 typedef endian_arithmetic<order::big, int_least64_t, 40> big_int40_t;
115 typedef endian_arithmetic<order::big, int_least64_t, 48> big_int48_t;
116 typedef endian_arithmetic<order::big, int_least64_t, 56> big_int56_t;
117 typedef endian_arithmetic<order::big, int_least64_t, 64> big_int64_t;
118
119 // big endian unsigned integer unaligned types
120 typedef endian_arithmetic<order::big, uint_least8_t, 8> big_uint8_t;
121 typedef endian_arithmetic<order::big, uint_least16_t, 16> big_uint16_t;
122 typedef endian_arithmetic<order::big, uint_least32_t, 24> big_uint24_t;
123 typedef endian_arithmetic<order::big, uint_least32_t, 32> big_uint32_t;
124 typedef endian_arithmetic<order::big, uint_least64_t, 40> big_uint40_t;
125 typedef endian_arithmetic<order::big, uint_least64_t, 48> big_uint48_t;
126 typedef endian_arithmetic<order::big, uint_least64_t, 56> big_uint56_t;
127 typedef endian_arithmetic<order::big, uint_least64_t, 64> big_uint64_t;
128
129 // little endian signed integer unaligned types
130 typedef endian_arithmetic<order::little, int_least8_t, 8> little_int8_t;
131 typedef endian_arithmetic<order::little, int_least16_t, 16> little_int16_t;
132 typedef endian_arithmetic<order::little, int_least32_t, 24> little_int24_t;
133 typedef endian_arithmetic<order::little, int_least32_t, 32> little_int32_t;
134 typedef endian_arithmetic<order::little, int_least64_t, 40> little_int40_t;
135 typedef endian_arithmetic<order::little, int_least64_t, 48> little_int48_t;
136 typedef endian_arithmetic<order::little, int_least64_t, 56> little_int56_t;
137 typedef endian_arithmetic<order::little, int_least64_t, 64> little_int64_t;
138
139 // little endian unsigned integer unaligned types
140 typedef endian_arithmetic<order::little, uint_least8_t, 8> little_uint8_t;
141 typedef endian_arithmetic<order::little, uint_least16_t, 16> little_uint16_t;
142 typedef endian_arithmetic<order::little, uint_least32_t, 24> little_uint24_t;
143 typedef endian_arithmetic<order::little, uint_least32_t, 32> little_uint32_t;
144 typedef endian_arithmetic<order::little, uint_least64_t, 40> little_uint40_t;
145 typedef endian_arithmetic<order::little, uint_least64_t, 48> little_uint48_t;
146 typedef endian_arithmetic<order::little, uint_least64_t, 56> little_uint56_t;
147 typedef endian_arithmetic<order::little, uint_least64_t, 64> little_uint64_t;
148
149# ifdef BOOST_BIG_ENDIAN
150 // native endian signed integer unaligned types
151 typedef big_int8_t native_int8_t;
152 typedef big_int16_t native_int16_t;
153 typedef big_int24_t native_int24_t;
154 typedef big_int32_t native_int32_t;
155 typedef big_int40_t native_int40_t;
156 typedef big_int48_t native_int48_t;
157 typedef big_int56_t native_int56_t;
158 typedef big_int64_t native_int64_t;
159
160 // native endian unsigned integer unaligned types
161 typedef big_uint8_t native_uint8_t;
162 typedef big_uint16_t native_uint16_t;
163 typedef big_uint24_t native_uint24_t;
164 typedef big_uint32_t native_uint32_t;
165 typedef big_uint40_t native_uint40_t;
166 typedef big_uint48_t native_uint48_t;
167 typedef big_uint56_t native_uint56_t;
168 typedef big_uint64_t native_uint64_t;
169# else
170 // native endian signed integer unaligned types
171 typedef little_int8_t native_int8_t;
172 typedef little_int16_t native_int16_t;
173 typedef little_int24_t native_int24_t;
174 typedef little_int32_t native_int32_t;
175 typedef little_int40_t native_int40_t;
176 typedef little_int48_t native_int48_t;
177 typedef little_int56_t native_int56_t;
178 typedef little_int64_t native_int64_t;
179
180 // native endian unsigned integer unaligned types
181 typedef little_uint8_t native_uint8_t;
182 typedef little_uint16_t native_uint16_t;
183 typedef little_uint24_t native_uint24_t;
184 typedef little_uint32_t native_uint32_t;
185 typedef little_uint40_t native_uint40_t;
186 typedef little_uint48_t native_uint48_t;
187 typedef little_uint56_t native_uint56_t;
188 typedef little_uint64_t native_uint64_t;
189# endif
190
191# ifdef BOOST_ENDIAN_DEPRECATED_NAMES
192
193 typedef order endianness;
194 typedef align alignment;
195
196# ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES
197 template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits,
198 BOOST_SCOPED_ENUM(align) Align = align::no>
199 using endian = endian_arithmetic<Order, T, n_bits, Align>;
200# endif
201
202 // unaligned big endian signed integer types
203 typedef endian_arithmetic< order::big, int_least8_t, 8 > big8_t;
204 typedef endian_arithmetic< order::big, int_least16_t, 16 > big16_t;
205 typedef endian_arithmetic< order::big, int_least32_t, 24 > big24_t;
206 typedef endian_arithmetic< order::big, int_least32_t, 32 > big32_t;
207 typedef endian_arithmetic< order::big, int_least64_t, 40 > big40_t;
208 typedef endian_arithmetic< order::big, int_least64_t, 48 > big48_t;
209 typedef endian_arithmetic< order::big, int_least64_t, 56 > big56_t;
210 typedef endian_arithmetic< order::big, int_least64_t, 64 > big64_t;
211
212 // unaligned big endian_arithmetic unsigned integer types
213 typedef endian_arithmetic< order::big, uint_least8_t, 8 > ubig8_t;
214 typedef endian_arithmetic< order::big, uint_least16_t, 16 > ubig16_t;
215 typedef endian_arithmetic< order::big, uint_least32_t, 24 > ubig24_t;
216 typedef endian_arithmetic< order::big, uint_least32_t, 32 > ubig32_t;
217 typedef endian_arithmetic< order::big, uint_least64_t, 40 > ubig40_t;
218 typedef endian_arithmetic< order::big, uint_least64_t, 48 > ubig48_t;
219 typedef endian_arithmetic< order::big, uint_least64_t, 56 > ubig56_t;
220 typedef endian_arithmetic< order::big, uint_least64_t, 64 > ubig64_t;
221
222 // unaligned little endian_arithmetic signed integer types
223 typedef endian_arithmetic< order::little, int_least8_t, 8 > little8_t;
224 typedef endian_arithmetic< order::little, int_least16_t, 16 > little16_t;
225 typedef endian_arithmetic< order::little, int_least32_t, 24 > little24_t;
226 typedef endian_arithmetic< order::little, int_least32_t, 32 > little32_t;
227 typedef endian_arithmetic< order::little, int_least64_t, 40 > little40_t;
228 typedef endian_arithmetic< order::little, int_least64_t, 48 > little48_t;
229 typedef endian_arithmetic< order::little, int_least64_t, 56 > little56_t;
230 typedef endian_arithmetic< order::little, int_least64_t, 64 > little64_t;
231
232 // unaligned little endian_arithmetic unsigned integer types
233 typedef endian_arithmetic< order::little, uint_least8_t, 8 > ulittle8_t;
234 typedef endian_arithmetic< order::little, uint_least16_t, 16 > ulittle16_t;
235 typedef endian_arithmetic< order::little, uint_least32_t, 24 > ulittle24_t;
236 typedef endian_arithmetic< order::little, uint_least32_t, 32 > ulittle32_t;
237 typedef endian_arithmetic< order::little, uint_least64_t, 40 > ulittle40_t;
238 typedef endian_arithmetic< order::little, uint_least64_t, 48 > ulittle48_t;
239 typedef endian_arithmetic< order::little, uint_least64_t, 56 > ulittle56_t;
240 typedef endian_arithmetic< order::little, uint_least64_t, 64 > ulittle64_t;
241
242 // unaligned native endian_arithmetic signed integer types
243 typedef endian_arithmetic< order::native, int_least8_t, 8 > native8_t;
244 typedef endian_arithmetic< order::native, int_least16_t, 16 > native16_t;
245 typedef endian_arithmetic< order::native, int_least32_t, 24 > native24_t;
246 typedef endian_arithmetic< order::native, int_least32_t, 32 > native32_t;
247 typedef endian_arithmetic< order::native, int_least64_t, 40 > native40_t;
248 typedef endian_arithmetic< order::native, int_least64_t, 48 > native48_t;
249 typedef endian_arithmetic< order::native, int_least64_t, 56 > native56_t;
250 typedef endian_arithmetic< order::native, int_least64_t, 64 > native64_t;
251
252 // unaligned native endian_arithmetic unsigned integer types
253 typedef endian_arithmetic< order::native, uint_least8_t, 8 > unative8_t;
254 typedef endian_arithmetic< order::native, uint_least16_t, 16 > unative16_t;
255 typedef endian_arithmetic< order::native, uint_least32_t, 24 > unative24_t;
256 typedef endian_arithmetic< order::native, uint_least32_t, 32 > unative32_t;
257 typedef endian_arithmetic< order::native, uint_least64_t, 40 > unative40_t;
258 typedef endian_arithmetic< order::native, uint_least64_t, 48 > unative48_t;
259 typedef endian_arithmetic< order::native, uint_least64_t, 56 > unative56_t;
260 typedef endian_arithmetic< order::native, uint_least64_t, 64 > unative64_t;
261
262 // aligned native endian_arithmetic typedefs are not provided because
263 // <cstdint> types are superior for this use case
264
265 typedef endian_arithmetic< order::big, int16_t, 16, align::yes > aligned_big16_t;
266 typedef endian_arithmetic< order::big, uint16_t, 16, align::yes > aligned_ubig16_t;
267 typedef endian_arithmetic< order::little, int16_t, 16, align::yes > aligned_little16_t;
268 typedef endian_arithmetic< order::little, uint16_t, 16, align::yes > aligned_ulittle16_t;
269
270 typedef endian_arithmetic< order::big, int32_t, 32, align::yes > aligned_big32_t;
271 typedef endian_arithmetic< order::big, uint32_t, 32, align::yes > aligned_ubig32_t;
272 typedef endian_arithmetic< order::little, int32_t, 32, align::yes > aligned_little32_t;
273 typedef endian_arithmetic< order::little, uint32_t, 32, align::yes > aligned_ulittle32_t;
274
275 typedef endian_arithmetic< order::big, int64_t, 64, align::yes > aligned_big64_t;
276 typedef endian_arithmetic< order::big, uint64_t, 64, align::yes > aligned_ubig64_t;
277 typedef endian_arithmetic< order::little, int64_t, 64, align::yes > aligned_little64_t;
278 typedef endian_arithmetic< order::little, uint64_t, 64, align::yes > aligned_ulittle64_t;
279
280# endif
281
282//---------------------------------- end synopsis ------------------------------------//
283
284// endian class template specializations ---------------------------------------------//
285
286 // Specializations that represent unaligned bytes.
287 // Taking an integer type as a parameter provides a nice way to pass both
288 // the size and signness of the desired integer and get the appropriate
289 // corresponding integer type for the interface.
290
291 // unaligned integer big endian specialization
292 template <typename T, std::size_t n_bits>
293 class endian_arithmetic< order::big, T, n_bits, align::no >
294 : public endian_buffer< order::big, T, n_bits, align::no >,
295 cover_operators<endian_arithmetic<order::big, T, n_bits>, T>
296 {
297 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
298 public:
299 typedef T value_type;
300# ifndef BOOST_ENDIAN_NO_CTORS
301 endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
302 BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
303 {
304# ifdef BOOST_ENDIAN_LOG
305 if ( endian_log )
306 std::cout << "big, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
307# endif
308 detail::store_big_endian<T, n_bits/8>(this->m_value, val);
309 }
310# endif
311 endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
312 { detail::store_big_endian<T, n_bits/8>(this->m_value, val); return *this; }
313 operator value_type() const BOOST_NOEXCEPT { return this->value(); }
314 };
315
316 // unaligned little endian specialization
317 template <typename T, std::size_t n_bits>
318 class endian_arithmetic< order::little, T, n_bits, align::no >
319 : public endian_buffer< order::little, T, n_bits, align::no >,
320 cover_operators< endian_arithmetic< order::little, T, n_bits >, T >
321 {
322 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
323 public:
324 typedef T value_type;
325# ifndef BOOST_ENDIAN_NO_CTORS
326 endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
327 BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
328 {
329# ifdef BOOST_ENDIAN_LOG
330 if ( endian_log )
331 std::cout << "little, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
332# endif
333 detail::store_little_endian<T, n_bits/8>(this->m_value, val);
334 }
335# endif
336 endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
337 { detail::store_little_endian<T, n_bits/8>(this->m_value, val); return *this; }
338 operator value_type() const BOOST_NOEXCEPT { return this->value(); }
339 };
340
341 // align::yes specializations; only n_bits == 16/32/64 supported
342
343 // aligned big endian specialization
344 template <typename T, std::size_t n_bits>
345 class endian_arithmetic<order::big, T, n_bits, align::yes>
346 : public endian_buffer< order::big, T, n_bits, align::yes >,
347 cover_operators<endian_arithmetic<order::big, T, n_bits, align::yes>, T>
348 {
349 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
350 BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
351 public:
352 typedef T value_type;
353# ifndef BOOST_ENDIAN_NO_CTORS
354 endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
355 BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
356 {
357# ifdef BOOST_ENDIAN_LOG
358 if ( endian_log )
359 std::cout << "big, aligned, " << n_bits << "-bits, construct(" << val << ")\n";
360# endif
361 this->m_value = ::boost::endian::native_to_big(val);
362 }
363
364# endif
365 endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
366 {
367 this->m_value = ::boost::endian::native_to_big(val);
368 return *this;
369 }
370 operator value_type() const BOOST_NOEXCEPT { return this->value(); }
371 };
372
373 // aligned little endian specialization
374 template <typename T, std::size_t n_bits>
375 class endian_arithmetic<order::little, T, n_bits, align::yes>
376 : public endian_buffer< order::little, T, n_bits, align::yes >,
377 cover_operators<endian_arithmetic<order::little, T, n_bits, align::yes>, T>
378 {
379 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
380 BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
381 public:
382 typedef T value_type;
383# ifndef BOOST_ENDIAN_NO_CTORS
384 endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
385 BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
386 {
387# ifdef BOOST_ENDIAN_LOG
388 if ( endian_log )
389 std::cout << "little, aligned, " << n_bits << "-bits, construct(" << val << ")\n";
390# endif
391 this->m_value = ::boost::endian::native_to_little(val);
392 }
393# endif
394 endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
395 {
396 this->m_value = ::boost::endian::native_to_little(val);
397 return *this;
398 }
399 operator value_type() const BOOST_NOEXCEPT { return this->value(); }
400 };
401
402} // namespace endian
403} // namespace boost
404
405#if defined(__BORLANDC__) || defined( __CODEGEARC__)
406# pragma pack(pop)
407#endif
408
409#if defined(_MSC_VER)
410# pragma warning(pop)
411#endif
412
413#endif // BOOST_ENDIAN_ARITHMETIC_HPP
0414
=== added file '3rd-party/boost/endian/buffers.hpp'
--- 3rd-party/boost/endian/buffers.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/endian/buffers.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,515 @@
1// boost/endian/buffers.hpp ----------------------------------------------------------//
2
3// (C) Copyright Darin Adler 2000
4// (C) Copyright Beman Dawes 2006, 2009, 2014
5
6// Distributed under the Boost Software License, Version 1.0.
7// See http://www.boost.org/LICENSE_1_0.txt
8
9// See library home page at http://www.boost.org/libs/endian
10
11//--------------------------------------------------------------------------------------//
12
13// Original design developed by Darin Adler based on classes developed by Mark
14// Borgerding. Four original class templates were combined into a single endian
15// class template by Beman Dawes, who also added the unrolled_byte_loops sign
16// partial specialization to correctly extend the sign when cover integer size
17// differs from endian representation size.
18
19// TODO: When a compiler supporting constexpr becomes available, try possible uses.
20
21#ifndef BOOST_ENDIAN_BUFFERS_HPP
22#define BOOST_ENDIAN_BUFFERS_HPP
23
24#if defined(_MSC_VER)
25# pragma warning(push)
26# pragma warning(disable:4365) // conversion ... signed/unsigned mismatch
27#endif
28
29#ifdef BOOST_ENDIAN_LOG
30# include <iostream>
31#endif
32
33#if defined(__BORLANDC__) || defined( __CODEGEARC__)
34# pragma pack(push, 1)
35#endif
36
37#include <boost/config.hpp>
38#include <boost/predef/detail/endian_compat.h>
39#include <boost/endian/conversion.hpp>
40#include <boost/type_traits/is_signed.hpp>
41#include <boost/cstdint.hpp>
42#include <boost/static_assert.hpp>
43#include <boost/core/scoped_enum.hpp>
44#include <iosfwd>
45#include <climits>
46
47# if CHAR_BIT != 8
48# error Platforms with CHAR_BIT != 8 are not supported
49# endif
50
51# ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
52# define BOOST_ENDIAN_DEFAULT_CONSTRUCT {} // C++03
53# else
54# define BOOST_ENDIAN_DEFAULT_CONSTRUCT = default; // C++0x
55# endif
56
57# if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && defined(BOOST_ENDIAN_FORCE_PODNESS)
58# define BOOST_ENDIAN_NO_CTORS
59# endif
60
61//---------------------------------- synopsis ----------------------------------------//
62
63namespace boost
64{
65namespace endian
66{
67
68 BOOST_SCOPED_ENUM_START(align)
69 {no, yes
70# ifdef BOOST_ENDIAN_DEPRECATED_NAMES
71 , unaligned = no, aligned = yes
72# endif
73 }; BOOST_SCOPED_ENUM_END
74
75 template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits,
76 BOOST_SCOPED_ENUM(align) A = align::no>
77 class endian_buffer;
78
79 // aligned big endian signed integer buffers
80 typedef endian_buffer<order::big, int8_t, 8, align::yes> big_int8_buf_at;
81 typedef endian_buffer<order::big, int16_t, 16, align::yes> big_int16_buf_at;
82 typedef endian_buffer<order::big, int32_t, 32, align::yes> big_int32_buf_at;
83 typedef endian_buffer<order::big, int64_t, 64, align::yes> big_int64_buf_at;
84
85 // aligned big endian unsigned integer buffers
86 typedef endian_buffer<order::big, uint8_t, 8, align::yes> big_uint8_buf_at;
87 typedef endian_buffer<order::big, uint16_t, 16, align::yes> big_uint16_buf_at;
88 typedef endian_buffer<order::big, uint32_t, 32, align::yes> big_uint32_buf_at;
89 typedef endian_buffer<order::big, uint64_t, 64, align::yes> big_uint64_buf_at;
90
91 // aligned little endian signed integer buffers
92 typedef endian_buffer<order::little, int8_t, 8, align::yes> little_int8_buf_at;
93 typedef endian_buffer<order::little, int16_t, 16, align::yes> little_int16_buf_at;
94 typedef endian_buffer<order::little, int32_t, 32, align::yes> little_int32_buf_at;
95 typedef endian_buffer<order::little, int64_t, 64, align::yes> little_int64_buf_at;
96
97 // aligned little endian unsigned integer buffers
98 typedef endian_buffer<order::little, uint8_t, 8, align::yes> little_uint8_buf_at;
99 typedef endian_buffer<order::little, uint16_t, 16, align::yes> little_uint16_buf_at;
100 typedef endian_buffer<order::little, uint32_t, 32, align::yes> little_uint32_buf_at;
101 typedef endian_buffer<order::little, uint64_t, 64, align::yes> little_uint64_buf_at;
102
103 // aligned native endian typedefs are not provided because
104 // <cstdint> types are superior for this use case
105
106 // unaligned big endian signed integer buffers
107 typedef endian_buffer<order::big, int_least8_t, 8> big_int8_buf_t;
108 typedef endian_buffer<order::big, int_least16_t, 16> big_int16_buf_t;
109 typedef endian_buffer<order::big, int_least32_t, 24> big_int24_buf_t;
110 typedef endian_buffer<order::big, int_least32_t, 32> big_int32_buf_t;
111 typedef endian_buffer<order::big, int_least64_t, 40> big_int40_buf_t;
112 typedef endian_buffer<order::big, int_least64_t, 48> big_int48_buf_t;
113 typedef endian_buffer<order::big, int_least64_t, 56> big_int56_buf_t;
114 typedef endian_buffer<order::big, int_least64_t, 64> big_int64_buf_t;
115
116 // unaligned big endian unsigned integer buffers
117 typedef endian_buffer<order::big, uint_least8_t, 8> big_uint8_buf_t;
118 typedef endian_buffer<order::big, uint_least16_t, 16> big_uint16_buf_t;
119 typedef endian_buffer<order::big, uint_least32_t, 24> big_uint24_buf_t;
120 typedef endian_buffer<order::big, uint_least32_t, 32> big_uint32_buf_t;
121 typedef endian_buffer<order::big, uint_least64_t, 40> big_uint40_buf_t;
122 typedef endian_buffer<order::big, uint_least64_t, 48> big_uint48_buf_t;
123 typedef endian_buffer<order::big, uint_least64_t, 56> big_uint56_buf_t;
124 typedef endian_buffer<order::big, uint_least64_t, 64> big_uint64_buf_t;
125
126 // unaligned little endian signed integer buffers
127 typedef endian_buffer<order::little, int_least8_t, 8> little_int8_buf_t;
128 typedef endian_buffer<order::little, int_least16_t, 16> little_int16_buf_t;
129 typedef endian_buffer<order::little, int_least32_t, 24> little_int24_buf_t;
130 typedef endian_buffer<order::little, int_least32_t, 32> little_int32_buf_t;
131 typedef endian_buffer<order::little, int_least64_t, 40> little_int40_buf_t;
132 typedef endian_buffer<order::little, int_least64_t, 48> little_int48_buf_t;
133 typedef endian_buffer<order::little, int_least64_t, 56> little_int56_buf_t;
134 typedef endian_buffer<order::little, int_least64_t, 64> little_int64_buf_t;
135
136 // unaligned little endian unsigned integer buffers
137 typedef endian_buffer<order::little, uint_least8_t, 8> little_uint8_buf_t;
138 typedef endian_buffer<order::little, uint_least16_t, 16> little_uint16_buf_t;
139 typedef endian_buffer<order::little, uint_least32_t, 24> little_uint24_buf_t;
140 typedef endian_buffer<order::little, uint_least32_t, 32> little_uint32_buf_t;
141 typedef endian_buffer<order::little, uint_least64_t, 40> little_uint40_buf_t;
142 typedef endian_buffer<order::little, uint_least64_t, 48> little_uint48_buf_t;
143 typedef endian_buffer<order::little, uint_least64_t, 56> little_uint56_buf_t;
144 typedef endian_buffer<order::little, uint_least64_t, 64> little_uint64_buf_t;
145
146# ifdef BOOST_BIG_ENDIAN
147 // unaligned native endian signed integer buffers
148 typedef big_int8_buf_t native_int8_buf_t;
149 typedef big_int16_buf_t native_int16_buf_t;
150 typedef big_int24_buf_t native_int24_buf_t;
151 typedef big_int32_buf_t native_int32_buf_t;
152 typedef big_int40_buf_t native_int40_buf_t;
153 typedef big_int48_buf_t native_int48_buf_t;
154 typedef big_int56_buf_t native_int56_buf_t;
155 typedef big_int64_buf_t native_int64_buf_t;
156
157 // unaligned native endian unsigned integer buffers
158 typedef big_uint8_buf_t native_uint8_buf_t;
159 typedef big_uint16_buf_t native_uint16_buf_t;
160 typedef big_uint24_buf_t native_uint24_buf_t;
161 typedef big_uint32_buf_t native_uint32_buf_t;
162 typedef big_uint40_buf_t native_uint40_buf_t;
163 typedef big_uint48_buf_t native_uint48_buf_t;
164 typedef big_uint56_buf_t native_uint56_buf_t;
165 typedef big_uint64_buf_t native_uint64_buf_t;
166# else
167 // unaligned native endian signed integer buffers
168 typedef little_int8_buf_t native_int8_buf_t;
169 typedef little_int16_buf_t native_int16_buf_t;
170 typedef little_int24_buf_t native_int24_buf_t;
171 typedef little_int32_buf_t native_int32_buf_t;
172 typedef little_int40_buf_t native_int40_buf_t;
173 typedef little_int48_buf_t native_int48_buf_t;
174 typedef little_int56_buf_t native_int56_buf_t;
175 typedef little_int64_buf_t native_int64_buf_t;
176
177 // unaligned native endian unsigned integer buffers
178 typedef little_uint8_buf_t native_uint8_buf_t;
179 typedef little_uint16_buf_t native_uint16_buf_t;
180 typedef little_uint24_buf_t native_uint24_buf_t;
181 typedef little_uint32_buf_t native_uint32_buf_t;
182 typedef little_uint40_buf_t native_uint40_buf_t;
183 typedef little_uint48_buf_t native_uint48_buf_t;
184 typedef little_uint56_buf_t native_uint56_buf_t;
185 typedef little_uint64_buf_t native_uint64_buf_t;
186# endif
187
188 // Stream inserter
189 template <class charT, class traits, BOOST_SCOPED_ENUM(order) Order, class T,
190 std::size_t n_bits, BOOST_SCOPED_ENUM(align) A>
191 std::basic_ostream<charT, traits>&
192 operator<<(std::basic_ostream<charT, traits>& os,
193 const endian_buffer<Order, T, n_bits, A>& x)
194 {
195 return os << x.value();
196 }
197
198 // Stream extractor
199 template <class charT, class traits, BOOST_SCOPED_ENUM(order) Order, class T,
200 std::size_t n_bits, BOOST_SCOPED_ENUM(align) A>
201 std::basic_istream<charT, traits>&
202 operator>>(std::basic_istream<charT, traits>& is,
203 endian_buffer<Order, T, n_bits, A>& x)
204 {
205 T i;
206 if (is >> i)
207 x = i;
208 return is;
209 }
210
211//---------------------------------- end synopsis ------------------------------------//
212
213 namespace detail
214 {
215
216 // Unrolled loops for loading and storing streams of bytes.
217
218 template <typename T, std::size_t n_bytes,
219 bool sign=boost::is_signed<T>::value >
220 struct unrolled_byte_loops
221 {
222 typedef unrolled_byte_loops<T, n_bytes - 1, sign> next;
223
224 static T load_big(const unsigned char* bytes) BOOST_NOEXCEPT
225 { return static_cast<T>(*(bytes - 1) | (next::load_big(bytes - 1) << 8)); }
226 static T load_little(const unsigned char* bytes) BOOST_NOEXCEPT
227 { return static_cast<T>(*bytes | (next::load_little(bytes + 1) << 8)); }
228
229 static void store_big(char* bytes, T value) BOOST_NOEXCEPT
230 {
231 *(bytes - 1) = static_cast<char>(value);
232 next::store_big(bytes - 1, static_cast<T>(value >> 8));
233 }
234 static void store_little(char* bytes, T value) BOOST_NOEXCEPT
235 {
236 *bytes = static_cast<char>(value);
237 next::store_little(bytes + 1, static_cast<T>(value >> 8));
238 }
239 };
240
241 template <typename T>
242 struct unrolled_byte_loops<T, 1, false>
243 {
244 static T load_big(const unsigned char* bytes) BOOST_NOEXCEPT
245 { return *(bytes - 1); }
246 static T load_little(const unsigned char* bytes) BOOST_NOEXCEPT
247 { return *bytes; }
248 static void store_big(char* bytes, T value) BOOST_NOEXCEPT
249 { *(bytes - 1) = static_cast<char>(value); }
250 static void store_little(char* bytes, T value) BOOST_NOEXCEPT
251 { *bytes = static_cast<char>(value); }
252
253 };
254
255 template <typename T>
256 struct unrolled_byte_loops<T, 1, true>
257 {
258 static T load_big(const unsigned char* bytes) BOOST_NOEXCEPT
259 { return *reinterpret_cast<const signed char*>(bytes - 1); }
260 static T load_little(const unsigned char* bytes) BOOST_NOEXCEPT
261 { return *reinterpret_cast<const signed char*>(bytes); }
262 static void store_big(char* bytes, T value) BOOST_NOEXCEPT
263 { *(bytes - 1) = static_cast<char>(value); }
264 static void store_little(char* bytes, T value) BOOST_NOEXCEPT
265 { *bytes = static_cast<char>(value); }
266 };
267
268 template <typename T, std::size_t n_bytes>
269 inline
270 T load_big_endian(const void* bytes) BOOST_NOEXCEPT
271 {
272 return unrolled_byte_loops<T, n_bytes>::load_big
273 (static_cast<const unsigned char*>(bytes) + n_bytes);
274 }
275
276 template <typename T, std::size_t n_bytes>
277 inline
278 T load_little_endian(const void* bytes) BOOST_NOEXCEPT
279 {
280# if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
281 // On x86 (which is little endian), unaligned loads are permitted
282 if (sizeof(T) == n_bytes) // GCC 4.9, VC++ 14.0, and probably others, elide this
283 // test and generate code only for the applicable return
284 // case since sizeof(T) and n_bytes are known at compile
285 // time.
286 {
287 return *reinterpret_cast<T const *>(bytes);
288 }
289# endif
290 return unrolled_byte_loops<T, n_bytes>::load_little
291 (static_cast<const unsigned char*>(bytes));
292 }
293
294 template <typename T, std::size_t n_bytes>
295 inline
296 void store_big_endian(void* bytes, T value) BOOST_NOEXCEPT
297 {
298 unrolled_byte_loops<T, n_bytes>::store_big
299 (static_cast<char*>(bytes) + n_bytes, value);
300 }
301
302 template <typename T, std::size_t n_bytes>
303 inline
304 void store_little_endian(void* bytes, T value) BOOST_NOEXCEPT
305 {
306# if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
307 // On x86 (which is little endian), unaligned stores are permitted
308 if (sizeof(T) == n_bytes) // GCC 4.9, VC++ 14.0, and probably others, elide this
309 // test and generate code only for the applicable return
310 // case since sizeof(T) and n_bytes are known at compile
311 // time.
312 {
313 *reinterpret_cast<T *>(bytes) = value;
314 return;
315 }
316# endif
317 unrolled_byte_loops<T, n_bytes>::store_little
318 (static_cast<char*>(bytes), value);
319 }
320
321 } // namespace detail
322
323# ifdef BOOST_ENDIAN_LOG
324 bool endian_log(true);
325# endif
326
327// endian_buffer class template specializations --------------------------------------//
328
329 // Specializations that represent unaligned bytes.
330 // Taking an integer type as a parameter provides a nice way to pass both
331 // the size and signedness of the desired integer and get the appropriate
332 // corresponding integer type for the interface.
333
334 // Q: Should endian_buffer supply "value_type operator value_type() const noexcept"?
335 // A: No. The rationale for endian_buffers is to prevent high-cost hidden
336 // conversions. If an implicit conversion operator is supplied, hidden conversions
337 // can occur.
338
339 // unaligned big endian_buffer specialization
340 template <typename T, std::size_t n_bits>
341 class endian_buffer< order::big, T, n_bits, align::no >
342 {
343 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
344 public:
345 typedef T value_type;
346# ifndef BOOST_ENDIAN_NO_CTORS
347 endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
348 explicit endian_buffer(T val) BOOST_NOEXCEPT
349 {
350# ifdef BOOST_ENDIAN_LOG
351 if ( endian_log )
352 std::cout << "big, unaligned, "
353 << n_bits << "-bits, construct(" << val << ")\n";
354# endif
355 detail::store_big_endian<T, n_bits/8>(m_value, val);
356 }
357# endif
358 endian_buffer & operator=(T val) BOOST_NOEXCEPT
359 {
360# ifdef BOOST_ENDIAN_LOG
361 if (endian_log)
362 std::cout << "big, unaligned, " << n_bits << "-bits, assign(" << val << ")\n";
363# endif
364 detail::store_big_endian<T, n_bits/8>(m_value, val);
365 return *this;
366 }
367 value_type value() const BOOST_NOEXCEPT
368 {
369# ifdef BOOST_ENDIAN_LOG
370 if ( endian_log )
371 std::cout << "big, unaligned, " << n_bits << "-bits, convert("
372 << detail::load_big_endian<T, n_bits/8>(m_value) << ")\n";
373# endif
374 return detail::load_big_endian<T, n_bits/8>(m_value);
375 }
376 const char* data() const BOOST_NOEXCEPT { return m_value; }
377 protected:
378 char m_value[n_bits/8];
379 };
380
381 // unaligned little endian_buffer specialization
382 template <typename T, std::size_t n_bits>
383 class endian_buffer< order::little, T, n_bits, align::no >
384 {
385 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
386 public:
387 typedef T value_type;
388# ifndef BOOST_ENDIAN_NO_CTORS
389 endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
390 explicit endian_buffer(T val) BOOST_NOEXCEPT
391 {
392# ifdef BOOST_ENDIAN_LOG
393 if ( endian_log )
394 std::cout << "little, unaligned, " << n_bits << "-bits, construct("
395 << val << ")\n";
396# endif
397 detail::store_little_endian<T, n_bits/8>(m_value, val);
398 }
399# endif
400 endian_buffer & operator=(T val) BOOST_NOEXCEPT
401 { detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
402 value_type value() const BOOST_NOEXCEPT
403 {
404# ifdef BOOST_ENDIAN_LOG
405 if ( endian_log )
406 std::cout << "little, unaligned, " << n_bits << "-bits, convert("
407 << detail::load_little_endian<T, n_bits/8>(m_value) << ")\n";
408# endif
409 return detail::load_little_endian<T, n_bits/8>(m_value);
410 }
411 const char* data() const BOOST_NOEXCEPT { return m_value; }
412 protected:
413 char m_value[n_bits/8];
414 };
415
416 // align::yes specializations; only n_bits == 16/32/64 supported
417
418 // aligned big endian_buffer specialization
419 template <typename T, std::size_t n_bits>
420 class endian_buffer<order::big, T, n_bits, align::yes>
421 {
422 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
423 BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
424 public:
425 typedef T value_type;
426# ifndef BOOST_ENDIAN_NO_CTORS
427 endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
428 explicit endian_buffer(T val) BOOST_NOEXCEPT
429 {
430# ifdef BOOST_ENDIAN_LOG
431 if ( endian_log )
432 std::cout << "big, aligned, " << n_bits
433 << "-bits, construct(" << val << ")\n";
434# endif
435 m_value = ::boost::endian::native_to_big(val);
436 }
437
438# endif
439 endian_buffer& operator=(T val) BOOST_NOEXCEPT
440 {
441 m_value = ::boost::endian::native_to_big(val);
442 return *this;
443 }
444 //operator value_type() const BOOST_NOEXCEPT
445 //{
446 // return ::boost::endian::big_to_native(m_value);
447 //}
448 value_type value() const BOOST_NOEXCEPT
449 {
450# ifdef BOOST_ENDIAN_LOG
451 if ( endian_log )
452 std::cout << "big, aligned, " << n_bits << "-bits, convert("
453 << ::boost::endian::big_to_native(m_value) << ")\n";
454# endif
455 return ::boost::endian::big_to_native(m_value);
456 }
457 const char* data() const BOOST_NOEXCEPT
458 {return reinterpret_cast<const char*>(&m_value);}
459 protected:
460 T m_value;
461 };
462
463 // aligned little endian_buffer specialization
464 template <typename T, std::size_t n_bits>
465 class endian_buffer<order::little, T, n_bits, align::yes>
466 {
467 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
468 BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
469 public:
470 typedef T value_type;
471# ifndef BOOST_ENDIAN_NO_CTORS
472 endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
473 explicit endian_buffer(T val) BOOST_NOEXCEPT
474 {
475# ifdef BOOST_ENDIAN_LOG
476 if ( endian_log )
477 std::cout << "little, aligned, " << n_bits
478 << "-bits, construct(" << val << ")\n";
479# endif
480 m_value = ::boost::endian::native_to_little(val);
481 }
482
483# endif
484 endian_buffer& operator=(T val) BOOST_NOEXCEPT
485 {
486 m_value = ::boost::endian::native_to_little(val);
487 return *this;
488 }
489 value_type value() const BOOST_NOEXCEPT
490 {
491# ifdef BOOST_ENDIAN_LOG
492 if ( endian_log )
493 std::cout << "little, aligned, " << n_bits << "-bits, convert("
494 << ::boost::endian::little_to_native(m_value) << ")\n";
495# endif
496 return ::boost::endian::little_to_native(m_value);
497 }
498 const char* data() const BOOST_NOEXCEPT
499 {return reinterpret_cast<const char*>(&m_value);}
500 protected:
501 T m_value;
502 };
503
504} // namespace endian
505} // namespace boost
506
507#if defined(__BORLANDC__) || defined( __CODEGEARC__)
508# pragma pack(pop)
509#endif
510
511#if defined(_MSC_VER)
512# pragma warning(pop)
513#endif
514
515#endif // BOOST_ENDIAN_BUFFERS_HPP
0516
=== added file '3rd-party/boost/endian/conversion.hpp'
--- 3rd-party/boost/endian/conversion.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/endian/conversion.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,487 @@
1// boost/endian/conversion.hpp -------------------------------------------------------//
2
3// Copyright Beman Dawes 2010, 2011, 2014
4
5// Distributed under the Boost Software License, Version 1.0.
6// http://www.boost.org/LICENSE_1_0.txt
7
8#ifndef BOOST_ENDIAN_CONVERSION_HPP
9#define BOOST_ENDIAN_CONVERSION_HPP
10
11#include <boost/config.hpp>
12#include <boost/predef/detail/endian_compat.h>
13#include <boost/cstdint.hpp>
14#include <boost/endian/detail/intrinsic.hpp>
15#include <boost/core/scoped_enum.hpp>
16#include <boost/static_assert.hpp>
17#include <algorithm>
18#include <cstring> // for memcpy
19
20//------------------------------------- synopsis ---------------------------------------//
21
22namespace boost
23{
24namespace endian
25{
26#ifndef BOOST_ENDIAN_ORDER_ENUM_DEFINED
27 BOOST_SCOPED_ENUM_START(order)
28 {
29 big, little,
30# ifdef BOOST_BIG_ENDIAN
31 native = big
32# else
33 native = little
34# endif
35 }; BOOST_SCOPED_ENUM_END
36# define BOOST_ENDIAN_ORDER_ENUM_DEFINED
37#endif
38
39//--------------------------------------------------------------------------------------//
40// //
41// return-by-value interfaces //
42// suggested by Phil Endecott //
43// //
44// user-defined types (UDTs) //
45// //
46// All return-by-value conversion function templates are required to be implemented in //
47// terms of an unqualified call to "endian_reverse(x)", a function returning the //
48// value of x with endianness reversed. This provides a customization point for any //
49// UDT that provides a "endian_reverse" free-function meeting the requirements. //
50// It must be defined in the same namespace as the UDT itself so that it will be found //
51// by argument dependent lookup (ADL). //
52// //
53//--------------------------------------------------------------------------------------//
54
55 // customization for exact-length arithmetic types. See doc/conversion.html/#FAQ
56 inline int8_t endian_reverse(int8_t x) BOOST_NOEXCEPT;
57 inline int16_t endian_reverse(int16_t x) BOOST_NOEXCEPT;
58 inline int32_t endian_reverse(int32_t x) BOOST_NOEXCEPT;
59 inline int64_t endian_reverse(int64_t x) BOOST_NOEXCEPT;
60 inline uint8_t endian_reverse(uint8_t x) BOOST_NOEXCEPT;
61 inline uint16_t endian_reverse(uint16_t x) BOOST_NOEXCEPT;
62 inline uint32_t endian_reverse(uint32_t x) BOOST_NOEXCEPT;
63 inline uint64_t endian_reverse(uint64_t x) BOOST_NOEXCEPT;
64
65 // reverse byte order unless native endianness is big
66 template <class EndianReversible >
67 inline EndianReversible big_to_native(EndianReversible x) BOOST_NOEXCEPT;
68 // Returns: x if native endian order is big, otherwise endian_reverse(x)
69 template <class EndianReversible >
70 inline EndianReversible native_to_big(EndianReversible x) BOOST_NOEXCEPT;
71 // Returns: x if native endian order is big, otherwise endian_reverse(x)
72
73 // reverse byte order unless native endianness is little
74 template <class EndianReversible >
75 inline EndianReversible little_to_native(EndianReversible x) BOOST_NOEXCEPT;
76 // Returns: x if native endian order is little, otherwise endian_reverse(x)
77 template <class EndianReversible >
78 inline EndianReversible native_to_little(EndianReversible x) BOOST_NOEXCEPT;
79 // Returns: x if native endian order is little, otherwise endian_reverse(x)
80
81 // generic conditional reverse byte order
82 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
83 class EndianReversible>
84 inline EndianReversible conditional_reverse(EndianReversible from) BOOST_NOEXCEPT;
85 // Returns: If From == To have different values, from.
86 // Otherwise endian_reverse(from).
87 // Remarks: The From == To test, and as a consequence which form the return takes, is
88 // is determined at compile time.
89
90 // runtime conditional reverse byte order
91 template <class EndianReversible >
92 inline EndianReversible conditional_reverse(EndianReversible from,
93 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order)
94 BOOST_NOEXCEPT;
95 // Returns: from_order == to_order ? from : endian_reverse(from).
96
97 //------------------------------------------------------------------------------------//
98
99
100 // Q: What happended to bswap, htobe, and the other synonym functions based on names
101 // popularized by BSD, OS X, and Linux?
102 // A: Turned out these may be implemented as macros on some systems. Ditto POSIX names
103 // for such functionality. Since macros would cause endless problems with functions
104 // of the same names, and these functions are just synonyms anyhow, they have been
105 // removed.
106
107
108 //------------------------------------------------------------------------------------//
109 // //
110 // reverse in place interfaces //
111 // //
112 // user-defined types (UDTs) //
113 // //
114 // All reverse in place function templates are required to be implemented in terms //
115 // of an unqualified call to "endian_reverse_inplace(x)", a function reversing //
116 // the endianness of x, which is a non-const reference. This provides a //
117 // customization point for any UDT that provides a "reverse_inplace" free-function //
118 // meeting the requirements. The free-function must be declared in the same //
119 // namespace as the UDT itself so that it will be found by argument-dependent //
120 // lookup (ADL). //
121 // //
122 //------------------------------------------------------------------------------------//
123
124 // reverse in place
125 template <class EndianReversible>
126 inline void endian_reverse_inplace(EndianReversible& x) BOOST_NOEXCEPT;
127 // Effects: x = endian_reverse(x)
128
129 // reverse in place unless native endianness is big
130 template <class EndianReversibleInplace>
131 inline void big_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
132 // Effects: none if native byte-order is big, otherwise endian_reverse_inplace(x)
133 template <class EndianReversibleInplace>
134 inline void native_to_big_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
135 // Effects: none if native byte-order is big, otherwise endian_reverse_inplace(x)
136
137 // reverse in place unless native endianness is little
138 template <class EndianReversibleInplace>
139 inline void little_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
140 // Effects: none if native byte-order is little, otherwise endian_reverse_inplace(x);
141 template <class EndianReversibleInplace>
142 inline void native_to_little_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
143 // Effects: none if native byte-order is little, otherwise endian_reverse_inplace(x);
144
145 // generic conditional reverse in place
146 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
147 class EndianReversibleInplace>
148 inline void conditional_reverse_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
149
150 // runtime reverse in place
151 template <class EndianReversibleInplace>
152 inline void conditional_reverse_inplace(EndianReversibleInplace& x,
153 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order)
154 BOOST_NOEXCEPT;
155
156//----------------------------------- end synopsis -------------------------------------//
157
158 namespace detail
159 {
160 // generic reverse function template implementation approach using std::reverse
161 // suggested by Mathias Gaunard. Primary motivation for inclusion is to have an
162 // independent implementation to test against.
163
164 template <class T>
165 inline T std_endian_reverse(T x) BOOST_NOEXCEPT
166 {
167 T tmp(x);
168 std::reverse(
169 reinterpret_cast<unsigned char*>(&tmp),
170 reinterpret_cast<unsigned char*>(&tmp) + sizeof(T));
171 return tmp;
172 }
173
174 // conditional unaligned reverse copy, patterned after std::reverse_copy
175 template <class T>
176 inline void big_reverse_copy(T from, char* to) BOOST_NOEXCEPT;
177 template <class T>
178 inline void big_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT;
179 template <class T>
180 inline void little_reverse_copy(T from, char* to) BOOST_NOEXCEPT;
181 template <class T>
182 inline void little_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT;
183 } // namespace detail
184
185//--------------------------------------------------------------------------------------//
186// //
187// return-by-value implementation //
188// //
189// -- portable approach suggested by tymofey, with avoidance of undefined behavior //
190// as suggested by Giovanni Piero Deretta, with a further refinement suggested //
191// by Pyry Jahkola. //
192// -- intrinsic approach suggested by reviewers, and by David Stone, who provided //
193// his Boost licensed macro implementation (detail/intrinsic.hpp) //
194// //
195//--------------------------------------------------------------------------------------//
196
197 inline int8_t endian_reverse(int8_t x) BOOST_NOEXCEPT
198 {
199 return x;
200 }
201
202 inline int16_t endian_reverse(int16_t x) BOOST_NOEXCEPT
203 {
204# ifdef BOOST_ENDIAN_NO_INTRINSICS
205 return (static_cast<uint16_t>(x) << 8)
206 | (static_cast<uint16_t>(x) >> 8);
207# else
208 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(static_cast<uint16_t>(x));
209# endif
210 }
211
212 inline int32_t endian_reverse(int32_t x) BOOST_NOEXCEPT
213 {
214# ifdef BOOST_ENDIAN_NO_INTRINSICS
215 uint32_t step16;
216 step16 = static_cast<uint32_t>(x) << 16 | static_cast<uint32_t>(x) >> 16;
217 return
218 ((static_cast<uint32_t>(step16) << 8) & 0xff00ff00)
219 | ((static_cast<uint32_t>(step16) >> 8) & 0x00ff00ff);
220# else
221 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(static_cast<uint32_t>(x));
222# endif
223 }
224
225 inline int64_t endian_reverse(int64_t x) BOOST_NOEXCEPT
226 {
227# ifdef BOOST_ENDIAN_NO_INTRINSICS
228 uint64_t step32, step16;
229 step32 = static_cast<uint64_t>(x) << 32 | static_cast<uint64_t>(x) >> 32;
230 step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16
231 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
232 return static_cast<int64_t>((step16 & 0x00FF00FF00FF00FFULL) << 8
233 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8);
234# else
235 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(static_cast<uint64_t>(x));
236# endif
237 }
238
239 inline uint8_t endian_reverse(uint8_t x) BOOST_NOEXCEPT
240 {
241 return x;
242 }
243
244 inline uint16_t endian_reverse(uint16_t x) BOOST_NOEXCEPT
245 {
246# ifdef BOOST_ENDIAN_NO_INTRINSICS
247 return (x << 8)
248 | (x >> 8);
249# else
250 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x);
251# endif
252 }
253
254 inline uint32_t endian_reverse(uint32_t x) BOOST_NOEXCEPT
255 {
256# ifdef BOOST_ENDIAN_NO_INTRINSICS
257 uint32_t step16;
258 step16 = x << 16 | x >> 16;
259 return
260 ((step16 << 8) & 0xff00ff00)
261 | ((step16 >> 8) & 0x00ff00ff);
262# else
263 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x);
264# endif
265 }
266
267 inline uint64_t endian_reverse(uint64_t x) BOOST_NOEXCEPT
268 {
269# ifdef BOOST_ENDIAN_NO_INTRINSICS
270 uint64_t step32, step16;
271 step32 = x << 32 | x >> 32;
272 step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16
273 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
274 return (step16 & 0x00FF00FF00FF00FFULL) << 8
275 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8;
276# else
277 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x);
278# endif
279 }
280
281 template <class EndianReversible >
282 inline EndianReversible big_to_native(EndianReversible x) BOOST_NOEXCEPT
283 {
284# ifdef BOOST_BIG_ENDIAN
285 return x;
286# else
287 return endian_reverse(x);
288# endif
289 }
290
291 template <class EndianReversible >
292 inline EndianReversible native_to_big(EndianReversible x) BOOST_NOEXCEPT
293 {
294# ifdef BOOST_BIG_ENDIAN
295 return x;
296# else
297 return endian_reverse(x);
298# endif
299 }
300
301 template <class EndianReversible >
302 inline EndianReversible little_to_native(EndianReversible x) BOOST_NOEXCEPT
303 {
304# ifdef BOOST_LITTLE_ENDIAN
305 return x;
306# else
307 return endian_reverse(x);
308# endif
309 }
310
311 template <class EndianReversible >
312 inline EndianReversible native_to_little(EndianReversible x) BOOST_NOEXCEPT
313 {
314# ifdef BOOST_LITTLE_ENDIAN
315 return x;
316# else
317 return endian_reverse(x);
318# endif
319 }
320
321 namespace detail
322 {
323 // Primary template and specializations to support endian_reverse().
324 // See rationale in endian_reverse() below.
325 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
326 class EndianReversible>
327 class value_converter ; // primary template
328 template <class T> class value_converter <order::big, order::big, T>
329 {public: T operator()(T x) BOOST_NOEXCEPT {return x;}};
330 template <class T> class value_converter <order::little, order::little, T>
331 {public: T operator()(T x) BOOST_NOEXCEPT {return x;}};
332 template <class T> class value_converter <order::big, order::little, T>
333 {public: T operator()(T x) BOOST_NOEXCEPT {return endian_reverse(x);}};
334 template <class T> class value_converter <order::little, order::big, T>
335 {public: T operator()(T x) BOOST_NOEXCEPT {return endian_reverse(x);}};
336 }
337
338 // generic conditional reverse
339 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
340 class EndianReversible>
341 inline EndianReversible conditional_reverse(EndianReversible from) BOOST_NOEXCEPT {
342 // work around lack of function template partial specialization by instantiating
343 // a function object of a class that is partially specialized on the two order
344 // template parameters, and then calling its operator().
345 detail::value_converter <From, To, EndianReversible> tmp;
346 return tmp(from);
347 }
348
349 // runtime conditional reverse
350 template <class EndianReversible >
351 inline EndianReversible conditional_reverse(EndianReversible from,
352 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order) BOOST_NOEXCEPT
353 {
354 return from_order == to_order ? from : endian_reverse(from);
355 }
356
357//--------------------------------------------------------------------------------------//
358// reverse-in-place implementation //
359//--------------------------------------------------------------------------------------//
360
361 // reverse in place
362 template <class EndianReversible>
363 inline void endian_reverse_inplace(EndianReversible& x) BOOST_NOEXCEPT
364 {
365 x = endian_reverse(x);
366 }
367
368 template <class EndianReversibleInplace>
369# ifdef BOOST_BIG_ENDIAN
370 inline void big_to_native_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
371# else
372 inline void big_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
373 { endian_reverse_inplace(x); }
374# endif
375 template <class EndianReversibleInplace>
376# ifdef BOOST_BIG_ENDIAN
377 inline void native_to_big_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
378# else
379 inline void native_to_big_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
380 {
381 endian_reverse_inplace(x);
382 }
383# endif
384
385 template <class EndianReversibleInplace>
386# ifdef BOOST_LITTLE_ENDIAN
387 inline void little_to_native_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
388# else
389 inline void little_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
390 { endian_reverse_inplace(x); }
391# endif
392 template <class EndianReversibleInplace>
393# ifdef BOOST_LITTLE_ENDIAN
394 inline void native_to_little_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
395# else
396 inline void native_to_little_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
397 {
398 endian_reverse_inplace(x);
399 }
400# endif
401
402 namespace detail
403 {
404 // Primary template and specializations support generic
405 // endian_reverse_inplace().
406 // See rationale in endian_reverse_inplace() below.
407 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
408 class EndianReversibleInplace>
409 class converter; // primary template
410 template <class T> class converter<order::big, order::big, T>
411 {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}};
412 template <class T> class converter<order::little, order::little, T>
413 {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}};
414 template <class T> class converter<order::big, order::little, T>
415 {public: void operator()(T& x) BOOST_NOEXCEPT { endian_reverse_inplace(x); }};
416 template <class T> class converter<order::little, order::big, T>
417 {public: void operator()(T& x) BOOST_NOEXCEPT { endian_reverse_inplace(x); }};
418 } // namespace detail
419
420 // generic conditional reverse in place
421 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
422 class EndianReversibleInplace>
423 inline void conditional_reverse_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
424 {
425 // work around lack of function template partial specialization by instantiating
426 // a function object of a class that is partially specialized on the two order
427 // template parameters, and then calling its operator().
428 detail::converter<From, To, EndianReversibleInplace> tmp;
429 tmp(x); // call operator ()
430 }
431
432 // runtime reverse in place
433 template <class EndianReversibleInplace>
434 inline void conditional_reverse_inplace(EndianReversibleInplace& x,
435 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order)
436 BOOST_NOEXCEPT
437 {
438 if (from_order != to_order)
439 endian_reverse_inplace(x);
440 }
441
442
443 namespace detail
444 {
445 template <class T>
446 inline void big_reverse_copy(T from, char* to) BOOST_NOEXCEPT
447 {
448# ifdef BOOST_BIG_ENDIAN
449 std::memcpy(to, reinterpret_cast<const char*>(&from), sizeof(T));
450# else
451 std::reverse_copy(reinterpret_cast<const char*>(&from),
452 reinterpret_cast<const char*>(&from) + sizeof(T), to);
453# endif
454 }
455 template <class T>
456 inline void big_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT
457 {
458# ifdef BOOST_BIG_ENDIAN
459 std::memcpy(reinterpret_cast<char*>(&to), from, sizeof(T));
460# else
461 std::reverse_copy(from, from + sizeof(T), reinterpret_cast<char*>(&to));
462# endif
463 }
464 template <class T>
465 inline void little_reverse_copy(T from, char* to) BOOST_NOEXCEPT
466 {
467# ifdef BOOST_LITTLE_ENDIAN
468 std::memcpy(to, reinterpret_cast<const char*>(&from), sizeof(T));
469# else
470 std::reverse_copy(reinterpret_cast<const char*>(&from),
471 reinterpret_cast<const char*>(&from) + sizeof(T), to);
472# endif
473 }
474 template <class T>
475 inline void little_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT
476 {
477# ifdef BOOST_LITTLE_ENDIAN
478 std::memcpy(reinterpret_cast<char*>(&to), from, sizeof(T));
479# else
480 std::reverse_copy(from, from + sizeof(T), reinterpret_cast<char*>(&to));
481# endif
482 }
483 } // namespace detail
484} // namespace endian
485} // namespace boost
486
487#endif // BOOST_ENDIAN_CONVERSION_HPP
0488
=== added directory '3rd-party/boost/endian/detail'
=== added file '3rd-party/boost/endian/detail/config.hpp'
--- 3rd-party/boost/endian/detail/config.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/endian/detail/config.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,62 @@
1// boost/endian/detail/config.hpp ----------------------------------------------------//
2
3// Copyright Beman Dawes 2003, 2010
4
5// Distributed under the Boost Software License, Version 1.0.
6// See http://www.boost.org/LICENSE_1_0.txt
7
8//--------------------------------------------------------------------------------------//
9
10#ifndef BOOST_ENDIAN_CONFIG_HPP
11#define BOOST_ENDIAN_CONFIG_HPP
12
13// This header implements separate compilation features as described in
14// http://www.boost.org/more/separate_compilation.html
15
16#include <boost/config.hpp>
17#include <boost/system/api_config.hpp> // for BOOST_POSIX_API or BOOST_WINDOWS_API
18
19// throw an exception ----------------------------------------------------------------//
20//
21// Exceptions were originally thrown via boost::throw_exception().
22// As throw_exception() became more complex, it caused user error reporting
23// to be harder to interpret, since the exception reported became much more complex.
24// The immediate fix was to throw directly, wrapped in a macro to make any later change
25// easier.
26
27#define BOOST_ENDIAN_THROW(EX) throw EX
28
29// enable dynamic linking -------------------------------------------------------------//
30
31#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_ENDIAN_DYN_LINK)
32# if defined(BOOST_ENDIAN_SOURCE)
33# define BOOST_ENDIAN_DECL BOOST_SYMBOL_EXPORT
34# else
35# define BOOST_ENDIAN_DECL BOOST_SYMBOL_IMPORT
36# endif
37#else
38# define BOOST_ENDIAN_DECL
39#endif
40
41// enable automatic library variant selection ----------------------------------------//
42
43#if !defined(BOOST_ENDIAN_SOURCE) && !defined(BOOST_ALL_NO_LIB) \
44 && !defined(BOOST_ENDIAN_NO_LIB)
45//
46// Set the name of our library, this will get undef'ed by auto_link.hpp
47// once it's done with it:
48//
49#define BOOST_LIB_NAME boost_endian
50//
51// If we're importing code from a dll, then tell auto_link.hpp about it:
52//
53#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_ENDIAN_DYN_LINK)
54# define BOOST_DYN_LINK
55#endif
56//
57// And include the header that does the work:
58//
59#include <boost/config/auto_link.hpp>
60#endif // auto-linking disabled
61
62#endif // BOOST_ENDIAN_CONFIG_HPP
063
=== added file '3rd-party/boost/endian/detail/cover_operators.hpp'
--- 3rd-party/boost/endian/detail/cover_operators.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/endian/detail/cover_operators.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,142 @@
1// boost/endian/detail/cover_operators.hpp ----------------------------------//
2
3// Copyright Darin Adler 2000
4// Copyright Beman Dawes 2008
5
6// Distributed under the Boost Software License, Version 1.0. (See accompanying
7// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
9#ifndef BOOST_ENDIAN_COVER_OPERATORS_HPP
10#define BOOST_ENDIAN_COVER_OPERATORS_HPP
11
12#if defined(_MSC_VER)
13# pragma warning(push)
14# pragma warning(disable:4365) // conversion ... signed/unsigned mismatch
15#endif
16
17# ifndef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
18# include <boost/operators.hpp>
19# endif
20
21#include <boost/config.hpp>
22#include <iosfwd>
23
24namespace boost
25{
26 namespace endian
27 {
28
29//--------------------------------------------------------------------------------------//
30
31// A class that adds arithmetic operators to an arithmetic cover class
32//
33// Uses the curiously recurring template pattern (CRTP).
34//
35// If the class being covered has a non-explicit conversion to an integer type
36// then a smaller number of cover operations are needed. Define the macro
37// BOOST_ENDIAN_MINIMAL_COVER_OPERATORS to indicate this.
38//
39// Define BOOST_NO_IO_COVER_OPERATORS if I/O cover operations are not desired.
40
41//--------------------------------------------------------------------------------------//
42
43 template <class D, // D is the CRTP derived type, i.e. the cover class
44 class ArithmeticT>
45 class cover_operators
46# ifndef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
47 : boost::operators<D>
48# endif
49 {
50 // The other operations take advantage of the type conversion that's
51 // built into unary +.
52
53 // Unary operations.
54 friend ArithmeticT operator+(const D& x) BOOST_NOEXCEPT { return x; }
55# ifndef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
56 friend ArithmeticT operator-(const D& x) BOOST_NOEXCEPT { return -+x; }
57 friend ArithmeticT operator~(const D& x) BOOST_NOEXCEPT { return ~+x; }
58 friend ArithmeticT operator!(const D& x) BOOST_NOEXCEPT { return !+x; }
59
60 // The basic ordering operations.
61 friend bool operator==(const D& x, ArithmeticT y) BOOST_NOEXCEPT { return +x == y; }
62 friend bool operator<(const D& x, ArithmeticT y) BOOST_NOEXCEPT { return +x < y; }
63# endif
64
65 // The basic arithmetic operations.
66 friend D& operator+=(D& x, ArithmeticT y) BOOST_NOEXCEPT
67 { return x = static_cast<ArithmeticT>(+x + y); }
68 friend D& operator-=(D& x, ArithmeticT y) BOOST_NOEXCEPT
69 { return x = static_cast<ArithmeticT>(+x - y); }
70 friend D& operator*=(D& x, ArithmeticT y) BOOST_NOEXCEPT
71 { return x = static_cast<ArithmeticT>(+x * y); }
72 friend D& operator/=(D& x, ArithmeticT y) BOOST_NOEXCEPT
73 { return x = static_cast<ArithmeticT>(+x / y); }
74 friend D& operator%=(D& x, ArithmeticT y) BOOST_NOEXCEPT
75 { return x = static_cast<ArithmeticT>(+x % y); }
76 friend D& operator&=(D& x, ArithmeticT y) BOOST_NOEXCEPT
77 { return x = static_cast<ArithmeticT>(+x & y); }
78 friend D& operator|=(D& x, ArithmeticT y) BOOST_NOEXCEPT
79 { return x = static_cast<ArithmeticT>(+x | y); }
80 friend D& operator^=(D& x, ArithmeticT y) BOOST_NOEXCEPT
81 { return x = static_cast<ArithmeticT>(+x ^ y); }
82 friend D& operator<<=(D& x, ArithmeticT y) BOOST_NOEXCEPT
83 { return x = static_cast<ArithmeticT>(+x << y); }
84 friend D& operator>>=(D& x, ArithmeticT y) BOOST_NOEXCEPT
85 { return x = static_cast<ArithmeticT>(+x >> y); }
86
87 // A few binary arithmetic operations not covered by operators base class.
88 friend ArithmeticT operator<<(const D& x, ArithmeticT y) BOOST_NOEXCEPT
89 { return static_cast<ArithmeticT>(+x << y); }
90 friend ArithmeticT operator>>(const D& x, ArithmeticT y) BOOST_NOEXCEPT
91 { return static_cast<ArithmeticT>(+x >> y); }
92
93 // Auto-increment and auto-decrement can be defined in terms of the
94 // arithmetic operations.
95 friend D& operator++(D& x) BOOST_NOEXCEPT { return x += 1; }
96 friend D& operator--(D& x) BOOST_NOEXCEPT { return x -= 1; }
97
98# ifdef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
99 friend D operator++(D& x, int) BOOST_NOEXCEPT
100 {
101 D tmp(x);
102 x += 1;
103 return tmp;
104 }
105 friend D operator--(D& x, int) BOOST_NOEXCEPT
106 {
107 D tmp(x);
108 x -= 1;
109 return tmp;
110 }
111# endif
112
113# ifndef BOOST_NO_IO_COVER_OPERATORS
114
115 // Stream inserter
116 template <class charT, class traits>
117 friend std::basic_ostream<charT, traits>&
118 operator<<(std::basic_ostream<charT, traits>& os, const D& x)
119 {
120 return os << +x;
121 }
122
123 // Stream extractor
124 template <class charT, class traits>
125 friend std::basic_istream<charT, traits>&
126 operator>>(std::basic_istream<charT, traits>& is, D& x)
127 {
128 ArithmeticT i;
129 if (is >> i)
130 x = i;
131 return is;
132 }
133# endif
134 };
135 } // namespace endian
136} // namespace boost
137
138#if defined(_MSC_VER)
139# pragma warning(pop)
140#endif
141
142#endif // BOOST_ENDIAN_COVER_OPERATORS_HPP
0143
=== added file '3rd-party/boost/endian/detail/disable_warnings.hpp'
--- 3rd-party/boost/endian/detail/disable_warnings.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/endian/detail/disable_warnings.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,33 @@
1// disable_warnings.hpp --------------------------------------------------------------//
2
3// Copyright Beman Dawes 2011
4
5// Distributed under the Boost Software License, Version 1.0.
6// See http://www.boost.org/LICENSE_1_0.txt
7
8//--------------------------------------------------------------------------------------//
9
10#ifdef _MSC_VER
11
12#ifndef _SCL_SECURE_NO_WARNINGS
13# define _SCL_SECURE_NO_WARNINGS
14#endif
15
16#ifndef _CRT_SECURE_NO_WARNINGS
17# define _CRT_SECURE_NO_WARNINGS
18#endif
19
20# pragma warning(push)
21
22// triggered by boost/detail/lightweight_test.hpp
23# pragma warning( disable : 4640 ) // ... construction of local static object is not thread-safe
24
25// triggered by Microsoft's own headers, so disable
26# pragma warning( disable : 4820 ) // padding added after data member
27# pragma warning( disable : 4548 ) // expression before comma has no effect
28# pragma warning( disable : 4668 ) // ... is not defined as a preprocessor macro
29# pragma warning( disable : 4514 ) // ... unreferenced inline function has been removed
30# pragma warning( disable : 4710 ) // ... function not inlined
31# pragma warning( disable : 4986 ) // ... exception specification does not match previous declaration
32# pragma warning( disable : 4711 ) // ... selected for automatic inline expansion
33#endif
034
=== added file '3rd-party/boost/endian/detail/disable_warnings_pop.hpp'
--- 3rd-party/boost/endian/detail/disable_warnings_pop.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/endian/detail/disable_warnings_pop.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,12 @@
1// disable_warnings_pop.hpp ----------------------------------------------------------//
2
3// Copyright Beman Dawes 2011
4
5// Distributed under the Boost Software License, Version 1.0.
6// See http://www.boost.org/LICENSE_1_0.txt
7
8//--------------------------------------------------------------------------------------//
9
10#ifdef _MSC_VER
11# pragma warning(push)
12#endif
013
=== added file '3rd-party/boost/endian/detail/intrinsic.hpp'
--- 3rd-party/boost/endian/detail/intrinsic.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/endian/detail/intrinsic.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,64 @@
1// endian/detail/intrinsic.hpp -------------------------------------------------------//
2
3// Copyright (C) 2012 David Stone
4// Copyright Beman Dawes 2013
5
6// Distributed under the Boost Software License, Version 1.0.
7// http://www.boost.org/LICENSE_1_0.txt
8
9#ifndef BOOST_ENDIAN_INTRINSIC_HPP
10#define BOOST_ENDIAN_INTRINSIC_HPP
11
12// Allow user to force BOOST_ENDIAN_NO_INTRINSICS in case they aren't available for a
13// particular platform/compiler combination. Please report such platform/compiler
14// combinations to the Boost mailing list.
15#ifndef BOOST_ENDIAN_NO_INTRINSICS
16
17#ifndef __has_builtin // Optional of course
18 #define __has_builtin(x) 0 // Compatibility with non-clang compilers
19#endif
20
21// GCC and Clang recent versions provide intrinsic byte swaps via builtins
22#if (defined(__clang__) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)) \
23 || (defined(__GNUC__ ) && \
24 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
25# define BOOST_ENDIAN_INTRINSIC_MSG "__builtin_bswap16, etc."
26// prior to 4.8, gcc did not provide __builtin_bswap16 on some platforms so we emulate it
27// see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624
28// Clang has a similar problem, but their feature test macros make it easier to detect
29# if (defined(__clang__) && __has_builtin(__builtin_bswap16)) \
30 || (defined(__GNUC__) &&(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
31# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x) __builtin_bswap16(x)
32# else
33# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x) __builtin_bswap32((x) << 16)
34# endif
35# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x) __builtin_bswap32(x)
36# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x) __builtin_bswap64(x)
37
38// Linux systems provide the byteswap.h header, with
39#elif defined(__linux__)
40// don't check for obsolete forms defined(linux) and defined(__linux) on the theory that
41// compilers that predefine only these are so old that byteswap.h probably isn't present.
42# define BOOST_ENDIAN_INTRINSIC_MSG "byteswap.h bswap_16, etc."
43# include <byteswap.h>
44# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x) bswap_16(x)
45# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x) bswap_32(x)
46# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x) bswap_64(x)
47
48#elif defined(_MSC_VER)
49// Microsoft documents these as being compatible since Windows 95 and specificly
50// lists runtime library support since Visual Studio 2003 (aka 7.1).
51# define BOOST_ENDIAN_INTRINSIC_MSG "cstdlib _byteswap_ushort, etc."
52# include <cstdlib>
53# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x) _byteswap_ushort(x)
54# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x) _byteswap_ulong(x)
55# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x) _byteswap_uint64(x)
56#else
57# define BOOST_ENDIAN_NO_INTRINSICS
58# define BOOST_ENDIAN_INTRINSIC_MSG "no byte swap intrinsics"
59#endif
60
61#elif !defined(BOOST_ENDIAN_INTRINSIC_MSG)
62# define BOOST_ENDIAN_INTRINSIC_MSG "no byte swap intrinsics"
63#endif // BOOST_ENDIAN_NO_INTRINSICS
64#endif // BOOST_ENDIAN_INTRINSIC_HPP
065
=== added file '3rd-party/boost/endian/detail/lightweight_test.hpp'
--- 3rd-party/boost/endian/detail/lightweight_test.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/endian/detail/lightweight_test.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,223 @@
1// boost/endian/detail/lightweight_test.hpp --------------------------------------------//
2
3#ifndef BOOST_ENDIAN_LIGHTWEIGHT_TEST_HPP
4#define BOOST_ENDIAN_LIGHTWEIGHT_TEST_HPP
5
6// MS compatible compilers support #pragma once
7
8#if defined(_MSC_VER)
9# pragma once
10#endif
11
12//
13// Copyright (c) 2002, 2009, 2014 Peter Dimov
14// Copyright (2) Beman Dawes 2010, 2011, 2015
15// Copyright (3) Ion Gaztanaga 2013
16//
17// Distributed under the Boost Software License, Version 1.0.
18// See http://www.boost.org/LICENSE_1_0.txt
19//
20
21#include <boost/assert.hpp>
22#include <boost/current_function.hpp>
23#include <boost/core/no_exceptions_support.hpp>
24#include <cstring> // for memcmp
25#include <iostream>
26
27// IDE's like Visual Studio perform better if output goes to std::cout or
28// some other stream, so allow user to configure output stream:
29#ifndef BOOST_LIGHTWEIGHT_TEST_OSTREAM
30# define BOOST_LIGHTWEIGHT_TEST_OSTREAM std::cerr
31#endif
32
33namespace boost
34{
35namespace endian
36{
37namespace detail
38{
39
40struct report_errors_reminder
41{
42 bool called_report_errors_function;
43
44 report_errors_reminder() : called_report_errors_function(false) {}
45
46 ~report_errors_reminder()
47 {
48 BOOST_ASSERT(called_report_errors_function); // verify report_errors() was called
49 }
50};
51
52inline report_errors_reminder& report_errors_remind()
53{
54 static report_errors_reminder r;
55 return r;
56}
57
58inline int & test_errors()
59{
60 static int x = 0;
61 report_errors_remind();
62 return x;
63}
64
65inline void test_failed_impl(char const * expr, char const * file, int line, char const * function)
66{
67 BOOST_LIGHTWEIGHT_TEST_OSTREAM
68 << file << "(" << line << "): test '" << expr << "' failed in function '"
69 << function << "'" << std::endl;
70 ++test_errors();
71}
72
73inline void error_impl(char const * msg, char const * file, int line, char const * function)
74{
75 BOOST_LIGHTWEIGHT_TEST_OSTREAM
76 << file << "(" << line << "): " << msg << " in function '"
77 << function << "'" << std::endl;
78 ++test_errors();
79}
80
81inline void throw_failed_impl(char const * excep, char const * file, int line, char const * function)
82{
83 BOOST_LIGHTWEIGHT_TEST_OSTREAM
84 << file << "(" << line << "): Exception '" << excep << "' not thrown in function '"
85 << function << "'" << std::endl;
86 ++test_errors();
87}
88
89template<class T, class U> inline void test_eq_impl( char const * expr1, char const * expr2,
90 char const * file, int line, char const * function, T const & t, U const & u )
91{
92 if( t == u )
93 {
94 report_errors_remind();
95 }
96 else
97 {
98 BOOST_LIGHTWEIGHT_TEST_OSTREAM
99 << file << "(" << line << "): test '" << expr1 << " == " << expr2
100 << "' failed in function '" << function << "': "
101 << "'" << t << "' != '" << u << "'" << std::endl;
102 ++test_errors();
103 }
104}
105
106template<class T, class U> inline void test_ne_impl( char const * expr1, char const * expr2,
107 char const * file, int line, char const * function, T const & t, U const & u )
108{
109 if( t != u )
110 {
111 report_errors_remind();
112 }
113 else
114 {
115 BOOST_LIGHTWEIGHT_TEST_OSTREAM
116 << file << "(" << line << "): test '" << expr1 << " != " << expr2
117 << "' failed in function '" << function << "': "
118 << "'" << t << "' == '" << u << "'" << std::endl;
119 ++test_errors();
120 }
121}
122
123template <class T>
124std::string to_hex(const T& x)
125{
126 const char hex[] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
127 std::string tmp;
128 const unsigned char* p = reinterpret_cast<const unsigned char*>(&x);
129 const unsigned char* e = p + sizeof(T);
130
131 for (; p < e; ++p)
132 {
133 tmp += hex[*p >> 4]; // high-order nibble
134 tmp += hex[*p & 0x0f]; // low-order nibble
135 }
136 return tmp;
137}
138
139template<class T, class U> inline bool test_memcmp_eq_impl(char const * expr1,
140 char const * expr2, char const * file, int line, char const * function, T const & t,
141 U const & u)
142{
143 BOOST_ASSERT(sizeof(T) == sizeof(U));
144 if (sizeof(T) == sizeof(U)
145 && std::memcmp(&t, &u, sizeof(T)) == 0)
146 {
147 report_errors_remind();
148 return true;
149 }
150 else
151 {
152 BOOST_LIGHTWEIGHT_TEST_OSTREAM
153 << file << "(" << line << "): test 'std::memcmp(" << expr1 << ", " << expr2
154 << ") == 0' fails in function '" << function << "': "
155 << " with values '" << to_hex(t) << "' and '" << to_hex(u) << "'" << std::endl;
156 ++test_errors();
157 return false;
158 }
159}
160
161} // namespace detail
162
163inline int report_errors()
164{
165 boost::endian::detail::report_errors_remind().called_report_errors_function = true;
166
167 int errors = boost::endian::detail::test_errors();
168
169 if( errors == 0 )
170 {
171 BOOST_LIGHTWEIGHT_TEST_OSTREAM
172 << "No errors detected." << std::endl;
173 return 0;
174 }
175 else
176 {
177 BOOST_LIGHTWEIGHT_TEST_OSTREAM
178 << errors << " error" << (errors == 1? "": "s") << " detected." << std::endl;
179 return 1;
180 }
181}
182
183} // namespace endian
184} // namespace boost
185
186//////////////////////////////////////////////////////////////////////////////////////////
187// TODO: Should all test macros return bool? See BOOST_TEST_MEM_EQ usage in fp_exaustive_test,cpp
188//////////////////////////////////////////////////////////////////////////////////////////
189
190
191#define BOOST_TEST(expr) \
192 ((expr)? (void)0: ::boost::endian::detail::test_failed_impl(#expr, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION))
193
194#define BOOST_ERROR(msg) \
195 ( ::boost::endian::detail::error_impl(msg, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) )
196
197#define BOOST_TEST_EQ(expr1,expr2) \
198 ( ::boost::endian::detail::test_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
199#define BOOST_TEST_NE(expr1,expr2) \
200 ( ::boost::endian::detail::test_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
201
202#define BOOST_TEST_MEM_EQ(expr1,expr2) \
203 (::boost::endian::detail::test_memcmp_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2))
204
205#ifndef BOOST_NO_EXCEPTIONS
206 #define BOOST_TEST_THROWS( EXPR, EXCEP ) \
207 try { \
208 EXPR; \
209 ::boost::detail::throw_failed_impl \
210 (#EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
211 } \
212 catch(EXCEP const&) { \
213 } \
214 catch(...) { \
215 ::boost::detail::throw_failed_impl \
216 (#EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
217 } \
218 //
219#else
220 #define BOOST_TEST_THROWS( EXPR, EXCEP )
221#endif
222
223#endif // #ifndef BOOST_ENDIAN_LIGHTWEIGHT_TEST_HPP
0224
=== added file '3rd-party/boost/endian/endian.hpp'
--- 3rd-party/boost/endian/endian.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/endian/endian.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,19 @@
1// boost/endian/endian.hpp -----------------------------------------------------------//
2
3// Copyright Beman Dawes 2015
4
5// Distributed under the Boost Software License, Version 1.0.
6// See http://www.boost.org/LICENSE_1_0.txt
7
8// See library home page at http://www.boost.org/libs/endian
9
10#ifndef BOOST_ENDIAN_ENDIAN_HPP
11#define BOOST_ENDIAN_ENDIAN_HPP
12
13#ifndef BOOST_ENDIAN_DEPRECATED_NAMES
14# error "<boost/endian/endian.hpp> is deprecated. Define BOOST_ENDIAN_DEPRECATED_NAMES to use."
15#endif
16
17#include <boost/endian/arithmetic.hpp>
18
19#endif //BOOST_ENDIAN_ENDIAN_HPP
020
=== added file '3rd-party/boost/endian/std_pair.hpp'
--- 3rd-party/boost/endian/std_pair.hpp 1970-01-01 00:00:00 +0000
+++ 3rd-party/boost/endian/std_pair.hpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,38 @@
1// boost/endian/std_pair.hpp ---------------------------------------------------------//
2
3// Copyright Beman Dawes 2013
4
5// Distributed under the Boost Software License, Version 1.0.
6// http://www.boost.org/LICENSE_1_0.txt
7
8//--------------------------------------------------------------------------------------//
9
10#ifndef BOOST_ENDIAN_STD_PAIR_HPP
11#define BOOST_ENDIAN_STD_PAIR_HPP
12
13#include <boost/endian/conversion.hpp>
14#include <utility>
15
16namespace boost
17{
18namespace endian
19{
20 template <class ReversibleValueT, class ReversibleValueU>
21 std::pair<ReversibleValueT, ReversibleValueU>
22 reverse_value(std::pair<ReversibleValueT, ReversibleValueU> x)
23 {
24 return std::pair<ReversibleValueT, ReversibleValueU>(reverse_value(x.first),
25 reverse_value(x.second));
26 }
27
28 template <class ReversibleT, class ReversibleU>
29 void reverse(std::pair<ReversibleT, ReversibleU>& x)
30 {
31 reverse(x.first);
32 reverse(x.second);
33 }
34
35}
36}
37
38#endif // BOOST_ENDIAN_STD_PAIR_HPP
039
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2015-02-03 08:38:21 +0000
+++ CMakeLists.txt 2016-03-10 19:55:08 +0000
@@ -34,6 +34,7 @@
34pkg_check_modules(PROCESS_CPP process-cpp REQUIRED)34pkg_check_modules(PROCESS_CPP process-cpp REQUIRED)
35pkg_check_modules(PROPERTIES_CPP properties-cpp REQUIRED)35pkg_check_modules(PROPERTIES_CPP properties-cpp REQUIRED)
36pkg_check_modules(TRUST_STORE trust-store REQUIRED)36pkg_check_modules(TRUST_STORE trust-store REQUIRED)
37pkg_check_modules(UBUNTU_PLATFORM_HARDWARE_API ubuntu-platform-hardware-api)
37#####################################################################38#####################################################################
38# Enable code coverage calculation with gcov/gcovr/lcov39# Enable code coverage calculation with gcov/gcovr/lcov
39# Usage:40# Usage:
@@ -69,6 +70,8 @@
69endif()70endif()
7071
71include_directories(72include_directories(
73 3rd-party/
74
72 ${Boost_INCLUDE_DIRS}75 ${Boost_INCLUDE_DIRS}
73 ${DBUS_INCLUDE_DIRS}76 ${DBUS_INCLUDE_DIRS}
74 ${DBUS_CPP_INCLUDE_DIRS}77 ${DBUS_CPP_INCLUDE_DIRS}
7578
=== modified file 'include/location_service/com/ubuntu/location/connectivity/manager.h'
--- include/location_service/com/ubuntu/location/connectivity/manager.h 2014-07-10 16:44:26 +0000
+++ include/location_service/com/ubuntu/location/connectivity/manager.h 2016-03-10 19:55:08 +0000
@@ -219,6 +219,27 @@
219 Manager() = default;219 Manager() = default;
220};220};
221221
222/** @brief ExtendedManager extends the Manager interface in an ABI-stable way. */
223class ExtendedManager : public Manager
224{
225public:
226 /**
227 * @brief ismis requests enumeration of the imsis of all SIMs installed in the device.
228 */
229 virtual void enumerate_imsis(const std::function<void(const std::string&)>&) const = 0;
230
231 /**
232 * @brief msisdns requests enumeration of all mobile station international subscriber directory numbers
233 * of all SIMs installed in the device.
234 */
235 virtual void enumerate_msisdns(const std::function<void(const std::string&)>&) const = 0;
236
237protected:
238 /** @cond */
239 ExtendedManager() = default;
240 /** @endcond */
241};
242
222/**243/**
223 * @brief Provides access to a platform-specific implementation/instance of a connectivity manager.244 * @brief Provides access to a platform-specific implementation/instance of a connectivity manager.
224 * @throw Manager::Errors::ConnectivityManagementNotSupported.245 * @throw Manager::Errors::ConnectivityManagementNotSupported.
225246
=== modified file 'src/location_service/com/ubuntu/location/CMakeLists.txt'
--- src/location_service/com/ubuntu/location/CMakeLists.txt 2015-11-26 08:28:38 +0000
+++ src/location_service/com/ubuntu/location/CMakeLists.txt 2016-03-10 19:55:08 +0000
@@ -1,3 +1,7 @@
1if (UBUNTU_PLATFORM_HARDWARE_API_FOUND)
2 add_definitions(-DCOM_UBUNTU_LOCATION_SERVICE_HAVE_UBUNTU_PLATFORM_HARDWARE_API)
3endif()
4
1if (NET_CPP_FOUND)5if (NET_CPP_FOUND)
2 add_definitions(-DCOM_UBUNTU_LOCATION_SERVICE_HAVE_NET_CPP=1)6 add_definitions(-DCOM_UBUNTU_LOCATION_SERVICE_HAVE_NET_CPP=1)
37
@@ -10,6 +14,8 @@
10 service/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/service/config.h @ONLY14 service/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/service/config.h @ONLY
11)15)
1216
17include_directories(${UBUNTU_PLATFORM_HARDWARE_API_INCLUDE_DIRS})
18
13add_library(19add_library(
14 ubuntu-location-service SHARED20 ubuntu-location-service SHARED
1521
@@ -29,6 +35,7 @@
29 settings.cpp35 settings.cpp
30 time_based_update_policy.cpp36 time_based_update_policy.cpp
31 set_name_for_thread.cpp37 set_name_for_thread.cpp
38 time_since_boot.cpp
32 wifi_and_cell_reporting_state.cpp39 wifi_and_cell_reporting_state.cpp
3340
34 boost_ptree_settings.cpp41 boost_ptree_settings.cpp
@@ -126,6 +133,7 @@
126 ${LIBAPPARMOR_LDFLAGS}133 ${LIBAPPARMOR_LDFLAGS}
127 ${NET_CPP_LDFLAGS}134 ${NET_CPP_LDFLAGS}
128 ${TRUST_STORE_LDFLAGS}135 ${TRUST_STORE_LDFLAGS}
136 ${UBUNTU_PLATFORM_HARDWARE_API_LDFLAGS}
129 ${GLog_LIBRARY}137 ${GLog_LIBRARY}
130 ${GFlags_LIBRARY}138 ${GFlags_LIBRARY}
131)139)
132140
=== modified file 'src/location_service/com/ubuntu/location/connectivity/ofono.h'
--- src/location_service/com/ubuntu/location/connectivity/ofono.h 2015-01-06 12:35:02 +0000
+++ src/location_service/com/ubuntu/location/connectivity/ofono.h 2016-03-10 19:55:08 +0000
@@ -640,6 +640,118 @@
640 } signals;640 } signals;
641 };641 };
642642
643 struct SimManager
644 {
645 static const std::string& name()
646 {
647 static const std::string s{"org.ofono.SimManager"};
648 return s;
649 }
650
651 struct GetProperties
652 {
653 static const std::string& name()
654 {
655 static const std::string s{"GetProperties"};
656 return s;
657 }
658
659 typedef SimManager Interface;
660 typedef std::map<std::string, core::dbus::types::Variant> ValueType;
661
662 static std::chrono::milliseconds default_timeout()
663 {
664 return std::chrono::seconds{1};
665 }
666 };
667
668 struct PropertyChanged
669 {
670 inline static std::string name()
671 {
672 return "PropertyChanged";
673 }
674
675 typedef SimManager Interface;
676
677 typedef std::tuple<std::string, core::dbus::types::Variant> ArgumentType;
678 };
679
680 struct Present
681 {
682 static const std::string& name()
683 {
684 static const std::string s{"Present"};
685 return s;
686 }
687
688 typedef SimManager Interface;
689 typedef bool ValueType;
690 static const bool readable = true;
691 static const bool writable = false;
692 };
693
694 struct SubscriberIdentity
695 {
696 static const std::string& name()
697 {
698 static const std::string s{"SubscriberIdentity"};
699 return s;
700 }
701
702 typedef SimManager Interface;
703 typedef std::string ValueType;
704 static const bool readable = true;
705 static const bool writable = false;
706 };
707
708 struct SubscriberNumbers
709 {
710 static const std::string& name()
711 {
712 static const std::string s{"SubscriberNumbers"};
713 return s;
714 }
715
716 typedef SimManager Interface;
717 typedef std::vector<std::string> ValueType;
718 static const bool readable = true;
719 static const bool writable = false;
720 };
721
722 SimManager(const std::shared_ptr<core::dbus::Object>& object)
723 : object(object)
724 {
725 }
726
727 template<typename Property>
728 void async_get(const std::function<void(const typename Property::ValueType& result)>& cb) const
729 {
730 object->invoke_method_asynchronously_with_callback<GetProperties, GetProperties::ValueType>(
731 [cb](const core::dbus::Result<GetProperties::ValueType>& result)
732 {
733 if (result.is_error())
734 {
735 LOG(WARNING) << "Failed to query properties: " << result.error().print();
736 return;
737 }
738
739 auto properties = result.value();
740 auto it = properties.find(Property::name());
741
742 if (it == properties.end())
743 {
744 VLOG(1) << "Could not find property for name " << Property::name();
745 return;
746 }
747
748 cb(it->second.template as<typename Property::ValueType>());
749 });
750 }
751
752 std::shared_ptr<core::dbus::Object> object;
753 };
754
643 Modem(const std::shared_ptr<core::dbus::Service>& service,755 Modem(const std::shared_ptr<core::dbus::Service>& service,
644 const std::shared_ptr<core::dbus::Object>& object)756 const std::shared_ptr<core::dbus::Object>& object)
645 : service(service),757 : service(service),
@@ -648,7 +760,8 @@
648 {760 {
649 object->get_signal<PropertyChanged>()761 object->get_signal<PropertyChanged>()
650 },762 },
651 network_registration{object}763 network_registration{object},
764 sim_manager{object}
652 {765 {
653 }766 }
654767
@@ -661,6 +774,7 @@
661 } signals;774 } signals;
662775
663 NetworkRegistration network_registration;776 NetworkRegistration network_registration;
777 SimManager sim_manager;
664 };778 };
665779
666 Manager(const core::dbus::Bus::Ptr& bus)780 Manager(const core::dbus::Bus::Ptr& bus)
667781
=== modified file 'src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp'
--- src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp 2015-12-02 12:00:25 +0000
+++ src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp 2016-03-10 19:55:08 +0000
@@ -126,6 +126,33 @@
126 return d.active_connection_characteristics;126 return d.active_connection_characteristics;
127}127}
128128
129void connectivity::OfonoNmConnectivityManager::enumerate_imsis(const std::function<void(const std::string&)>& cb) const
130{
131 std::lock_guard<std::mutex> lg(d.cached.guard);
132
133 for (const auto& modem : d.cached.modems)
134 {
135 modem.second.sim_manager.async_get<org::Ofono::Manager::Modem::SimManager::SubscriberIdentity>([cb](const std::string& imsi)
136 {
137 cb(imsi);
138 });
139 }
140}
141
142void connectivity::OfonoNmConnectivityManager::enumerate_msisdns(const std::function<void(const std::string&)>& cb) const
143{
144 std::lock_guard<std::mutex> lg(d.cached.guard);
145
146 for (const auto& modem : d.cached.modems)
147 {
148 modem.second.sim_manager.async_get<org::Ofono::Manager::Modem::SimManager::SubscriberNumbers>([cb](const std::vector<std::string>& msisdns)
149 {
150 for (const auto& nr : msisdns)
151 cb(nr);
152 });
153 }
154}
155
129connectivity::OfonoNmConnectivityManager::Private::Private(const core::dbus::Bus::Ptr& bus)156connectivity::OfonoNmConnectivityManager::Private::Private(const core::dbus::Bus::Ptr& bus)
130 : bus{bus},157 : bus{bus},
131 bus_daemon{std::make_shared<core::dbus::DBus>(bus)}158 bus_daemon{std::make_shared<core::dbus::DBus>(bus)}
@@ -340,11 +367,16 @@
340 auto itt = cached.cells.find(path);367 auto itt = cached.cells.find(path);
341 const bool has_cell_for_modem = itt != cached.cells.end();368 const bool has_cell_for_modem = itt != cached.cells.end();
342369
343 auto it = std::find(370 auto itnr = std::find(
344 interfaces.begin(),371 interfaces.begin(),
345 interfaces.end(),372 interfaces.end(),
346 std::string{org::Ofono::Manager::Modem::Properties::Interfaces::network_registration});373 std::string{org::Ofono::Manager::Modem::Properties::Interfaces::network_registration});
347 const bool modem_has_network_registration = it != interfaces.end();374 auto itsm = std::find(
375 interfaces.begin(),
376 interfaces.end(),
377 std::string{org::Ofono::Manager::Modem::Properties::Interfaces::sim_manager});
378 const bool modem_has_network_registration = itnr != interfaces.end();
379 const bool modem_has_sim_manager = itnr != interfaces.end();
348380
349 if (has_cell_for_modem and not modem_has_network_registration)381 if (has_cell_for_modem and not modem_has_network_registration)
350 {382 {
351383
=== modified file 'src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h'
--- src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h 2015-04-27 15:44:40 +0000
+++ src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.h 2016-03-10 19:55:08 +0000
@@ -52,7 +52,7 @@
52namespace dbus = core::dbus;52namespace dbus = core::dbus;
5353
54namespace com { namespace ubuntu { namespace location { namespace connectivity {54namespace com { namespace ubuntu { namespace location { namespace connectivity {
55struct OfonoNmConnectivityManager : public com::ubuntu::location::connectivity::Manager55struct OfonoNmConnectivityManager : public com::ubuntu::location::connectivity::ExtendedManager
56{56{
57 // Creates an instance of the manager, resolving services on the given bus.57 // Creates an instance of the manager, resolving services on the given bus.
58 OfonoNmConnectivityManager(const core::dbus::Bus::Ptr& bus);58 OfonoNmConnectivityManager(const core::dbus::Bus::Ptr& bus);
@@ -82,6 +82,10 @@
8282
83 const core::Property<com::ubuntu::location::connectivity::Characteristics>& active_connection_characteristics() const;83 const core::Property<com::ubuntu::location::connectivity::Characteristics>& active_connection_characteristics() const;
8484
85 void enumerate_imsis(const std::function<void(const std::string&)>&) const override;
86
87 void enumerate_msisdns(const std::function<void(const std::string&)>&) const override;
88
85 struct Private89 struct Private
86 {90 {
87 Private(const core::dbus::Bus::Ptr& bus);91 Private(const core::dbus::Bus::Ptr& bus);
8892
=== modified file 'src/location_service/com/ubuntu/location/providers/gps/CMakeLists.txt'
--- src/location_service/com/ubuntu/location/providers/gps/CMakeLists.txt 2014-07-28 19:14:58 +0000
+++ src/location_service/com/ubuntu/location/providers/gps/CMakeLists.txt 2016-03-10 19:55:08 +0000
@@ -4,30 +4,34 @@
4 ON4 ON
5)5)
66
7if (LOCATION_SERVICE_ENABLE_GPS_PROVIDER)7if ((LOCATION_SERVICE_ENABLE_GPS_PROVIDER) AND (UBUNTU_PLATFORM_HARDWARE_API_FOUND))
8 find_file(
9 UBUNTU_HARDWARE_GPS_H gps.h
10 NAMES ubuntu/hardware/gps.h
11 )
12
13 if (UBUNTU_HARDWARE_GPS_H)
14 message(STATUS "Enabling GPS location provider")8 message(STATUS "Enabling GPS location provider")
159
10 include_directories(${UBUNTU_PLATFORM_HARDWARE_API_INCLUDE_DIRS})
11
16 add_library(12 add_library(
17 gps13 gps
1814
19 gps.conf15 gps.conf
2016
17 hardware_abstraction_layer.cpp
18
21 android_hardware_abstraction_layer.h19 android_hardware_abstraction_layer.h
22 android_hardware_abstraction_layer.cpp20 android_hardware_abstraction_layer.cpp
2321
22 sntp_reference_time_source.h
23 sntp_reference_time_source.cpp
24
25 sntp_client.h
26 sntp_client.cpp
27
24 hardware_abstraction_layer.h28 hardware_abstraction_layer.h
25 # hardware_abstraction_layer.cpp29 # hardware_abstraction_layer.cpp
2630
27 provider.h31 provider.h
28 provider.cpp)32 provider.cpp)
2933
30 target_link_libraries(gps ubuntu_platform_hardware_api.so)34 target_link_libraries(gps ${UBUNTU_PLATFORM_HARDWARE_API_LDFLAGS})
31 35
32 set(36 set(
33 ENABLED_PROVIDER_TARGETS37 ENABLED_PROVIDER_TARGETS
@@ -41,5 +45,4 @@
41 )45 )
4246
43 install(FILES gps.conf DESTINATION /etc/)47 install(FILES gps.conf DESTINATION /etc/)
44 endif (UBUNTU_HARDWARE_GPS_H)48endif ()
45endif (LOCATION_SERVICE_ENABLE_GPS_PROVIDER)
4649
=== modified file 'src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp'
--- src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp 2015-11-13 10:19:29 +0000
+++ src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp 2016-03-10 19:55:08 +0000
@@ -17,6 +17,7 @@
17 */17 */
1818
19#include "android_hardware_abstraction_layer.h"19#include "android_hardware_abstraction_layer.h"
20#include "sntp_reference_time_source.h"
2021
21#if defined(COM_UBUNTU_LOCATION_SERVICE_HAVE_NET_CPP)22#if defined(COM_UBUNTU_LOCATION_SERVICE_HAVE_NET_CPP)
22#include "net_cpp_gps_xtra_downloader.h"23#include "net_cpp_gps_xtra_downloader.h"
@@ -93,6 +94,44 @@
93 return impl.server_ip;94 return impl.server_ip;
94}95}
9596
97void android::HardwareAbstractionLayer::SuplAssistant::set_set_id(SetIdType type, const std::string& id) const
98{
99 u_hardware_gps_agps_set_set_id(
100 impl.hal.impl.gps_handle,
101 static_cast<UHardwareGpsAgpsSetIdType>(type),
102 id.c_str());
103}
104
105
106void android::HardwareAbstractionLayer::SuplAssistant::inject_radio_cell_information(const location::connectivity::RadioCell& cell) const
107{
108 UHardwareGpsAGpsRefLocation ref_loc;
109 switch (cell.type())
110 {
111 case location::connectivity::RadioCell::Type::gsm:
112 ref_loc.type = U_HARDWARE_GPS_AGPS_REF_LOCATION_TYPE_GSM_CELLID;
113 ref_loc.u.cellID.mcc = cell.gsm().mobile_country_code;
114 ref_loc.u.cellID.mnc = cell.gsm().mobile_network_code;
115 ref_loc.u.cellID.lac = cell.gsm().location_area_code;
116 ref_loc.u.cellID.cid = cell.gsm().id;
117 break;
118 case location::connectivity::RadioCell::Type::umts:
119 ref_loc.type = U_HARDWARE_GPS_AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
120 ref_loc.u.cellID.mcc = cell.umts().mobile_country_code;
121 ref_loc.u.cellID.mnc = cell.umts().mobile_network_code;
122 ref_loc.u.cellID.lac = cell.umts().location_area_code;
123 ref_loc.u.cellID.cid = cell.umts().id;
124 break;
125 default:
126 return;
127 }
128
129 u_hardware_gps_agps_set_reference_location(
130 impl.hal.impl.gps_handle,
131 &ref_loc,
132 sizeof(ref_loc));
133}
134
96void android::HardwareAbstractionLayer::SuplAssistant::set_server(const std::string& host_name, std::uint16_t port)135void android::HardwareAbstractionLayer::SuplAssistant::set_server(const std::string& host_name, std::uint16_t port)
97{136{
98 // TODO(tvoss): Reenable this once the platform api HAL changes land.137 // TODO(tvoss): Reenable this once the platform api HAL changes land.
@@ -169,16 +208,47 @@
169208
170void android::HardwareAbstractionLayer::on_ril_request_set_id(uint32_t flags, void* context)209void android::HardwareAbstractionLayer::on_ril_request_set_id(uint32_t flags, void* context)
171{210{
172 VLOG(1) << __PRETTY_FUNCTION__ << ": "211 VLOG(1) << __PRETTY_FUNCTION__ << ": " << "flags=" << flags << " " << "context=" << context;
173 << "flags=" << flags << " "212
174 << "context=" << context;213 if (auto thiz = static_cast<android::HardwareAbstractionLayer*>(context))
214 {
215 switch (flags)
216 {
217 case U_HARDWARE_GPS_AGPS_REQUEST_SETID_IMSI:
218 thiz->impl.connectivity_manager->enumerate_imsis([thiz](const std::string& imsi)
219 {
220 thiz->impl.supl_assistant.set_set_id(SuplAssistant::SetIdType::imsi, imsi);
221 });
222 break;
223 case U_HARDWARE_GPS_AGPS_REQUEST_SETID_MSISDN:
224 thiz->impl.connectivity_manager->enumerate_msisdns([thiz](const std::string& msisdn)
225 {
226 thiz->impl.supl_assistant.set_set_id(SuplAssistant::SetIdType::msisdn, msisdn);
227 });
228 break;
229 }
230 }
175}231}
176232
177void android::HardwareAbstractionLayer::on_ril_request_reference_location(uint32_t flags, void* context)233void android::HardwareAbstractionLayer::on_ril_request_reference_location(uint32_t flags, void* context)
178{234{
179 VLOG(1) << __PRETTY_FUNCTION__ << ": "235 VLOG(1) << __PRETTY_FUNCTION__ << ": " << "flags=" << flags << " " << "context=" << context;
180 << "flags=" << flags << " "236
181 << "context=" << context;237 if (auto thiz = static_cast<android::HardwareAbstractionLayer*>(context))
238 {
239 switch (flags)
240 {
241 case U_HARDWARE_GPS_AGPS_REQUEST_REFLOC_CELLID:
242 thiz->impl.connectivity_manager->enumerate_connected_radio_cells([thiz](const connectivity::RadioCell::Ptr& cell)
243 {
244 thiz->impl.supl_assistant.inject_radio_cell_information(*cell);
245 });
246 break;
247 case U_HARDWARE_GPS_AGPS_REQUEST_REFLOC_MAC:
248 default:
249 break;
250 }
251 }
182}252}
183253
184void android::HardwareAbstractionLayer::on_location_update(UHardwareGpsLocation* location, void* context)254void android::HardwareAbstractionLayer::on_location_update(UHardwareGpsLocation* location, void* context)
@@ -323,23 +393,18 @@
323{393{
324 VLOG(1) << __PRETTY_FUNCTION__;394 VLOG(1) << __PRETTY_FUNCTION__;
325395
326 auto thiz = static_cast<android::HardwareAbstractionLayer*>(context);396 try
327397 {
328 if (thiz->impl.utc_time_request_handler)398 if (auto thiz = static_cast<android::HardwareAbstractionLayer*>(context))
329 {399 thiz->inject_reference_time(thiz->impl.reference_time_source->sample());
330 thiz->impl.utc_time_request_handler();400 }
331 } else401 catch (const std::runtime_error& e)
332 {402 {
333 auto now = location::Clock::now().time_since_epoch();403 LOG(WARNING) << "Failed to inject reference time to chipset: " << e.what();
334 auto ms_since_epoch = std::chrono::duration_cast<std::chrono::milliseconds>(now);404 }
335405 catch (...)
336 static const int zero_uncertainty = 0;406 {
337407 LOG(WARNING) << "Failed to inject reference time to chipset.";
338 u_hardware_gps_inject_time(
339 thiz->impl.gps_handle,
340 ms_since_epoch.count(),
341 ms_since_epoch.count(),
342 zero_uncertainty);
343 }408 }
344}409}
345410
@@ -534,19 +599,22 @@
534 return true;599 return true;
535}600}
536601
537bool android::HardwareAbstractionLayer::inject_reference_time(602bool android::HardwareAbstractionLayer::inject_reference_time(const ReferenceTimeSample& sample)
538 const std::chrono::microseconds& reference_time,
539 const std::chrono::microseconds& sample_time)
540{603{
541 if (!is_capable_of(gps::Capability::on_demand_time_injection))604 if (!is_capable_of(gps::Capability::on_demand_time_injection))
542 return false;605 return false;
543606
544 // TODO(tvoss): We should expose the int return type of the underyling607 // TODO(tvoss): We should expose the int return type of the underyling
545 // Android HAL to capture errors here.608 // Android HAL to capture errors here.
609 //
610 // Please see:
611 // http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/net/SntpClient.java#72
612 // for the bloody details of relating the system wall clock time to the elapsed realtime since boot
613 // including deep sleep.
546 u_hardware_gps_inject_time(impl.gps_handle,614 u_hardware_gps_inject_time(impl.gps_handle,
547 reference_time.count(),615 sample.since_epoch.count(),
548 sample_time.count(),616 sample.since_boot.count(),
549 10);617 sample.uncertainty.count());
550 return true;618 return true;
551}619}
552620
@@ -557,6 +625,8 @@
557 assistance_mode(gps::AssistanceMode::mobile_station_based),625 assistance_mode(gps::AssistanceMode::mobile_station_based),
558 position_mode(gps::PositionMode::periodic),626 position_mode(gps::PositionMode::periodic),
559 supl_assistant(*parent),627 supl_assistant(*parent),
628 connectivity_manager(configuration.connectivity_manager),
629 reference_time_source(configuration.reference_time_source),
560 gps_xtra_configuration(configuration.gps_xtra.configuration),630 gps_xtra_configuration(configuration.gps_xtra.configuration),
561 gps_xtra_downloader(configuration.gps_xtra.downloader)631 gps_xtra_downloader(configuration.gps_xtra.downloader)
562{632{
@@ -615,6 +685,22 @@
615685
616namespace686namespace
617{687{
688gps::SntpReferenceTimeSource::Configuration sntp_reference_time_source_configuration(std::istream& in)
689{
690 gps::SntpReferenceTimeSource::Configuration config;
691
692 try
693 {
694 config = gps::SntpReferenceTimeSource::Configuration::from_gps_conf_ini_file(in);
695 }
696 catch (...)
697 {
698 // Consciously dropping all exceptions here.
699 }
700
701 return config;
702}
703
618android::GpsXtraDownloader::Configuration gps_xtra_downloader_configuration(std::istream& in)704android::GpsXtraDownloader::Configuration gps_xtra_downloader_configuration(std::istream& in)
619{705{
620 android::GpsXtraDownloader::Configuration config;706 android::GpsXtraDownloader::Configuration config;
@@ -641,6 +727,8 @@
641727
642 return config;728 return config;
643}729}
730
731
644}732}
645733
646std::shared_ptr<gps::HardwareAbstractionLayer> gps::HardwareAbstractionLayer::create_default_instance()734std::shared_ptr<gps::HardwareAbstractionLayer> gps::HardwareAbstractionLayer::create_default_instance()
@@ -664,7 +752,9 @@
664 {752 {
665 create_xtra_downloader(),753 create_xtra_downloader(),
666 gps_xtra_downloader_configuration((in_system_gps_conf ? in_system_gps_conf : in_gps_conf))754 gps_xtra_downloader_configuration((in_system_gps_conf ? in_system_gps_conf : in_gps_conf))
667 }755 },
756 std::dynamic_pointer_cast<connectivity::ExtendedManager>(connectivity::platform_default_manager()),
757 std::make_shared<gps::SntpReferenceTimeSource>(sntp_reference_time_source_configuration((in_system_gps_conf ? in_system_gps_conf : in_gps_conf)))
668 };758 };
669759
670 static std::shared_ptr<gps::HardwareAbstractionLayer> instance760 static std::shared_ptr<gps::HardwareAbstractionLayer> instance
671761
=== modified file 'src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h'
--- src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h 2015-11-13 10:19:29 +0000
+++ src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h 2016-03-10 19:55:08 +0000
@@ -19,6 +19,9 @@
19#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_ANDROID_HARDWARE_ABSTRACTION_LAYER_H_19#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_ANDROID_HARDWARE_ABSTRACTION_LAYER_H_
2020
21#include <com/ubuntu/location/providers/gps/hardware_abstraction_layer.h>21#include <com/ubuntu/location/providers/gps/hardware_abstraction_layer.h>
22#include <com/ubuntu/location/providers/gps/sntp_client.h>
23
24#include <com/ubuntu/location/connectivity/manager.h>
2225
23#include <ubuntu/hardware/gps.h>26#include <ubuntu/hardware/gps.h>
2427
@@ -66,7 +69,24 @@
66};69};
6770
68struct HardwareAbstractionLayer : public gps::HardwareAbstractionLayer71struct HardwareAbstractionLayer : public gps::HardwareAbstractionLayer
69{72{
73 /** @brief A ReferenceTimeSource provides samples of an arbitrary reference time source. */
74 class ReferenceTimeSource
75 {
76 public:
77 /** @cond */
78 typedef std::shared_ptr<ReferenceTimeSource> Ptr;
79
80 virtual ~ReferenceTimeSource() = default;
81 /** @endcond */
82
83 /** @brief sample returns a sample of the current ReferenceTimeSource. */
84 virtual ReferenceTimeSample sample() = 0;
85
86 protected:
87 ReferenceTimeSource() = default;
88 };
89
70 /** @brief Implements gps::HardwareAbstractionLayer::SuplAssistant interface for the android gps HAL. */90 /** @brief Implements gps::HardwareAbstractionLayer::SuplAssistant interface for the android gps HAL. */
71 struct SuplAssistant : public gps::HardwareAbstractionLayer::SuplAssistant91 struct SuplAssistant : public gps::HardwareAbstractionLayer::SuplAssistant
72 {92 {
@@ -74,6 +94,10 @@
74 SuplAssistant(android::HardwareAbstractionLayer& hal);94 SuplAssistant(android::HardwareAbstractionLayer& hal);
75 /** @brief Getable/observable access to the status of the assistant instance. */95 /** @brief Getable/observable access to the status of the assistant instance. */
76 const core::Property<Status>& status() const override;96 const core::Property<Status>& status() const override;
97 /** @brief Sets mobile subscriber identity. */
98 void set_set_id(SetIdType type, const std::string& id) const override;
99 /** @brief Injects reference location information. */
100 void inject_radio_cell_information(const connectivity::RadioCell& radio_cell) const override;
77 /** @brief Getable/setable/observable access to the status of the assistant instance. */101 /** @brief Getable/setable/observable access to the status of the assistant instance. */
78 core::Property<Status>& status();102 core::Property<Status>& status();
79 /** @brief Getable/observable access to the ip the assistance instance uses. */103 /** @brief Getable/observable access to the ip the assistance instance uses. */
@@ -186,6 +210,9 @@
186 std::shared_ptr<GpsXtraDownloader> downloader;210 std::shared_ptr<GpsXtraDownloader> downloader;
187 GpsXtraDownloader::Configuration configuration;211 GpsXtraDownloader::Configuration configuration;
188 } gps_xtra;212 } gps_xtra;
213
214 std::shared_ptr<connectivity::ExtendedManager> connectivity_manager;
215 ReferenceTimeSource::Ptr reference_time_source;
189 };216 };
190217
191 HardwareAbstractionLayer(const Configuration& configuration);218 HardwareAbstractionLayer(const Configuration& configuration);
@@ -227,8 +254,8 @@
227 bool set_position_mode(gps::PositionMode mode) override;254 bool set_position_mode(gps::PositionMode mode) override;
228255
229 bool inject_reference_position(const location::Position& position) override;256 bool inject_reference_position(const location::Position& position) override;
230 bool inject_reference_time(const std::chrono::microseconds& reference_time,257 bool inject_reference_time(const ReferenceTimeSample& sample) override;
231 const std::chrono::microseconds& sample_time) override;258
232 struct Impl259 struct Impl
233 {260 {
234 // Bootstraps access to the GPS chipset, wiring up all callbacks.261 // Bootstraps access to the GPS chipset, wiring up all callbacks.
@@ -252,8 +279,10 @@
252 // An implementation of the gps::HardwareAbstractionLayer::SuplAssistant interface.279 // An implementation of the gps::HardwareAbstractionLayer::SuplAssistant interface.
253 SuplAssistant supl_assistant;280 SuplAssistant supl_assistant;
254281
255 // Callback for handling utc time requests.282 // An implementation of connectivity::Manager.
256 gps::HardwareAbstractionLayer::UtcTimeRequestHandler utc_time_request_handler;283 std::shared_ptr<connectivity::ExtendedManager> connectivity_manager;
284 // An implementation of ReferenceTimeSource.
285 ReferenceTimeSource::Ptr reference_time_source;
257286
258 // Emitted whenever the set of visible space vehicles changes.287 // Emitted whenever the set of visible space vehicles changes.
259 core::Signal<std::set<location::SpaceVehicle>> space_vehicle_updates;288 core::Signal<std::set<location::SpaceVehicle>> space_vehicle_updates;
260289
=== added file 'src/location_service/com/ubuntu/location/providers/gps/hardware_abstraction_layer.cpp'
--- src/location_service/com/ubuntu/location/providers/gps/hardware_abstraction_layer.cpp 1970-01-01 00:00:00 +0000
+++ src/location_service/com/ubuntu/location/providers/gps/hardware_abstraction_layer.cpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,30 @@
1/*
2 * Copyright © 2012-2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */
18
19#include <com/ubuntu/location/providers/gps/hardware_abstraction_layer.h>
20
21#include <iostream>
22
23namespace gps = com::ubuntu::location::providers::gps;
24
25std::ostream& gps::operator<<(std::ostream& out, const gps::HardwareAbstractionLayer::ReferenceTimeSample& sample)
26{
27 return out << "[since epoch: " << sample.since_epoch.count() << " [ms], since boot: "
28 << sample.since_boot.count() << " [ms], uncertainty: "
29 << sample.uncertainty.count() << " [ms]";
30}
031
=== modified file 'src/location_service/com/ubuntu/location/providers/gps/hardware_abstraction_layer.h'
--- src/location_service/com/ubuntu/location/providers/gps/hardware_abstraction_layer.h 2014-06-06 17:52:59 +0000
+++ src/location_service/com/ubuntu/location/providers/gps/hardware_abstraction_layer.h 2016-03-10 19:55:08 +0000
@@ -18,11 +18,14 @@
18#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_HARDWARE_ABSTRACTION_LAYER_H_18#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_HARDWARE_ABSTRACTION_LAYER_H_
19#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_HARDWARE_ABSTRACTION_LAYER_H_19#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_HARDWARE_ABSTRACTION_LAYER_H_
2020
21#include <com/ubuntu/location/clock.h>
21#include <com/ubuntu/location/heading.h>22#include <com/ubuntu/location/heading.h>
22#include <com/ubuntu/location/position.h>23#include <com/ubuntu/location/position.h>
23#include <com/ubuntu/location/space_vehicle.h>24#include <com/ubuntu/location/space_vehicle.h>
24#include <com/ubuntu/location/velocity.h>25#include <com/ubuntu/location/velocity.h>
2526
27#include <com/ubuntu/location/connectivity/radio_cell.h>
28
26#include <core/property.h>29#include <core/property.h>
2730
28#include <chrono>31#include <chrono>
@@ -104,6 +107,13 @@
104class HardwareAbstractionLayer107class HardwareAbstractionLayer
105{108{
106public:109public:
110 /** @brief ReferenceTimeSample bundles together the local reference. */
111 struct ReferenceTimeSample
112 {
113 std::chrono::milliseconds since_epoch; /**< Reference wall-clock time since the epoch (UTC). */
114 std::chrono::milliseconds since_boot; /**< Reference time since boot. */
115 std::chrono::milliseconds uncertainty; /**< Uncertainty estimate of the sample. */
116 };
107117
108 class SuplAssistant118 class SuplAssistant
109 {119 {
@@ -148,6 +158,16 @@
148 data_connection_failed = 5158 data_connection_failed = 5
149 };159 };
150160
161 /**
162 * @brief The SetIdType enum enumerates all valid types of SetIds.
163 */
164 enum class SetIdType
165 {
166 none,
167 imsi,
168 msisdn
169 };
170
151 virtual ~SuplAssistant() = default;171 virtual ~SuplAssistant() = default;
152 SuplAssistant(const SuplAssistant&) = delete;172 SuplAssistant(const SuplAssistant&) = delete;
153173
@@ -165,6 +185,16 @@
165 virtual const core::Property<IpV4Address>& server_ip() const = 0;185 virtual const core::Property<IpV4Address>& server_ip() const = 0;
166186
167 /**187 /**
188 * @brief Sets mobile subscriber identity.
189 */
190 virtual void set_set_id(SetIdType type, const std::string& id) const = 0;
191
192 /**
193 * @brief Injects reference location information.
194 */
195 virtual void inject_radio_cell_information(const connectivity::RadioCell& radio_cell) const = 0;
196
197 /**
168 * @brief set_server informs the assistant instance about the SUPL server it should talk to.198 * @brief set_server informs the assistant instance about the SUPL server it should talk to.
169 * @param host_name The host name of the SUPL server.199 * @param host_name The host name of the SUPL server.
170 * @param port The port of the SUPL server.200 * @param port The port of the SUPL server.
@@ -304,16 +334,17 @@
304334
305 /**335 /**
306 * @brief Injects a new reference time to the underlying gps driver/chipset.336 * @brief Injects a new reference time to the underlying gps driver/chipset.
307 * @param reference_time The new reference time.337 * @param sample The reference time sample
308 * @param sample_time When the reference time was sampled.
309 * @return true iff the injection was successful, false otherwise.338 * @return true iff the injection was successful, false otherwise.
310 */339 */
311 virtual bool inject_reference_time(const std::chrono::microseconds& reference_time,340 virtual bool inject_reference_time(const ReferenceTimeSample& sample) = 0;
312 const std::chrono::microseconds& sample_time) = 0;
313341
314protected:342protected:
315 HardwareAbstractionLayer() = default;343 HardwareAbstractionLayer() = default;
316};344};
345
346/** @brief operator<< inserts sample into out. */
347std::ostream& operator<<(std::ostream& out, const HardwareAbstractionLayer::ReferenceTimeSample& sample);
317}348}
318}349}
319}350}
320351
=== added file 'src/location_service/com/ubuntu/location/providers/gps/sntp_client.cpp'
--- src/location_service/com/ubuntu/location/providers/gps/sntp_client.cpp 1970-01-01 00:00:00 +0000
+++ src/location_service/com/ubuntu/location/providers/gps/sntp_client.cpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,210 @@
1/*
2 * Copyright © 2012-2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */
18
19#include <com/ubuntu/location/providers/gps/sntp_client.h>
20
21#include <com/ubuntu/location/time_since_boot.h>
22
23#include <boost/asio/ip/udp.hpp>
24#include <boost/endian/buffers.hpp>
25
26#include <bitset>
27#include <fstream>
28#include <future>
29#include <iostream>
30#include <thread>
31
32namespace location = com::ubuntu::location;
33namespace gps = location::providers::gps;
34namespace ip = boost::asio::ip;
35
36namespace
37{
38
39template<typename T>
40T sync_or_throw(std::future<T>& f)
41{
42 return f.get();
43}
44
45template<>
46void sync_or_throw<>(std::future<void>& f)
47{
48 f.get();
49}
50
51struct Now
52{
53 std::chrono::nanoseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(
54 std::chrono::system_clock::now().time_since_epoch());
55 std::chrono::nanoseconds ticks = location::time_since_boot();
56};
57}
58
59const std::chrono::seconds& gps::sntp::offset_1900_to_1970()
60{
61 static const std::uint64_t secs = ((365ull * 70ull) + 17ull) * 24ull * 60ull * 60ull;
62 static const std::chrono::seconds seconds{secs};
63 return seconds;
64}
65
66gps::sntp::LeapIndicator gps::sntp::Packet::LeapIndicatorVersionMode::leap_indicator() const
67{
68 return static_cast<LeapIndicator>((livm.value() >> 6) & 0x3);
69}
70
71gps::sntp::Packet::LeapIndicatorVersionMode& gps::sntp::Packet::LeapIndicatorVersionMode::leap_indicator(LeapIndicator li)
72{
73 livm = livm.value() | (static_cast<uint8_t>(li) << 6);
74 return *this;
75}
76
77std::uint8_t gps::sntp::Packet::LeapIndicatorVersionMode::version() const
78{
79 return (livm.value() >> 3) & 0x7;
80}
81
82gps::sntp::Packet::LeapIndicatorVersionMode& gps::sntp::Packet::LeapIndicatorVersionMode::version(std::uint8_t version)
83{
84 livm = livm.value() | (version << 3);
85 return *this;
86}
87
88gps::sntp::Mode gps::sntp::Packet::LeapIndicatorVersionMode::mode() const
89{
90 return static_cast<Mode>(livm.value() & 0x7);
91}
92
93gps::sntp::Packet::LeapIndicatorVersionMode& gps::sntp::Packet::LeapIndicatorVersionMode::mode(Mode m)
94{
95 livm = static_cast<uint8_t>(m) | livm.value();
96 return *this;
97}
98
99gps::sntp::Client::Response gps::sntp::Client::request_time(const std::string& host, const std::chrono::milliseconds& timeout, boost::asio::io_service& ios)
100{
101 ip::udp::resolver resolver{ios};
102 ip::udp::socket socket{ios};
103 bool timed_out{false};
104
105 std::promise<ip::udp::resolver::iterator> promise_resolve;
106 auto future_resolve= promise_resolve.get_future();
107
108 boost::asio::deadline_timer timer{ios};
109 timer.expires_from_now(boost::posix_time::milliseconds{timeout.count()});
110 timer.async_wait([&timed_out, &resolver, &socket](const boost::system::error_code& ec)
111 {
112 if (ec)
113 return;
114
115 timed_out = true;
116
117 resolver.cancel();
118 socket.shutdown(ip::udp::socket::shutdown_both);
119 socket.close();
120 });
121
122 ip::udp::resolver::query query{ip::udp::v4(), host, "ntp"};
123
124 resolver.async_resolve(query, [&promise_resolve](const boost::system::error_code& ec, ip::udp::resolver::iterator it)
125 {
126 if (ec)
127 promise_resolve.set_exception(std::make_exception_ptr(boost::system::system_error(ec)));
128 else
129 promise_resolve.set_value(it);
130 });
131
132 auto it = sync_or_throw(future_resolve);
133
134 std::promise<void> promise_connect;
135 auto future_connect = promise_connect.get_future();
136
137 socket.async_connect(*it, [&promise_connect](const boost::system::error_code& ec)
138 {
139 if (ec)
140 promise_connect.set_exception(std::make_exception_ptr(boost::system::system_error(ec)));
141 else
142 promise_connect.set_value();
143 });
144
145 sync_or_throw(future_connect);
146
147 sntp::Packet packet;
148
149 Now before;
150 {
151 packet = request(socket);
152 timer.cancel();
153
154 if (timed_out)
155 throw std::runtime_error("Operation timed out.");
156 }
157 Now after;
158
159 auto originate = packet.originate.to_milliseconds_since_epoch();
160 auto receive = packet.receive.to_milliseconds_since_epoch();
161 auto transmit = packet.transmit.to_milliseconds_since_epoch();
162
163 auto rtt = after.ticks - before.ticks - (transmit - receive);
164 auto offset = ((receive - originate) + (transmit - after.time))/2;
165
166 return
167 {
168 packet,
169 std::chrono::duration_cast<std::chrono::milliseconds>(after.time + offset),
170 std::chrono::duration_cast<std::chrono::milliseconds>(after.ticks),
171 std::chrono::duration_cast<std::chrono::milliseconds>(rtt)
172 };
173}
174
175gps::sntp::Packet gps::sntp::Client::request(boost::asio::ip::udp::socket& socket)
176{
177 sntp::Packet packet;
178 packet.transmit.from_milliseconds_since_epoch(
179 std::chrono::duration_cast<std::chrono::milliseconds>(
180 std::chrono::system_clock::now().time_since_epoch()));
181 packet.livm.mode(sntp::Mode::client).version(sntp::version);
182
183 std::promise<std::size_t> promise_send;
184 auto future_send = promise_send.get_future();
185
186 socket.async_send(boost::asio::buffer(&packet, sizeof(packet)), [&promise_send](const boost::system::error_code& ec, std::size_t transferred)
187 {
188 if (ec)
189 promise_send.set_exception(std::make_exception_ptr(boost::system::system_error(ec)));
190 else
191 promise_send.set_value(transferred);
192 });
193
194 sync_or_throw(future_send);
195
196 std::promise<std::size_t> promise_receive;
197 auto future_receive = promise_receive.get_future();
198
199 socket.async_receive(boost::asio::buffer(&packet, sizeof(packet)), [&promise_receive](const boost::system::error_code& ec, std::size_t transferred)
200 {
201 if (ec)
202 promise_receive.set_exception(std::make_exception_ptr(boost::system::system_error(ec)));
203 else
204 promise_receive.set_value(transferred);
205 });
206
207 sync_or_throw(future_receive);
208
209 return packet;
210}
0211
=== added file 'src/location_service/com/ubuntu/location/providers/gps/sntp_client.h'
--- src/location_service/com/ubuntu/location/providers/gps/sntp_client.h 1970-01-01 00:00:00 +0000
+++ src/location_service/com/ubuntu/location/providers/gps/sntp_client.h 2016-03-10 19:55:08 +0000
@@ -0,0 +1,210 @@
1/*
2 * Copyright © 2012-2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */
18#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_SNTP_CLIENT_H_
19#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_SNTP_CLIENT_H_
20
21#include <com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h>
22
23#include <boost/asio.hpp>
24#include <boost/endian/buffers.hpp>
25
26#include <chrono>
27#include <string>
28
29namespace com { namespace ubuntu { namespace location { namespace providers { namespace gps { namespace sntp {
30// Please see https://tools.ietf.org/html/rfc4330 for a discussion of sntp
31// and for a detailed explanation of the different types and algorithms.
32
33namespace detail
34{
35// enum_constant returns a compile-time constant assembled from 4 or at least
36// 3 individual characters.
37template<std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d = 0>
38constexpr uint32_t enum_constant()
39{
40 return (a << 24) | (b << 16) | (c << 8) | d;
41}
42}
43
44// offset_1900_to_1970 returns the number of seconds that elapsed between 1900 and 1970.
45const std::chrono::seconds& offset_1900_to_1970();
46
47// LeapIndicator enumerates warnings of an impending
48// leap second to be inserted/deleted in the last minute of the current
49// day.
50enum class LeapIndicator : std::uint8_t
51{
52 no_warning = 0,
53 last_minute_has_61_seconds = 1,
54 last_minute_has_59_seconds = 2,
55 alarm = 3
56};
57
58// Mode enumerates the different protocol modes.
59enum class Mode : std::uint8_t
60{
61 reserved = 0,
62 symmetric_active = 1,
63 symmetric_passive = 2,
64 client = 3,
65 server = 4,
66 broadcast = 5,
67 reserved_for_control = 6,
68 reserved_for_private_use = 7
69};
70
71// ReferenceIdentifier enumerates known references for NTP-servers
72// on stratum 0 or 1.
73enum class ReferenceIdentifier : std::uint32_t
74{
75 locl = detail::enum_constant<'L','O','C','L'>(), // uncalibrated local clock
76 cesm = detail::enum_constant<'C','E','S','M'>(), // calibrated Cesium clock
77 rbdm = detail::enum_constant<'R','B','D','M'>(), // calibrated Rubidium clock
78 pps = detail::enum_constant<'P','P','S'>(), // calibrated quartz clock or other pulse-per-second source
79 irig = detail::enum_constant<'I','R','I','G'>(), // Inter-Range Instrumentation Group
80 acts = detail::enum_constant<'A','C','T','S'>(), // NIST telephone modem service
81 usno = detail::enum_constant<'U','S','N','O'>(), // USNO telephone modem service
82 ptb = detail::enum_constant<'P','T','B'>(), // PTB (Germany) telephone modem service
83 tdf = detail::enum_constant<'T','D','F'>(), // Allouis (France) Radio 164 kHz
84 dcf = detail::enum_constant<'D','C','F'>(), // Mainflingen (Germany) Radio 77.5 kHz
85 msf = detail::enum_constant<'M','S', 'F'>(), // Rugby (UK) Radio 60 kHz
86 wwv = detail::enum_constant<'W','W','V'>(), // Ft. Collins (US) Radio 2.5, 5, 10, 15, 20 MHz
87 wwvb = detail::enum_constant<'W','W','V','B'>(), // Boulder (US) Radio 60 kHz
88 wwvh = detail::enum_constant<'W','W','V','H'>(), // Kauai Hawaii (US) Radio 2.5, 5, 10, 15 MHz
89 chu = detail::enum_constant<'C','H','U'>(), // Ottawa (Canada) Radio 3330, 7335, 14670 kHz
90 lorc = detail::enum_constant<'L','O','R','C'>(), // LORAN-C radionavigation system
91 omeg = detail::enum_constant<'O','M','E','G'>(), // OMEGA radionavigation system
92 gps = detail::enum_constant<'G','P','S'>() // Global Positioning Service
93};
94
95// Timestamp models a fixed-point NTP timestamp relative to 01.01.1900
96template<typename Seconds, typename FractionalSeconds = Seconds>
97struct Timestamp
98{
99 // To stay on the safe side, we only allow for the types specified below.
100 // With that, we make sure that we only ever use endian-save types.
101 static_assert(std::is_same<Seconds, boost::endian::big_int16_buf_t>::value ||
102 std::is_same<Seconds, boost::endian::big_uint16_buf_t>::value ||
103 std::is_same<Seconds, boost::endian::big_int32_buf_t>::value ||
104 std::is_same<Seconds, boost::endian::big_uint32_buf_t>::value,
105 "Timestamp<> only supports boost::endian::big_{{u}int{16,32}}_buf_t");
106
107 // from_milliseconds_since_epoch fills in seconds/fractional_seconds from
108 // ms, converting to NTP's reference time.
109 void from_milliseconds_since_epoch(const std::chrono::milliseconds& ts)
110 {
111 using s = std::chrono::seconds;
112 using ms = std::chrono::milliseconds;
113
114 auto secs = std::chrono::duration_cast<s>(ts);
115 auto msecs = std::chrono::duration_cast<ms>(ts - secs);
116
117 secs += offset_1900_to_1970();
118
119 seconds = secs.count();
120 fractional_seconds = msecs.count() * std::numeric_limits<typename FractionalSeconds::value_type>::max() + 1 / 1000;
121 }
122
123 // to_milliseconds_since_epoch returns a unix timestamp calculated from
124 // an NTP-timestamp.
125 std::chrono::milliseconds to_milliseconds_since_epoch() const
126 {
127 return std::chrono::seconds{seconds.value()} - offset_1900_to_1970() +
128 std::chrono::milliseconds{(fractional_seconds.value() * 1000) / std::numeric_limits<typename FractionalSeconds::value_type>::max()};
129 }
130
131 Seconds seconds;
132 FractionalSeconds fractional_seconds;
133};
134
135// Duration is just an alias to an sntp::Timestamp.
136template<typename T, typename U>
137using Duration = Timestamp<T, U>;
138
139// Packet models the SNTP wire format.
140struct Packet
141{
142 // LeapIndicatorVersionMode helps in handling the bitfield setup
143 // for the first byte of an sntp::Packet in a portable and endianess-safe way.
144 struct LeapIndicatorVersionMode
145 {
146 // leap_indicator extracts the LeapIndicator from the underlying data.
147 LeapIndicator leap_indicator() const;
148 // leap_indicator sets the value of the leap_indicatorin in the underyling
149 // data to li.
150 LeapIndicatorVersionMode& leap_indicator(LeapIndicator li);
151
152 // version extracts the version from the underlying data.
153 std::uint8_t version() const;
154 // version adjusts the version to version in the underlying data.
155 LeapIndicatorVersionMode& version(std::uint8_t version);
156
157 // mode extracts the mode from the underlying data.
158 Mode mode() const;
159 // mode adjusts the mode to m in the underlying data.
160 LeapIndicatorVersionMode& mode(Mode m);
161
162 boost::endian::big_uint8_buf_t livm;
163 };
164
165 LeapIndicatorVersionMode livm;
166 boost::endian::big_uint8_buf_t stratum;
167 boost::endian::big_uint8_buf_t poll_interval;
168 boost::endian::big_int8_buf_t precision;
169 Duration<boost::endian::big_int16_buf_t, boost::endian::big_uint16_buf_t> root_delay;
170 Duration<boost::endian::big_uint16_buf_t, boost::endian::big_uint16_buf_t> root_dispersion;
171 boost::endian::big_uint32_buf_t reference_identifier;
172 Timestamp<boost::endian::big_uint32_buf_t> reference;
173 Timestamp<boost::endian::big_uint32_buf_t> originate;
174 Timestamp<boost::endian::big_uint32_buf_t> receive;
175 Timestamp<boost::endian::big_uint32_buf_t> transmit;
176};
177// The SNTP version we are working with.
178static constexpr const std::uint8_t version = 3;
179
180// SntpClient provides access to querying time from an NTP server in
181// a unicast scenario.
182class Client
183{
184public:
185 // Response is returned in a request for time information.
186 struct Response
187 {
188 // The raw packet that was returned from the request.
189 sntp::Packet packet;
190 // Time computed from the NTP transaction.
191 std::chrono::milliseconds ntp_time;
192 // Reference clock value corresponding to the NTP time.
193 std::chrono::milliseconds ntp_time_reference;
194 // Round-trip time of the last NTP transaction.
195 std::chrono::milliseconds round_trip_time;
196 };
197
198 // request_time_with_timeout reaches out to the SNTP server known under host,
199 // and tries to determine the current UTC reference time. The operation aborts after
200 // timeout milliseconds.
201 //
202 // std::runtime_error is thrown in case of issues.
203 Response request_time(const std::string& host, const std::chrono::milliseconds& timeout, boost::asio::io_service& ios);
204 sntp::Packet request(boost::asio::ip::udp::socket& socket);
205};
206}
207}
208
209}}}}
210#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_SNTP_CLIENT_H_
0211
=== added file 'src/location_service/com/ubuntu/location/providers/gps/sntp_reference_time_source.cpp'
--- src/location_service/com/ubuntu/location/providers/gps/sntp_reference_time_source.cpp 1970-01-01 00:00:00 +0000
+++ src/location_service/com/ubuntu/location/providers/gps/sntp_reference_time_source.cpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,57 @@
1/*
2 * Copyright © 2012-2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */
18
19#include <com/ubuntu/location/providers/gps/sntp_reference_time_source.h>
20
21#include <com/ubuntu/location/configuration.h>
22#include <com/ubuntu/location/service/runtime.h>
23
24#include <boost/property_tree/ini_parser.hpp>
25
26#include <future>
27
28namespace location = com::ubuntu::location;
29namespace gps = com::ubuntu::location::providers::gps;
30
31gps::SntpReferenceTimeSource::Configuration gps::SntpReferenceTimeSource::Configuration::from_gps_conf_ini_file(std::istream& in)
32{
33 gps::SntpReferenceTimeSource::Configuration result;
34
35 location::Configuration config;
36 boost::property_tree::read_ini(in, config);
37
38 if (config.count("NTP_SERVER") > 0)
39 result.host = config.get<std::string>("NTP_SERVER");
40
41 return result;
42}
43gps::SntpReferenceTimeSource::SntpReferenceTimeSource(const Configuration& config)
44 : config(config)
45{
46}
47
48gps::HardwareAbstractionLayer::ReferenceTimeSample gps::SntpReferenceTimeSource::sample()
49{
50 auto rt = location::service::Runtime::create();
51 rt->start();
52
53 location::providers::gps::sntp::Client sntp_client;
54 auto result = sntp_client.request_time(config.host, config.timeout, rt->service());
55
56 return {result.ntp_time, result.ntp_time_reference, result.round_trip_time};
57}
058
=== added file 'src/location_service/com/ubuntu/location/providers/gps/sntp_reference_time_source.h'
--- src/location_service/com/ubuntu/location/providers/gps/sntp_reference_time_source.h 1970-01-01 00:00:00 +0000
+++ src/location_service/com/ubuntu/location/providers/gps/sntp_reference_time_source.h 2016-03-10 19:55:08 +0000
@@ -0,0 +1,51 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */
18#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_SNTP_REFERENCE_TIME_SOURCE_H_
19#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_SNTP_REFERENCE_TIME_SOURCE_H_
20
21#include <com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h>
22
23#include <com/ubuntu/location/providers/gps/sntp_client.h>
24
25namespace com { namespace ubuntu { namespace location { namespace providers { namespace gps {
26
27class SntpReferenceTimeSource : public android::HardwareAbstractionLayer::ReferenceTimeSource
28{
29public:
30
31 /** @brief Configuration summarizes default parameter available to implementations. */
32 struct Configuration
33 {
34 /** @brief Reads a configuration from a gps.conf file in INI format. */
35 static Configuration from_gps_conf_ini_file(std::istream& in);
36
37 std::string host{"pool.ntp.org"}; /**< NTP host. */
38 std::chrono::milliseconds timeout{5000}; /**< Timeout when querying the NTP server. */
39 };
40
41 SntpReferenceTimeSource(const Configuration& configuration);
42
43 gps::HardwareAbstractionLayer::ReferenceTimeSample sample() override;
44
45private:
46 const Configuration config;
47};
48
49}}}}}
50
51#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_GPS_SNTP_REFERENCE_TIME_SOURCE_H_
052
=== modified file 'src/location_service/com/ubuntu/location/service/runtime.h'
--- src/location_service/com/ubuntu/location/service/runtime.h 2015-11-25 09:20:12 +0000
+++ src/location_service/com/ubuntu/location/service/runtime.h 2016-03-10 19:55:08 +0000
@@ -42,7 +42,7 @@
42{42{
43public:43public:
44 // Our default concurrency setup.44 // Our default concurrency setup.
45 static constexpr const std::uint32_t worker_threads = 2;45 static constexpr const std::uint32_t worker_threads = 4;
4646
47 // create returns a Runtime instance with pool_size worker threads47 // create returns a Runtime instance with pool_size worker threads
48 // executing the underlying service.48 // executing the underlying service.
4949
=== modified file 'src/location_service/com/ubuntu/location/service/runtime_tests.cpp'
--- src/location_service/com/ubuntu/location/service/runtime_tests.cpp 2015-01-26 20:15:05 +0000
+++ src/location_service/com/ubuntu/location/service/runtime_tests.cpp 2016-03-10 19:55:08 +0000
@@ -16,6 +16,7 @@
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */17 */
1818
19#include <com/ubuntu/location/service/runtime.h>
19#include <com/ubuntu/location/service/runtime_tests.h>20#include <com/ubuntu/location/service/runtime_tests.h>
2021
21#include <com/ubuntu/location/clock.h>22#include <com/ubuntu/location/clock.h>
2223
=== added file 'src/location_service/com/ubuntu/location/time_since_boot.cpp'
--- src/location_service/com/ubuntu/location/time_since_boot.cpp 1970-01-01 00:00:00 +0000
+++ src/location_service/com/ubuntu/location/time_since_boot.cpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,140 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */
18
19#include <com/ubuntu/location/time_since_boot.h>
20#include <com/ubuntu/location/logging.h>
21
22#if defined(COM_UBUNTU_LOCATION_SERVICE_HAVE_UBUNTU_PLATFORM_HARDWARE_API)
23#include <ubuntu/hardware/alarm.h>
24#endif // COM_UBUNTU_LOCATION_SERVICE_HAVE_UBUNTU_PLATFORM_HARDWARE_API
25
26#include <fstream>
27#include <sstream>
28#include <stdexcept>
29#include <system_error>
30
31namespace location = com::ubuntu::location;
32
33namespace
34{
35bool have_ubuntu_hardware_alarm()
36{
37#if defined(COM_UBUNTU_LOCATION_SERVICE_HAVE_UBUNTU_PLATFORM_HARDWARE_API)
38 return true;
39#else
40 return false;
41#endif // COM_UBUNTU_LOCATION_SERVICE_HAVE_UBUNTU_PLATFORM_HARDWARE_API
42}
43
44std::chrono::nanoseconds from_ubuntu_hardware_alarm()
45{
46#if defined(COM_UBUNTU_LOCATION_SERVICE_HAVE_UBUNTU_PLATFORM_HARDWARE_API)
47 struct Scope
48 {
49 Scope() : alarm{u_hardware_alarm_create()}
50 {
51 }
52
53 ~Scope()
54 {
55 u_hardware_alarm_unref(alarm);
56 }
57
58 UHardwareAlarm alarm{nullptr};
59 };
60
61 static Scope scope;
62
63 ::timespec ts;
64 if (not scope.alarm)
65 throw std::runtime_error{"Failed to access UHardwareAlarm subsystem."};
66
67 if (U_STATUS_SUCCESS != u_hardware_alarm_get_elapsed_real_time(scope.alarm, &ts))
68 throw std::runtime_error{"Failed to query time since boot from UHardwareAlarm."};
69
70 return std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec};
71#else
72 throw std::logic_error{"not implemented"};
73#endif // COM_UBUNTU_LOCATION_SERVICE_HAVE_UBUNTU_PLATFORM_HARDWARE_API
74}
75
76
77std::chrono::nanoseconds from_clock_boottime()
78{
79 ::timespec ts;
80 if (-1 == clock_gettime(CLOCK_BOOTTIME, &ts))
81 throw std::system_error(errno, std::system_category());
82
83 return std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec};
84}
85
86std::chrono::nanoseconds boot_time()
87{
88 std::ifstream in{"/proc/stat"};
89 std::string line;
90
91 while (std::getline(in, line))
92 {
93 if (line.empty())
94 continue;
95
96 std::stringstream ss{line};
97 std::string name; ss >> name;
98
99 if (name != "btime")
100 continue;
101
102 std::uint64_t ts; ss >> ts;
103 return std::chrono::nanoseconds{std::chrono::seconds{ts}};
104 }
105
106 throw std::runtime_error{"Failed to determine system boot time."};
107}
108
109std::chrono::nanoseconds from_proc_stat()
110{
111 static const std::chrono::nanoseconds bt{boot_time()};
112 return std::chrono::system_clock::now().time_since_epoch() - bt;
113}
114}
115
116std::chrono::nanoseconds location::time_since_boot()
117{
118 if (have_ubuntu_hardware_alarm())
119 {
120 try
121 {
122 return from_ubuntu_hardware_alarm();
123 }
124 catch (const std::exception& e)
125 {
126 VLOG(1) << e.what();
127 }
128 }
129
130 try
131 {
132 return from_clock_boottime();
133 }
134 catch (const std::exception& e)
135 {
136 VLOG(1) << e.what();
137 }
138
139 return from_proc_stat();
140}
0141
=== added file 'src/location_service/com/ubuntu/location/time_since_boot.h'
--- src/location_service/com/ubuntu/location/time_since_boot.h 1970-01-01 00:00:00 +0000
+++ src/location_service/com/ubuntu/location/time_since_boot.h 2016-03-10 19:55:08 +0000
@@ -0,0 +1,35 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */
18#ifndef LOCATION_SERVICE_UBUNTU_LOCATION_SERVICE_TIME_SINCE_BOOT_H_
19#define LOCATION_SERVICE_UBUNTU_LOCATION_SERVICE_TIME_SINCE_BOOT_H_
20
21#include <chrono>
22
23namespace com
24{
25namespace ubuntu
26{
27namespace location
28{
29/** @brief time_since_boot returns the nanoseconds that elapsed since boot. */
30std::chrono::nanoseconds time_since_boot();
31}
32}
33}
34
35#endif // LOCATION_SERVICE_UBUNTU_LOCATION_SERVICE_TIME_SINCE_BOOT_H_
036
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2015-12-01 14:36:55 +0000
+++ tests/CMakeLists.txt 2016-03-10 19:55:08 +0000
@@ -98,6 +98,7 @@
98if (LOCATION_SERVICE_ENABLE_GPS_PROVIDER)98if (LOCATION_SERVICE_ENABLE_GPS_PROVIDER)
99 include_directories(${CMAKE_SOURCE_DIR}/src/location_service)99 include_directories(${CMAKE_SOURCE_DIR}/src/location_service)
100 LOCATION_SERVICE_ADD_TEST(gps_provider_test gps_provider_test.cpp)100 LOCATION_SERVICE_ADD_TEST(gps_provider_test gps_provider_test.cpp)
101 LOCATION_SERVICE_ADD_TEST(sntp_client_test sntp_client_test.cpp)
101endif(LOCATION_SERVICE_ENABLE_GPS_PROVIDER)102endif(LOCATION_SERVICE_ENABLE_GPS_PROVIDER)
102103
103if (LOCATION_SERVICE_ENABLE_GEOCLUE_PROVIDERS)104if (LOCATION_SERVICE_ENABLE_GEOCLUE_PROVIDERS)
104105
=== modified file 'tests/gps_provider_test.cpp'
--- tests/gps_provider_test.cpp 2015-10-19 13:04:06 +0000
+++ tests/gps_provider_test.cpp 2016-03-10 19:55:08 +0000
@@ -81,6 +81,11 @@
81 MOCK_METHOD1(on_space_vehicles_updated, void(const std::set<location::SpaceVehicle>&));81 MOCK_METHOD1(on_space_vehicles_updated, void(const std::set<location::SpaceVehicle>&));
82};82};
8383
84struct MockReferenceTimeSource : public gps::android::HardwareAbstractionLayer::ReferenceTimeSource
85{
86 MOCK_METHOD0(sample, gps::HardwareAbstractionLayer::ReferenceTimeSample());
87};
88
84struct MockSuplAssistant : public gps::HardwareAbstractionLayer::SuplAssistant89struct MockSuplAssistant : public gps::HardwareAbstractionLayer::SuplAssistant
85{90{
86 MockSuplAssistant()91 MockSuplAssistant()
@@ -93,6 +98,8 @@
9398
94 MOCK_CONST_METHOD0(status, const core::Property<Status>&());99 MOCK_CONST_METHOD0(status, const core::Property<Status>&());
95 MOCK_CONST_METHOD0(server_ip, const core::Property<IpV4Address>&());100 MOCK_CONST_METHOD0(server_ip, const core::Property<IpV4Address>&());
101 MOCK_CONST_METHOD2(set_set_id, void(SetIdType, const std::string&));
102 MOCK_CONST_METHOD1(inject_radio_cell_information, void(const location::connectivity::RadioCell& radio_cell));
96 MOCK_METHOD2(set_server, void(const std::string&, std::uint16_t));103 MOCK_METHOD2(set_server, void(const std::string&, std::uint16_t));
97 MOCK_METHOD1(notify_data_connection_open_via_apn, void(const std::string&));104 MOCK_METHOD1(notify_data_connection_open_via_apn, void(const std::string&));
98 MOCK_METHOD0(notify_data_connection_closed, void());105 MOCK_METHOD0(notify_data_connection_closed, void());
@@ -133,9 +140,7 @@
133 MOCK_METHOD1(set_assistance_mode, bool(gps::AssistanceMode));140 MOCK_METHOD1(set_assistance_mode, bool(gps::AssistanceMode));
134 MOCK_METHOD1(set_position_mode, bool(gps::PositionMode));141 MOCK_METHOD1(set_position_mode, bool(gps::PositionMode));
135 MOCK_METHOD1(inject_reference_position, bool(const location::Position&));142 MOCK_METHOD1(inject_reference_position, bool(const location::Position&));
136 MOCK_METHOD2(inject_reference_time,143 MOCK_METHOD1(inject_reference_time, bool(const location::providers::gps::HardwareAbstractionLayer::ReferenceTimeSample&));
137 bool(const std::chrono::microseconds&,
138 const std::chrono::microseconds&));
139144
140 MockSuplAssistant supl_assistant_;145 MockSuplAssistant supl_assistant_;
141 core::Signal<location::Position> position_updates_;146 core::Signal<location::Position> position_updates_;
@@ -322,24 +327,54 @@
322 provider.on_reference_location_updated(pos);327 provider.on_reference_location_updated(pos);
323}328}
324329
330TEST(GpsProvider, time_requests_query_reference_time_source)
331{
332 using namespace ::testing;
333
334 NiceMock<MockHardwareGps> hardwareGps;
335
336 auto mock_reference_time_source = std::make_shared<MockReferenceTimeSource>();
337 EXPECT_CALL(*mock_reference_time_source, sample())
338 .Times(1)
339 .WillRepeatedly(Return(gps::HardwareAbstractionLayer::ReferenceTimeSample{}));
340
341 gps::android::HardwareAbstractionLayer::Configuration configuration;
342 configuration.reference_time_source = mock_reference_time_source;
343 gps::android::HardwareAbstractionLayer hal(configuration);
344
345 gps::android::HardwareAbstractionLayer::on_request_utc_time(&hal);
346}
347
325TEST(GpsProvider, time_requests_inject_current_time_into_the_hal)348TEST(GpsProvider, time_requests_inject_current_time_into_the_hal)
326{349{
327 using namespace ::testing;350 using namespace ::testing;
328351
352 auto sample_reference_time = []()
353 {
354 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(location::Clock::now().time_since_epoch());
355 std::cout << duration.count() << std::endl;
356 return gps::HardwareAbstractionLayer::ReferenceTimeSample{duration, duration, std::chrono::milliseconds{0}};
357 };
358
329 NiceMock<MockHardwareGps> hardwareGps;359 NiceMock<MockHardwareGps> hardwareGps;
330360
361 auto mock_reference_time_source = std::make_shared<MockReferenceTimeSource>();
362 EXPECT_CALL(*mock_reference_time_source, sample())
363 .Times(1)
364 .WillRepeatedly(Invoke(sample_reference_time));
365
331 gps::android::HardwareAbstractionLayer::Configuration configuration;366 gps::android::HardwareAbstractionLayer::Configuration configuration;
367 configuration.reference_time_source = mock_reference_time_source;
332 gps::android::HardwareAbstractionLayer hal(configuration);368 gps::android::HardwareAbstractionLayer hal(configuration);
333 std::shared_ptr<gps::HardwareAbstractionLayer> hal_ptr(&hal, [](gps::HardwareAbstractionLayer*){});369 hal.capabilities() = U_HARDWARE_GPS_CAPABILITY_ON_DEMAND_TIME;
334370
335 gps::Provider provider(hal_ptr);
336 int64_t time = 0;371 int64_t time = 0;
337 EXPECT_CALL(hardwareGps, inject_time(_, _, 0)).Times(1).WillOnce(SaveArg<0>(&time));372 EXPECT_CALL(hardwareGps, inject_time(_, _, 0)).Times(1).WillOnce(SaveArg<0>(&time));
338373
339 auto t0 = std::chrono::duration_cast<std::chrono::milliseconds>(location::Clock::now().time_since_epoch());374 auto t0 = std::chrono::duration_cast<std::chrono::milliseconds>(location::Clock::now().time_since_epoch());
340375 //std::this_thread::sleep_for(std::chrono::milliseconds{10});
341 gps::android::HardwareAbstractionLayer::on_request_utc_time(&hal);376 gps::android::HardwareAbstractionLayer::on_request_utc_time(&hal);
342377 //std::this_thread::sleep_for(std::chrono::milliseconds{10});
343 auto t1 = std::chrono::duration_cast<std::chrono::milliseconds>(location::Clock::now().time_since_epoch());378 auto t1 = std::chrono::duration_cast<std::chrono::milliseconds>(location::Clock::now().time_since_epoch());
344 EXPECT_THAT(time, AllOf(Ge(t0.count()), Le(t1.count())));379 EXPECT_THAT(time, AllOf(Ge(t0.count()), Le(t1.count())));
345}380}
@@ -929,4 +964,3 @@
929 static_cast<std::uint64_t>(variance(stats)))).count()964 static_cast<std::uint64_t>(variance(stats)))).count()
930 << std::endl;965 << std::endl;
931}966}
932
933967
=== added file 'tests/sntp_client_test.cpp'
--- tests/sntp_client_test.cpp 1970-01-01 00:00:00 +0000
+++ tests/sntp_client_test.cpp 2016-03-10 19:55:08 +0000
@@ -0,0 +1,104 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */
18
19#include <com/ubuntu/location/providers/gps/sntp_client.h>
20#include <com/ubuntu/location/service/runtime.h>
21
22#include <future>
23
24#include <core/posix/this_process.h>
25
26#include <gtest/gtest.h>
27
28namespace env = core::posix::this_process::env;
29namespace location = com::ubuntu::location;
30namespace sntp = location::providers::gps::sntp;
31
32namespace
33{
34struct SntpClient : public ::testing::Test
35{
36 void SetUp()
37 {
38 rt->start();
39 }
40
41 void TearDown()
42 {
43 rt->stop();
44 }
45
46 std::shared_ptr<location::service::Runtime> rt = location::service::Runtime::create();
47 std::string host = env::get("UBUNTU_LOCATION_SERVICE_NTP_HOST_FOR_TESTING", "ntp.ubuntu.com");
48};
49}
50
51TEST_F(SntpClient, packet_has_correct_size)
52{
53 static_assert(sizeof(sntp::Packet) == 48, "");
54}
55
56#pragma GCC diagnostic push
57#pragma GCC diagnostic ignored "-Wmultichar"
58TEST(EnumConstant, yields_same_value_as_multibyte_constant)
59{
60 static_assert(sntp::detail::enum_constant<'L','O','C','L'>() == 'LOCL', "");
61}
62#pragma GCC diagnostic pop
63
64TEST_F(SntpClient, succeeds_in_querying_time_from_server)
65{
66 location::providers::gps::sntp::Client sntp_client;
67 try
68 {
69 sntp_client.request_time(host, std::chrono::milliseconds{5000}, rt->service());
70 }
71 catch(...)
72 {
73 }
74}
75
76TEST_F(SntpClient, throws_for_timed_out_operation)
77{
78 location::providers::gps::sntp::Client sntp_client;
79 EXPECT_ANY_THROW(sntp_client.request_time(host, std::chrono::milliseconds{1}, rt->service()));
80}
81
82TEST_F(SntpClient, returns_correct_data_in_packet)
83{
84 for (unsigned int i = 0; i < 10; i++)
85 {
86 location::providers::gps::sntp::Client sntp_client;
87 try
88 {
89 auto response = sntp_client.request_time(host, std::chrono::milliseconds{1000}, rt->service());
90
91 EXPECT_LE(0, response.packet.stratum.value());
92 if (response.packet.stratum.value() <= 1)
93 {
94 std::stringstream ss; ss << response.packet.reference_identifier;
95 EXPECT_TRUE(ss.str().size() > 0);
96 }
97 }
98 catch(...)
99 {
100 // We ignore any exception being thrown as we are working against a real-world server
101 // in a load-test scenario.
102 }
103 }
104}

Subscribers

People subscribed via source and target branches