Hal Canary | 0569447 | 2019-05-03 17:14:21 -0400 | [diff] [blame] | 1 | // Copyright 2019 Google LLC. |
| 2 | // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. |
| 3 | |
Hal Canary | a0b66fc | 2019-08-23 10:16:51 -0400 | [diff] [blame] | 4 | #include "modules/skplaintexteditor/include/stringslice.h" |
Hal Canary | 0569447 | 2019-05-03 17:14:21 -0400 | [diff] [blame] | 5 | |
| 6 | #include <algorithm> |
| 7 | #include <cassert> |
| 8 | #include <cstdlib> |
| 9 | #include <cstring> |
| 10 | |
Hal Canary | a0b66fc | 2019-08-23 10:16:51 -0400 | [diff] [blame] | 11 | using namespace SkPlainTextEditor; |
Hal Canary | 0569447 | 2019-05-03 17:14:21 -0400 | [diff] [blame] | 12 | |
| 13 | void StringSlice::FreeWrapper::operator()(void* t) { std::free(t); } |
| 14 | |
| 15 | StringSlice::StringSlice(StringSlice&& that) |
| 16 | : fPtr(std::move(that.fPtr)) |
| 17 | , fLength(that.fLength) |
| 18 | , fCapacity(that.fCapacity) |
| 19 | { |
| 20 | that.fLength = 0; |
| 21 | that.fCapacity = 0; |
| 22 | } |
| 23 | |
| 24 | StringSlice& StringSlice::operator=(StringSlice&& that) { |
| 25 | if (this != &that) { |
| 26 | this->~StringSlice(); |
| 27 | new (this)StringSlice(std::move(that)); |
| 28 | } |
| 29 | return *this; |
| 30 | } |
| 31 | |
Hal Canary | 66bf2cf | 2019-06-20 11:29:10 -0400 | [diff] [blame] | 32 | StringSlice& StringSlice::operator=(const StringSlice& that) { |
| 33 | if (this != &that) { |
| 34 | fLength = 0; |
| 35 | if (that.size() > 0) { |
| 36 | this->insert(0, that.begin(), that.size()); |
| 37 | } |
| 38 | } |
| 39 | return *this; |
| 40 | } |
| 41 | |
Hal Canary | 0569447 | 2019-05-03 17:14:21 -0400 | [diff] [blame] | 42 | void StringSlice::insert(std::size_t offset, const char* text, std::size_t length) { |
| 43 | if (length) { |
| 44 | offset = std::min(fLength, offset); |
Hal Canary | 66bf2cf | 2019-06-20 11:29:10 -0400 | [diff] [blame] | 45 | this->reserve(fLength + length); |
Hal Canary | 0569447 | 2019-05-03 17:14:21 -0400 | [diff] [blame] | 46 | char* s = fPtr.get(); |
| 47 | assert(s); |
| 48 | if (offset != fLength) { |
| 49 | std::memmove(s + offset + length, s + offset, fLength - offset); |
| 50 | } |
| 51 | if (text) { |
| 52 | std::memcpy(s + offset, text, length); |
| 53 | } else { |
| 54 | std::memset(s + offset, 0, length); |
| 55 | } |
| 56 | fLength += length; |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | void StringSlice::remove(std::size_t offset, std::size_t length) { |
| 61 | if (length && offset < fLength) { |
| 62 | length = std::min(length, fLength - offset); |
| 63 | assert(length > 0); |
| 64 | assert(length + offset <= fLength); |
| 65 | if (length + offset < fLength) { |
| 66 | char* s = fPtr.get(); |
| 67 | assert(s); |
| 68 | std::memmove(s + offset, s + offset + length, fLength - (length + offset)); |
| 69 | } |
| 70 | fLength -= length; |
| 71 | } |
| 72 | } |
| 73 | |
Hal Canary | 66bf2cf | 2019-06-20 11:29:10 -0400 | [diff] [blame] | 74 | void StringSlice::realloc(std::size_t size) { |
| 75 | // round up to multiple of (1 << kBits) bytes |
| 76 | static constexpr unsigned kBits = 4; |
| 77 | fCapacity = size ? (((size - 1) >> kBits) + 1) << kBits : 0; |
| 78 | assert(fCapacity % (1u << kBits) == 0); |
| 79 | assert(fCapacity >= size); |
| 80 | fPtr.reset((char*)std::realloc(fPtr.release(), fCapacity)); |
| 81 | assert(fCapacity >= fLength); |
Hal Canary | 0569447 | 2019-05-03 17:14:21 -0400 | [diff] [blame] | 82 | } |