skia2/experimental/editor/stringslice.cpp
Hal Canary 66bf2cfb93 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>
2019-06-24 17:24:35 +00:00

83 lines
2.3 KiB
C++

// Copyright 2019 Google LLC.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
#include "experimental/editor/stringslice.h"
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <cstring>
using namespace editor;
void StringSlice::FreeWrapper::operator()(void* t) { std::free(t); }
StringSlice::StringSlice(StringSlice&& that)
: fPtr(std::move(that.fPtr))
, fLength(that.fLength)
, fCapacity(that.fCapacity)
{
that.fLength = 0;
that.fCapacity = 0;
}
StringSlice& StringSlice::operator=(StringSlice&& that) {
if (this != &that) {
this->~StringSlice();
new (this)StringSlice(std::move(that));
}
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);
char* s = fPtr.get();
assert(s);
if (offset != fLength) {
std::memmove(s + offset + length, s + offset, fLength - offset);
}
if (text) {
std::memcpy(s + offset, text, length);
} else {
std::memset(s + offset, 0, length);
}
fLength += length;
}
}
void StringSlice::remove(std::size_t offset, std::size_t length) {
if (length && offset < fLength) {
length = std::min(length, fLength - offset);
assert(length > 0);
assert(length + offset <= fLength);
if (length + offset < fLength) {
char* s = fPtr.get();
assert(s);
std::memmove(s + offset, s + offset + length, fLength - (length + offset));
}
fLength -= length;
}
}
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);
}