Source code
Revision control
Copy as Markdown
Other Tools
/*
* 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
*
*
* 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_ */