fork download
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <array>
  4. #include <streambuf>
  5. #include <cassert>
  6.  
  7. namespace GrosserWerner {
  8. template< unsigned N, unsigned Reserve = 0 >
  9. class BufferN : public std::streambuf
  10. {
  11. public:
  12. BufferN( std::streambuf* src )
  13. : src_( src )
  14. , p0_( 0 )
  15. {
  16. setg( buf_, buf_, buf_ );
  17. }
  18. protected:
  19. virtual int_type underflow() override
  20. {
  21. assert( gptr() != 0 ); // garantiert der Konstruktor
  22. assert( gptr() == egptr() ); // ...sollte der Aufrufer garantieren
  23. const int_type m = src_->sbumpc();
  24. if( traits_type::eq_int_type( m, traits_type::eof() ) )
  25. return traits_type::eof();
  26. if( egptr() == end() )
  27. {
  28. traits_type::move( buf_, buf_+(Reserve+1), N-1 );
  29. setg( buf_, buf_+(N-1), buf_+N );
  30. p0_ += Reserve+1;
  31. }
  32. else
  33. {
  34. setg( buf_, egptr(), egptr()+1 );
  35. }
  36. *gptr() = traits_type::to_char_type( m );
  37. return m;
  38. }
  39.  
  40. virtual pos_type seekoff( off_type off, std::ios_base::seekdir way, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) override
  41. {
  42. if( which != std::ios_base::in ) // nur input-Zeiger setzen erlaubt
  43. return pos_type( off_type(-1) );
  44. off_type local_off; // zeigt in den lokalen 'buf_'
  45. switch( way )
  46. {
  47. case std::ios_base::beg:
  48. local_off = off_type( off - p0_ );
  49. break;
  50.  
  51. case std::ios_base::cur:
  52. local_off = off + (gptr() - eback());
  53. break;
  54.  
  55. case std::ios_base::end: // not implemented
  56. default:
  57. return pos_type( off_type(-1) );
  58. }
  59. if( local_off < 0 || local_off > off_type(egptr() - eback()) )
  60. return pos_type( off_type(-1) ); // Fehler: local_off zeigt außerhalb der pending sequence
  61. setg( buf_, buf_+local_off, egptr() );
  62. return p0_ + local_off;
  63. }
  64. virtual pos_type seekpos( pos_type sp, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out ) override
  65. {
  66. return seekoff( off_type(sp - (p0_ + off_type(gptr() - eback()))), std::ios_base::cur, which );
  67. }
  68.  
  69. private:
  70. const char_type* end() const { return buf_ + sizeof(buf_)/sizeof(*buf_); }
  71. std::streambuf* src_;
  72. char_type buf_[N+Reserve];
  73. pos_type p0_;
  74. };
  75.  
  76. void parse1(std::istream& in, std::ostream& out)
  77. {
  78. out << "Format 1\n";
  79. std::istreambuf_iterator<char> i(in), j;
  80. std::copy(i, j, std::ostreambuf_iterator<char>(out));
  81. }
  82.  
  83. void parse2(std::istream& in, std::ostream& out)
  84. {
  85. out << "Format 2\n";
  86. std::istreambuf_iterator<char> i(in), j;
  87. std::copy(i, j, std::ostreambuf_iterator<char>(out));
  88. }
  89.  
  90. void parse(std::istream& in, std::ostream& out)
  91. {
  92. BufferN< 64, 1 > sb( in.rdbuf() );
  93. // ^- don't override the first character
  94. in.rdbuf( &sb );
  95. std::istreambuf_iterator< char > it( in );
  96. int magic = 17;
  97. for (int i = 0; i < 64; ++i)
  98. magic = 13*magic + *it++;
  99. in.seekg( 0, std::ios_base::beg );
  100. if ( magic%2 )
  101. parse1( in, out );
  102. else
  103. parse2( in, out );
  104. }
  105. }
  106.  
  107. namespace werni {
  108. void parse1(std::istreambuf_iterator<char> it, std::istreambuf_iterator<char> end,
  109. std::ostream& out, std::array<char, 64> const& arr)
  110. {
  111. out << "Format 1\n";
  112. std::ostreambuf_iterator<char> o(out);
  113. std::copy(arr.begin(), arr.end(), o);
  114. std::copy(++it, end, o);
  115. }
  116.  
  117. void parse2(std::istreambuf_iterator<char> it, std::istreambuf_iterator<char> end,
  118. std::ostream& out, std::array<char, 64> const& arr)
  119. {
  120. out << "Format 2\n";
  121. std::ostreambuf_iterator<char> o(out);
  122. std::copy(arr.begin(), arr.end(), o);
  123. std::copy(++it, end, o);
  124. }
  125.  
  126. void parse(std::istream& in, std::ostream& out)
  127. {
  128. std::istreambuf_iterator<char> it(in), end;
  129. std::array<char, 64> save;
  130. std::copy_n(it, 64, save.begin());
  131. int magic = 17;
  132. for (int i=0; i<64; ++i)
  133. magic = 13*magic + save[i];
  134. if (magic%2)
  135. parse1(it, end, out, save);
  136. else
  137. parse2(in, end, out, save);
  138. }
  139. }
  140.  
  141. int main(int argc, char *argv[])
  142. {
  143. std::ios_base::sync_with_stdio(false);
  144. if (argc != 2)
  145. std::cout << "usage: " << argv[0] << " [werni|Werner]";
  146. else if (std::string("werni") == argv[1])
  147. werni::parse(std::cin, std::cout);
  148. else
  149. GrosserWerner::parse(std::cin, std::cout);
  150. }
Success #stdin #stdout 0s 3040KB
stdin
Standard input is empty
stdout
usage: ./prog [werni|Werner]