/*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#pragma once
#include <atomic>
+#include <cstddef>
+#include <ios>
#include <limits>
#include <type_traits>
template <class Pod, class T>
inline void podFill(Pod* b, Pod* e, T c) {
FBSTRING_ASSERT(b && e && b <= e);
- /*static*/ if (sizeof(T) == 1) {
- memset(b, c, e - b);
+ constexpr auto kUseMemset = sizeof(T) == 1;
+ /* static */ if (kUseMemset) {
+ memset(b, c, size_t(e - b));
} else {
auto const ee = b + ((e - b) & ~7u);
for (; b != ee; b += 8) {
std::atomic<size_t> refCount_;
Char data_[1];
+ constexpr static size_t getDataOffset() {
+ return offsetof(RefCounted, data_);
+ }
+
static RefCounted * fromData(Char * p) {
- return static_cast<RefCounted*>(
- static_cast<void*>(
- static_cast<unsigned char*>(static_cast<void*>(p))
- - sizeof(refCount_)));
+ return static_cast<RefCounted*>(static_cast<void*>(
+ static_cast<unsigned char*>(static_cast<void*>(p)) -
+ getDataOffset()));
}
static size_t refs(Char * p) {
}
static RefCounted * create(size_t * size) {
- // Don't forget to allocate one extra Char for the terminating
- // null. In this case, however, one Char is already part of the
- // struct.
- const size_t allocSize = goodMallocSize(
- sizeof(RefCounted) + *size * sizeof(Char));
+ const size_t allocSize =
+ goodMallocSize(getDataOffset() + (*size + 1) * sizeof(Char));
auto result = static_cast<RefCounted*>(checkedMalloc(allocSize));
result->refCount_.store(1, std::memory_order_release);
- *size = (allocSize - sizeof(RefCounted)) / sizeof(Char);
+ *size = (allocSize - getDataOffset()) / sizeof(Char) - 1;
return result;
}
static RefCounted * reallocate(Char *const data,
const size_t currentSize,
const size_t currentCapacity,
- const size_t newCapacity) {
- FBSTRING_ASSERT(newCapacity > 0 && newCapacity > currentSize);
+ size_t * newCapacity) {
+ FBSTRING_ASSERT(*newCapacity > 0 && *newCapacity > currentSize);
+ const size_t allocNewCapacity =
+ goodMallocSize(getDataOffset() + (*newCapacity + 1) * sizeof(Char));
auto const dis = fromData(data);
FBSTRING_ASSERT(dis->refCount_.load(std::memory_order_acquire) == 1);
- // Don't forget to allocate one extra Char for the terminating
- // null. In this case, however, one Char is already part of the
- // struct.
- auto result = static_cast<RefCounted*>(
- smartRealloc(dis,
- sizeof(RefCounted) + currentSize * sizeof(Char),
- sizeof(RefCounted) + currentCapacity * sizeof(Char),
- sizeof(RefCounted) + newCapacity * sizeof(Char)));
+ auto result = static_cast<RefCounted*>(smartRealloc(
+ dis,
+ getDataOffset() + (currentSize + 1) * sizeof(Char),
+ getDataOffset() + (currentCapacity + 1) * sizeof(Char),
+ allocNewCapacity));
FBSTRING_ASSERT(result->refCount_.load(std::memory_order_acquire) == 1);
+ *newCapacity = (allocNewCapacity - getDataOffset()) / sizeof(Char) - 1;
return result;
}
};
// small_[maxSmallSize].
FBSTRING_ASSERT(s <= maxSmallSize);
constexpr auto shift = kIsLittleEndian ? 0 : 2;
- small_[maxSmallSize] = (maxSmallSize - s) << shift;
+ small_[maxSmallSize] = char((maxSmallSize - s) << shift);
small_[s] = '\0';
FBSTRING_ASSERT(category() == Category::isSmall && size() == s);
}
if (minCapacity > ml_.capacity()) {
// Asking for more memory
auto const newRC = RefCounted::reallocate(
- ml_.data_, ml_.size_, ml_.capacity(), minCapacity);
+ ml_.data_, ml_.size_, ml_.capacity(), &minCapacity);
ml_.data_ = newRC->data_;
ml_.setCapacity(minCapacity, Category::isLarge);
}
// Specialization for const char*, const char*
FOLLY_MALLOC_NOINLINE
basic_fbstring(const value_type* b, const value_type* e, const A& /*a*/ = A())
- : store_(b, e - b) {
+ : store_(b, size_type(e - b)) {
}
// Nonstandard constructor
}
#elif defined(_MSC_VER)
// MSVC doesn't define __ostream_insert
- os.write(str.data(), str.size());
+ os.write(str.data(), std::streamsize(str.size()));
#else
std::__ostream_insert(os, str.data(), str.size());
#endif