From d7703c822c7b2373615a972f02667287635c667b Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 29 Oct 2020 16:32:32 +0100 Subject: Simplify header names --- bindings/cxx/include/pugl/cairo.hpp | 50 +++++++++ bindings/cxx/include/pugl/gl.hpp | 60 +++++++++++ bindings/cxx/include/pugl/pugl_cairo.hpp | 50 --------- bindings/cxx/include/pugl/pugl_gl.hpp | 60 ----------- bindings/cxx/include/pugl/pugl_stub.hpp | 50 --------- bindings/cxx/include/pugl/pugl_vulkan.hpp | 170 ------------------------------ bindings/cxx/include/pugl/stub.hpp | 50 +++++++++ bindings/cxx/include/pugl/vulkan.hpp | 170 ++++++++++++++++++++++++++++++ 8 files changed, 330 insertions(+), 330 deletions(-) create mode 100644 bindings/cxx/include/pugl/cairo.hpp create mode 100644 bindings/cxx/include/pugl/gl.hpp delete mode 100644 bindings/cxx/include/pugl/pugl_cairo.hpp delete mode 100644 bindings/cxx/include/pugl/pugl_gl.hpp delete mode 100644 bindings/cxx/include/pugl/pugl_stub.hpp delete mode 100644 bindings/cxx/include/pugl/pugl_vulkan.hpp create mode 100644 bindings/cxx/include/pugl/stub.hpp create mode 100644 bindings/cxx/include/pugl/vulkan.hpp (limited to 'bindings') diff --git a/bindings/cxx/include/pugl/cairo.hpp b/bindings/cxx/include/pugl/cairo.hpp new file mode 100644 index 0000000..4df2702 --- /dev/null +++ b/bindings/cxx/include/pugl/cairo.hpp @@ -0,0 +1,50 @@ +/* + Copyright 2012-2020 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file cairo.hpp + @brief Declaration of Cairo backend accessor for C++. +*/ + +#ifndef PUGL_CAIRO_HPP +#define PUGL_CAIRO_HPP + +#include "pugl/cairo.h" +#include "pugl/pugl.h" + +namespace pugl { + +/** + @defgroup cairoxx Cairo + Cairo graphics support. + @ingroup pugl_cxx + @{ +*/ + +/// @copydoc puglCairoBackend +static inline const PuglBackend* +cairoBackend() noexcept +{ + return puglCairoBackend(); +} + +/** + @} +*/ + +} // namespace pugl + +#endif // PUGL_CAIRO_HPP diff --git a/bindings/cxx/include/pugl/gl.hpp b/bindings/cxx/include/pugl/gl.hpp new file mode 100644 index 0000000..2777cbf --- /dev/null +++ b/bindings/cxx/include/pugl/gl.hpp @@ -0,0 +1,60 @@ +/* + Copyright 2012-2020 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file gl.hpp + @brief OpenGL-specific C++ API. +*/ + +#ifndef PUGL_GL_HPP +#define PUGL_GL_HPP + +#include "pugl/gl.h" +#include "pugl/pugl.h" + +namespace pugl { + +/** + @defgroup glxx OpenGL + OpenGL graphics support. + @ingroup pugl_cxx + @{ +*/ + +/// @copydoc PuglGlFunc +using GlFunc = PuglGlFunc; + +/// @copydoc puglGetProcAddress +static inline GlFunc +getProcAddress(const char* name) noexcept +{ + return puglGetProcAddress(name); +} + +/// @copydoc puglGlBackend +static inline const PuglBackend* +glBackend() noexcept +{ + return puglGlBackend(); +} + +/** + @} +*/ + +} // namespace pugl + +#endif // PUGL_GL_HPP diff --git a/bindings/cxx/include/pugl/pugl_cairo.hpp b/bindings/cxx/include/pugl/pugl_cairo.hpp deleted file mode 100644 index 213c977..0000000 --- a/bindings/cxx/include/pugl/pugl_cairo.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright 2012-2020 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file pugl_cairo.hpp - @brief Declaration of Cairo backend accessor for C++. -*/ - -#ifndef PUGL_PUGL_CAIRO_HPP -#define PUGL_PUGL_CAIRO_HPP - -#include "pugl/pugl.h" -#include "pugl/pugl_cairo.h" - -namespace pugl { - -/** - @defgroup cairoxx Cairo - Cairo graphics support. - @ingroup pugl_cxx - @{ -*/ - -/// @copydoc puglCairoBackend -static inline const PuglBackend* -cairoBackend() noexcept -{ - return puglCairoBackend(); -} - -/** - @} -*/ - -} // namespace pugl - -#endif // PUGL_PUGL_CAIRO_HPP diff --git a/bindings/cxx/include/pugl/pugl_gl.hpp b/bindings/cxx/include/pugl/pugl_gl.hpp deleted file mode 100644 index b7c581e..0000000 --- a/bindings/cxx/include/pugl/pugl_gl.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright 2012-2020 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file pugl_gl.hpp - @brief OpenGL-specific C++ API. -*/ - -#ifndef PUGL_PUGL_GL_HPP -#define PUGL_PUGL_GL_HPP - -#include "pugl/pugl.h" -#include "pugl/pugl_gl.h" - -namespace pugl { - -/** - @defgroup glxx OpenGL - OpenGL graphics support. - @ingroup pugl_cxx - @{ -*/ - -/// @copydoc PuglGlFunc -using GlFunc = PuglGlFunc; - -/// @copydoc puglGetProcAddress -static inline GlFunc -getProcAddress(const char* name) noexcept -{ - return puglGetProcAddress(name); -} - -/// @copydoc puglGlBackend -static inline const PuglBackend* -glBackend() noexcept -{ - return puglGlBackend(); -} - -/** - @} -*/ - -} // namespace pugl - -#endif // PUGL_PUGL_GL_HPP diff --git a/bindings/cxx/include/pugl/pugl_stub.hpp b/bindings/cxx/include/pugl/pugl_stub.hpp deleted file mode 100644 index 362682b..0000000 --- a/bindings/cxx/include/pugl/pugl_stub.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright 2012-2020 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file pugl_stub.hpp - @brief Declaration of Stub backend accessor for C++. -*/ - -#ifndef PUGL_PUGL_STUB_HPP -#define PUGL_PUGL_STUB_HPP - -#include "pugl/pugl.h" -#include "pugl/pugl_stub.h" - -namespace pugl { - -/** - @defgroup stubxx Stub - Stub graphics support. - @ingroup pugl_cxx - @{ -*/ - -/// @copydoc puglStubBackend -static inline const PuglBackend* -stubBackend() noexcept -{ - return puglStubBackend(); -} - -/** - @} -*/ - -} // namespace pugl - -#endif // PUGL_PUGL_STUB_HPP diff --git a/bindings/cxx/include/pugl/pugl_vulkan.hpp b/bindings/cxx/include/pugl/pugl_vulkan.hpp deleted file mode 100644 index 9241aba..0000000 --- a/bindings/cxx/include/pugl/pugl_vulkan.hpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - Copyright 2012-2020 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file pugl_vulkan.hpp Vulkan-specific C++ API. - - Note that this header includes Vulkan headers, so if you are writing a - program or plugin that dynamically loads vulkan, you should first define - `VK_NO_PROTOTYPES` before including it. -*/ - -#ifndef PUGL_PUGL_VULKAN_HPP -#define PUGL_PUGL_VULKAN_HPP - -#include "pugl/pugl.h" -#include "pugl/pugl.hpp" -#include "pugl/pugl_vulkan.h" - -#include - -#include - -namespace pugl { - -/** - @defgroup vulkanxx Vulkan - Vulkan graphics support. - - Note that the Pugl C++ wrapper does not use vulkan.hpp because it is a - heavyweight dependency which not everyone uses, and its design is not very - friendly to dynamic loading in plugins anyway. However, if you do use - vulkan.hpp smart handles, it is relatively straightforward to wrap the - result of createSurface() manually. - - @ingroup pugl_cxx - @{ -*/ - -/// @copydoc PuglVulkanLoader -class PUGL_API VulkanLoader final - : public detail::Wrapper -{ -public: - /** - Create a new dynamic loader for Vulkan functions. - - This dynamically loads the Vulkan library and gets the load functions - from it. - - Note that this constructor does not throw exceptions, though failure is - possible. To check if the Vulkan library failed to load, test this - loader, which is explicitly convertible to `bool`. It is safe to use a - failed loader, but the accessors will always return null. - */ - explicit VulkanLoader(World& world) noexcept - : Wrapper{puglNewVulkanLoader(world.cobj())} - {} - - /** - Return the `vkGetInstanceProcAddr` function. - - @return Null if the Vulkan library failed to load, or does not contain - this function (which is unlikely and indicates a broken system). - */ - PFN_vkGetInstanceProcAddr getInstanceProcAddrFunc() const noexcept - { - return cobj() ? puglGetInstanceProcAddrFunc(cobj()) : nullptr; - } - - /** - Return the `vkGetDeviceProcAddr` function. - - @return Null if the Vulkan library failed to load, or does not contain - this function (which is unlikely and indicates a broken system). - */ - PFN_vkGetDeviceProcAddr getDeviceProcAddrFunc() const noexcept - { - return cobj() ? puglGetDeviceProcAddrFunc(cobj()) : nullptr; - } - - /// Return true if this loader is valid to use - explicit operator bool() const noexcept { return cobj(); } -}; - -/** - A simple wrapper for an array of static C strings. - - This provides a minimal API that supports iteration, like `std::vector`, but - avoids allocation, exceptions, and a dependency on the C++ standard library. -*/ -class PUGL_API StaticStringArray final -{ -public: - using value_type = const char*; - using const_iterator = const char* const*; - using size_type = uint32_t; - - StaticStringArray(const char* const* strings, const uint32_t size) noexcept - : _strings{strings} - , _size{size} - {} - - const char* const* begin() const noexcept { return _strings; } - const char* const* end() const noexcept { return _strings + _size; } - const char* const* data() const noexcept { return _strings; } - uint32_t size() const noexcept { return _size; } - -private: - const char* const* _strings; - uint32_t _size; -}; - -/** - Return the Vulkan instance extensions required to draw to a PuglView. - - If successful, the returned array always contains "VK_KHR_surface", along - with whatever other platform-specific extensions are required. - - @return An array of extension name strings. -*/ -inline StaticStringArray -getInstanceExtensions() noexcept -{ - uint32_t count = 0; - const char* const* const extensions = puglGetInstanceExtensions(&count); - - return StaticStringArray{extensions, count}; -} - -/// @copydoc puglCreateSurface -inline VkResult -createSurface(const VulkanLoader& loader, - View& view, - VkInstance instance, - const VkAllocationCallbacks* const allocator, - VkSurfaceKHR* const surface) noexcept -{ - const VkResult r = puglCreateSurface( - loader.cobj(), view.cobj(), instance, allocator, surface); - - return (!r && !surface) ? VK_ERROR_INITIALIZATION_FAILED : r; -} - -/// @copydoc puglVulkanBackend -static inline const PuglBackend* -vulkanBackend() noexcept -{ - return puglVulkanBackend(); -} - -/** - @} -*/ - -} // namespace pugl - -#endif // PUGL_PUGL_VULKAN_HPP diff --git a/bindings/cxx/include/pugl/stub.hpp b/bindings/cxx/include/pugl/stub.hpp new file mode 100644 index 0000000..74e8ef2 --- /dev/null +++ b/bindings/cxx/include/pugl/stub.hpp @@ -0,0 +1,50 @@ +/* + Copyright 2012-2020 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file stub.hpp + @brief Declaration of Stub backend accessor for C++. +*/ + +#ifndef PUGL_STUB_HPP +#define PUGL_STUB_HPP + +#include "pugl/pugl.h" +#include "pugl/stub.h" + +namespace pugl { + +/** + @defgroup stubxx Stub + Stub graphics support. + @ingroup pugl_cxx + @{ +*/ + +/// @copydoc puglStubBackend +static inline const PuglBackend* +stubBackend() noexcept +{ + return puglStubBackend(); +} + +/** + @} +*/ + +} // namespace pugl + +#endif // PUGL_STUB_HPP diff --git a/bindings/cxx/include/pugl/vulkan.hpp b/bindings/cxx/include/pugl/vulkan.hpp new file mode 100644 index 0000000..a7b16cb --- /dev/null +++ b/bindings/cxx/include/pugl/vulkan.hpp @@ -0,0 +1,170 @@ +/* + Copyright 2012-2020 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file vulkan.hpp Vulkan-specific C++ API. + + Note that this header includes Vulkan headers, so if you are writing a + program or plugin that dynamically loads vulkan, you should first define + `VK_NO_PROTOTYPES` before including it. +*/ + +#ifndef PUGL_VULKAN_HPP +#define PUGL_VULKAN_HPP + +#include "pugl/pugl.h" +#include "pugl/pugl.hpp" +#include "pugl/vulkan.h" + +#include + +#include + +namespace pugl { + +/** + @defgroup vulkanxx Vulkan + Vulkan graphics support. + + Note that the Pugl C++ wrapper does not use vulkan.hpp because it is a + heavyweight dependency which not everyone uses, and its design is not very + friendly to dynamic loading in plugins anyway. However, if you do use + vulkan.hpp smart handles, it is relatively straightforward to wrap the + result of createSurface() manually. + + @ingroup pugl_cxx + @{ +*/ + +/// @copydoc PuglVulkanLoader +class PUGL_API VulkanLoader final + : public detail::Wrapper +{ +public: + /** + Create a new dynamic loader for Vulkan functions. + + This dynamically loads the Vulkan library and gets the load functions + from it. + + Note that this constructor does not throw exceptions, though failure is + possible. To check if the Vulkan library failed to load, test this + loader, which is explicitly convertible to `bool`. It is safe to use a + failed loader, but the accessors will always return null. + */ + explicit VulkanLoader(World& world) noexcept + : Wrapper{puglNewVulkanLoader(world.cobj())} + {} + + /** + Return the `vkGetInstanceProcAddr` function. + + @return Null if the Vulkan library failed to load, or does not contain + this function (which is unlikely and indicates a broken system). + */ + PFN_vkGetInstanceProcAddr getInstanceProcAddrFunc() const noexcept + { + return cobj() ? puglGetInstanceProcAddrFunc(cobj()) : nullptr; + } + + /** + Return the `vkGetDeviceProcAddr` function. + + @return Null if the Vulkan library failed to load, or does not contain + this function (which is unlikely and indicates a broken system). + */ + PFN_vkGetDeviceProcAddr getDeviceProcAddrFunc() const noexcept + { + return cobj() ? puglGetDeviceProcAddrFunc(cobj()) : nullptr; + } + + /// Return true if this loader is valid to use + explicit operator bool() const noexcept { return cobj(); } +}; + +/** + A simple wrapper for an array of static C strings. + + This provides a minimal API that supports iteration, like `std::vector`, but + avoids allocation, exceptions, and a dependency on the C++ standard library. +*/ +class PUGL_API StaticStringArray final +{ +public: + using value_type = const char*; + using const_iterator = const char* const*; + using size_type = uint32_t; + + StaticStringArray(const char* const* strings, const uint32_t size) noexcept + : _strings{strings} + , _size{size} + {} + + const char* const* begin() const noexcept { return _strings; } + const char* const* end() const noexcept { return _strings + _size; } + const char* const* data() const noexcept { return _strings; } + uint32_t size() const noexcept { return _size; } + +private: + const char* const* _strings; + uint32_t _size; +}; + +/** + Return the Vulkan instance extensions required to draw to a PuglView. + + If successful, the returned array always contains "VK_KHR_surface", along + with whatever other platform-specific extensions are required. + + @return An array of extension name strings. +*/ +inline StaticStringArray +getInstanceExtensions() noexcept +{ + uint32_t count = 0; + const char* const* const extensions = puglGetInstanceExtensions(&count); + + return StaticStringArray{extensions, count}; +} + +/// @copydoc puglCreateSurface +inline VkResult +createSurface(const VulkanLoader& loader, + View& view, + VkInstance instance, + const VkAllocationCallbacks* const allocator, + VkSurfaceKHR* const surface) noexcept +{ + const VkResult r = puglCreateSurface( + loader.cobj(), view.cobj(), instance, allocator, surface); + + return (!r && !surface) ? VK_ERROR_INITIALIZATION_FAILED : r; +} + +/// @copydoc puglVulkanBackend +static inline const PuglBackend* +vulkanBackend() noexcept +{ + return puglVulkanBackend(); +} + +/** + @} +*/ + +} // namespace pugl + +#endif // PUGL_VULKAN_HPP -- cgit v1.2.1