将较小的数据块合并到一个较大的内存区中



我有这样的代码:

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()));是否分配最高body_lefttmp_read.size()ByteArray ?

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

行。

它的形状不同,因为我已经应用了dirty hack(效果不太好)。

ret.resize (MAX (body_left tmp_read.size ()));分配的ByteArray的最高body_left或tmp_read.size()?

MAX很可能是一个宏,返回两个参数中较大的一个。ret.resize(MAX(body_left,tmp_read.size()));行确保ret足够大,可以执行任何可能发生的写入操作。

In ByteArray::Write r = tmp_read.write();r变成指针了吗将用于写入数据的空间位置?

在ByteArray::Write w = ret.write();中,w是否变成像r一样的指针在上一个问题中?

Write是在第187行定义的类。write()是在第209行定义的函数,它返回一个Write对象,而不是一个指针。因此,rw绝不是指针。

class Write {
  // ...
};
Write write() {
  Write w;
  // ...
  return w; 
}

同样,在这一行:

copymem(w.ptr(),r.ptr(),rec);

我理解这一行,所有的数据是收集在指针r被复制到指针w下的位置,问题是它们的大小不同,如何移动指针w.ptr()来保存数据完好无损,顺序正确吗?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_toget_partial_data将要读的量输入rec,然后作为m_count传递给copymem

总结我(我们)所学到的一切:

原代码如下:

    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;

评论/意见吗?

最新更新