blob: 8f9f9788f6ad3bf0dbb87022e81751f0d7c7a0c3 [file] [log] [blame]
//===--- CompactArray.cpp -------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "sourcekitd/CompactArray.h"
#include "SourceKit/Core/LLVM.h"
#include "SourceKit/Support/UIdent.h"
#include "llvm/Support/MemoryBuffer.h"
#include <limits.h>
using namespace SourceKit;
using namespace sourcekitd;
template <typename T>
static void addScalar(T Val, SmallVectorImpl<uint8_t> &Buf) {
const uint8_t *ValPtr = reinterpret_cast<const uint8_t *>(&Val);
Buf.append(ValPtr, ValPtr + sizeof(Val));
}
CompactArrayBuilderImpl::CompactArrayBuilderImpl() {
// Offset 0 is used for empty strings.
StringBuffer += '\0';
}
void CompactArrayBuilderImpl::addImpl(uint8_t Val) {
addScalar(Val, EntriesBuffer);
}
void CompactArrayBuilderImpl::addImpl(unsigned Val) {
addScalar(Val, EntriesBuffer);
}
void CompactArrayBuilderImpl::addImpl(StringRef Val) {
addScalar(getOffsetForString(Val), EntriesBuffer);
}
void CompactArrayBuilderImpl::addImpl(UIdent Val) {
if (Val.isValid()) {
sourcekitd_uid_t uid = SKDUIDFromUIdent(Val);
addScalar(uid, EntriesBuffer);
} else {
addScalar(sourcekitd_uid_t(nullptr), EntriesBuffer);
}
}
void CompactArrayBuilderImpl::addImpl(Optional<llvm::StringRef> Val) {
if (Val.hasValue()) {
addImpl(Val.getValue());
} else {
addImpl(unsigned(-1));
}
}
unsigned CompactArrayBuilderImpl::getOffsetForString(StringRef Str) {
if (Str.empty())
return 0;
unsigned Offset = StringBuffer.size();
StringBuffer += Str;
StringBuffer += '\0';
return Offset;
}
std::unique_ptr<llvm::MemoryBuffer>
CompactArrayBuilderImpl::createBuffer() const {
std::unique_ptr<llvm::MemoryBuffer> Buf;
Buf = llvm::MemoryBuffer::getNewUninitMemBuffer(sizeInBytes());
copyInto(const_cast<char *>(Buf->getBufferStart()), Buf->getBufferSize());
return Buf;
}
void CompactArrayBuilderImpl::appendTo(SmallVectorImpl<char> &Buf) const {
size_t OrigSize = Buf.size();
size_t NewSize = OrigSize + sizeInBytes();
Buf.resize(NewSize);
copyInto(Buf.data() + OrigSize, NewSize - OrigSize);
}
void CompactArrayBuilderImpl::copyInto(char *BufPtr, size_t Length) const {
uint64_t EntriesBufSize = EntriesBuffer.size();
assert(Length >= sizeInBytes());
memcpy(BufPtr, &EntriesBufSize, sizeof(EntriesBufSize));
BufPtr += sizeof(EntriesBufSize);
memcpy(BufPtr, EntriesBuffer.data(), EntriesBufSize);
BufPtr += EntriesBufSize;
memcpy(BufPtr, StringBuffer.data(), StringBuffer.size());
}
bool CompactArrayBuilderImpl::empty() const {
return EntriesBuffer.empty();
}
size_t CompactArrayBuilderImpl::sizeInBytes() const {
return sizeof(uint64_t) + EntriesBuffer.size() + StringBuffer.size();
}
template <typename T>
static void readScalar(const uint8_t *Buf, T &Val) {
memcpy(&Val, Buf, sizeof(Val));
}
void CompactArrayReaderImpl::readImpl(size_t Offset, uint8_t &Val) {
readScalar(getEntriesBufStart() + Offset, Val);
}
void CompactArrayReaderImpl::readImpl(size_t Offset, unsigned &Val) {
readScalar(getEntriesBufStart() + Offset, Val);
}
void CompactArrayReaderImpl::readImpl(size_t Offset, const char * &Val) {
unsigned StrOffset;
readScalar(getEntriesBufStart() + Offset, StrOffset);
if (StrOffset == unsigned(-1)) {
Val = nullptr;
return;
}
Val = getStringBufStart() + StrOffset;
}
void CompactArrayReaderImpl::readImpl(size_t Offset, sourcekitd_uid_t &Val) {
readScalar(getEntriesBufStart() + Offset, Val);
}