blob: 62cfe87ed50c2e60140646a988e03bd2d50645b1 [file] [log] [blame]
// Copyright 2011 The Goma 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 "content.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory>
#ifndef _WIN32
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#else
# include "config_win.h"
#endif
#include "scoped_fd.h"
#include <glog/logging.h>
namespace devtools_goma {
// static
std::unique_ptr<Content> Content::CreateFromFile(const string& filepath) {
ScopedFd fd(ScopedFd::OpenForRead(filepath));
if (!fd.valid())
return nullptr;
size_t len = 0;
if (!fd.GetFileSize(&len)) {
PLOG(ERROR) << "fd:" << fd << " filepath:" << filepath;
return nullptr;
}
return CreateFromFileDescriptor(filepath, fd, len);
}
// static
std::unique_ptr<Content> Content::CreateFromFileDescriptor(
const string& filepath, const ScopedFd& fd, size_t filesize) {
DCHECK(fd.valid());
std::unique_ptr<char[]> buf(new char[filesize + 1]);
CHECK(buf.get() != nullptr) << "filepath:" << filepath
<< "filesize:" << filesize;
char* buf_end = buf.get() + filesize;
*buf_end = '\0';
size_t offset = 0;
while (offset < filesize) {
ssize_t actual_read = fd.Read(buf.get() + offset, filesize - offset);
if (actual_read <= 0) {
PLOG(ERROR) << "fd: " << fd << " filepath:" << filepath
<< " offset: " << offset
<< " actual_read: " << actual_read;
return nullptr;
}
offset += actual_read;
}
if (offset != filesize) {
LOG(ERROR) << "size mismatch filepath:" << filepath << " fd:" << fd
<< " offset:" << offset << " filesize:" << filesize;
return CreateFromUnique(std::move(buf), offset);
}
return CreateFromUnique(std::move(buf), filesize);
}
// static
std::unique_ptr<Content> Content::CreateFromString(const string& str) {
std::unique_ptr<char[]> buf(new char[str.length() + 1]);
CHECK(buf != nullptr);
memcpy(static_cast<void*>(buf.get()),
static_cast<const void*>(str.data()),
str.length());
return CreateFromUnique(std::move(buf), str.length());
}
// static
std::unique_ptr<Content> Content::CreateFromContent(const Content& content) {
const size_t content_length = content.size();
return CreateFromBuffer(content.buf_.get(), content_length);
}
// static
std::unique_ptr<Content> Content::CreateFromBuffer(const char* buffer,
size_t len) {
std::unique_ptr<char[]> new_buffer(new char[len + 1]);
CHECK(new_buffer != nullptr);
memcpy(new_buffer.get(), buffer, len);
new_buffer[len] = '\0';
return CreateFromUnique(std::move(new_buffer), len);
}
// static
std::unique_ptr<Content> Content::CreateFromUnique(
std::unique_ptr<const char[]> buffer, size_t len) {
const char* buffer_end = buffer.get() + len;
return std::unique_ptr<Content>(new Content(std::move(buffer), buffer_end));
}
} // namespace devtools_goma