experimental/editor: progress on newlines

Editor:
  - Editor::Shape(): Place end-of-line cursor correctly.
  - Editor::insert(): Allow insertion of '\n' character.
  - Don't try to reshape empty string each time.
  - Editor::insert(), Editor::setText(): Validate utf8 input
  - Editor::remove(): Delete across newlines.
  - Editor::copy(): implement.
  - Editor::text() Iterator.

App:
  - Implement Ctrl-c, Ctrl-x, Ctr-v
  - Implement Ctrl-s
  - Handle "Enter" key as "insert '\n'"

StringSlice:
  - Cleanup, copy ctor.

Change-Id: I724edb82c93b30f4d5279f5a99036459a21ca2cd
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/222508
Auto-Submit: Hal Canary <halcanary@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/experimental/editor/stringslice.cpp b/experimental/editor/stringslice.cpp
index 23fbcfa..fc78a35 100644
--- a/experimental/editor/stringslice.cpp
+++ b/experimental/editor/stringslice.cpp
@@ -29,10 +29,20 @@
     return *this;
 }
 
+StringSlice& StringSlice::operator=(const StringSlice& that) {
+    if (this != &that) {
+        fLength = 0;
+        if (that.size() > 0) {
+            this->insert(0, that.begin(), that.size());
+        }
+    }
+    return *this;
+}
+
 void StringSlice::insert(std::size_t offset, const char* text, std::size_t length) {
     if (length) {
         offset = std::min(fLength, offset);
-        this->reserve(fLength + length); // TODO: reserve extra???
+        this->reserve(fLength + length);
         char* s = fPtr.get();
         assert(s);
         if (offset != fLength) {
@@ -61,14 +71,12 @@
     }
 }
 
-void StringSlice::reserve(std::size_t length) {
-    if (length && length > fCapacity) {
-        fPtr.reset((char*)std::realloc(fPtr.release(), length));
-        fCapacity = length;
-    }
-}
-
-void StringSlice::shrink() {
-    fPtr.reset((char*)std::realloc(fPtr.release(), fLength));
-    fCapacity = fLength;
+void StringSlice::realloc(std::size_t size) {
+    // round up to multiple of (1 << kBits) bytes
+    static constexpr unsigned kBits = 4;
+    fCapacity = size ? (((size - 1) >> kBits) + 1) << kBits : 0;
+    assert(fCapacity % (1u << kBits) == 0);
+    assert(fCapacity >= size);
+    fPtr.reset((char*)std::realloc(fPtr.release(), fCapacity));
+    assert(fCapacity >= fLength);
 }