229 lines
6.5 KiB
C++
229 lines
6.5 KiB
C++
/*
|
|
* Copyright 2016 WebAssembly Community Group participants
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef WABT_STREAM_H_
|
|
#define WABT_STREAM_H_
|
|
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "wabt/common.h"
|
|
|
|
namespace wabt {
|
|
|
|
/* whether to display the ASCII characters in the debug output for
|
|
* write_memory */
|
|
enum class PrintChars {
|
|
No = 0,
|
|
Yes = 1,
|
|
};
|
|
|
|
class Stream {
|
|
public:
|
|
explicit Stream(Stream* log_stream = nullptr);
|
|
virtual ~Stream() = default;
|
|
|
|
size_t offset() { return offset_; }
|
|
Result result() { return result_; }
|
|
|
|
void set_log_stream(Stream* stream) {
|
|
assert(stream);
|
|
log_stream_ = stream;
|
|
}
|
|
|
|
Stream& log_stream() {
|
|
assert(log_stream_);
|
|
return *log_stream_;
|
|
}
|
|
|
|
bool has_log_stream() const { return log_stream_ != nullptr; }
|
|
|
|
void ClearOffset() { offset_ = 0; }
|
|
void AddOffset(ssize_t delta);
|
|
|
|
void WriteData(const void* src,
|
|
size_t size,
|
|
const char* desc = nullptr,
|
|
PrintChars = PrintChars::No);
|
|
|
|
template <typename T>
|
|
void WriteData(const std::vector<T> src,
|
|
const char* desc,
|
|
PrintChars print_chars = PrintChars::No) {
|
|
if (!src.empty()) {
|
|
WriteData(src.data(), src.size() * sizeof(T), desc, print_chars);
|
|
}
|
|
}
|
|
|
|
void WriteDataAt(size_t offset,
|
|
const void* src,
|
|
size_t size,
|
|
const char* desc = nullptr,
|
|
PrintChars = PrintChars::No);
|
|
|
|
void MoveData(size_t dst_offset, size_t src_offset, size_t size);
|
|
|
|
void Truncate(size_t size);
|
|
|
|
void WABT_PRINTF_FORMAT(2, 3) Writef(const char* format, ...);
|
|
|
|
// Specified as uint32_t instead of uint8_t so we can check if the value
|
|
// given is in range before wrapping.
|
|
void WriteU8(uint32_t value,
|
|
const char* desc = nullptr,
|
|
PrintChars print_chars = PrintChars::No) {
|
|
assert(value <= UINT8_MAX);
|
|
Write(static_cast<uint8_t>(value), desc, print_chars);
|
|
}
|
|
void WriteU32(uint32_t value,
|
|
const char* desc = nullptr,
|
|
PrintChars print_chars = PrintChars::No) {
|
|
Write(value, desc, print_chars);
|
|
}
|
|
void WriteU64(uint64_t value,
|
|
const char* desc = nullptr,
|
|
PrintChars print_chars = PrintChars::No) {
|
|
Write(value, desc, print_chars);
|
|
}
|
|
void WriteU128(v128 value,
|
|
const char* desc = nullptr,
|
|
PrintChars print_chars = PrintChars::No) {
|
|
Write(value, desc, print_chars);
|
|
}
|
|
|
|
void WriteChar(char c,
|
|
const char* desc = nullptr,
|
|
PrintChars print_chars = PrintChars::No) {
|
|
WriteU8(static_cast<unsigned char>(c), desc, print_chars);
|
|
}
|
|
|
|
// Dump memory as text, similar to the xxd format.
|
|
void WriteMemoryDump(const void* start,
|
|
size_t size,
|
|
size_t offset = 0,
|
|
PrintChars print_chars = PrintChars::No,
|
|
const char* prefix = nullptr,
|
|
const char* desc = nullptr);
|
|
|
|
// Convenience functions for writing enums.
|
|
template <typename T>
|
|
void WriteU8Enum(T value,
|
|
const char* desc = nullptr,
|
|
PrintChars print_chars = PrintChars::No) {
|
|
WriteU8(static_cast<uint32_t>(value), desc, print_chars);
|
|
}
|
|
|
|
virtual void Flush() {}
|
|
|
|
protected:
|
|
virtual Result WriteDataImpl(size_t offset,
|
|
const void* data,
|
|
size_t size) = 0;
|
|
virtual Result MoveDataImpl(size_t dst_offset,
|
|
size_t src_offset,
|
|
size_t size) = 0;
|
|
virtual Result TruncateImpl(size_t size) = 0;
|
|
|
|
private:
|
|
template <typename T>
|
|
void Write(const T& data, const char* desc, PrintChars print_chars) {
|
|
#if WABT_BIG_ENDIAN
|
|
char tmp[sizeof(T)];
|
|
memcpy(tmp, &data, sizeof(tmp));
|
|
SwapBytesSized(tmp, sizeof(tmp));
|
|
WriteData(tmp, sizeof(tmp), desc, print_chars);
|
|
#else
|
|
WriteData(&data, sizeof(data), desc, print_chars);
|
|
#endif
|
|
}
|
|
|
|
size_t offset_;
|
|
Result result_;
|
|
// Not owned. If non-null, log all writes to this stream.
|
|
Stream* log_stream_;
|
|
};
|
|
|
|
struct OutputBuffer {
|
|
Result WriteToFile(std::string_view filename) const;
|
|
Result WriteToStdout() const;
|
|
|
|
void clear() { data.clear(); }
|
|
size_t size() const { return data.size(); }
|
|
|
|
std::vector<uint8_t> data;
|
|
};
|
|
|
|
class MemoryStream : public Stream {
|
|
public:
|
|
WABT_DISALLOW_COPY_AND_ASSIGN(MemoryStream);
|
|
MemoryStream(MemoryStream&&) = default;
|
|
explicit MemoryStream(Stream* log_stream = nullptr);
|
|
explicit MemoryStream(std::unique_ptr<OutputBuffer>&&,
|
|
Stream* log_stream = nullptr);
|
|
|
|
OutputBuffer& output_buffer() { return *buf_; }
|
|
std::unique_ptr<OutputBuffer> ReleaseOutputBuffer();
|
|
|
|
void Clear();
|
|
|
|
Result WriteToFile(std::string_view filename) {
|
|
return buf_->WriteToFile(filename);
|
|
}
|
|
|
|
protected:
|
|
Result WriteDataImpl(size_t offset, const void* data, size_t size) override;
|
|
Result MoveDataImpl(size_t dst_offset,
|
|
size_t src_offset,
|
|
size_t size) override;
|
|
Result TruncateImpl(size_t size) override;
|
|
|
|
private:
|
|
std::unique_ptr<OutputBuffer> buf_;
|
|
};
|
|
|
|
class FileStream : public Stream {
|
|
public:
|
|
WABT_DISALLOW_COPY_AND_ASSIGN(FileStream);
|
|
explicit FileStream(std::string_view filename, Stream* log_stream = nullptr);
|
|
explicit FileStream(FILE*, Stream* log_stream = nullptr);
|
|
FileStream(FileStream&&);
|
|
FileStream& operator=(FileStream&&);
|
|
~FileStream() override;
|
|
|
|
static std::unique_ptr<FileStream> CreateStdout();
|
|
static std::unique_ptr<FileStream> CreateStderr();
|
|
|
|
bool is_open() const { return file_ != nullptr; }
|
|
|
|
void Flush() override;
|
|
|
|
protected:
|
|
Result WriteDataImpl(size_t offset, const void* data, size_t size) override;
|
|
Result MoveDataImpl(size_t dst_offset,
|
|
size_t src_offset,
|
|
size_t size) override;
|
|
Result TruncateImpl(size_t size) override;
|
|
|
|
private:
|
|
FILE* file_;
|
|
size_t offset_;
|
|
bool should_close_;
|
|
};
|
|
|
|
} // namespace wabt
|
|
|
|
#endif /* WABT_STREAM_H_ */
|