| // 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 |