Skip to content

Commit

Permalink
Writing tags (mikekazakov#153)
Browse files Browse the repository at this point in the history
* Implementing routines to write the Finder Tags

* Expanded the WritePListObject function to support long strings and unicode strings

* Added routines to write tags into actual files

* Added a function that gathers all tags on the filesystem via Spotlight

* Added comments
  • Loading branch information
mikekazakov authored Feb 8, 2024
1 parent 1fd4382 commit 414e4c2
Show file tree
Hide file tree
Showing 3 changed files with 548 additions and 7 deletions.
44 changes: 39 additions & 5 deletions Source/Utility/include/Utility/Tags.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
#include <vector>
#include <string>
#include <filesystem>
#include <optional>
#include <utility>

namespace nc::utility {

class Tags
{
public:
enum class Color : unsigned char
{
enum class Color : unsigned char {
None = 0,
Gray = 1,
Green = 2,
Expand All @@ -32,18 +33,37 @@ class Tags
// Parses the "com.apple.FinderInfo" xattr and extracts a tag color if any is present.
// Returns an empty vector as an error mechanism.
static std::vector<Tag> ParseFinderInfo(std::span<const std::byte> _bytes) noexcept;

// Loads the contents an the xattrs and processes it with ParseMDItemUserTags
static std::vector<Tag> ReadMDItemUserTags(int _fd) noexcept;

// Loads the contents an the xattrs and processes it with ParseFinderInfo
static std::vector<Tag> ReadFinderInfo(int _fd) noexcept;

// Loads tags from MDItemUserTags (1st priority) or from FinderInfo(2nd priority), works with file handles
static std::vector<Tag> ReadTags(int _fd) noexcept;

// Loads tags from MDItemUserTags (1st priority) or from FinderInfo(2nd priority), works with file paths
static std::vector<Tag> ReadTags(const std::filesystem::path &_path) noexcept;

// Composes a binary blob representing the contents of the "com.apple.metadata:_kMDItemUserTags" xattr corresponding
// to the specified list of tags. Empty blob is returned if no tags were provided.
static std::vector<std::byte> BuildMDItemUserTags(std::span<const Tag> _tags) noexcept;

// Writes the "com.apple.metadata:_kMDItemUserTags" and "com.apple.FinderInfo" xattrs to the specified file
// according to the provided set of tags.
static bool WriteTags(int _fd, std::span<const Tag> _tags) noexcept;

// Writes the "com.apple.metadata:_kMDItemUserTags" and "com.apple.FinderInfo" xattrs to the specified file
// according to the provided set of tags.
static bool WriteTags(const std::filesystem::path &_path, std::span<const Tag> _tags) noexcept;

// Executes a "kMDItemUserTags=*" query by Spotlight to gather all indexed items on the filesystem that contain any
// tags.
static std::vector<std::filesystem::path> GatherAllItemsWithTags() noexcept;

// Gather a current set of tags used by the items on the filesystem.
static std::vector<Tag> GatherAllItemsTags() noexcept;
};

// Non-owning class that represent a text label and a color of a tag.
Expand All @@ -62,3 +82,17 @@ class Tags::Tag
};

} // namespace nc::utility

namespace std {

template <>
class hash<nc::utility::Tags::Tag>
{
public:
size_t operator()(const nc::utility::Tags::Tag &_tag) const noexcept
{
return std::hash<std::string>{}(_tag.Label()) + std::to_underlying(_tag.Color());
}
};

} // namespace std
Loading

0 comments on commit 414e4c2

Please sign in to comment.