Resource.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/ByteBuffer.h>
  8. #include <AK/Error.h>
  9. #include <AK/MemoryStream.h>
  10. #include <AK/RefPtr.h>
  11. #include <AK/Span.h>
  12. #include <AK/String.h>
  13. #include <AK/StringView.h>
  14. #include <AK/Variant.h>
  15. #include <LibCore/File.h>
  16. #include <LibCore/MappedFile.h>
  17. namespace Core {
  18. class Resource : public RefCounted<Resource> {
  19. public:
  20. static ErrorOr<NonnullRefPtr<Resource>> load_from_filesystem(StringView);
  21. static ErrorOr<NonnullRefPtr<Resource>> load_from_uri(StringView);
  22. [[nodiscard]] bool is_file() const { return !m_data.has<DirectoryTag>(); }
  23. [[nodiscard]] bool is_directory() const { return m_data.has<DirectoryTag>(); }
  24. [[nodiscard]] String uri() const;
  25. [[nodiscard]] String filename() const;
  26. [[nodiscard]] String filesystem_path() const;
  27. [[nodiscard]] String file_url() const;
  28. [[nodiscard]] ByteBuffer clone_data() const;
  29. [[nodiscard]] ByteBuffer release_data() &&;
  30. [[nodiscard]] ReadonlyBytes data() const;
  31. [[nodiscard]] FixedMemoryStream stream() const;
  32. [[nodiscard]] Vector<String> children() const;
  33. // Depth-first
  34. template<IteratorFunction<Resource const&> Callback>
  35. IterationDecision for_each_descendant(Callback&&) const;
  36. template<IteratorFunction<Resource const&> Callback>
  37. void for_each_descendant_file(Callback&&) const;
  38. struct DirectoryTag { };
  39. private:
  40. friend class ResourceImplementation;
  41. enum class Scheme {
  42. File,
  43. Resource,
  44. };
  45. Resource(String path, Scheme, NonnullOwnPtr<Core::MappedFile>);
  46. Resource(String path, Scheme, ByteBuffer);
  47. Resource(String path, Scheme, DirectoryTag);
  48. String m_path; // Relative to scheme root. File: abspath, Resource: resource root
  49. Scheme m_scheme;
  50. Variant<DirectoryTag, NonnullOwnPtr<Core::MappedFile>, ByteBuffer> m_data;
  51. };
  52. template<IteratorFunction<Resource const&> Callback>
  53. IterationDecision Resource::for_each_descendant(Callback&& callback) const
  54. {
  55. auto children = this->children();
  56. for (auto const& child : children) {
  57. if (auto child_resource = load_from_uri(MUST(String::formatted("{}/{}", uri(), child))); !child_resource.is_error()) {
  58. if (callback(*child_resource.value()) == IterationDecision::Break)
  59. return IterationDecision::Break;
  60. if (child_resource.value()->for_each_descendant(callback) == IterationDecision::Break)
  61. return IterationDecision::Break;
  62. }
  63. }
  64. return IterationDecision::Continue;
  65. }
  66. template<IteratorFunction<Resource const&> Callback>
  67. void Resource::for_each_descendant_file(Callback&& callback) const
  68. {
  69. for_each_descendant([callback = forward<Callback>(callback)](Resource const& resource) {
  70. if (resource.is_directory())
  71. return IterationDecision::Continue;
  72. return callback(resource);
  73. });
  74. }
  75. }