Re[2]: boost base64->bin, bin->base64 (интересная фигня)
От: nen777w  
Дата: 13.07.11 11:37
Оценка:
Обновляю исходник.
Привёл к человеческому виду. Добавил буферезацию потока. Изменил именна классов на:
istream_iterator_encode_to_base64
istream_iterator_decode_from_base64

  "Исходник"
#ifndef __base64_h__
#define __base64_h__

#include <cstddef> // NULL
#include <istream>
#include <xutility>
#include <memory.h>
#include "boost/iterator/iterator_facade.hpp"
#include "boost/shared_array.hpp"

namespace boost { namespace archive { namespace iterators {

        enum {
            prebuf_default_buffer_size = 5242880 /*5 Mb*/
        };

        // given a type, make an input iterator based on a pointer to that type
        template<class Elem = char, Elem eof_value = -1, long buffer_size = prebuf_default_buffer_size>
        class base64_istream_iterator_ :  
            public boost::iterator_facade<base64_istream_iterator_<Elem, eof_value, buffer_size>, Elem, std::input_iterator_tag, Elem>
        {
            friend class boost::iterator_core_access;

            typedef base64_istream_iterator_ this_t ;

            typedef BOOST_DEDUCED_TYPENAME boost::iterator_facade<
                base64_istream_iterator_<Elem, eof_value, buffer_size>,
                Elem,
                std::input_iterator_tag,
                Elem
            > super_t;

        protected:

            typedef BOOST_DEDUCED_TYPENAME std::basic_istream<Elem> istream_type;

            typedef BOOST_DEDUCED_TYPENAME boost::shared_array<Elem> shared_array;

            //Access the value referred to 
            Elem dereference() const {
                return m_current_value;
            }

            bool equal(const this_t & rhs) const {
                // note: only  works for comparison against end of stream
                return m_istream == rhs.m_istream;
            }

            bool pre_read() {

                assert( m_prebuf_pos >= m_prebuf_len );
                if( NULL != m_istream ) {
                    //calculate remain length of stream
                    istream_type::pos_type cur_pos = m_istream->tellg();
                    m_istream->seekg(-1, std::ios_base::end);
                    istream_type::pos_type end_pos = m_istream->tellg();
                    m_istream->seekg(cur_pos, std::ios_base::beg);
                    long remain = (long)(end_pos - cur_pos)+1;
                    assert(remain >= 0);
                    if( 0 == remain ) {
                        m_istream->get(); //eof
                        assert(! m_istream->good());
                        m_istream = NULL;
                        return false;
                    }
            
                    m_prebuf_len = min( remain, buffer_size );
                    m_istream->read( m_prebuf.get(), m_prebuf_len );
                    m_prebuf_pos = 0;
                    return true;
                }

                return false;
            }

            void increment() {

                ++m_prebuf_pos;
                if( m_prebuf_pos >= m_prebuf_len ) {
                    if( !pre_read() ) { 
                        m_current_value = eof_value; 
                        return; 
                    }
                }

                m_current_value = m_prebuf[m_prebuf_pos];
            }

        private:
            istream_type *m_istream;
            Elem          m_current_value;
            
            //pre-buffer
            shared_array    m_prebuf;
            //current pre-buffer length
            long        m_prebuf_len;
            //current position in pre-buffer
            long        m_prebuf_pos;
        public:
              base64_istream_iterator_(istream_type & is) 
                  : m_istream(& is)
                  , m_prebuf_len(0)
                  , m_prebuf_pos(0)
              {
                  m_prebuf.reset( new Elem[buffer_size] );
                  increment();
              }

              base64_istream_iterator_() 
                  : m_istream(NULL)
                  , m_prebuf_len(0)
                  , m_prebuf_pos(0)

              {}

              base64_istream_iterator_(const base64_istream_iterator_<Elem, eof_value, buffer_size> & rhs) 
                  : m_istream(rhs.m_istream)
                  , m_current_value(rhs.m_current_value)
                  , m_prebuf_len(rhs.m_prebuf_len)
                  , m_prebuf_pos(rhs.m_prebuf_pos)
                  , m_prebuf(rhs.m_prebuf)
              {}
        };

        //...........................................................................................................

        template<class Elem = char, long buffer_size = prebuf_default_buffer_size>
        class istream_iterator_encode_to_base64 : public base64_istream_iterator_<Elem, 0, buffer_size> 
        {            
            friend class boost::iterator_core_access;

            typedef base64_istream_iterator_<Elem, 0, buffer_size> base_;
            
        public:
            istream_iterator_encode_to_base64(BOOST_DEDUCED_TYPENAME base_::istream_type & is) 
                : base_(is)
            {}

            istream_iterator_encode_to_base64() 
                : base_()
            {}

            istream_iterator_encode_to_base64(const istream_iterator_encode_to_base64<Elem, buffer_size> & rhs) 
                : base_(rhs)
            {}
        };
        

        template<class Elem = char, long buffer_size = prebuf_default_buffer_size>
        class istream_iterator_decode_from_base64 : public base64_istream_iterator_<Elem, 65, buffer_size> 
        {
            friend class boost::iterator_core_access;

            typedef base64_istream_iterator_<Elem, 65, buffer_size> base_;
        
        public:
            istream_iterator_decode_from_base64(BOOST_DEDUCED_TYPENAME base_::istream_type & is) 
                : base_(is)
            {}

            istream_iterator_decode_from_base64() 
                : base_()
            {}

            istream_iterator_decode_from_base64(const istream_iterator_decode_from_base64<Elem, buffer_size> & rhs) 
                : base_(rhs)
            {}
        };

        //...........................................................................................................
        //...........................................................................................................


        template<class InIt, class OutIt>
        inline void __CLRCALL_OR_CDECL copy_base64_to_bin(InIt First, InIt Last, OutIt Dest)
        {
            for (; First != Last; ++Dest, ++First )
            {
                typename InIt::value_type val = *First;
                if( First != Last )
                    *Dest = val;
                else
                    break;
            }
        }
} } }

#endif


Жаль, но мои вопли по поводу этой баги boost-овциами небыли услышавны.
Возможно потому что плохо описал ошибку.
base64 boost::iterators
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.