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

时间:2014-08-21 01:30:55

标签: c++ pointers copymemory

我有这样的代码:

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()));分配ByteArraybody_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行。

它有不同的形状,因为我已经应用了肮脏的黑客(这样做不好)。

2 个答案:

答案 0 :(得分:1)

  

是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这样的指针   在上一个问题中?

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

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_toget_partial_data将要读取的金额提供给rec,该copymem作为m_count传递给{{1}}。

答案 1 :(得分: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 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);

使用remyable向我解释的所有内容我删除了宏用法,因为据我所知,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;

评论/意见?