Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> запись данных в буфер 
:(
    Опции темы
GoldFinch
Дата 24.5.2009, 20:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 6
Всего: 26



класс с буфером
Код

class basic_packetstream 
{
public:
    typedef std::vector<char> buf_t;
    static const int maxlength=0xFFFF;
protected:
    explicit basic_packetstream(Network& serv_):serv(serv_)
    {
        buf.reserve(maxlength);
    }
    buf_t buf;
};

class opacketstream: public basic_packetstream
{
public:
    opacketstream(Network& serv_):basic_packetstream(serv_) {};
    template<typename T> opacketstream& operator<<(T data);
};


код записи в буфер
Код

template<typename T>
opacketstream& opacketstream::operator<<( T data )
{
    buf_t::value_type* begin=reinterpret_cast<buf_t::value_type*>(&data);
    buf_t::value_type* end=begin+sizeof(data);
    buf.insert(buf.end(),begin,end);
    return *this;
}

несколько ранее код выглядел как
Код

template<typename T>
opacketstream& opacketstream::operator<<( T data )
{
    buf_t::iterator end=buf.end();
    buf.resize(buf.size()+sizeof(T));
    memcpy(&*end,&data,sizeof(T));
    return *this;
}

вроде должно быть оптимальнее за счет memcpy, но в отладочной версии не работает из за кривой реализации отладочной версии итератора end(), который при разыменовывании не проверяет новое значение _Mylast а юзает старое

как лучше организовать добавление в буфер данных различных типов?
PM MAIL ICQ   Вверх
mes
Дата 24.5.2009, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(GoldFinch @  24.5.2009,  19:44 Найти цитируемый пост)
как лучше организовать добавление в буфер данных различных типов? 

вариацией на тему :  перегрузка под конкретный тип.


Это сообщение отредактировал(а) mes - 24.5.2009, 21:08


--------------------
PM MAIL WWW   Вверх
GoldFinch
Дата 24.5.2009, 21:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 6
Всего: 26



mes, мне хочется писать любой POD тип, например так:
Код

    struct {
        char login[14];
        char password[16];
    }authdata={"foo","bar"};
    pout<<authdata;

вариант с insert мне не нравится тем что я сомневаюсь что insert развернет цикл и будет копировать по 4 байта
а вариант с memcpy (или __movsd) хорош из за ее intrinsic формы, но в отладочной версии не работает

Это сообщение отредактировал(а) GoldFinch - 24.5.2009, 21:54
PM MAIL ICQ   Вверх
GoldFinch
Дата 25.5.2009, 20:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 6
Всего: 26



Цитата(GoldFinch @  24.5.2009,  21:44 Найти цитируемый пост)
buf_t::iterator end=buf.end();

заменил на 
Код

char* dst=static_cast<char*>(&*buf.begin())+buf.size();

PM MAIL ICQ   Вверх
mes
Дата 25.5.2009, 20:12 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



я знаю, что Вы все равно останетесь при своем мнение, но, имхо, стиль программирования, продемонстрированный в этом топике, идет в разрез с принципами C++
и предполагаю, что именно из за этих двух причин, тема остается без ответов.





Это сообщение отредактировал(а) mes - 25.5.2009, 20:13


--------------------
PM MAIL WWW   Вверх
GoldFinch
Дата 25.5.2009, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 6
Всего: 26



mes, как же решить эту задачу, согласно принципам С++ ?
надо организовать бинарный буфер(поток) в который будут записываться данные различных типов, 
предпочитаемый синтаксис
Код

OutputPacketStream pout(...);
pout<<data1<<data2<<...<<stuff(n)<<...<<dataN<<chksum<<crypt(key)<<send;

где data1-dataN - данные различных типов
stuff(), chksum, crypt(), send - манипуляторы

на данный момент все комбинации и типы данных неизвестны, однако т.к. данные будут передаваться по сети, там будут только POD-типы
и как организовать эту запись разнородных данных?
PM MAIL ICQ   Вверх
mes
Дата 26.5.2009, 03:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(GoldFinch @  25.5.2009,  21:28 Найти цитируемый пост)
надо организовать бинарный буфер(поток)  

Код

class stream
{
    public:
        void write (const char* begin, const char* end) 
        {
               std::cout <<end-begin <<" "; for (;begin<end; ++begin) std::cout<<*begin;  // условное тело
        }
    private:

};

класс потока не должен обладать ничем лишним, кроме того что действительно ему требуется. В нашем случае мы ограничиваем его интерфейс функцией write,
принимающей на вход два условных итератора, на последовательность символов на входе, с которой можно манипулировать по своему желанию.

Цитата(GoldFinch @  25.5.2009,  21:28 Найти цитируемый пост)
в который будут записываться данные различных типов, 

Для этого перегружаем operator << для каждого нужного типа

Цитата(GoldFinch @  25.5.2009,  21:28 Найти цитируемый пост)
, там будут только POD-типы

для POD`ов можно пойти на уступку, и сделать функцию-конвертер, для получения нужных итераторов на бинарную последовательность
тут можно схимичить Вашим способом.
Код

template <class T>
/*inline*/ void pod_to_stream (stream & strm, T& data)
{
   char * begin = static_cast <char*>(static_cast<void*>(&data));
   strm.write (begin, begin+sizeof(data));
}

Но надо бы обеспечить гарантию того, что с помощью конвертера в поток попадут только подходящие типы.
тут два варианта, либо вручную для каждого типа описать оператор << (думаю самый оптимальный вариант)
Код

stream& operator << (stream & strm, test& pod) { pod_to_stream(strm, pod); }

либо привлечь кого-нибудь, например, Loki::TypeList или boost::is_pod.

в итоге :
Код

#include <iostream>
#include <vector>

class stream
{
    public:
        void write(const char* begin, const char* end) {std::cout <<end-begin <<" "; for (;begin<end; ++begin) std::cout<<*begin; };
    private:

};

template <class T>
inline void pod_to_stream (stream & strm, T& data)
{
   char * begin = static_cast <char*>(static_cast<void*>(&data));
   strm.write (begin, begin+sizeof(data));
}

struct test
{
    char a[5];
    char b[5];
} t = { "t_a", "t_b"},
  z = { "z_a", "z_b"};


stream& operator << (stream & strm, test& pod) { pod_to_stream(strm, pod); }

main(void)
{
    stream s;
    s<<t <<z << t << z;

    return 0;
}







Это сообщение отредактировал(а) mes - 26.5.2009, 03:07


--------------------
PM MAIL WWW   Вверх
GoldFinch
Дата 26.5.2009, 08:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 6
Всего: 26



mes, я не понимаю зачем писать сотни одинаковых строк кода, потом постоянно еще что дописывать, если можно применить 1 шаблон для любого типа.
Чтобы идиоты не смогли кинуть в поток указатель? Так ведь человек который понимает что он делает - указатели туда где они будут невалидными передавать не будет. А если случайно передаст, то на другом конце это сразу будет видно.
PM MAIL ICQ   Вверх
mes
Дата 26.5.2009, 09:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(GoldFinch @  26.5.2009,  07:50 Найти цитируемый пост)
mes, я не понимаю зачем писать сотни одинаковых строк кода, 

если уверены что все используемые объекты типа POD, напишите один шаблонный оператор. Суть не в этом, а в том, чтоб класс стрим был лишен знаний о конвертации.
также  чтоб не писать много, можно просто 
Цитата(mes @  26.5.2009,  02:06 Найти цитируемый пост)
привлечь кого-нибудь, например, Loki::TypeList или boost::is_pod.

Код

template <class T> stream& operator << (stream & strm, T& pod) { STATIC_CHECK(std::tr1::is_pod<T>::value) ; pod_to_stream(strm, pod); }


Цитата(GoldFinch @  26.5.2009,  07:50 Найти цитируемый пост)
Чтобы идиоты не смогли кинуть в поток указатель? Т

ну это легко решается, путем добавления шаблонной функции перегруженного для указателей.
Код

template <class T> stream& operator << (stream & strm, T* ptr) { STATIC_CHECK(false); }

ну или просто оставить ее без определения :
Код

template <class T> stream& operator << (stream & strm, T* ptr);


Это сообщение отредактировал(а) mes - 26.5.2009, 09:03


--------------------
PM MAIL WWW   Вверх
Lazin
Дата 26.5.2009, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 27
Всего: 154



Цитата(GoldFinch @  25.5.2009,  22:28 Найти цитируемый пост)
надо организовать бинарный буфер(поток) в который будут записываться данные различных типов, 
предпочитаемый синтаксис
Код

OutputPacketStream pout(...);
pout<<data1<<data2<<...<<stuff(n)<<...<<dataN<<chksum<<crypt(key)<<send;

оператор << какбэ намекает на то, что поток - символьный и данные форматируются, то-есть тут будет полный когнитивный диссонанс у человека, пытающегося написать свой оператор << для вашего буфера smile

Добавлено через 8 минут и 37 секунд
Код

namespace detail
{
    template<class T>
    char* begin(T & t);

    template<class T>
    char const* end(T & t);
}

class buffer
{
  std::vector<char> buff;

public:
...
  template<class T>
  buffer& write(T const& data)
  {
    std::insert_iterator<std::vector<char> > i(buff, buff.end());
    std::copy( detail::begin<T>(data), detail::end<T>(data), i );
    return *this;
  }
};

namespace detail
{
  template<>
  char* begin<MyType>(MyType & m)
  {
      return reinterpret_cast<char*>(&m);
  }
  template<>
  char const* end<MyType>(MyType & m)
  {
    return reinterpret_cast<char const*>(&m) + sizeof(MyType);
  }
}

PM MAIL Skype GTalk   Вверх
mes
Дата 26.5.2009, 09:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Lazin, а почему end указатель на константу, а begin нет ?



--------------------
PM MAIL WWW   Вверх
GoldFinch
Дата 26.5.2009, 11:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 6
Всего: 26



Цитата(Lazin @  26.5.2009,  10:13 Найти цитируемый пост)
оператор << какбэ намекает на то, что поток - символьный и данные форматируются

а на двоичный сдвиг он не намекает?
я не вижу никаких признаков символьности у этого оператора
PM MAIL ICQ   Вверх
Lazin
Дата 26.5.2009, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 27
Всего: 154



Цитата(mes @  26.5.2009,  09:54 Найти цитируемый пост)
Lazin, а почему end указатель на константу, а begin нет ?

потому-что делать *detail::end<SomeType>(mydata) = 0; в корне неправильно, begin то-же должен быть const smile

Добавлено через 4 минуты и 6 секунд
Цитата(GoldFinch @  26.5.2009,  11:02 Найти цитируемый пост)
а на двоичный сдвиг он не намекает?
я не вижу никаких признаков символьности у этого оператора

:facepalm
в контексте стандартной библиотеки потоков это именно форматирование, для записи в поток двоичных данных там используется метод write и метод put. Когда программист видит подобный синтаксис:
Код

OutputPacketStream pout(...);
pout<<data1<<data2<<...<<stuff(n)<<...<<dataN<<chksum<<crypt(key)<<send;

то о двоичном сдвиге он как-то незадумывается даже smile 
PM MAIL Skype GTalk   Вверх
mes
Дата 26.5.2009, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Lazin @  26.5.2009,  11:08 Найти цитируемый пост)
потому-что делать *detail::end<SomeType>(mydata) = 0; в корне неправильно, 

а делать *detail::begin<SomeType>(mydata)  =0;  правильно ?!  smile 
не знаю, как для Вас, но для меня в плане константности оба итератора равноправны.

Цитата(Lazin @  26.5.2009,  11:08 Найти цитируемый пост)
begin то-же должен быть const 

 smile

Добавлено через 4 минуты и 55 секунд
Цитата(mes @  26.5.2009,  02:06 Найти цитируемый пост)
template <class T>
inline void pod_to_stream (stream & strm, T& data)
{
   char * begin = static_cast <char*>(static_cast<void*>(&data));
   strm.write (begin, begin+sizeof(data));
}

вместо этой функции, будут лучше две функции возвращающие (условные) итераторы. 

Это сообщение отредактировал(а) mes - 26.5.2009, 12:33


--------------------
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0583 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.