Merge branch 'variant'
This commit is contained in:
@@ -8,7 +8,7 @@ before_install:
|
||||
- sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get -y install gcc-4.8 g++-4.8
|
||||
- sudo apt-get -y install git cmake make pkg-config libboost-dev libpng-dev
|
||||
- sudo apt-get -y install git cmake make pkg-config libpng-dev
|
||||
- sudo apt-get -y install libxi-dev libglu1-mesa-dev x11proto-randr-dev x11proto-xext-dev libxrandr-dev x11proto-xf86vidmode-dev libxxf86vm-dev
|
||||
|
||||
install:
|
||||
|
||||
15
README.md
15
README.md
@@ -14,16 +14,16 @@ implemented in C++11, targeting iOS & OS X.
|
||||
|
||||
## OS X
|
||||
|
||||
Install boost, libpng, and [glfw3](http://www.glfw.org/docs/latest/):
|
||||
Install libpng and [glfw3](http://www.glfw.org/docs/latest/):
|
||||
|
||||
```
|
||||
brew install boost libpng
|
||||
brew install libpng
|
||||
brew install homebrew/versions/glfw3
|
||||
```
|
||||
|
||||
Then configure the project:
|
||||
|
||||
./configure --boost=`brew --prefix` --glfw3=`brew --prefix` --png=`brew --prefix`
|
||||
./configure --glfw3=`brew --prefix` --png=`brew --prefix`
|
||||
|
||||
See all the options by calling `./configure --help`
|
||||
|
||||
@@ -34,7 +34,6 @@ Usage: configure [options]
|
||||
Options:
|
||||
-h, --help show this help message and exit
|
||||
--debug Also build debug build
|
||||
--boost=BOOST_ROOT Path to boost (defaults to /usr/local)
|
||||
--glfw3=GLFW3 Path to gflw3 (defaults to using pkg-config)
|
||||
--png=PNG Path to png (defaults to using pkg-config)
|
||||
--png-includes=PNG_INCLUDES
|
||||
@@ -53,10 +52,6 @@ Or generate a dual iOS/OS X-compatible Xcode project for `libllmr` to include as
|
||||
|
||||
## iOS
|
||||
|
||||
Install boost:
|
||||
|
||||
brew install boost
|
||||
|
||||
Because `libpng` isn't included in the iOS SDK, you will need to build a cross-architecture version yourself. Run `./ios/setup_libpng.sh`, which is derived from Mapnik's cross-architecture build scripts. This will also run `./configure`.
|
||||
|
||||
Then you can build the iOS app with make:
|
||||
@@ -79,10 +74,6 @@ Install a `-std=c++11` capable compiler
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-4.8 g++-4.8
|
||||
|
||||
Install boost (we only need headers):
|
||||
|
||||
sudo apt-get install libboost-dev
|
||||
|
||||
Install libpng-dev:
|
||||
|
||||
sudo apt-get install libpng-dev
|
||||
|
||||
11
common.gypi
11
common.gypi
@@ -9,18 +9,15 @@
|
||||
'cflags_cc': ['-std=c++11'],
|
||||
'configurations': {
|
||||
'Debug': {
|
||||
'cflags': [ '-g', '-O0', '-I<(boost_root)/include' ],
|
||||
'cflags': [ '-g', '-O0' ],
|
||||
'defines': [ 'DEBUG' ],
|
||||
'xcode_settings': {
|
||||
'OTHER_CPLUSPLUSFLAGS': [ '-g', '-I<(boost_root)/include' ]
|
||||
'OTHER_CPLUSPLUSFLAGS': [ '-g']
|
||||
}
|
||||
},
|
||||
'Release': {
|
||||
'cflags': [ '-O3', '-I<(boost_root)/include' ],
|
||||
'defines': [ 'NDEBUG' ],
|
||||
'xcode_settings': {
|
||||
'OTHER_CPLUSPLUSFLAGS': [ '-I<(boost_root)/include' ]
|
||||
}
|
||||
'cflags': [ '-O3'],
|
||||
'defines': [ 'NDEBUG' ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9
configure
vendored
9
configure
vendored
@@ -19,11 +19,6 @@ parser.add_option("--debug",
|
||||
dest="debug",
|
||||
help="Also build debug build")
|
||||
|
||||
parser.add_option("--boost",
|
||||
action="store",
|
||||
dest="boost_root",
|
||||
help="Path to boost (defaults to /usr/local)")
|
||||
|
||||
parser.add_option("--glfw3",
|
||||
action="store",
|
||||
dest="glfw3",
|
||||
@@ -60,10 +55,6 @@ def pkg_config(pkg):
|
||||
return (libs, cflags)
|
||||
|
||||
def configure_llmr(o):
|
||||
if options.boost_root:
|
||||
o['variables']['boost_root'] = options.boost_root
|
||||
else:
|
||||
o['variables']['boost_root'] = '/usr/local'
|
||||
o['target_defaults']['default_configuration'] = 'Debug' if options.debug else 'Release'
|
||||
|
||||
def configure_glfw3(o):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifndef LLMR_STYLE_VALUE
|
||||
#define LLMR_STYLE_VALUE
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
#include <llmr/util/variant.hpp>
|
||||
#include <llmr/util/pbf.hpp>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
typedef boost::variant<bool, int64_t, uint64_t, double, std::string> Value;
|
||||
typedef ::util::variant<bool, int64_t, uint64_t, double, std::string> Value;
|
||||
|
||||
Value parseValue(pbf data);
|
||||
|
||||
|
||||
380
include/llmr/util/variant.hpp
Normal file
380
include/llmr/util/variant.hpp
Normal file
@@ -0,0 +1,380 @@
|
||||
#ifndef UTIL_VARIANT_HPP
|
||||
#define UTIL_VARIANT_HPP
|
||||
|
||||
#include <utility>
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
#include <algorithm> // std::move/swap
|
||||
#include <stdexcept> // runtime_error
|
||||
#include <new> // operator new
|
||||
#include <cstddef> // size_t
|
||||
#include <iosfwd>
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define VARIANT_INLINE inline __attribute__((always_inline))
|
||||
#else
|
||||
#define VARIANT_INLINE __attribute__((noinline))
|
||||
#endif
|
||||
|
||||
namespace util {
|
||||
|
||||
namespace detail {
|
||||
|
||||
static constexpr std::size_t invalid_value = std::size_t(-1);
|
||||
|
||||
template <typename T, typename...Types>
|
||||
struct type_traits;
|
||||
|
||||
template <typename T, typename First, typename...Types>
|
||||
struct type_traits<T, First, Types...>
|
||||
{
|
||||
static constexpr std::size_t id = std::is_same<T, First>::value ? sizeof...(Types) : type_traits<T, Types...>::id;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct type_traits<T>
|
||||
{
|
||||
static constexpr std::size_t id = invalid_value;
|
||||
};
|
||||
|
||||
template <typename T, typename...Types>
|
||||
struct is_valid_type;
|
||||
|
||||
template <typename T, typename First, typename... Types>
|
||||
struct is_valid_type<T,First,Types...>
|
||||
{
|
||||
static constexpr bool value = std::is_same<T,First>::value
|
||||
|| is_valid_type<T,Types...>::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_valid_type<T> : std::false_type {};
|
||||
|
||||
}
|
||||
|
||||
template <std::size_t arg1, std::size_t ... others>
|
||||
struct static_max;
|
||||
|
||||
template <std::size_t arg>
|
||||
struct static_max<arg>
|
||||
{
|
||||
static const std::size_t value = arg;
|
||||
};
|
||||
|
||||
template <std::size_t arg1, std::size_t arg2, std::size_t ... others>
|
||||
struct static_max<arg1, arg2, others...>
|
||||
{
|
||||
static const std::size_t value = arg1 >= arg2 ? static_max<arg1, others...>::value :
|
||||
static_max<arg2, others...>::value;
|
||||
};
|
||||
|
||||
template<typename... Types>
|
||||
struct variant_helper;
|
||||
|
||||
template<typename T, typename... Types>
|
||||
struct variant_helper<T, Types...>
|
||||
{
|
||||
VARIANT_INLINE static void destroy(std::size_t id, void * data)
|
||||
{
|
||||
if (id == sizeof...(Types))
|
||||
{
|
||||
reinterpret_cast<T*>(data)->~T();
|
||||
}
|
||||
else
|
||||
{
|
||||
variant_helper<Types...>::destroy(id, data);
|
||||
}
|
||||
}
|
||||
|
||||
VARIANT_INLINE static void move(const std::size_t old_t, void * old_v, void * new_v)
|
||||
{
|
||||
if (old_t == sizeof...(Types))
|
||||
{
|
||||
new (new_v) T(std::move(*reinterpret_cast<T*>(old_v)));
|
||||
//std::memcpy(new_v, old_v, sizeof(T));
|
||||
// ^^ DANGER: this should only be considered for relocatable types e.g built-in types
|
||||
// Also, I don't see any measurable performance benefit just yet
|
||||
}
|
||||
else
|
||||
{
|
||||
variant_helper<Types...>::move(old_t, old_v, new_v);
|
||||
}
|
||||
}
|
||||
|
||||
VARIANT_INLINE static void copy(const std::size_t old_t, const void * old_v, void * new_v)
|
||||
{
|
||||
if (old_t == sizeof...(Types))
|
||||
{
|
||||
new (new_v) T(*reinterpret_cast<const T*>(old_v));
|
||||
}
|
||||
else
|
||||
{
|
||||
variant_helper<Types...>::copy(old_t, old_v, new_v);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct variant_helper<>
|
||||
{
|
||||
VARIANT_INLINE static void destroy(const std::size_t, void *) {}
|
||||
VARIANT_INLINE static void move(const std::size_t, void *, void *) {}
|
||||
VARIANT_INLINE static void copy(const std::size_t, const void *, void *) {}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename F, typename V, typename...Types>
|
||||
struct dispatcher;
|
||||
|
||||
template <typename F, typename V, typename T, typename...Types>
|
||||
struct dispatcher<F,V,T,Types...>
|
||||
{
|
||||
typedef typename std::result_of<F(V const&)>::type result_type;
|
||||
VARIANT_INLINE static result_type apply(V const& v, F f)
|
||||
{
|
||||
if (v.get_type_id() == sizeof...(Types))
|
||||
{
|
||||
return f(v. template get<T>());
|
||||
}
|
||||
else
|
||||
{
|
||||
return dispatcher<F,V,Types...>::apply(v, f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename F,typename V>
|
||||
struct dispatcher<F,V>
|
||||
{
|
||||
typedef typename std::result_of<F(V const&)>::type result_type;
|
||||
VARIANT_INLINE static result_type apply(V const&, F)
|
||||
{
|
||||
throw std::runtime_error("dispatch: FAIL");
|
||||
}
|
||||
};
|
||||
|
||||
// comparator functors
|
||||
struct equal_comp
|
||||
{
|
||||
template <typename T>
|
||||
bool operator()(T const& lhs, T const& rhs) const
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
};
|
||||
|
||||
struct less_comp
|
||||
{
|
||||
template <typename T>
|
||||
bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Variant, typename Comp>
|
||||
struct comparer
|
||||
{
|
||||
public:
|
||||
explicit comparer(Variant const& lhs) noexcept
|
||||
: lhs_(lhs) {}
|
||||
comparer& operator=(const comparer&) = delete;
|
||||
// visitor
|
||||
template<typename T>
|
||||
bool operator()(T const& rhs_content) const
|
||||
{
|
||||
T const& lhs_content = lhs_.template get<T>();
|
||||
return Comp()(lhs_content, rhs_content);
|
||||
}
|
||||
private:
|
||||
Variant const& lhs_;
|
||||
};
|
||||
|
||||
// operator<< helper
|
||||
template <typename Out>
|
||||
struct printer
|
||||
{
|
||||
public:
|
||||
explicit printer(Out & out)
|
||||
: out_(out) {}
|
||||
printer& operator=(const printer&) = delete;
|
||||
|
||||
// visitor
|
||||
template <typename T>
|
||||
void operator()(const T& operand) const
|
||||
{
|
||||
out_ << operand;
|
||||
}
|
||||
private:
|
||||
Out & out_;
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
template<typename... Types>
|
||||
struct variant
|
||||
{
|
||||
private:
|
||||
|
||||
static const std::size_t data_size = static_max<sizeof(Types)...>::value;
|
||||
static const std::size_t data_align = static_max<alignof(Types)...>::value;
|
||||
|
||||
using data_t = typename std::aligned_storage<data_size, data_align>::type;
|
||||
|
||||
using helper_t = variant_helper<Types...>;
|
||||
|
||||
std::size_t type_id;
|
||||
data_t data;
|
||||
|
||||
public:
|
||||
|
||||
VARIANT_INLINE variant()
|
||||
: type_id(detail::invalid_value) {}
|
||||
|
||||
template <typename T>
|
||||
VARIANT_INLINE explicit variant(T const& val) noexcept
|
||||
: type_id(detail::type_traits<T, Types...>::id)
|
||||
{
|
||||
static_assert(detail::is_valid_type<T,Types...>::value, "Not a valid type for this variant");
|
||||
new (&data) T(val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
VARIANT_INLINE variant(T && val) noexcept
|
||||
: type_id(detail::type_traits<T,Types...>::id)
|
||||
{
|
||||
static_assert(detail::is_valid_type<T,Types...>::value, "Not a valid type for this variant");
|
||||
new (&data) T(std::forward<T>(val)); // nothrow
|
||||
}
|
||||
|
||||
VARIANT_INLINE variant(variant<Types...> const& old)
|
||||
: type_id(old.type_id)
|
||||
{
|
||||
helper_t::copy(old.type_id, &old.data, &data);
|
||||
}
|
||||
|
||||
VARIANT_INLINE variant(variant<Types...>&& old) noexcept
|
||||
: type_id(old.type_id)
|
||||
{
|
||||
helper_t::move(old.type_id, &old.data, &data);
|
||||
}
|
||||
|
||||
friend void swap(variant<Types...> & first, variant<Types...> & second)
|
||||
{
|
||||
using std::swap; //enable ADL
|
||||
swap(first.type_id, second.type_id);
|
||||
swap(first.data, second.data);
|
||||
}
|
||||
|
||||
VARIANT_INLINE variant<Types...>& operator= (variant<Types...> other)
|
||||
{
|
||||
swap(*this, other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
VARIANT_INLINE void is() const
|
||||
{
|
||||
return (type_id == detail::type_traits<T, Types...>::id);
|
||||
}
|
||||
|
||||
VARIANT_INLINE void valid() const
|
||||
{
|
||||
return (type_id != detail::invalid_value);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
VARIANT_INLINE void set(Args&&... args)
|
||||
{
|
||||
helper_t::destroy(type_id, &data);
|
||||
new (&data) T(std::forward<Args>(args)...);
|
||||
type_id = detail::type_traits<T,Types...>::id;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
VARIANT_INLINE T& get()
|
||||
{
|
||||
if (type_id == detail::type_traits<T,Types...>::id)
|
||||
{
|
||||
return *reinterpret_cast<T*>(&data);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("in get()");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
VARIANT_INLINE T const& get() const
|
||||
{
|
||||
if (type_id == detail::type_traits<T,Types...>::id)
|
||||
{
|
||||
return *reinterpret_cast<T const*>(&data);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("in get()");
|
||||
}
|
||||
}
|
||||
|
||||
VARIANT_INLINE std::size_t get_type_id() const
|
||||
{
|
||||
return type_id;
|
||||
}
|
||||
|
||||
// visitor
|
||||
template <typename F, typename V>
|
||||
typename std::result_of<F(V const&)>::type
|
||||
VARIANT_INLINE static visit(V const& v, F f)
|
||||
{
|
||||
return detail::dispatcher<F, V, Types...>::apply(v, f);
|
||||
}
|
||||
|
||||
~variant() noexcept
|
||||
{
|
||||
helper_t::destroy(type_id, &data);
|
||||
}
|
||||
|
||||
// comparison operators
|
||||
// equality
|
||||
VARIANT_INLINE bool operator==(variant const& rhs) const
|
||||
{
|
||||
if (this->get_type_id() != rhs.get_type_id())
|
||||
return false;
|
||||
detail::comparer<variant, detail::equal_comp> visitor(*this);
|
||||
return visit(rhs, visitor);
|
||||
}
|
||||
// less than
|
||||
VARIANT_INLINE bool operator<(variant const& rhs) const
|
||||
{
|
||||
if (this->get_type_id() != rhs.get_type_id())
|
||||
{
|
||||
return this->get_type_id() < rhs.get_type_id();
|
||||
// ^^ borrowed from boost::variant
|
||||
}
|
||||
detail::comparer<variant, detail::less_comp> visitor(*this);
|
||||
return visit(rhs, visitor);
|
||||
}
|
||||
};
|
||||
|
||||
// unary visitor interface
|
||||
template <typename V, typename F>
|
||||
typename std::result_of<F(V const&)>::type
|
||||
VARIANT_INLINE static apply_visitor(V const& v, F f)
|
||||
{
|
||||
return V::visit(v,f);
|
||||
}
|
||||
|
||||
// operator<<
|
||||
template <typename charT, typename traits, typename Variant>
|
||||
VARIANT_INLINE std::basic_ostream<charT,traits>&
|
||||
operator<< (std::basic_ostream<charT,traits>& out, Variant const& rhs)
|
||||
{
|
||||
detail::printer<std::basic_ostream<charT,traits> > visitor(out);
|
||||
apply_visitor(rhs, visitor);
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // UTIL_VARIANT_HPP
|
||||
@@ -12,7 +12,7 @@ VectorTile::VectorTile(pbf tile) {
|
||||
while (tile.next()) {
|
||||
if (tile.tag == 3) { // layer
|
||||
VectorTileLayer layer(tile.message());
|
||||
layers.emplace(layer.name, layer);
|
||||
layers.emplace(layer.name, std::forward<VectorTileLayer>(layer));
|
||||
} else {
|
||||
tile.skip();
|
||||
}
|
||||
@@ -34,7 +34,7 @@ VectorTileLayer::VectorTileLayer(pbf layer) : data(layer) {
|
||||
} else if (layer.tag == 3) { // keys
|
||||
keys.emplace_back(layer.string());
|
||||
} else if (layer.tag == 4) { // values
|
||||
values.emplace_back(parseValue(layer.message()));
|
||||
values.emplace_back(std::move(parseValue(layer.message())));
|
||||
} else if (layer.tag == 5) { // extent
|
||||
extent = layer.varint();
|
||||
} else {
|
||||
|
||||
@@ -61,7 +61,7 @@ std::pair<std::string, BucketDescription> Style::parseBucket(pbf data) {
|
||||
}
|
||||
}
|
||||
|
||||
return { name, bucket };
|
||||
return { name, std::forward<BucketDescription>(bucket) };
|
||||
}
|
||||
|
||||
LayerDescription Style::parseLayer(pbf data) {
|
||||
|
||||
@@ -8,7 +8,7 @@ llmr::Value llmr::parseValue(pbf data) {
|
||||
case 1: // string_value
|
||||
return data.string();
|
||||
case 2: // float_value
|
||||
return data.float32();
|
||||
return static_cast<double>(data.float32());
|
||||
case 3: // double_value
|
||||
return data.float64();
|
||||
case 4: // int_value
|
||||
|
||||
Reference in New Issue
Block a user