// Copyright 2010-2020, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// 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.
// Provides CodeGenByteArrayStream class which generates C/C++ source code
// to define a byte array as a C string literal.
//
// Usage:
// ofstream ofs("output.cc");
// CodeGenByteArrayOutputStream codegen_stream(&ofs,
// codegenstream::NOT_OWN_STREAM);
// codegen_stream.OpenVarDef("MyVar");
// codegen_stream.put(single_byte_data);
// codegen_stream.write(large_data, large_data_size);
// codegen_stream.CloseVarDef();
#ifndef MOZC_BASE_CODEGEN_BYTEARRAY_STREAM_H_
#define MOZC_BASE_CODEGEN_BYTEARRAY_STREAM_H_
#include <algorithm>
#include <memory>
#include <ostream>
#include <streambuf>
#include <string>
#include "base/port.h"
#ifdef OS_ANDROID
// This is used only for code generation, so shouldn't be used from android
// platform.
#error \
"base/codegen_bytearray_stream.h shouldn't be used from android platform."
#endif
#ifdef OS_WIN
// Visual C++ does not support string literals longer than 65535 characters
// so integer arrays (e.g. arrays of uint64) are used to represent byte arrays
// on Windows.
//
// The generated code looks like:
// const uint64 kVAR_data_wordtype[] = {
// 0x0123456789ABCDEF, ...
// };
// const char * const kVAR_data =
// reinterpret_cast<const char *>(kVAR_data_wordtype);
// const size_t kVAR_size = 123;
//
// This implementation works well with other toolchains, too, but we use
// string literals for other toolchains.
//
// The generated code with a string literal looks like:
// const char kVAR_data[] =
// "\\x12\\x34\\x56\\x78...";
// const size_t kVAR_size = 123;
#define MOZC_CODEGEN_BYTEARRAY_STREAM_USES_WORD_ARRAY
#endif // OS_WIN
namespace mozc {
namespace codegenstream {
enum StreamOwner {
NOT_OWN_STREAM,
OWN_STREAM,
};
} // namespace codegenstream
class BasicCodeGenByteArrayStreamBuf : public std::streambuf {
public:
typedef std::char_traits<char> traits_type;
// Args:
// output_stream: The output stream to which generated code is written.
// own_output_stream: The object pointed to by |output_stream| will be
// destroyed if |own_output_stream| equals to |OWN_STREAM|.
BasicCodeGenByteArrayStreamBuf(std::ostream *output_stream,
codegenstream::StreamOwner own_output_stream);
~BasicCodeGenByteArrayStreamBuf() override;
// Writes the beginning of a variable definition.
bool OpenVarDef(const std::string &var_name_base);
// Writes the end of a variable definition.
bool CloseVarDef();
protected:
// Flushes.
int sync() override;
// Writes a given character sequence. The implementation is expected to be
// more efficient than the one of the base class.
std::streamsize xsputn(const char *s, std::streamsize n) override;
// Writes the data body of a variable definition.
int overflow(int c) override;
private:
static constexpr size_t kDefaultInternalBufferSize =
4000 * 1024; // 4 mega chars
#ifdef MOZC_CODEGEN_BYTEARRAY_STREAM_USES_WORD_ARRAY
static const size_t kNumOfBytesOnOneLine = 4 * sizeof(uint64);
#else
static constexpr size_t kNumOfBytesOnOneLine = 20;
#endif
// Converts a raw byte stream to C source code.
void WriteBytes(const char *begin, const char *end);
#ifdef MOZC_CODEGEN_BYTEARRAY_STREAM_USES_WORD_ARRAY
void WriteWordBuffer();
#endif
size_t internal_output_buffer_size_;
std::unique_ptr<char[]> internal_output_buffer_;
std::basic_ostream<char> *output_stream_;
codegenstream::StreamOwner own_output_stream_;
#ifdef MOZC_CODEGEN_BYTEARRAY_STREAM_USES_WORD_ARRAY
std::ios_base::fmtflags output_stream_format_flags_;
char output_stream_format_fill_;
#endif
bool is_open_;
std::string var_name_base_;
size_t output_count_;
#ifdef MOZC_CODEGEN_BYTEARRAY_STREAM_USES_WORD_ARRAY
uint64 word_buffer_;
#endif
DISALLOW_COPY_AND_ASSIGN(BasicCodeGenByteArrayStreamBuf);
};
class CodeGenByteArrayOutputStream : public std::ostream {
public:
// Args:
// output_stream: The output stream to which generated code is written.
// own_output_stream: The object pointed to by |output_stream| will be
// destroyed if |own_output_stream| equals to |OWN_STREAM|.
CodeGenByteArrayOutputStream(std::ostream *output_stream,
codegenstream::StreamOwner own_output_stream);
// Writes the beginning of a variable definition.
// A call to |OpenVarDef| must precede any output to the instance.
void OpenVarDef(const std::string &var_name_base);
// Writes the end of a variable definition.
// An output to the instance after a call to |CloseVarDef| is not allowed
// unless |OpenVarDef| is called with a different variable name.
void CloseVarDef();
private:
BasicCodeGenByteArrayStreamBuf streambuf_;
DISALLOW_COPY_AND_ASSIGN(CodeGenByteArrayOutputStream);
};
} // namespace mozc
#endif // MOZC_BASE_CODEGEN_BYTEARRAY_STREAM_H_