Skip to content

Commit

Permalink
Add a Span layer to AttributedString
Browse files Browse the repository at this point in the history
  • Loading branch information
cubuspl42 committed Dec 1, 2023
1 parent a3f238a commit 9b35462
Show file tree
Hide file tree
Showing 18 changed files with 821 additions and 160 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ namespace facebook::react {

using Fragment = AttributedString::Fragment;
using Fragments = AttributedString::Fragments;
using FragmentHandle = AttributedString::FragmentHandle;

using Span = AttributedString::Span;
using Spans = AttributedString::Spans;

#pragma mark - Fragment

Expand Down Expand Up @@ -51,9 +55,25 @@ bool Fragment::operator!=(const Fragment& rhs) const {
return !(*this == rhs);
}

#pragma mark - AttributedString
#pragma mark - Span

const Fragments& Span::getFragments() const {
return fragments_;
}

Fragments& Span::getFragments() {
return fragments_;
}

void AttributedString::appendFragment(const Fragment& fragment) {
std::string Span::getString() const {
auto string = std::string{};
for (const auto& fragment : fragments_) {
string += fragment.string;
}
return string;
}

void Span::appendFragment(const Fragment& fragment) {
ensureUnsealed();

if (fragment.string.empty()) {
Expand All @@ -63,7 +83,7 @@ void AttributedString::appendFragment(const Fragment& fragment) {
fragments_.push_back(fragment);
}

void AttributedString::prependFragment(const Fragment& fragment) {
void Span::prependFragment(const Fragment& fragment) {
ensureUnsealed();

if (fragment.string.empty()) {
Expand All @@ -73,86 +93,196 @@ void AttributedString::prependFragment(const Fragment& fragment) {
fragments_.insert(fragments_.begin(), fragment);
}

bool Span::isEmpty() const {
return fragments_.empty();
}

bool Span::compareTextAttributesWithoutFrame(const Span& rhs) const {
if (fragments_.size() != rhs.fragments_.size()) {
return false;
}

for (size_t i = 0; i < fragments_.size(); i++) {
if (fragments_[i].textAttributes != rhs.fragments_[i].textAttributes ||
fragments_[i].string != rhs.fragments_[i].string) {
return false;
}
}

return true;
}

bool Span::isContentEqual(const Span& rhs) const {
if (fragments_.size() != rhs.fragments_.size()) {
return false;
}

for (size_t i = 0; i < fragments_.size(); i++) {
if (!fragments_[i].isContentEqual(rhs.fragments_[i])) {
return false;
}
}

return true;
}

int Span::countAttachments() const {
int count = 0;

for (const auto& fragment : fragments_) {
if (fragment.isAttachment()) {
count++;
}
}

return count;
}

bool Span::operator==(const Span& rhs) const {
return fragments_ == rhs.fragments_;
}

bool Span::operator!=(const Span& rhs) const {
return !(*this == rhs);
}

#pragma mark - AttributedString

void AttributedString::appendSpan(const Span& span) {
ensureUnsealed();

if (span.isEmpty()) {
return;
}

spans_.push_back(span);
}

void AttributedString::prependSpan(const Span& span) {
ensureUnsealed();

if (span.isEmpty()) {
return;
}

spans_.insert(spans_.begin(), span);
}

void AttributedString::appendAttributedString(
const AttributedString& attributedString) {
ensureUnsealed();
fragments_.insert(
fragments_.end(),
attributedString.fragments_.begin(),
attributedString.fragments_.end());
spans_.insert(
spans_.end(),
attributedString.spans_.begin(),
attributedString.spans_.end());
}

void AttributedString::prependAttributedString(
const AttributedString& attributedString) {
ensureUnsealed();
fragments_.insert(
fragments_.begin(),
attributedString.fragments_.begin(),
attributedString.fragments_.end());
spans_.insert(
spans_.begin(),
attributedString.spans_.begin(),
attributedString.spans_.end());
}

const Fragments& AttributedString::getFragments() const {
return fragments_;
const Spans& AttributedString::getSpans() const {
return spans_;
}

Fragments& AttributedString::getFragments() {
return fragments_;
Spans& AttributedString::getSpans() {
return spans_;
}

const Fragments AttributedString::getAllFragments() const {
auto fragments = Fragments{};

for (const auto& span : spans_) {
for (const auto& fragment : span.getFragments()) {
fragments.push_back(fragment);
}
}

return fragments;
}

Fragment& AttributedString::getFragment(FragmentHandle handle) {
return getSpans()[handle.spanIndex].getFragments()[handle.fragmentIndex];
}

const Fragment& AttributedString::getFragment(FragmentHandle handle) const {
return getSpans()[handle.spanIndex].getFragments()[handle.fragmentIndex];
}

std::string AttributedString::getString() const {
auto string = std::string{};
for (const auto& fragment : fragments_) {
string += fragment.string;
for (const auto& span : spans_) {
string += span.getString();
}
return string;
}

bool AttributedString::isEmpty() const {
return fragments_.empty();
return spans_.empty();
}

bool AttributedString::compareTextAttributesWithoutFrame(
const AttributedString& rhs) const {
if (fragments_.size() != rhs.fragments_.size()) {
if (spans_.size() != rhs.spans_.size()) {
return false;
}

for (size_t i = 0; i < fragments_.size(); i++) {
if (fragments_[i].textAttributes != rhs.fragments_[i].textAttributes ||
fragments_[i].string != rhs.fragments_[i].string) {
for (size_t i = 0; i < spans_.size(); i++) {
if (!spans_[i].compareTextAttributesWithoutFrame(rhs.spans_[i])) {
return false;
}
}

return true;
}

bool AttributedString::operator==(const AttributedString& rhs) const {
return fragments_ == rhs.fragments_;
}

bool AttributedString::operator!=(const AttributedString& rhs) const {
return !(*this == rhs);
}

bool AttributedString::isContentEqual(const AttributedString& rhs) const {
if (fragments_.size() != rhs.fragments_.size()) {
if (spans_.size() != rhs.spans_.size()) {
return false;
}

for (size_t i = 0; i < fragments_.size(); i++) {
if (!fragments_[i].isContentEqual(rhs.fragments_[i])) {
for (size_t i = 0; i < spans_.size(); i++) {
if (!spans_[i].isContentEqual(rhs.spans_[i])) {
return false;
}
}

return true;
}

int AttributedString::countAttachments() const {
int count = 0;

for (const auto& span : spans_) {
count += span.countAttachments();
}

return count;
}

void AttributedString::sealChildren() const {
for (const Span& span : spans_) {
span.seal();
}
}

bool AttributedString::operator==(const AttributedString& rhs) const {
return spans_ == rhs.spans_;
}

bool AttributedString::operator!=(const AttributedString& rhs) const {
return !(*this == rhs);
}

#pragma mark - DebugStringConvertible

#if RN_DEBUG_STRING_CONVERTIBLE
SharedDebugStringConvertibleList AttributedString::getDebugChildren() const {
SharedDebugStringConvertibleList Span::getDebugChildren() const {
auto list = SharedDebugStringConvertibleList{};

for (auto&& fragment : fragments_) {
Expand All @@ -168,6 +298,17 @@ SharedDebugStringConvertibleList AttributedString::getDebugChildren() const {

return list;
}

SharedDebugStringConvertibleList AttributedString::getDebugChildren() const {
auto list = SharedDebugStringConvertibleList{};

for (auto&& span : spans_) {
list.push_back(
std::make_shared<DebugStringConvertibleItem>("Span", span.getString()));
}

return list;
}
#endif

} // namespace facebook::react
Loading

0 comments on commit 9b35462

Please sign in to comment.