+ /**
+ * Replaces the content of the range, starting at position 'pos', with
+ * contents of 'replacement'. Entire 'replacement' must fit into the
+ * range. Returns false if 'replacements' does not fit. Example use:
+ *
+ * char in[] = "buffer";
+ * auto msp = MutablesStringPiece(input);
+ * EXPECT_TRUE(msp.replaceAt(2, "tt"));
+ * EXPECT_EQ(msp, "butter");
+ *
+ * // not enough space
+ * EXPECT_FALSE(msp.replace(msp.size() - 1, "rr"));
+ * EXPECT_EQ(msp, "butter"); // unchanged
+ */
+ bool replaceAt(size_t pos, const_range_type replacement) {
+ if (size() < pos + replacement.size()) {
+ return false;
+ }
+
+ std::copy(replacement.begin(), replacement.end(), begin() + pos);
+
+ return true;
+ }
+
+ /**
+ * Replaces all occurences of 'source' with 'dest'. Returns number
+ * of replacements made. Source and dest have to have the same
+ * length. Throws if the lengths are different. If 'source' is a
+ * pattern that is overlapping with itself, we perform sequential
+ * replacement: "aaaaaaa".replaceAll("aa", "ba") --> "bababaa"
+ *
+ * Example use:
+ *
+ * char in[] = "buffer";
+ * auto msp = MutablesStringPiece(input);
+ * EXPECT_EQ(msp.replaceAll("ff","tt"), 1);
+ * EXPECT_EQ(msp, "butter");
+ */
+ size_t replaceAll(const_range_type source, const_range_type dest) {
+ if (source.size() != dest.size()) {
+ throw std::invalid_argument(
+ "replacement must have the same size as source");
+ }
+
+ if (dest.empty()) {
+ return 0;
+ }
+
+ size_t pos = 0;
+ size_t num_replaced = 0;
+ size_type found = std::string::npos;
+ while ((found = find(source, pos)) != std::string::npos) {
+ replaceAt(found, dest);
+ pos += source.size();
+ ++num_replaced;
+ }
+
+ return num_replaced;
+ }
+