diff options
author | Ryan Rector <rmrector@gmail.com> | 2024-04-07 15:45:38 -0600 |
---|---|---|
committer | Ryan Rector <rmrector@gmail.com> | 2024-05-28 20:29:56 -0600 |
commit | df84be09bef1c0e3c2c096c5e76957ec97d78b8e (patch) | |
tree | aef0e0c4d66a2022da8e041c78d3b35b42a5446d | |
parent | e8906a9cf6c173e00ac8486cf455289bdfbd4a00 (diff) |
add ImageFileURL for explicit image URL handling
-rw-r--r-- | cmake/treedata/common/tests.txt | 1 | ||||
-rw-r--r-- | xbmc/imagefiles/CMakeLists.txt | 6 | ||||
-rw-r--r-- | xbmc/imagefiles/ImageFileURL.cpp | 107 | ||||
-rw-r--r-- | xbmc/imagefiles/ImageFileURL.h | 90 | ||||
-rw-r--r-- | xbmc/imagefiles/test/CMakeLists.txt | 3 | ||||
-rw-r--r-- | xbmc/imagefiles/test/TestImageFileURL.cpp | 45 |
6 files changed, 250 insertions, 2 deletions
diff --git a/cmake/treedata/common/tests.txt b/cmake/treedata/common/tests.txt index 8d8d1107f2..3141b916cd 100644 --- a/cmake/treedata/common/tests.txt +++ b/cmake/treedata/common/tests.txt @@ -6,6 +6,7 @@ xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/test test/videoshaders xbmc/filesystem/test test/filesystem xbmc/games/addons/input/test test/games/addons/input xbmc/games/controllers/input/test test/games/controllers/input +xbmc/imagefiles/test test/imagefiles xbmc/input/keyboard/test test/input/keyboard xbmc/interfaces/python/test test/python xbmc/music/test test/music diff --git a/xbmc/imagefiles/CMakeLists.txt b/xbmc/imagefiles/CMakeLists.txt index 48f00441a5..66d1b45aa8 100644 --- a/xbmc/imagefiles/CMakeLists.txt +++ b/xbmc/imagefiles/CMakeLists.txt @@ -1,6 +1,8 @@ -set(SOURCES SpecialImageLoaderFactory.cpp) +set(SOURCES ImageFileURL.cpp + SpecialImageLoaderFactory.cpp) -set(HEADERS SpecialImageFileLoader.h +set(HEADERS ImageFileURL.h + SpecialImageFileLoader.h SpecialImageLoaderFactory.h) core_add_library(imagefiles) diff --git a/xbmc/imagefiles/ImageFileURL.cpp b/xbmc/imagefiles/ImageFileURL.cpp new file mode 100644 index 0000000000..d2d1cddfce --- /dev/null +++ b/xbmc/imagefiles/ImageFileURL.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2024 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "ImageFileURL.h" + +#include "URL.h" +#include "utils/URIUtils.h" + +#include <charconv> + +namespace IMAGE_FILES +{ + +CImageFileURL::CImageFileURL(const std::string& imageFileURL) +{ + if (!URIUtils::IsProtocol(imageFileURL, "image")) + { + m_filePath = imageFileURL; + return; + } + + CURL url{imageFileURL}; + m_filePath = url.GetHostName(); + m_specialType = url.GetUserName(); + + url.GetOptions(m_options); + + auto option = m_options.find("flipped"); + if (option != m_options.end()) + { + flipped = true; + m_options.erase(option); + } +} + +CImageFileURL::CImageFileURL() +{ +} + +CImageFileURL CImageFileURL::FromFile(const std::string& filePath, std::string specialType) +{ + if (URIUtils::IsProtocol(filePath, "image")) + { + // this function should not be called with an image file URL + return CImageFileURL(filePath); + } + + CImageFileURL item; + item.m_filePath = filePath; + item.m_specialType = std::move(specialType); + + return item; +} + +void CImageFileURL::AddOption(std::string key, std::string value) +{ + m_options[std::move(key)] = std::move(value); +} + +std::string CImageFileURL::GetOption(const std::string& key) const +{ + auto value = m_options.find(key); + if (value == m_options.end()) + { + return {}; + } + return value->second; +} + +std::string CImageFileURL::ToString() const +{ + CURL url; + url.SetProtocol("image"); + url.SetUserName(m_specialType); + url.SetHostName(m_filePath); + if (flipped) + url.SetOption("flipped", ""); + for (const auto& option : m_options) + url.SetOption(option.first, option.second); + + return url.Get(); +} + +std::string CImageFileURL::ToCacheKey() const +{ + if (!flipped && m_specialType.empty() && m_options.empty()) + return m_filePath; + + return ToString(); +} + +std::string URLFromFile(const std::string& filePath, std::string specialType) +{ + return CImageFileURL::FromFile(filePath, std::move(specialType)).ToString(); +} + +std::string ToCacheKey(const std::string& imageFileURL) +{ + return CImageFileURL(imageFileURL).ToCacheKey(); +} + +} // namespace IMAGE_FILES diff --git a/xbmc/imagefiles/ImageFileURL.h b/xbmc/imagefiles/ImageFileURL.h new file mode 100644 index 0000000000..e55d5b1d42 --- /dev/null +++ b/xbmc/imagefiles/ImageFileURL.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2024 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include <map> +#include <string> + +class CURL; + +namespace IMAGE_FILES +{ +/*! + * \brief A mostly-typed representation of a URL to any image, whether a simple path to an image + * file, embedded in another file, or generated in some way. + * + * A URL string is good to pass between most classes, store, and transmit, but use this if you need + * to _create_ or _modify_ a special image path, or are working on the details of such image files. + * + * URL string format is `image://[type@]<url_encoded_path>?options` +*/ +class CImageFileURL +{ +public: + /*! + * \brief Create an ImageFileURL from a string representation. + */ + CImageFileURL(const std::string& imageFileURL); + + /*! + * \brief Create an ImageFileURL pointing to a specific file. + * + * Provide a 'specialType' parameter to specify a special image loader. + * + * \param specialType set a special image type - an implementation of \ref ISpecialImageFileLoader + */ + static CImageFileURL FromFile(const std::string& filePath, std::string specialType = ""); + + void AddOption(std::string key, std::string value); + + std::string GetOption(const std::string& key) const; + + /*! + * \brief Build a complete string representation of this ImageFileURL. + */ + std::string ToString() const; + + /*! + * \brief Build a cache key for this ImageFileURL. + * + * Return base filePath if not special and multiple options are in a stable order, + * otherwise return a complete string representation. + */ + std::string ToCacheKey() const; + + std::string GetTargetFile() const { return m_filePath; } + + bool IsSpecialImage() const { return !m_specialType.empty(); } + std::string GetSpecialType() const { return m_specialType; } + + bool flipped{false}; + +private: + CImageFileURL(); + std::string m_filePath; + std::string m_specialType; + + std::map<std::string, std::string> m_options{}; +}; + +/*! + * \brief Build an ImageFileURL string from a file path. + * + * Provide a 'specialType' parameter to specify a special image loader. + * + * \param specialType set a special image type - an implementation of \ref ISpecialImageFileLoader +*/ +std::string URLFromFile(const std::string& filePath, std::string specialType = ""); + +/*! + * \brief Build a cache key for an ImageFileURL string. +*/ +std::string ToCacheKey(const std::string& imageFileURL); + +} // namespace IMAGE_FILES diff --git a/xbmc/imagefiles/test/CMakeLists.txt b/xbmc/imagefiles/test/CMakeLists.txt new file mode 100644 index 0000000000..5bd4bbbfb2 --- /dev/null +++ b/xbmc/imagefiles/test/CMakeLists.txt @@ -0,0 +1,3 @@ +set(SOURCES TestImageFileURL.cpp) + +core_add_test_library(imagefiles_test) diff --git a/xbmc/imagefiles/test/TestImageFileURL.cpp b/xbmc/imagefiles/test/TestImageFileURL.cpp new file mode 100644 index 0000000000..65ca769784 --- /dev/null +++ b/xbmc/imagefiles/test/TestImageFileURL.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "URL.h" +#include "imagefiles/ImageFileURL.h" + +#include <gtest/gtest.h> + +using ::testing::ValuesIn; + +namespace +{ +typedef struct +{ + const char* in; + const char* type; + const char* out; +} TestFiles; + +const TestFiles test_files[] = { + {"/path/to/image/file.jpg", "", "image://%2fpath%2fto%2fimage%2ffile.jpg/"}, + {"/path/to/video/file.mkv", "video", "image://video@%2fpath%2fto%2fvideo%2ffile.mkv/"}, + {"/path/to/music/file.mp3", "music", "image://music@%2fpath%2fto%2fmusic%2ffile.mp3/"}, + {"image://%2fpath%2fto%2fimage%2ffile.jpg/", "", "image://%2fpath%2fto%2fimage%2ffile.jpg/"}}; + +class TestImageFileURL : public ::testing::TestWithParam<TestFiles> +{ +}; + +TEST_P(TestImageFileURL, URLFromFile) +{ + const TestFiles& testFiles(GetParam()); + + std::string expected = testFiles.out; + std::string out = IMAGE_FILES::URLFromFile(testFiles.in, testFiles.type); + EXPECT_EQ(expected, out); +} + +INSTANTIATE_TEST_SUITE_P(SampleFiles, TestImageFileURL, ValuesIn(test_files)); +} // namespace |