2012-09-13 4 views
2

나는 장소에서 압축하고 싶은 문자 버퍼를 가지고있다. 지금 나는 두 개의 버퍼가 있고 zlib의 수축이 입력 버퍼에서 읽고 출력 버퍼에 씁니다. 그런 다음 출력 버퍼를 가리 키도록 입력 버퍼 포인터를 변경하고 이전 입력 버퍼를 해제해야합니다. 이것은 불필요한 할당량처럼 보입니다. zlib이 압축되기 때문에 next_out 포인터는 항상 next_in 포인터보다 뒤쳐져야합니다. 어쨌든, 나는 이것을 확인하기에 충분한 문서를 찾을 수없고 누군가가 이것에 대해 약간의 경험이 있었으면한다. 시간 내 줘서 고마워!zlib에서 동일한 메모리 버퍼를 읽고 쓸 수 있습니까?

답변

5

약간의주의를 기울여 수행 할 수 있습니다. 아래 루틴은 그것을 수행합니다. 모든 데이터가 압축 가능한 것은 아니므로 출력 데이터가 입력 데이터를 따라 잡는 경우를 처리해야합니다. 비압축성 데이터가 많이 발생하지만 코드에서 주석을 볼 수 있습니다.이 경우 버퍼를 할당하여 나머지 입력을 일시적으로 보관할 수 있습니다.

/* Compress buf[0..len-1] in place into buf[0..*max-1]. *max must be greater 
    than or equal to len. Return Z_OK on success, Z_BUF_ERROR if *max is not 
    enough output space, Z_MEM_ERROR if there is not enough memory, or 
    Z_STREAM_ERROR if *strm is corrupted (e.g. if it wasn't initialized or if it 
    was inadvertently written over). If Z_OK is returned, *max is set to the 
    actual size of the output. If Z_BUF_ERROR is returned, then *max is 
    unchanged and buf[] is filled with *max bytes of uncompressed data (which is 
    not all of it, but as much as would fit). 

    Incompressible data will require more output space than len, so max should 
    be sufficiently greater than len to handle that case in order to avoid a 
    Z_BUF_ERROR. To assure that there is enough output space, max should be 
    greater than or equal to the result of deflateBound(strm, len). 

    strm is a deflate stream structure that has already been successfully 
    initialized by deflateInit() or deflateInit2(). That structure can be 
    reused across multiple calls to deflate_inplace(). This avoids unnecessary 
    memory allocations and deallocations from the repeated use of deflateInit() 
    and deflateEnd(). */ 
int deflate_inplace(z_stream *strm, unsigned char *buf, unsigned len, 
        unsigned *max) 
{ 
    int ret;     /* return code from deflate functions */ 
    unsigned have;    /* number of bytes in temp[] */ 
    unsigned char *hold;  /* allocated buffer to hold input data */ 
    unsigned char temp[11];  /* must be large enough to hold zlib or gzip 
            header (if any) and one more byte -- 11 
            works for the worst case here, but if gzip 
            encoding is used and a deflateSetHeader() 
            call is inserted in this code after the 
            deflateReset(), then the 11 needs to be 
            increased to accomodate the resulting gzip 
            header size plus one */ 

    /* initialize deflate stream and point to the input data */ 
    ret = deflateReset(strm); 
    if (ret != Z_OK) 
     return ret; 
    strm->next_in = buf; 
    strm->avail_in = len; 

    /* kick start the process with a temporary output buffer -- this allows 
     deflate to consume a large chunk of input data in order to make room for 
     output data there */ 
    if (*max < len) 
     *max = len; 
    strm->next_out = temp; 
    strm->avail_out = sizeof(temp) > *max ? *max : sizeof(temp); 
    ret = deflate(strm, Z_FINISH); 
    if (ret == Z_STREAM_ERROR) 
     return ret; 

    /* if we can, copy the temporary output data to the consumed portion of the 
     input buffer, and then continue to write up to the start of the consumed 
     input for as long as possible */ 
    have = strm->next_out - temp; 
    if (have <= (strm->avail_in ? len - strm->avail_in : *max)) { 
     memcpy(buf, temp, have); 
     strm->next_out = buf + have; 
     have = 0; 
     while (ret == Z_OK) { 
      strm->avail_out = strm->avail_in ? strm->next_in - strm->next_out : 
               (buf + *max) - strm->next_out; 
      ret = deflate(strm, Z_FINISH); 
     } 
     if (ret != Z_BUF_ERROR || strm->avail_in == 0) { 
      *max = strm->next_out - buf; 
      return ret == Z_STREAM_END ? Z_OK : ret; 
     } 
    } 

    /* the output caught up with the input due to insufficiently compressible 
     data -- copy the remaining input data into an allocated buffer and 
     complete the compression from there to the now empty input buffer (this 
     will only occur for long incompressible streams, more than ~20 MB for 
     the default deflate memLevel of 8, or when *max is too small and less 
     than the length of the header plus one byte) */ 
    hold = strm->zalloc(strm->opaque, strm->avail_in, 1); 
    if (hold == Z_NULL) 
     return Z_MEM_ERROR; 
    memcpy(hold, strm->next_in, strm->avail_in); 
    strm->next_in = hold; 
    if (have) { 
     memcpy(buf, temp, have); 
     strm->next_out = buf + have; 
    } 
    strm->avail_out = (buf + *max) - strm->next_out; 
    ret = deflate(strm, Z_FINISH); 
    strm->zfree(strm->opaque, hold); 
    *max = strm->next_out - buf; 
    return ret == Z_OK ? Z_BUF_ERROR : (ret == Z_STREAM_END ? Z_OK : ret); 
} 
+0

굉장 !! 이 곳을 사랑해. 그리고 저는 긴 압축되지 않는 스트림이 없으므로 더 좋습니다! 엄청 고마워! – Ben

관련 문제