Welcome to mirror list, hosted at ThFree Co, Russian Federation.

BKE_asset_catalog_path.hh « blenkernel « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 93ab0389dafa4b851dd6765cf8f7bc6dff50d986 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* SPDX-License-Identifier: GPL-2.0-or-later */

/** \file
 * \ingroup bke
 */

#pragma once

#ifndef __cplusplus
#  error This is a C++ header.
#endif

#include "BLI_function_ref.hh"
#include "BLI_string_ref.hh"
#include "BLI_sys_types.h"

#include <string>

namespace blender::bke {

/**
 * Location of an Asset Catalog in the catalog tree, denoted by slash-separated path components.
 *
 * Each path component is a string that is not allowed to have slashes or colons. The latter is to
 * make things easy to save in the colon-delimited Catalog Definition File format.
 *
 * The path of a catalog determines where in the catalog hierarchy the catalog is shown. Examples
 * are "Characters/Ellie/Poses/Hand" or "Kit_bash/City/Skyscrapers". The path looks like a
 * file-system path, with a few differences:
 *
 * - Only slashes are used as path component separators.
 * - All paths are absolute, so there is no need for a leading slash.
 *
 * See https://wiki.blender.org/wiki/Source/Architecture/Asset_System/Catalogs
 *
 * Paths are stored as byte sequences, and assumed to be UTF-8.
 */
class AssetCatalogPath {
  friend std::ostream &operator<<(std::ostream &stream, const AssetCatalogPath &path_to_append);

 private:
  /**
   * The path itself, such as "Agents/Secret/327".
   */
  std::string path_ = "";

 public:
  static const char SEPARATOR;

  AssetCatalogPath() = default;
  AssetCatalogPath(StringRef path);
  AssetCatalogPath(std::string path);
  AssetCatalogPath(const char *path);
  AssetCatalogPath(const AssetCatalogPath &other_path) = default;
  AssetCatalogPath(AssetCatalogPath &&other_path) noexcept;
  ~AssetCatalogPath() = default;

  uint64_t hash() const;
  uint64_t length() const; /* Length of the path in bytes. */

  /** C-string representation of the path. */
  const char *c_str() const;
  const std::string &str() const;

  /* The last path component, used as label in the tree view. */
  StringRefNull name() const;

  /* In-class operators, because of the implicit `AssetCatalogPath(StringRef)` constructor.
   * Otherwise `string == string` could cast both sides to `AssetCatalogPath`. */
  bool operator==(const AssetCatalogPath &other_path) const;
  bool operator!=(const AssetCatalogPath &other_path) const;
  bool operator<(const AssetCatalogPath &other_path) const;
  AssetCatalogPath &operator=(const AssetCatalogPath &other_path) = default;
  AssetCatalogPath &operator=(AssetCatalogPath &&other_path) = default;

  /** Concatenate two paths, returning the new path. */
  AssetCatalogPath operator/(const AssetCatalogPath &path_to_append) const;

  /* False when the path is empty, true otherwise. */
  operator bool() const;

  /**
   * Clean up the path. This ensures:
   * - Every path component is stripped of its leading/trailing spaces.
   * - Empty components (caused by double slashes or leading/trailing slashes) are removed.
   * - Invalid characters are replaced with valid ones.
   */
  [[nodiscard]] AssetCatalogPath cleanup() const;

  /**
   * \return true only if the given path is a parent of this catalog's path.
   * When this catalog's path is equal to the given path, return true as well.
   * In other words, this defines a weak subset.
   *
   * True: "some/path/there" is contained in "some/path" and "some".
   * False: "path/there" is not contained in "some/path/there".
   *
   * Note that non-cleaned-up paths (so for example starting or ending with a
   * slash) are not supported, and result in undefined behavior.
   */
  bool is_contained_in(const AssetCatalogPath &other_path) const;

  /**
   * \return the parent path, or an empty path if there is no parent.
   */
  AssetCatalogPath parent() const;

  /**
   * Change the initial part of the path from `from_path` to `to_path`.
   * If this path does not start with `from_path`, return an empty path as result.
   *
   * Example:
   *
   * AssetCatalogPath path("some/path/to/some/catalog");
   * path.rebase("some/path", "new/base") -> "new/base/to/some/catalog"
   */
  AssetCatalogPath rebase(const AssetCatalogPath &from_path,
                          const AssetCatalogPath &to_path) const;

  /** Call the callback function for each path component, in left-to-right order. */
  using ComponentIteratorFn = FunctionRef<void(StringRef component_name, bool is_last_component)>;
  void iterate_components(ComponentIteratorFn callback) const;

 protected:
  /** Strip leading/trailing spaces and replace disallowed characters. */
  static std::string cleanup_component(StringRef component_name);
};

/** Output the path as string. */
std::ostream &operator<<(std::ostream &stream, const AssetCatalogPath &path_to_append);

}  // namespace blender::bke