开发者

boost memorybuffer and char array

开发者 https://www.devze.com 2022-12-16 07:22 出处:网络
I\'m currently unpacking one of blizzard\'s .mpq file for reading. For accessing the unpacked char buffer, I\'m using a boost::interprocess::stream::memorybuffer.

I'm currently unpacking one of blizzard's .mpq file for reading. For accessing the unpacked char buffer, I'm using a boost::interprocess::stream::memorybuffer. Because .mpq files have a chunked structure always beginning with a version header (usually 12 bytes, see http://wiki.devklog.net/index.php?title=The_MoPaQ_Archive_Format#2.2_Archive_Header), the char* array representation seems to truncate at the first \0, even if the filesize (something about 1.6mb) remains constant and (probably) always allocated. The result is a streambuffer with an effective length of 4 ('REVM' and byte nr.5 is \0). When attempting to read further, an exception is thrown. Here an example:

    // (somewhere in the code)
{
    MPQFile curAdt(FilePath);    
    size_t size = curAdt.getSize(); // roughly 1.6 mb
    bufferstream memorybuf((char*)curAdt.getBuffer(), curAdt.getSize());
    // bufferstream.m_buf.m_buffer is now 'REVM\0' (Debugger says so), 
    // but internal length field still at 1.6 mb
}
//////////////////////////////////////////////////////////////////////////////

// wrapper around a file oof the mpq_archive of libmpq
MPQFile::MPQFile(const char* filename)    // I apologize my naming inconsistent convention :P
{
    for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
    {
        // gOpenArchives points to MPQArchive, wrapper around the mpq_archive, has mpq_archive * mpq_a as member
        mpq_archive &mpq_a = (*i)->mpq_a; 

        // if file exists in that archive, tested via hash table in file, not important here, scroll down if you want

        mpq_hash hash = (*i)->GetHashEntry(filename);
        uint32 blockindex = hash.blockindex;

        if ((blockindex == 0xFFFFFFFF) || (blockindex == 0)) {
            continue; //file not found
        }

        uint32 fileno = blockindex;

        // Found!
        size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, fileno);
        // HACK: in patch.mpq some files don't want to open and give 1 for filesize
        if (size<=1) {
            eof = true;
            buffer = 0;
            return;
        }
        buffer = new char[size];  // note: size is 1.6 mb at this time

        // Now here comes the tricky part... if I step over the libmpq_file_getdata
        // function, I'll get my truncated char array, which I absolutely don't want^^
        libmpq_file_getdata(&mpq_a, hash, f开发者_开发知识库ileno, (unsigned char*)buffer);
        return;
    }
}

Maybe someone could help me. I'm really new to STL and boost programming and also inexperienced in C++ programming anyways :P Hope to get a convenient answer (plz not suggest to rewrite libmpq and the underlying zlib architecture^^). The MPQFile class and the underlying uncompress methods are acutally taken from a working project, so the mistake is either somewhere in the use of the buffer with the streambuffer class or something internal with char array arithmetic I haven't a clue of. By the way, what is the difference between using signed/unsigned chars as data buffers? Has it anything to do with my problem (you might see, that in the code randomly char* unsigned char* is taken as function arguments) If you need more infos, feel free to ask :)


How are you determining that your char* array is being 'truncated' as you call it? If you're printing it or viewing it in a debugger it will look truncated because it will be treated like a string, which is terminated by \0. The data in 'buffer' however (assuming libmpq_file_getdata() does what it's supposed to do) will contain the whole file or data chunk or whatever.


Sorry, messed up a bit with these terms (not memorybuffer actually, streambuffer is meant as in the code)

Yeah you where right... I had a mistake in my exception handling. Right after that first bit of code comes this:

// check if the file has been open
//if (!mpf.is_open())
        pair<char*, size_t> temp = memorybuf.buffer();
        if(temp.first)
            throw AdtException(ADT_PARSEERR_EFILE);//Can't open the File

notice the missing ! before temp.first . I was surprized by the exception thrown, looked at the streambuffer .. internal buffer at was confused of its length (C# background :P). Sorry for that, it's working as expected now.

0

精彩评论

暂无评论...
验证码 换一张
取 消