blob: 99af6fb674dc5b3a99abe2525f5444e33f898149 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "crazy_linker_util.h"
#include <stdio.h>
namespace crazy {
// Return the base name from a file path. Important: this is a pointer
// into the original string.
// static
const char* GetBaseNamePtr(const char* path) {
const char* p = strrchr(path, '/');
if (!p)
return path;
else
return p + 1;
}
// static
const char String::kEmpty[] = "";
String::String() { Init(); }
String::String(const String& other) {
InitFrom(other.ptr_, other.size_);
}
String::String(String&& other) noexcept
: ptr_(other.ptr_), size_(other.size_), capacity_(other.capacity_) {
other.Init();
}
String::String(const char* str) {
InitFrom(str, ::strlen(str));
}
String::String(char ch) {
InitFrom(&ch, 1);
}
String::~String() {
if (HasValidPointer()) {
free(ptr_);
ptr_ = const_cast<char*>(kEmpty);
}
}
String::String(const char* str, size_t len) {
InitFrom(str, len);
}
String& String::operator=(String&& other) noexcept {
if (this != &other) {
this->~String(); // Free pointer if needed.
ptr_ = other.ptr_;
size_ = other.size_;
capacity_ = other.capacity_;
other.Init();
}
return *this;
}
void String::Assign(const char* str, size_t len) {
Resize(len);
if (len > 0) {
memcpy(ptr_, str, len);
}
}
void String::Append(const char* str, size_t len) {
if (len > 0) {
size_t old_size = size_;
Resize(size_ + len);
memcpy(ptr_ + old_size, str, len);
}
}
void String::Resize(size_t new_size) {
if (new_size > capacity_) {
size_t new_capacity = capacity_;
while (new_capacity < new_size) {
new_capacity += (new_capacity >> 1) + 16;
}
Reserve(new_capacity);
}
if (new_size > size_)
memset(ptr_ + size_, '\0', new_size - size_);
size_ = new_size;
if (HasValidPointer()) {
ptr_[size_] = '\0';
}
}
void String::Reserve(size_t new_capacity) {
char* old_ptr = HasValidPointer() ? ptr_ : nullptr;
// Always allocate one more byte for the trailing \0
ptr_ = reinterpret_cast<char*>(realloc(old_ptr, new_capacity + 1));
ptr_[new_capacity] = '\0';
capacity_ = new_capacity;
if (size_ > new_capacity)
size_ = new_capacity;
}
void String::InitFrom(const char* str, size_t len) {
Init();
if (str != nullptr && len != 0) {
Resize(len);
memcpy(ptr_, str, len);
}
}
bool String::operator==(const String& other) const {
return size_ == other.size_ && !::memcmp(ptr_, other.ptr_, size_);
}
bool String::operator==(const char* str) const {
return !::strcmp(ptr_, str);
}
VectorBase::~VectorBase() {
::free(data_);
}
VectorBase::VectorBase(VectorBase&& other) noexcept
: data_(other.data_), count_(other.count_), capacity_(other.capacity_) {
other.DoReset();
}
VectorBase& VectorBase::operator=(VectorBase&& other) noexcept {
if (&other != this) {
::free(data_);
data_ = other.data_;
count_ = other.count_;
capacity_ = other.capacity_;
other.DoReset();
}
return *this;
}
void VectorBase::DoResize(size_t new_count, size_t item_size) {
if (new_count > capacity_) {
DoReserve(new_count, item_size);
}
if (new_count > count_)
::memset(data_ + count_ * item_size, 0, (new_count - count_) * item_size);
count_ = new_count;
}
void VectorBase::DoReserve(size_t new_capacity, size_t item_size) {
data_ = static_cast<char*>(::realloc(data_, new_capacity * item_size));
capacity_ = new_capacity;
if (count_ > capacity_)
count_ = capacity_;
}
void* VectorBase::DoInsert(size_t pos, size_t item_size) {
return DoInsert(pos, 1, item_size);
}
void* VectorBase::DoInsert(size_t pos, size_t count, size_t item_size) {
if (pos >= count_)
pos = count_;
size_t new_count = count_ + count;
if (new_count > capacity_) {
size_t new_capacity = capacity_;
while (new_capacity < new_count) {
new_capacity += (new_capacity >> 2) + 4;
}
DoReserve(new_capacity, item_size);
}
char* from_data = data_ + pos * item_size;
char* to_data = from_data + count * item_size;
::memmove(to_data, from_data, (count_ - pos) * item_size);
::memset(from_data, 0, count * item_size);
count_ = new_count;
return from_data;
}
void VectorBase::DoRemove(size_t pos, size_t item_size) {
DoRemove(pos, 1, item_size);
}
void VectorBase::DoRemove(size_t pos, size_t count, size_t item_size) {
if (pos >= count_)
return;
if (count > count_ - pos)
count = count_ - pos;
char* to_data = data_ + pos * item_size;
char* from_data = to_data + count * item_size;
::memmove(to_data, from_data, (count_ - pos - count) * item_size);
count_ -= count;
}
} // namespace crazy