From 0627324da62922d332c75ec51525141329187beb Mon Sep 17 00:00:00 2001 From: frsyuki Date: Mon, 10 Aug 2009 18:26:01 +0900 Subject: c++: rebuild type/*.hpp --- cpp/Makefile.am | 8 +-- cpp/type.hpp | 8 +-- cpp/type/array.hpp | 57 -------------------- cpp/type/bool.hpp | 47 ++++++++++++++++ cpp/type/boolean.hpp | 47 ---------------- cpp/type/deque.hpp | 56 ++++++++++++++++++++ cpp/type/float.hpp | 2 - cpp/type/int.hpp | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++ cpp/type/integer.hpp | 147 --------------------------------------------------- cpp/type/list.hpp | 56 ++++++++++++++++++++ cpp/type/pair.hpp | 1 - cpp/type/raw.hpp | 19 ------- cpp/type/string.hpp | 47 ++++++++++++++++ cpp/type/vector.hpp | 56 ++++++++++++++++++++ 14 files changed, 419 insertions(+), 279 deletions(-) delete mode 100644 cpp/type/array.hpp create mode 100644 cpp/type/bool.hpp delete mode 100644 cpp/type/boolean.hpp create mode 100644 cpp/type/deque.hpp create mode 100644 cpp/type/int.hpp delete mode 100644 cpp/type/integer.hpp create mode 100644 cpp/type/list.hpp create mode 100644 cpp/type/string.hpp create mode 100644 cpp/type/vector.hpp (limited to 'cpp') diff --git a/cpp/Makefile.am b/cpp/Makefile.am index edbeb28..45cc13c 100644 --- a/cpp/Makefile.am +++ b/cpp/Makefile.am @@ -12,15 +12,17 @@ nobase_include_HEADERS = \ msgpack/object.hpp \ msgpack/zone.hpp \ msgpack/type.hpp \ - msgpack/type/array.hpp \ - msgpack/type/boolean.hpp \ + msgpack/type/bool.hpp \ msgpack/type/float.hpp \ - msgpack/type/integer.hpp \ + msgpack/type/int.hpp \ + msgpack/type/list.hpp \ msgpack/type/map.hpp \ msgpack/type/nil.hpp \ msgpack/type/pair.hpp \ msgpack/type/raw.hpp \ msgpack/type/set.hpp \ + msgpack/type/string.hpp \ + msgpack/type/vector.hpp \ msgpack/type/tuple.hpp \ msgpack/type/define.hpp diff --git a/cpp/type.hpp b/cpp/type.hpp index 2a6aa62..2bd805d 100644 --- a/cpp/type.hpp +++ b/cpp/type.hpp @@ -1,12 +1,14 @@ -#include "msgpack/type/array.hpp" -#include "msgpack/type/boolean.hpp" +#include "msgpack/type/bool.hpp" #include "msgpack/type/float.hpp" -#include "msgpack/type/integer.hpp" +#include "msgpack/type/int.hpp" +#include "msgpack/type/list.hpp" #include "msgpack/type/map.hpp" #include "msgpack/type/nil.hpp" #include "msgpack/type/pair.hpp" #include "msgpack/type/raw.hpp" #include "msgpack/type/set.hpp" +#include "msgpack/type/string.hpp" +#include "msgpack/type/vector.hpp" #include "msgpack/type/tuple.hpp" #include "msgpack/type/define.hpp" diff --git a/cpp/type/array.hpp b/cpp/type/array.hpp deleted file mode 100644 index 5b80dc1..0000000 --- a/cpp/type/array.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// -// MessagePack for C++ static resolution routine -// -// Copyright (C) 2008-2009 FURUHASHI Sadayuki -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef MSGPACK_TYPE_ARRAY_HPP__ -#define MSGPACK_TYPE_ARRAY_HPP__ - -#include "msgpack/object.hpp" -#include - -namespace msgpack { - - -template -inline std::vector& operator>> (object o, std::vector& v) -{ - if(o.type != type::ARRAY) { throw type_error(); } - v.resize(o.via.array.size); - object* p = o.via.array.ptr; - object* const pend = o.via.array.ptr + o.via.array.size; - T* it = &v.front(); - for(; p < pend; ++p, ++it) { - p->convert(it); - } - return v; -} - - -template -inline packer& operator<< (packer& o, const std::vector& v) -{ - o.pack_array(v.size()); - for(typename std::vector::const_iterator it(v.begin()), it_end(v.end()); - it != it_end; ++it) { - o.pack(*it); - } - return o; -} - - -} // namespace msgpack - -#endif /* msgpack/type/array.hpp */ - diff --git a/cpp/type/bool.hpp b/cpp/type/bool.hpp new file mode 100644 index 0000000..f3ac6fa --- /dev/null +++ b/cpp/type/bool.hpp @@ -0,0 +1,47 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008-2009 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_BOOL_HPP__ +#define MSGPACK_TYPE_BOOL_HPP__ + +#include "msgpack/object.hpp" +#include + +namespace msgpack { + + +inline bool& operator>> (object o, bool& v) +{ + if(o.type != type::BOOLEAN) { throw type_error(); } + v = o.via.boolean; + return v; +} + + +template +inline packer& operator<< (packer& o, const bool& v) +{ + if(v) { o.pack_true(); } + else { o.pack_false(); } + return o; +} + + +} // namespace msgpack + +#endif /* msgpack/type/bool.hpp */ + diff --git a/cpp/type/boolean.hpp b/cpp/type/boolean.hpp deleted file mode 100644 index 86bd697..0000000 --- a/cpp/type/boolean.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// MessagePack for C++ static resolution routine -// -// Copyright (C) 2008-2009 FURUHASHI Sadayuki -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef MSGPACK_TYPE_BOOLEAN_HPP__ -#define MSGPACK_TYPE_BOOLEAN_HPP__ - -#include "msgpack/object.hpp" -#include - -namespace msgpack { - - -inline bool& operator>> (object o, bool& v) -{ - if(o.type != type::BOOLEAN) { throw type_error(); } - v = o.via.boolean; - return v; -} - - -template -inline packer& operator<< (packer& o, const bool& v) -{ - if(v) { o.pack_true(); } - else { o.pack_false(); } - return o; -} - - -} // namespace msgpack - -#endif /* msgpack/type/bool.hpp */ - diff --git a/cpp/type/deque.hpp b/cpp/type/deque.hpp new file mode 100644 index 0000000..d34d243 --- /dev/null +++ b/cpp/type/deque.hpp @@ -0,0 +1,56 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008-2009 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_DEQUE_HPP__ +#define MSGPACK_TYPE_DEQUE_HPP__ + +#include "msgpack/object.hpp" +#include + +namespace msgpack { + + +template +inline std::deque& operator>> (object o, std::deque& v) +{ + if(o.type != type::ARRAY) { throw type_error(); } + v.resize(o.via.array.size); + object* p = o.via.array.ptr; + object* const pend = o.via.array.ptr + o.via.array.size; + typename std::deque::iterator it = v.begin(); + for(; p < pend; ++p, ++it) { + p->convert(&*it); + } + return v; +} + +template +inline packer& operator<< (packer& o, const std::deque& v) +{ + o.pack_array(v.size()); + for(typename std::deque::const_iterator it(v.begin()), it_end(v.end()); + it != it_end; ++it) { + o.pack(*it); + } + return o; +} + + +} // namespace msgpack + +#endif /* msgpack/type/deque.hpp */ + diff --git a/cpp/type/float.hpp b/cpp/type/float.hpp index 108709d..390e340 100644 --- a/cpp/type/float.hpp +++ b/cpp/type/float.hpp @@ -34,7 +34,6 @@ inline float& operator>> (object o, float& v) return v; } - template inline packer& operator<< (packer& o, const float& v) { @@ -50,7 +49,6 @@ inline double& operator>> (object o, double& v) return v; } - template inline packer& operator<< (packer& o, const double& v) { diff --git a/cpp/type/int.hpp b/cpp/type/int.hpp new file mode 100644 index 0000000..8fdc386 --- /dev/null +++ b/cpp/type/int.hpp @@ -0,0 +1,147 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008-2009 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_INT_HPP__ +#define MSGPACK_TYPE_INT_HPP__ + +#include "msgpack/object.hpp" +#include + +namespace msgpack { + + +namespace type { +namespace detail { + template + struct convert_integer_sign; + + template + struct convert_integer_sign { + static inline T convert(object o) { + if(o.type == type::POSITIVE_INTEGER) { + if(o.via.u64 > (uint64_t)std::numeric_limits::max()) + { throw type_error(); } + return o.via.u64; + } else if(o.type == type::NEGATIVE_INTEGER) { + if(o.via.i64 < (int64_t)-std::numeric_limits::max()) + { throw type_error(); } + return o.via.i64; + } + throw type_error(); + } + }; + + template + struct convert_integer_sign { + static inline T convert(object o) { + if(o.type == type::POSITIVE_INTEGER) { + if(o.via.u64 > (uint64_t)std::numeric_limits::max()) + { throw type_error(); } + return o.via.u64; + } + throw type_error(); + } + }; + + template + static inline T convert_integer(object o) + { + return detail::convert_integer_sign::is_signed>::convert(o); + } + +} // namespace detail +} // namespace type + + +inline signed char& operator>> (object o, signed char& v) + { v = type::detail::convert_integer(o); return v; } + +inline signed short& operator>> (object o, signed short& v) + { v = type::detail::convert_integer(o); return v; } + +inline signed int& operator>> (object o, signed int& v) + { v = type::detail::convert_integer(o); return v; } + +inline signed long& operator>> (object o, signed long& v) + { v = type::detail::convert_integer(o); return v; } + +inline signed long long& operator>> (object o, signed long long& v) + { v = type::detail::convert_integer(o); return v; } + + +inline unsigned char& operator>> (object o, unsigned char& v) + { v = type::detail::convert_integer(o); return v; } + +inline unsigned short& operator>> (object o, unsigned short& v) + { v = type::detail::convert_integer(o); return v; } + +inline unsigned int& operator>> (object o, unsigned int& v) + { v = type::detail::convert_integer(o); return v; } + +inline unsigned long& operator>> (object o, unsigned long& v) + { v = type::detail::convert_integer(o); return v; } + +inline unsigned long long& operator>> (object o, unsigned long long& v) + { v = type::detail::convert_integer(o); return v; } + + +template +inline packer& operator<< (packer& o, const signed char& v) + { o.pack_int8(v); return o; } + +template +inline packer& operator<< (packer& o, const signed short& v) + { o.pack_short(v); return o; } + +template +inline packer& operator<< (packer& o, const signed int& v) + { o.pack_int(v); return o; } + +template +inline packer& operator<< (packer& o, const signed long& v) + { o.pack_long(v); return o; } + +template +inline packer& operator<< (packer& o, const signed long long& v) + { o.pack_long_long(v); return o; } + + +template +inline packer& operator<< (packer& o, const unsigned char& v) + { o.pack_uint8(v); return o; } + +template +inline packer& operator<< (packer& o, const unsigned short& v) + { o.pack_unsigned_short(v); return o; } + +template +inline packer& operator<< (packer& o, const unsigned int& v) + { o.pack_unsigned_int(v); return o; } + +template +inline packer& operator<< (packer& o, const unsigned long& v) + { o.pack_unsigned_long(v); return o; } + +template +inline packer& operator<< (packer& o, const unsigned long long& v) + { o.pack_unsigned_long_long(v); return o; } + + +} // namespace msgpack + +#endif /* msgpack/type/int.hpp */ + diff --git a/cpp/type/integer.hpp b/cpp/type/integer.hpp deleted file mode 100644 index ecb7b89..0000000 --- a/cpp/type/integer.hpp +++ /dev/null @@ -1,147 +0,0 @@ -// -// MessagePack for C++ static resolution routine -// -// Copyright (C) 2008-2009 FURUHASHI Sadayuki -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef MSGPACK_TYPE_INTEGER_HPP__ -#define MSGPACK_TYPE_INTEGER_HPP__ - -#include "msgpack/object.hpp" -#include - -namespace msgpack { - - -namespace type { -namespace detail { - template - struct convert_integer_sign; - - template - struct convert_integer_sign { - static inline T convert(object o) { - if(o.type == type::POSITIVE_INTEGER) { - if(o.via.u64 > (uint64_t)std::numeric_limits::max()) - { throw type_error(); } - return o.via.u64; - } else if(o.type == type::NEGATIVE_INTEGER) { - if(o.via.i64 < (int64_t)-std::numeric_limits::max()) - { throw type_error(); } - return o.via.i64; - } - throw type_error(); - } - }; - - template - struct convert_integer_sign { - static inline T convert(object o) { - if(o.type == type::POSITIVE_INTEGER) { - if(o.via.u64 > (uint64_t)std::numeric_limits::max()) - { throw type_error(); } - return o.via.u64; - } - throw type_error(); - } - }; - - template - static inline T convert_integer(object o) - { - return detail::convert_integer_sign::is_signed>::convert(o); - } - -} // namespace detail -} // namespace type - - -inline signed char& operator>> (object o, signed char& v) - { v = type::detail::convert_integer(o); return v; } - -inline signed short& operator>> (object o, signed short& v) - { v = type::detail::convert_integer(o); return v; } - -inline signed int& operator>> (object o, signed int& v) - { v = type::detail::convert_integer(o); return v; } - -inline signed long& operator>> (object o, signed long& v) - { v = type::detail::convert_integer(o); return v; } - -inline signed long long& operator>> (object o, signed long long& v) - { v = type::detail::convert_integer(o); return v; } - - -inline unsigned char& operator>> (object o, unsigned char& v) - { v = type::detail::convert_integer(o); return v; } - -inline unsigned short& operator>> (object o, unsigned short& v) - { v = type::detail::convert_integer(o); return v; } - -inline unsigned int& operator>> (object o, unsigned int& v) - { v = type::detail::convert_integer(o); return v; } - -inline unsigned long& operator>> (object o, unsigned long& v) - { v = type::detail::convert_integer(o); return v; } - -inline unsigned long long& operator>> (object o, unsigned long long& v) - { v = type::detail::convert_integer(o); return v; } - - -template -inline packer& operator<< (packer& o, const signed char& v) - { o.pack_int8(v); return o; } - -template -inline packer& operator<< (packer& o, const signed short& v) - { o.pack_short(v); return o; } - -template -inline packer& operator<< (packer& o, const signed int& v) - { o.pack_int(v); return o; } - -template -inline packer& operator<< (packer& o, const signed long& v) - { o.pack_long(v); return o; } - -template -inline packer& operator<< (packer& o, const signed long long& v) - { o.pack_long_long(v); return o; } - - -template -inline packer& operator<< (packer& o, const unsigned char& v) - { o.pack_uint8(v); return o; } - -template -inline packer& operator<< (packer& o, const unsigned short& v) - { o.pack_unsigned_short(v); return o; } - -template -inline packer& operator<< (packer& o, const unsigned int& v) - { o.pack_unsigned_int(v); return o; } - -template -inline packer& operator<< (packer& o, const unsigned long& v) - { o.pack_unsigned_long(v); return o; } - -template -inline packer& operator<< (packer& o, const unsigned long long& v) - { o.pack_unsigned_long_long(v); return o; } - - -} // namespace msgpack - -#endif /* msgpack/type/integer.hpp */ - diff --git a/cpp/type/list.hpp b/cpp/type/list.hpp new file mode 100644 index 0000000..6ecc02f --- /dev/null +++ b/cpp/type/list.hpp @@ -0,0 +1,56 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008-2009 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_LIST_HPP__ +#define MSGPACK_TYPE_LIST_HPP__ + +#include "msgpack/object.hpp" +#include + +namespace msgpack { + + +template +inline std::list& operator>> (object o, std::list& v) +{ + if(o.type != type::ARRAY) { throw type_error(); } + v.resize(o.via.array.size); + object* p = o.via.array.ptr; + object* const pend = o.via.array.ptr + o.via.array.size; + typename std::list::iterator it = v.begin(); + for(; p < pend; ++p, ++it) { + p->convert(&*it); + } + return v; +} + +template +inline packer& operator<< (packer& o, const std::list& v) +{ + o.pack_array(v.size()); + for(typename std::list::const_iterator it(v.begin()), it_end(v.end()); + it != it_end; ++it) { + o.pack(*it); + } + return o; +} + + +} // namespace msgpack + +#endif /* msgpack/type/list.hpp */ + diff --git a/cpp/type/pair.hpp b/cpp/type/pair.hpp index 316b9fe..ba72c1f 100644 --- a/cpp/type/pair.hpp +++ b/cpp/type/pair.hpp @@ -34,7 +34,6 @@ inline std::pair& operator>> (object o, std::pair& v) return v; } - template inline packer& operator<< (packer& o, const std::pair& v) { diff --git a/cpp/type/raw.hpp b/cpp/type/raw.hpp index b6ace3f..8c68aba 100644 --- a/cpp/type/raw.hpp +++ b/cpp/type/raw.hpp @@ -69,16 +69,6 @@ inline type::raw_ref& operator>> (object o, type::raw_ref& v) return v; } - -inline std::string& operator>> (object o, std::string& v) -{ - type::raw_ref r; - o >> r; - v.assign(r.ptr, r.size); - return v; -} - - template inline packer& operator<< (packer& o, const type::raw_ref& v) { @@ -88,15 +78,6 @@ inline packer& operator<< (packer& o, const type::raw_ref& v) } -template -inline packer& operator<< (packer& o, const std::string& v) -{ - o.pack_raw(v.size()); - o.pack_raw_body(v.data(), v.size()); - return o; -} - - } // namespace msgpack #endif /* msgpack/type/raw.hpp */ diff --git a/cpp/type/string.hpp b/cpp/type/string.hpp new file mode 100644 index 0000000..2a23058 --- /dev/null +++ b/cpp/type/string.hpp @@ -0,0 +1,47 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008-2009 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_STRING_HPP__ +#define MSGPACK_TYPE_STRING_HPP__ + +#include "msgpack/object.hpp" +#include + +namespace msgpack { + + +inline std::string& operator>> (object o, std::string& v) +{ + type::raw_ref r; + o >> r; + v.assign(r.ptr, r.size); + return v; +} + +template +inline packer& operator<< (packer& o, const std::string& v) +{ + o.pack_raw(v.size()); + o.pack_raw_body(v.data(), v.size()); + return o; +} + + +} // namespace msgpack + +#endif /* msgpack/type/string.hpp */ + diff --git a/cpp/type/vector.hpp b/cpp/type/vector.hpp new file mode 100644 index 0000000..754cdc0 --- /dev/null +++ b/cpp/type/vector.hpp @@ -0,0 +1,56 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2008-2009 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_VECTOR_HPP__ +#define MSGPACK_TYPE_VECTOR_HPP__ + +#include "msgpack/object.hpp" +#include + +namespace msgpack { + + +template +inline std::vector& operator>> (object o, std::vector& v) +{ + if(o.type != type::ARRAY) { throw type_error(); } + v.resize(o.via.array.size); + object* p = o.via.array.ptr; + object* const pend = o.via.array.ptr + o.via.array.size; + T* it = &v.front(); + for(; p < pend; ++p, ++it) { + p->convert(it); + } + return v; +} + +template +inline packer& operator<< (packer& o, const std::vector& v) +{ + o.pack_array(v.size()); + for(typename std::vector::const_iterator it(v.begin()), it_end(v.end()); + it != it_end; ++it) { + o.pack(*it); + } + return o; +} + + +} // namespace msgpack + +#endif /* msgpack/type/vector.hpp */ + -- cgit v1.2.1