AttributedString.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #pragma once
  8. #include <functional>
  9. #include <memory>
  10. #include <folly/Hash.h>
  11. #include <folly/Optional.h>
  12. #include <react/attributedstring/TextAttributes.h>
  13. #include <react/core/Sealable.h>
  14. #include <react/core/ShadowNode.h>
  15. #include <react/debug/DebugStringConvertible.h>
  16. #include <react/mounting/ShadowView.h>
  17. namespace facebook {
  18. namespace react {
  19. class AttributedString;
  20. using SharedAttributedString = std::shared_ptr<const AttributedString>;
  21. /*
  22. * Simple, cross-platfrom, React-specific implementation of attributed string
  23. * (aka spanned string).
  24. * `AttributedString` is basically a list of `Fragments` which have `string` and
  25. * `textAttributes` + `shadowNode` associated with the `string`.
  26. */
  27. class AttributedString : public Sealable, public DebugStringConvertible {
  28. public:
  29. class Fragment {
  30. public:
  31. static std::string AttachmentCharacter();
  32. std::string string;
  33. TextAttributes textAttributes;
  34. ShadowView parentShadowView;
  35. /*
  36. * Returns true is the Fragment represents an attachment.
  37. * Equivalent to `string == AttachmentCharacter()`.
  38. */
  39. bool isAttachment() const;
  40. bool operator==(const Fragment &rhs) const;
  41. bool operator!=(const Fragment &rhs) const;
  42. };
  43. class Range {
  44. public:
  45. int location{0};
  46. int length{0};
  47. };
  48. using Fragments = better::small_vector<Fragment, 1>;
  49. /*
  50. * Appends and prepends a `fragment` to the string.
  51. */
  52. void appendFragment(const Fragment &fragment);
  53. void prependFragment(const Fragment &fragment);
  54. /*
  55. * Appends and prepends an `attributedString` (all its fragments) to
  56. * the string.
  57. */
  58. void appendAttributedString(const AttributedString &attributedString);
  59. void prependAttributedString(const AttributedString &attributedString);
  60. /*
  61. * Returns a read-only reference to a list of fragments.
  62. */
  63. Fragments const &getFragments() const;
  64. /*
  65. * Returns a reference to a list of fragments.
  66. */
  67. Fragments &getFragments();
  68. /*
  69. * Returns a string constructed from all strings in all fragments.
  70. */
  71. std::string getString() const;
  72. /*
  73. * Returns `true` if the string is empty (has no any fragments).
  74. */
  75. bool isEmpty() const;
  76. /**
  77. * Compares equality of TextAttributes of all Fragments on both sides.
  78. */
  79. bool compareTextAttributesWithoutFrame(const AttributedString &rhs) const;
  80. bool operator==(const AttributedString &rhs) const;
  81. bool operator!=(const AttributedString &rhs) const;
  82. #pragma mark - DebugStringConvertible
  83. #if RN_DEBUG_STRING_CONVERTIBLE
  84. SharedDebugStringConvertibleList getDebugChildren() const override;
  85. #endif
  86. private:
  87. Fragments fragments_;
  88. };
  89. } // namespace react
  90. } // namespace facebook
  91. namespace std {
  92. template <>
  93. struct hash<facebook::react::AttributedString::Fragment> {
  94. size_t operator()(
  95. const facebook::react::AttributedString::Fragment &fragment) const {
  96. return folly::hash::hash_combine(
  97. 0, fragment.string, fragment.textAttributes, fragment.parentShadowView);
  98. }
  99. };
  100. template <>
  101. struct hash<facebook::react::AttributedString> {
  102. size_t operator()(
  103. const facebook::react::AttributedString &attributedString) const {
  104. auto seed = size_t{0};
  105. for (const auto &fragment : attributedString.getFragments()) {
  106. seed = folly::hash::hash_combine(seed, fragment);
  107. }
  108. return seed;
  109. }
  110. };
  111. } // namespace std