У меня есть такой код:
ByteArray ret;
ret.resize( MAX( body_left, tmp_read.size() ) );
while ( body_left > 0 ) {
ByteArray::Write r = tmp_read.write();
int rec = 0;
err = connection->get_partial_data( r.ptr(), MIN( body_left, tmp_read.size() ), rec );
if ( rec > 0 ) {
ByteArray::Write w = ret.write();
copymem( w.ptr(), r.ptr(), rec );
body_left -= rec;
}
}
Мне сложно понять этот код. Несколько вопросов:
Является ret.resize(MAX(body_left,tmp_read.size()));
выделяя ByteArray
из самых высоких body_left
или же tmp_read.size()
?
В ByteArray::Write r = tmp_read.write();
делает r
стать указателем на место в пространстве, которое будет использоваться для записи данных?
В ByteArray::Write w = ret.write();
делает w
стать указателем как r
в предыдущем вопросе?
Также в этой строке:
copymem(w.ptr(),r.ptr(),rec);
Как я понимаю в этой строке, все данные, которые собираются по указателю r
копируется в местоположение под указателем w
, Проблема в том, что они разного размера, как переместить указатель w.ptr()
сохранить данные в целости и в правильном порядке? Или w.ptr()
является указателем на функцию, и это не должно быть проблемой.
Дополнительный контекст:
метод get_partial_data
возвращает фрагменты данных — скажем, 20, 20 и 10 байтов каждый.
переменная ret
должен иметь длину 50 байт и объединить эти куски в один ByteArray
,
К сожалению, я не могу найти определение ByteArray
в этом проекте, так что я думаю, что это часть другой библиотеки (может быть, libGL?).
Я знаю, что этот вопрос не очень точен, и я делаю прыжок веры, но если кто-то может мне помочь, я был бы благодарен.
Исходный класс и проект, этот код был взят из:
https://github.com/okamstudio/godot/blob/master/core/io/http_client.cpp
Линии 503-516.
Это в другой форме, так как я уже применил грязный хак (который не очень хорошо работает).
Ret.resize (MAX (body_left, tmp_read.size ())); выделяя
ByteArray самого высокого body_left или tmp_read.size ()?
MAX
скорее всего, это макрос, который возвращает больший из двух аргументов. Линия ret.resize(MAX(body_left,tmp_read.size()));
гарантирует, что ret
достаточно велика для любых операций записи, которые могут произойти.
В ByteArray :: Write r = tmp_read.write (); становится ли указатель на
место в пространстве, которое будет использоваться для записи данных?В ByteArray :: Write w = ret.write () ;, w становится указателем как r
в предыдущем вопросе?
Написать это класс, определенный в строке 187. записывать() является функцией, определенной в строке 209, которая возвращает Write
объект, а не указатель. Следовательно r
а также w
никогда не указатели.
class Write {
// ...
};
Write write() {
Write w;
// ...
return w;
}
Также в этой строке:
copymem(w.ptr(),r.ptr(),rec);
Как я понимаю в этой строке, все данные, которые собираются под
указатель r копируется в местоположение под указателем w. Проблема в
что они разного размера, как переместить указатель w.ptr () для сохранения данных
в целости и сохранности? Или w.ptr () — указатель на функцию
и это не должно быть проблемой.
copymem макрос, определенный в строке 36
#define copymem(m_to,m_from,m_count) \
do { \
unsigned char * _from=(unsigned char*)m_from; \
unsigned char * _to=(unsigned char*)m_to; \
int _count=m_count; \
for (int _i=0;_i<_count;_i++) \
_to[_i]=_from[_i]; \
} while (0);
Все, что этот код, похоже, делает, это копирует содержимое m_from
в m_to
, get_partial_data
кормит количество для чтения в rec
, который передается copymem
как m_count
,
Чтобы обернуть все, что я (мы) узнали до сих пор:
Оригинальный код был следующим:
ByteArray::Write r = tmp_read.write();
int rec=0;
err = connection->get_partial_data(r.ptr(),MIN(body_left,tmp_read.size()),rec);
if (rec>0) {
ByteArray ret;
ret.resize(rec);
ByteArray::Write w = ret.write();
copymem(w.ptr(),r.ptr(),rec);
body_left-=rec;
if (body_left==0) {
status=STATUS_CONNECTED;
}
return ret;
}
Где copymem — это макрос, который выглядит следующим образом:
#define copymem(m_to,m_from,m_count) \
do { \
unsigned char * _from=(unsigned char*)m_from; \
unsigned char * _to=(unsigned char*)m_to; \
int _count=m_count; \
for (int _i=0;_i<_count;_i++) \
_to[_i]=_from[_i]; \
} while (0);
Используя все, что мне объяснили, я отказался от использования макросов, потому что, как я понимаю, w.ptr () возвращает раздел памяти, и макрос всегда начинает копироваться с первого байта этого раздела. Макрос не поддерживает смещение или передачу указателей.
Конечный результат выглядит следующим образом:
ByteArray ret;
ret.resize(MAX(body_left,tmp_read.size()));
ByteArray::Write w = ret.write();
unsigned char * _to = (unsigned char*) w.ptr();
int _offset = 0;
while (body_left > 0) {
ByteArray::Write r = tmp_read.write();
int rec=0;
err = connection->get_partial_data(r.ptr(),MIN(body_left,tmp_read.size()),rec);
if (rec>0) {
unsigned char * _from=(unsigned char*)r.ptr();
for (int _i=0;_i<rec;_i++)
_to[_offset+_i]=_from[_i];
_offset += rec;
body_left-=rec;
}
}
if (body_left==0) {
status=STATUS_CONNECTED;
}
return ret;
Кто-нибудь может подтвердить, что это жизнеспособное решение или даже предложить улучшение?
Обновить. Я обнаружил, что на самом деле могу переместить w.ptr () по смещению для макроса, альтернативный код выглядит следующим образом:
ByteArray ret;
ret.resize(MAX(body_left,tmp_read.size()));
ByteArray::Write w = ret.write();
int _offset = 0;
while (body_left > 0) {
ByteArray::Write r = tmp_read.write();
int rec=0;
err = connection->get_partial_data(r.ptr(),MIN(body_left,tmp_read.size()),rec);
if (rec>0) {
copymem(w.ptr()+_offset,r.ptr(),rec);
body_left-=rec;
_offset += rec;
}
}
if (body_left==0) {
status=STATUS_CONNECTED;
}
return ret;
Комментарии / мнение?