Path: blob/master/dep/rapidyaml/include/c4/yml/writer.hpp
4264 views
#ifndef _C4_YML_WRITER_HPP_1#define _C4_YML_WRITER_HPP_23#ifndef _C4_YML_COMMON_HPP_4#include "./common.hpp"5#endif67#include <c4/substr.hpp>8#include <stdio.h> // fwrite(), fputc()9#include <string.h> // memcpy()101112namespace c4 {13namespace yml {141516/** Repeat-Character: a character to be written a number of times. */17struct RepC18{19char c;20size_t num_times;21};22inline RepC indent_to(size_t num_levels)23{24return {' ', size_t(2) * num_levels};25}262728//-----------------------------------------------------------------------------29//-----------------------------------------------------------------------------30//-----------------------------------------------------------------------------31/** A writer that outputs to a file. Defaults to stdout. */32struct WriterFile33{34FILE * m_file;35size_t m_pos;3637WriterFile(FILE *f = nullptr) : m_file(f ? f : stdout), m_pos(0) {}3839inline substr _get(bool /*error_on_excess*/)40{41substr sp;42sp.str = nullptr;43sp.len = m_pos;44return sp;45}4647template<size_t N>48inline void _do_write(const char (&a)[N])49{50fwrite(a, sizeof(char), N - 1, m_file);51m_pos += N - 1;52}5354inline void _do_write(csubstr sp)55{56#if defined(__clang__)57# pragma clang diagnostic push58# pragma GCC diagnostic ignored "-Wsign-conversion"59#elif defined(__GNUC__)60# pragma GCC diagnostic push61# pragma GCC diagnostic ignored "-Wsign-conversion"62#endif63if(sp.empty()) return;64fwrite(sp.str, sizeof(csubstr::char_type), sp.len, m_file);65m_pos += sp.len;66#if defined(__clang__)67# pragma clang diagnostic pop68#elif defined(__GNUC__)69# pragma GCC diagnostic pop70#endif71}7273inline void _do_write(const char c)74{75fputc(c, m_file);76++m_pos;77}7879inline void _do_write(RepC const rc)80{81for(size_t i = 0; i < rc.num_times; ++i)82{83fputc(rc.c, m_file);84}85m_pos += rc.num_times;86}87};888990//-----------------------------------------------------------------------------91//-----------------------------------------------------------------------------92//-----------------------------------------------------------------------------93/** A writer that outputs to an STL-like ostream. */94template<class OStream>95struct WriterOStream96{97OStream& m_stream;98size_t m_pos;99100WriterOStream(OStream &s) : m_stream(s), m_pos(0) {}101102inline substr _get(bool /*error_on_excess*/)103{104substr sp;105sp.str = nullptr;106sp.len = m_pos;107return sp;108}109110template<size_t N>111inline void _do_write(const char (&a)[N])112{113m_stream.write(a, N - 1);114m_pos += N - 1;115}116117inline void _do_write(csubstr sp)118{119#if defined(__clang__)120# pragma clang diagnostic push121# pragma GCC diagnostic ignored "-Wsign-conversion"122#elif defined(__GNUC__)123# pragma GCC diagnostic push124# pragma GCC diagnostic ignored "-Wsign-conversion"125#endif126if(sp.empty()) return;127m_stream.write(sp.str, sp.len);128m_pos += sp.len;129#if defined(__clang__)130# pragma clang diagnostic pop131#elif defined(__GNUC__)132# pragma GCC diagnostic pop133#endif134}135136inline void _do_write(const char c)137{138m_stream.put(c);139++m_pos;140}141142inline void _do_write(RepC const rc)143{144for(size_t i = 0; i < rc.num_times; ++i)145{146m_stream.put(rc.c);147}148m_pos += rc.num_times;149}150};151152153//-----------------------------------------------------------------------------154//-----------------------------------------------------------------------------155//-----------------------------------------------------------------------------156/** a writer to a substr */157struct WriterBuf158{159substr m_buf;160size_t m_pos;161162WriterBuf(substr sp) : m_buf(sp), m_pos(0) {}163164inline substr _get(bool error_on_excess)165{166if(m_pos <= m_buf.len)167{168return m_buf.first(m_pos);169}170if(error_on_excess)171{172c4::yml::error("not enough space in the given buffer");173}174substr sp;175sp.str = nullptr;176sp.len = m_pos;177return sp;178}179180template<size_t N>181inline void _do_write(const char (&a)[N])182{183RYML_ASSERT( ! m_buf.overlaps(a));184if(m_pos + N-1 <= m_buf.len)185{186memcpy(&(m_buf[m_pos]), a, N-1);187}188m_pos += N-1;189}190191inline void _do_write(csubstr sp)192{193if(sp.empty()) return;194RYML_ASSERT( ! sp.overlaps(m_buf));195if(m_pos + sp.len <= m_buf.len)196{197memcpy(&(m_buf[m_pos]), sp.str, sp.len);198}199m_pos += sp.len;200}201202inline void _do_write(const char c)203{204if(m_pos + 1 <= m_buf.len)205{206m_buf[m_pos] = c;207}208++m_pos;209}210211inline void _do_write(RepC const rc)212{213if(m_pos + rc.num_times <= m_buf.len)214{215for(size_t i = 0; i < rc.num_times; ++i)216{217m_buf[m_pos + i] = rc.c;218}219}220m_pos += rc.num_times;221}222};223224225} // namespace yml226} // namespace c4227228#endif /* _C4_YML_WRITER_HPP_ */229230231