Commit f9ee42ce authored by Kenton Varda's avatar Kenton Varda

Split array and string stuff out of type-safety.h.

parent 80f24a34
......@@ -28,6 +28,7 @@
#include "layout.h"
#include "list.h"
#include <kj/string.h>
namespace capnproto {
......
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "array.h"
namespace kj {
} // namespace kj
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef KJ_ARRAY_H_
#define KJ_ARRAY_H_
#include "common.h"
#include "memory.h"
#include <string.h>
namespace kj {
// =======================================================================================
// Array
template <typename T>
class Array {
// An owned array which will automatically be deleted in the destructor. Can be moved, but not
// copied.
public:
inline Array(): ptr(nullptr), size_(0) {}
inline Array(decltype(nullptr)): ptr(nullptr), size_(0) {}
inline Array(Array&& other) noexcept: ptr(other.ptr), size_(other.size_) {
other.ptr = nullptr;
other.size_ = 0;
}
KJ_DISALLOW_COPY(Array);
inline ~Array() noexcept { delete[] ptr; }
inline operator ArrayPtr<T>() {
return ArrayPtr<T>(ptr, size_);
}
inline operator ArrayPtr<const T>() const {
return ArrayPtr<T>(ptr, size_);
}
inline ArrayPtr<T> asPtr() {
return ArrayPtr<T>(ptr, size_);
}
inline size_t size() const { return size_; }
inline T& operator[](size_t index) const {
KJ_INLINE_DPRECOND(index < size_, "Out-of-bounds Array access.");
return ptr[index];
}
inline T* begin() const { return ptr; }
inline T* end() const { return ptr + size_; }
inline T& front() const { return *ptr; }
inline T& back() const { return *(ptr + size_ - 1); }
inline ArrayPtr<T> slice(size_t start, size_t end) {
KJ_INLINE_DPRECOND(start <= end && end <= size_, "Out-of-bounds Array::slice().");
return ArrayPtr<T>(ptr + start, end - start);
}
inline ArrayPtr<const T> slice(size_t start, size_t end) const {
KJ_INLINE_DPRECOND(start <= end && end <= size_, "Out-of-bounds Array::slice().");
return ArrayPtr<const T>(ptr + start, end - start);
}
inline bool operator==(decltype(nullptr)) const { return size_ == 0; }
inline bool operator!=(decltype(nullptr)) const { return size_ != 0; }
inline Array& operator=(decltype(nullptr)) {
delete[] ptr;
ptr = nullptr;
size_ = 0;
return *this;
}
inline Array& operator=(Array&& other) {
delete[] ptr;
ptr = other.ptr;
size_ = other.size_;
other.ptr = nullptr;
other.size_ = 0;
return *this;
}
private:
T* ptr;
size_t size_;
inline explicit Array(size_t size): ptr(new T[size]), size_(size) {}
inline Array(T* ptr, size_t size): ptr(ptr), size_(size) {}
template <typename U>
friend Array<U> newArray(size_t size);
template <typename U>
friend class ArrayBuilder;
};
template <typename T>
inline Array<T> newArray(size_t size) {
return Array<T>(size);
}
// =======================================================================================
// ArrayBuilder
template <typename T>
class ArrayBuilder {
// TODO(cleanup): This class doesn't work for non-primitive types because Slot is not
// constructable. Giving Slot a constructor/destructor means arrays of it have to be tagged
// so operator delete can run the destructors. If we reinterpret_cast the array to an array
// of T and delete it as that type, operator delete gets very upset.
//
// Perhaps we should bite the bullet and make the Array family do manual memory allocation,
// bypassing the rather-stupid C++ array new/delete operators which store a redundant copy of
// the size anyway.
union Slot {
T value;
char dummy;
};
static_assert(sizeof(Slot) == sizeof(T), "union is bigger than content?");
public:
explicit ArrayBuilder(size_t size): ptr(new Slot[size]), pos(ptr), endPtr(ptr + size) {}
~ArrayBuilder() {
for (Slot* p = ptr; p < pos; ++p) {
p->value.~T();
}
delete [] ptr;
}
template <typename... Params>
void add(Params&&... params) {
KJ_INLINE_DPRECOND(pos < endPtr, "Added too many elements to ArrayBuilder.");
new(&pos->value) T(kj::fwd<Params>(params)...);
++pos;
}
template <typename Container>
void addAll(Container&& container) {
Slot* __restrict__ pos_ = pos;
auto i = container.begin();
auto end = container.end();
while (i != end) {
pos_++->value = *i++;
}
pos = pos_;
}
Array<T> finish() {
// We could allow partial builds if Array<T> used a deleter callback, but that would make
// Array<T> bigger for no benefit most of the time.
KJ_INLINE_DPRECOND(pos == endPtr, "ArrayBuilder::finish() called prematurely.");
Array<T> result(reinterpret_cast<T*>(ptr), pos - ptr);
ptr = nullptr;
pos = nullptr;
endPtr = nullptr;
return result;
}
private:
Slot* ptr;
Slot* pos;
Slot* endPtr;
};
} // namespace kj
#endif // KJ_ARRAY_H_
......@@ -462,6 +462,63 @@ private:
friend U* internal::readMaybe(const Maybe<U&>& maybe);
};
// =======================================================================================
// ArrayPtr
//
// So common that we put it in common.h rather than array.h.
template <typename T>
class ArrayPtr {
// A pointer to an array. Includes a size. Like any pointer, it doesn't own the target data,
// and passing by value only copies the pointer, not the target.
public:
inline constexpr ArrayPtr(): ptr(nullptr), size_(0) {}
inline constexpr ArrayPtr(decltype(nullptr)): ptr(nullptr), size_(0) {}
inline constexpr ArrayPtr(T* ptr, size_t size): ptr(ptr), size_(size) {}
inline constexpr ArrayPtr(T* begin, T* end): ptr(begin), size_(end - begin) {}
inline operator ArrayPtr<const T>() {
return ArrayPtr<const T>(ptr, size_);
}
inline size_t size() const { return size_; }
inline T& operator[](size_t index) const {
KJ_INLINE_DPRECOND(index < size_, "Out-of-bounds ArrayPtr access.");
return ptr[index];
}
inline T* begin() const { return ptr; }
inline T* end() const { return ptr + size_; }
inline T& front() const { return *ptr; }
inline T& back() const { return *(ptr + size_ - 1); }
inline ArrayPtr slice(size_t start, size_t end) {
KJ_INLINE_DPRECOND(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice().");
return ArrayPtr(ptr + start, end - start);
}
inline bool operator==(decltype(nullptr)) { return size_ == 0; }
inline bool operator!=(decltype(nullptr)) { return size_ != 0; }
private:
T* ptr;
size_t size_;
};
template <typename T>
inline constexpr ArrayPtr<T> arrayPtr(T* ptr, size_t size) {
// Use this function to construct ArrayPtrs without writing out the type name.
return ArrayPtr<T>(ptr, size);
}
template <typename T>
inline constexpr ArrayPtr<T> arrayPtr(T* begin, T* end) {
// Use this function to construct ArrayPtrs without writing out the type name.
return ArrayPtr<T>(begin, end);
}
// =======================================================================================
// Upcast/downcast
......
......@@ -25,7 +25,7 @@
#define KJ_EXCEPTION_H_
#include <exception>
#include "type-safety.h"
#include "array.h"
namespace kj {
......
......@@ -26,7 +26,7 @@
#include <cstddef>
#include "common.h"
#include "type-safety.h"
#include "array.h"
namespace kj {
......
......@@ -112,11 +112,11 @@ static Array<char> makeDescription(DescriptionStyle style, const char* code, int
}
{
ArrayPtr<const char> expected = arrayPtr("expected ");
ArrayPtr<const char> codeArray = style == LOG ? nullptr : arrayPtr(code);
ArrayPtr<const char> sep = arrayPtr(" = ");
ArrayPtr<const char> delim = arrayPtr("; ");
ArrayPtr<const char> colon = arrayPtr(": ");
ArrayPtr<const char> expected = stringPtr("expected ");
ArrayPtr<const char> codeArray = style == LOG ? nullptr : stringPtr(code);
ArrayPtr<const char> sep = stringPtr(" = ");
ArrayPtr<const char> delim = stringPtr("; ");
ArrayPtr<const char> colon = stringPtr(": ");
if (style == ASSERTION && strcmp(code, "false") == 0) {
// Don't print "expected false", that's silly.
......@@ -127,7 +127,7 @@ static Array<char> makeDescription(DescriptionStyle style, const char* code, int
#if __USE_GNU
char buffer[256];
if (style == SYSCALL) {
sysErrorArray = arrayPtr(strerror_r(errorNumber, buffer, sizeof(buffer)));
sysErrorArray = stringPtr(strerror_r(errorNumber, buffer, sizeof(buffer)));
}
#else
// TODO(port): Other unixes should have strerror_r but it may have a different signature.
......
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "memory.h"
namespace kj {
Disposer::~Disposer() {}
} // namespace kj
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef KJ_MEMORY_H_
#define KJ_MEMORY_H_
#include "common.h"
namespace kj {
// =======================================================================================
class Disposer {
// Abstract interface for a thing that disposes of some other object. Often, it makes sense to
// decouple an object from the knowledge of how to dispose of it.
protected:
virtual ~Disposer();
public:
virtual void dispose(void* interiorPointer) = 0;
// Disposes of the object that this Disposer owns, and possibly disposes of the disposer itself.
//
// Callers must assume that the Disposer itself is no longer valid once this returns -- e.g. it
// might delete itself. Callers must in particular be sure not to call the Disposer again even
// when dispose() throws an exception.
//
// `interiorPointer` points somewhere inside of the object -- NOT necessarily at the beginning,
// especially in the presence of multiple inheritance. Most implementations should ignore the
// pointer, though a tricky memory allocator could get away with sharing one Disposer among
// multiple objects if it can figure out how to find the beginning of the object given an
// arbitrary interior pointer.
};
// =======================================================================================
// Own<T> -- An owned pointer.
template <typename T>
class Own {
// A transferrable title to a T. When an Own<T> goes out of scope, the object's Disposer is
// called to dispose of it. An Own<T> can be efficiently passed by move, without relocating the
// underlying object; this transfers ownership.
//
// This is much like std::unique_ptr, except:
// - You cannot release(). An owned object is not necessarily allocated with new (see next
// point), so it would be hard to use release() correctly.
// - The deleter is made polymorphic by virtual call rather than by template. This is a much
// more powerful default -- it allows any random module to decide to use a custom allocator.
// This could be accomplished with unique_ptr by forcing everyone to use e.g.
// std::unique_ptr<T, kj::Disposer&>, but at that point we've lost basically any benefit
// of interoperating with std::unique_ptr anyway.
public:
Own(const Own& other) = delete;
inline Own(Own&& other) noexcept
: disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
template <typename U>
inline Own(Own<U>&& other) noexcept
: disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
inline Own(T* ptr, Disposer* disposer) noexcept: disposer(disposer), ptr(ptr) {}
~Own() noexcept { dispose(); }
inline Own& operator=(Own&& other) {
dispose();
disposer = other.disposer;
ptr = other.ptr;
other.ptr = nullptr;
return *this;
}
inline T* operator->() { return ptr; }
inline const T* operator->() const { return ptr; }
inline T& operator*() { return *ptr; }
inline const T& operator*() const { return *ptr; }
inline T* get() { return ptr; }
inline const T* get() const { return ptr; }
inline operator T*() { return ptr; }
inline operator const T*() const { return ptr; }
private:
Disposer* disposer; // Only valid if ptr != nullptr.
T* ptr;
inline void dispose() {
// Make sure that if an exception is thrown, we are left with a null ptr, so we won't possibly
// dispose again.
void* ptrCopy = ptr;
if (ptrCopy != nullptr) {
ptr = nullptr;
disposer->dispose(ptrCopy);
}
}
};
namespace internal {
template <typename T>
class HeapValue final: public Disposer {
public:
template <typename... Params>
inline HeapValue(Params&&... params): value(kj::fwd<Params>(params)...) {}
virtual void dispose(void*) override { delete this; }
T value;
};
} // namespace internal
template <typename T, typename... Params>
Own<T> heap(Params&&... params) {
// heap<T>(...) allocates a T on the heap, forwarding the parameters to its constructor. The
// exact heap implementation is unspecified -- for now it is operator new, but you should not
// assume anything.
auto result = new internal::HeapValue<T>(kj::fwd<Params>(params)...);
return Own<T>(&result->value, result);
}
} // namespace kj
#endif // KJ_MEMORY_H_
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "string.h"
namespace kj {
String::String(const char* value): content(newArray<char>(strlen(value) + 1)) {
strcpy(content.begin(), value);
}
String::String(const char* value, size_t length): content(newArray<char>(length + 1)) {
memcpy(content.begin(), value, length);
content[length] = '\0';
}
} // namespace kj
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef KJ_STRING_H_
#define KJ_STRING_H_
#include "array.h"
#include <string.h>
namespace kj {
inline ArrayPtr<const char> stringPtr(const char* text) {
return arrayPtr(text, strlen(text));
}
// =======================================================================================
// String -- Just a NUL-terminated Array<char>.
class String {
public:
String() = default;
String(const char* value);
String(const char* value, size_t length);
inline ArrayPtr<char> asArray();
inline ArrayPtr<const char> asArray() const;
inline const char* cStr() const { return content == nullptr ? "" : content.begin(); }
inline size_t size() const { return content == nullptr ? 0 : content.size() - 1; }
inline char* begin() { return content == nullptr ? nullptr : content.begin(); }
inline char* end() { return content == nullptr ? nullptr : content.end() - 1; }
inline const char* begin() const { return content == nullptr ? nullptr : content.begin(); }
inline const char* end() const { return content == nullptr ? nullptr : content.end() - 1; }
private:
Array<char> content;
};
inline ArrayPtr<char> String::asArray() {
return content == nullptr ? ArrayPtr<char>(nullptr) : content.slice(0, content.size() - 1);
}
inline ArrayPtr<const char> String::asArray() const {
return content == nullptr ? ArrayPtr<char>(nullptr) : content.slice(0, content.size() - 1);
}
} // namespace kj
#endif // KJ_STRING_H_
......@@ -25,15 +25,4 @@
namespace kj {
Disposer::~Disposer() {}
String::String(const char* value): content(newArray<char>(strlen(value) + 1)) {
strcpy(content.begin(), value);
}
String::String(const char* value, size_t length): content(newArray<char>(length + 1)) {
memcpy(content.begin(), value, length);
content[length] = '\0';
}
} // namespace kj
This diff is collapsed.
......@@ -27,7 +27,8 @@
#include <initializer_list>
#include <utility>
#include <type_traits>
#include "type-safety.h"
#include "array.h"
#include "string.h"
#include <string.h>
namespace kj {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment