📄 jma.cpp
字号:
} //Skip forward a given number of chunks void jma_open::chunk_seek(unsigned int chunk_num) throw(jma_errors) { //Check the stream is open if (!stream) { throw(JMA_NO_OPEN); } //Move forward over header stream.seekg(jma_total_header_length, ios::beg); unsigned char int4_buffer[UINT_SIZE]; while (chunk_num--) { //Read in size of chunk stream.read((char *)int4_buffer, UINT_SIZE); //Skip chunk plus it's CRC32 stream.seekg(charp_to_uint(int4_buffer)+UINT_SIZE, ios::cur); } } //Return a vector of pointers to each file in the JMA, the buffer to hold all the files //must be initilized outside. vector<unsigned char *> jma_open::get_all_files(unsigned char *buffer) throw(jma_errors) { //If there's no stream we can't read from it, so exit if (!stream) { throw(JMA_NO_OPEN); } //Seek to the first chunk chunk_seek(0); //Set the buffer that decompressed data goes to decompressed_buffer = buffer; //If the JMA is not solid if (chunk_size) { unsigned char int4_buffer[UINT_SIZE]; size_t size = get_total_size(files); //For each chunk in the file... for (size_t remaining_size = size; remaining_size; remaining_size -= chunk_size) { //Read the compressed size stream.read((char *)int4_buffer, UINT_SIZE); size_t compressed_size = charp_to_uint(int4_buffer); //Allocate memory of the correct size to hold the compressed data in the JMA //Throw error on failure as that is unrecoverable from try { compressed_buffer = new unsigned char[compressed_size]; } catch (bad_alloc xa) { throw(JMA_NO_MEM_ALLOC); } //Read all the compressed data in stream.read((char *)compressed_buffer, compressed_size); //Read the expected CRC of compressed data from the file stream.read((char *)int4_buffer, UINT_SIZE); //If it doesn't match, throw error and cleanup memory if (CRC32lib::CRC32(compressed_buffer, compressed_size) != charp_to_uint(int4_buffer)) { delete[] compressed_buffer; throw(JMA_BAD_FILE); } //Decompress the data, cleanup memory on failure if (!decompress_lzma_7z(compressed_buffer, compressed_size, decompressed_buffer+size-remaining_size, (remaining_size > chunk_size) ? chunk_size : remaining_size)) { delete[] compressed_buffer; throw(JMA_DECOMPRESS_FAILED); } delete[] compressed_buffer; } } else //Solidly compressed JMA { unsigned char int4_buffer[UINT_SIZE]; //read the size of the compressed data stream.read((char *)int4_buffer, UINT_SIZE); size_t compressed_size = charp_to_uint(int4_buffer); //Allocate memory of the right size to hold the compressed data in the JMA try { compressed_buffer = new unsigned char[compressed_size]; } catch (bad_alloc xa) { throw(JMA_NO_MEM_ALLOC); } //Copy the compressed data into memory stream.read((char *)compressed_buffer, compressed_size); size_t size = get_total_size(files); //Read the CRC of the compressed data stream.read((char *)int4_buffer, UINT_SIZE); //If it doesn't match, complain if (CRC32lib::CRC32(compressed_buffer, compressed_size) != charp_to_uint(int4_buffer)) { delete[] compressed_buffer; throw(JMA_BAD_FILE); } //decompress the data if (!decompress_lzma_7z(compressed_buffer, compressed_size, decompressed_buffer, size)) { delete[] compressed_buffer; throw(JMA_DECOMPRESS_FAILED); } delete[] compressed_buffer; } vector<unsigned char *> file_pointers; size_t size = 0; //For each file, add it's pointer to the vector, size is pointer offset in the buffer for (vector<jma_file_info>::iterator i = files.begin(); i != files.end(); i++) { i->buffer = decompressed_buffer+size; file_pointers.push_back(decompressed_buffer+size); size += i->size; } //Return the vector of pointers return(file_pointers); } //Extracts the file with a given name found in the archive to the given buffer void jma_open::extract_file(string& name, unsigned char *buffer) throw(jma_errors) { if (!stream) { throw(JMA_NO_OPEN); } size_t size_to_skip = 0; size_t our_file_size = 0; //Search through the vector of file information for (vector<jma_file_info>::iterator i = files.begin(); i != files.end(); i++) { if (i->name == name) { //Set the variable so we can tell we found it our_file_size = i->size; break; } //Keep a running total of size size_to_skip += i->size; } if (!our_file_size) //File with the specified name was not found in the archive { throw(JMA_FILE_NOT_FOUND); } //If the JMA only contains one file, we can skip a lot of overhead if (files.size() == 1) { get_all_files(buffer); return; } if (chunk_size) //we are using non-solid archive.. { unsigned int chunks_to_skip = size_to_skip / chunk_size; //skip over requisite number of chunks chunk_seek(chunks_to_skip); //Allocate memory for compressed and decompressed data unsigned char *comp_buffer = 0, *decomp_buffer = 0; try { //Compressed data size is <= non compressed size unsigned char *combined_buffer = new unsigned char[chunk_size*2]; comp_buffer = combined_buffer; decomp_buffer = combined_buffer+chunk_size; } catch (bad_alloc xa) { throw(JMA_NO_MEM_ALLOC); } size_t first_chunk_offset = size_to_skip % chunk_size; unsigned char int4_buffer[UINT_SIZE]; for (size_t i = 0; i < our_file_size;) { //Get size stream.read((char *) int4_buffer, UINT_SIZE); size_t compressed_size = charp_to_uint(int4_buffer); //Read all the compressed data in stream.read((char *)comp_buffer, compressed_size); //Read the CRC of the compressed data stream.read((char *)int4_buffer, UINT_SIZE); //If it doesn't match, complain if (CRC32lib::CRC32(comp_buffer, compressed_size) != charp_to_uint(int4_buffer)) { delete[] comp_buffer; throw(JMA_BAD_FILE); } //Decompress chunk if (!decompress_lzma_7z(comp_buffer, compressed_size, decomp_buffer, chunk_size)) { delete[] comp_buffer; throw(JMA_DECOMPRESS_FAILED); } else { size_t copy_amount = our_file_size-i > chunk_size ? chunk_size : our_file_size-i; copy_amount -= first_chunk_offset; memcpy(buffer+i, decomp_buffer+first_chunk_offset, copy_amount); first_chunk_offset = 0; i += copy_amount; } } delete[] comp_buffer; } else //Solid JMA { unsigned char *decomp_buffer = 0; try { decomp_buffer = new unsigned char[get_total_size(files)]; } catch (bad_alloc xa) { throw(JMA_NO_MEM_ALLOC); } get_all_files(decomp_buffer); memcpy(buffer, decomp_buffer+size_to_skip, our_file_size); delete[] decomp_buffer; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -