Resource.h 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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]] Optional<time_t> modified_time() const;
  29. [[nodiscard]] ByteBuffer clone_data() const;
  30. [[nodiscard]] ByteBuffer release_data() &&;
  31. [[nodiscard]] ReadonlyBytes data() const;
  32. [[nodiscard]] FixedMemoryStream stream() const;
  33. [[nodiscard]] Vector<String> children() const;
  34. // Depth-first
  35. template<IteratorFunction<Resource const&> Callback>
  36. IterationDecision for_each_descendant(Callback&&) const;
  37. template<IteratorFunction<Resource const&> Callback>
  38. void for_each_descendant_file(Callback&&) const;
  39. struct DirectoryTag { };
  40. private:
  41. friend class ResourceImplementation;
  42. enum class Scheme {
  43. File,
  44. Resource,
  45. };
  46. Resource(String path, Scheme, NonnullOwnPtr<Core::MappedFile>, time_t modified_time);
  47. Resource(String path, Scheme, ByteBuffer, time_t modified_time);
  48. Resource(String path, Scheme, DirectoryTag, time_t modified_time);
  49. String m_path; // Relative to scheme root. File: abspath, Resource: resource root
  50. Scheme m_scheme;
  51. Variant<DirectoryTag, NonnullOwnPtr<Core::MappedFile>, ByteBuffer> m_data;
  52. time_t m_modified_time {};
  53. };
  54. template<IteratorFunction<Resource const&> Callback>
  55. IterationDecision Resource::for_each_descendant(Callback&& callback) const
  56. {
  57. auto children = this->children();
  58. for (auto const& child : children) {
  59. if (auto child_resource = load_from_uri(MUST(String::formatted("{}/{}", uri(), child))); !child_resource.is_error()) {
  60. if (callback(*child_resource.value()) == IterationDecision::Break)
  61. return IterationDecision::Break;
  62. if (child_resource.value()->for_each_descendant(callback) == IterationDecision::Break)
  63. return IterationDecision::Break;
  64. }
  65. }
  66. return IterationDecision::Continue;
  67. }
  68. template<IteratorFunction<Resource const&> Callback>
  69. void Resource::for_each_descendant_file(Callback&& callback) const
  70. {
  71. for_each_descendant([callback = forward<Callback>(callback)](Resource const& resource) {
  72. if (resource.is_directory())
  73. return IterationDecision::Continue;
  74. return callback(resource);
  75. });
  76. }
  77. }