1
0

cmString.cxx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. // NOLINTNEXTLINE(bugprone-reserved-identifier)
  4. #define _SCL_SECURE_NO_WARNINGS
  5. #include "cmString.hxx"
  6. #include <memory>
  7. #include <ostream>
  8. #include <stdexcept>
  9. #include <string>
  10. namespace cm {
  11. static std::string const empty_string_;
  12. void String::internally_mutate_to_stable_string()
  13. {
  14. // We assume that only one thread mutates this instance at
  15. // a time even if we point to a shared string buffer referenced
  16. // by other threads.
  17. *this = String(this->data(), this->size());
  18. }
  19. bool String::is_stable() const
  20. {
  21. return this->str_if_stable() != nullptr;
  22. }
  23. void String::stabilize()
  24. {
  25. if (this->is_stable()) {
  26. return;
  27. }
  28. this->internally_mutate_to_stable_string();
  29. }
  30. std::string const* String::str_if_stable() const
  31. {
  32. if (!this->data()) {
  33. // We view no string.
  34. // This is stable for the lifetime of our current value.
  35. return &empty_string_;
  36. }
  37. if (this->string_ && this->data() == this->string_->data() &&
  38. this->size() == this->string_->size()) {
  39. // We view an entire string.
  40. // This is stable for the lifetime of our current value.
  41. return this->string_.get();
  42. }
  43. return nullptr;
  44. }
  45. std::string const& String::str()
  46. {
  47. if (std::string const* s = this->str_if_stable()) {
  48. return *s;
  49. }
  50. // Mutate to hold a std::string that is stable for the lifetime
  51. // of our current value.
  52. this->internally_mutate_to_stable_string();
  53. return *this->string_;
  54. }
  55. const char* String::c_str()
  56. {
  57. const char* c = this->data();
  58. if (!c) {
  59. return c;
  60. }
  61. // We always point into a null-terminated string so it is safe to
  62. // access one past the end. If it is a null byte then we can use
  63. // the pointer directly.
  64. if (c[this->size()] == '\0') {
  65. return c;
  66. }
  67. // Mutate to hold a std::string so we can get a null terminator.
  68. this->internally_mutate_to_stable_string();
  69. c = this->string_->c_str();
  70. return c;
  71. }
  72. String& String::insert(size_type index, size_type count, char ch)
  73. {
  74. std::string s;
  75. s.reserve(this->size() + count);
  76. s.assign(this->data(), this->size());
  77. s.insert(index, count, ch);
  78. return *this = std::move(s);
  79. }
  80. String& String::erase(size_type index, size_type count)
  81. {
  82. if (index > this->size()) {
  83. throw std::out_of_range("Index out of range in String::erase");
  84. }
  85. size_type const rcount = std::min(count, this->size() - index);
  86. size_type const rindex = index + rcount;
  87. std::string s;
  88. s.reserve(this->size() - rcount);
  89. s.assign(this->data(), index);
  90. s.append(this->data() + rindex, this->size() - rindex);
  91. return *this = std::move(s);
  92. }
  93. String String::substr(size_type pos, size_type count) const
  94. {
  95. if (pos > this->size()) {
  96. throw std::out_of_range("Index out of range in String::substr");
  97. }
  98. return String(*this, pos, count);
  99. }
  100. String::String(std::string&& s, Private)
  101. : string_(std::make_shared<std::string>(std::move(s)))
  102. , view_(this->string_->data(), this->string_->size())
  103. {
  104. }
  105. String::size_type String::copy(char* dest, size_type count,
  106. size_type pos) const
  107. {
  108. return this->view_.copy(dest, count, pos);
  109. }
  110. std::ostream& operator<<(std::ostream& os, String const& s)
  111. {
  112. return os.write(s.data(), s.size());
  113. }
  114. std::string& operator+=(std::string& self, String const& s)
  115. {
  116. return self += s.view();
  117. }
  118. String IntoString<char*>::into_string(const char* s)
  119. {
  120. if (!s) {
  121. return String();
  122. }
  123. return std::string(s);
  124. }
  125. string_view AsStringView<String>::view(String const& s)
  126. {
  127. return s.view();
  128. }
  129. } // namespace cm