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
4#include "modules/skplaintexteditor/include/stringslice.h"
5
6#include <algorithm>
7#include <cassert>
8#include <cstdlib>
9#include <cstring>
10
11using namespace SkPlainTextEditor;
12
13void StringSlice::FreeWrapper::operator()(void* t) { std::free(t); }
14
15StringSlice::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
24StringSlice& StringSlice::operator=(StringSlice&& that) {
25    if (this != &that) {
26        this->~StringSlice();
27        new (this)StringSlice(std::move(that));
28    }
29    return *this;
30}
31
32StringSlice& 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
42void StringSlice::insert(std::size_t offset, const char* text, std::size_t length) {
43    if (length) {
44        offset = std::min(fLength, offset);
45        this->reserve(fLength + length);
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
60void 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
74void 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);
82}
83