duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

writer.hpp (5440B)


      1 #ifndef _C4_YML_WRITER_HPP_
      2 #define _C4_YML_WRITER_HPP_
      3 
      4 #ifndef _C4_YML_COMMON_HPP_
      5 #include "./common.hpp"
      6 #endif
      7 
      8 #include <c4/substr.hpp>
      9 #include <stdio.h>  // fwrite(), fputc()
     10 #include <string.h> // memcpy()
     11 
     12 
     13 namespace c4 {
     14 namespace yml {
     15 
     16 
     17 /** Repeat-Character: a character to be written a number of times. */
     18 struct RepC
     19 {
     20     char c;
     21     size_t num_times;
     22 };
     23 inline RepC indent_to(size_t num_levels)
     24 {
     25     return {' ', size_t(2) * num_levels};
     26 }
     27 
     28 
     29 //-----------------------------------------------------------------------------
     30 //-----------------------------------------------------------------------------
     31 //-----------------------------------------------------------------------------
     32 /** A writer that outputs to a file. Defaults to stdout. */
     33 struct WriterFile
     34 {
     35     FILE * m_file;
     36     size_t m_pos;
     37 
     38     WriterFile(FILE *f = nullptr) : m_file(f ? f : stdout), m_pos(0) {}
     39 
     40     inline substr _get(bool /*error_on_excess*/)
     41     {
     42         substr sp;
     43         sp.str = nullptr;
     44         sp.len = m_pos;
     45         return sp;
     46     }
     47 
     48     template<size_t N>
     49     inline void _do_write(const char (&a)[N])
     50     {
     51         fwrite(a, sizeof(char), N - 1, m_file);
     52         m_pos += N - 1;
     53     }
     54 
     55     inline void _do_write(csubstr sp)
     56     {
     57         #if defined(__clang__)
     58         #   pragma clang diagnostic push
     59         #   pragma GCC diagnostic ignored "-Wsign-conversion"
     60         #elif defined(__GNUC__)
     61         #   pragma GCC diagnostic push
     62         #   pragma GCC diagnostic ignored "-Wsign-conversion"
     63         #endif
     64         if(sp.empty()) return;
     65         fwrite(sp.str, sizeof(csubstr::char_type), sp.len, m_file);
     66         m_pos += sp.len;
     67         #if defined(__clang__)
     68         #   pragma clang diagnostic pop
     69         #elif defined(__GNUC__)
     70         #   pragma GCC diagnostic pop
     71         #endif
     72     }
     73 
     74     inline void _do_write(const char c)
     75     {
     76         fputc(c, m_file);
     77         ++m_pos;
     78     }
     79 
     80     inline void _do_write(RepC const rc)
     81     {
     82         for(size_t i = 0; i < rc.num_times; ++i)
     83         {
     84             fputc(rc.c, m_file);
     85         }
     86         m_pos += rc.num_times;
     87     }
     88 };
     89 
     90 
     91 //-----------------------------------------------------------------------------
     92 //-----------------------------------------------------------------------------
     93 //-----------------------------------------------------------------------------
     94 /** A writer that outputs to an STL-like ostream. */
     95 template<class OStream>
     96 struct WriterOStream
     97 {
     98     OStream& m_stream;
     99     size_t   m_pos;
    100 
    101     WriterOStream(OStream &s) : m_stream(s), m_pos(0) {}
    102 
    103     inline substr _get(bool /*error_on_excess*/)
    104     {
    105         substr sp;
    106         sp.str = nullptr;
    107         sp.len = m_pos;
    108         return sp;
    109     }
    110 
    111     template<size_t N>
    112     inline void _do_write(const char (&a)[N])
    113     {
    114         m_stream.write(a, N - 1);
    115         m_pos += N - 1;
    116     }
    117 
    118     inline void _do_write(csubstr sp)
    119     {
    120         #if defined(__clang__)
    121         #   pragma clang diagnostic push
    122         #   pragma GCC diagnostic ignored "-Wsign-conversion"
    123         #elif defined(__GNUC__)
    124         #   pragma GCC diagnostic push
    125         #   pragma GCC diagnostic ignored "-Wsign-conversion"
    126         #endif
    127         if(sp.empty()) return;
    128         m_stream.write(sp.str, sp.len);
    129         m_pos += sp.len;
    130         #if defined(__clang__)
    131         #   pragma clang diagnostic pop
    132         #elif defined(__GNUC__)
    133         #   pragma GCC diagnostic pop
    134         #endif
    135     }
    136 
    137     inline void _do_write(const char c)
    138     {
    139         m_stream.put(c);
    140         ++m_pos;
    141     }
    142 
    143     inline void _do_write(RepC const rc)
    144     {
    145         for(size_t i = 0; i < rc.num_times; ++i)
    146         {
    147             m_stream.put(rc.c);
    148         }
    149         m_pos += rc.num_times;
    150     }
    151 };
    152 
    153 
    154 //-----------------------------------------------------------------------------
    155 //-----------------------------------------------------------------------------
    156 //-----------------------------------------------------------------------------
    157 /** a writer to a substr */
    158 struct WriterBuf
    159 {
    160     substr m_buf;
    161     size_t m_pos;
    162 
    163     WriterBuf(substr sp) : m_buf(sp), m_pos(0) {}
    164 
    165     inline substr _get(bool error_on_excess)
    166     {
    167         if(m_pos <= m_buf.len)
    168         {
    169             return m_buf.first(m_pos);
    170         }
    171         if(error_on_excess)
    172         {
    173             c4::yml::error("not enough space in the given buffer");
    174         }
    175         substr sp;
    176         sp.str = nullptr;
    177         sp.len = m_pos;
    178         return sp;
    179     }
    180 
    181     template<size_t N>
    182     inline void _do_write(const char (&a)[N])
    183     {
    184         RYML_ASSERT( ! m_buf.overlaps(a));
    185         if(m_pos + N-1 <= m_buf.len)
    186         {
    187             memcpy(&(m_buf[m_pos]), a, N-1);
    188         }
    189         m_pos += N-1;
    190     }
    191 
    192     inline void _do_write(csubstr sp)
    193     {
    194         if(sp.empty()) return;
    195         RYML_ASSERT( ! sp.overlaps(m_buf));
    196         if(m_pos + sp.len <= m_buf.len)
    197         {
    198             memcpy(&(m_buf[m_pos]), sp.str, sp.len);
    199         }
    200         m_pos += sp.len;
    201     }
    202 
    203     inline void _do_write(const char c)
    204     {
    205         if(m_pos + 1 <= m_buf.len)
    206         {
    207             m_buf[m_pos] = c;
    208         }
    209         ++m_pos;
    210     }
    211 
    212     inline void _do_write(RepC const rc)
    213     {
    214         if(m_pos + rc.num_times <= m_buf.len)
    215         {
    216             for(size_t i = 0; i < rc.num_times; ++i)
    217             {
    218                 m_buf[m_pos + i] = rc.c;
    219             }
    220         }
    221         m_pos += rc.num_times;
    222     }
    223 };
    224 
    225 
    226 } // namespace yml
    227 } // namespace c4
    228 
    229 #endif /* _C4_YML_WRITER_HPP_ */