ogzstream failures

Started by
-1 comments, last by Plasmarobo 13 years, 4 months ago
Alright, so some of you may have heard of the popular game Minecraft.
The map files use a named-binary-tag format that is gzipped with zlib.
I'm a windows programmer and a C++ programmer, so naturally I am working with the self-built zlib using gzstream. My problem is that it doesn't work.

The code compiles beautifully, but even when fed a known valid gz file (tested via 7zip), it returns a true bad() call. I've tried every file path combination I can think of, relative, absolute, drive-root, and I simply cannot get this thing to work.

I could use some help on this one, I'll post my code, but really, I need a starting point. Others on the internet have had similar problems, but as far as I know gzstream support is limited, and most people seem to be programming in straight-up C.

So here are the files in this order:

<MCmapper.h>
<MCmapper.cpp>
<nbtdef.h>
<nbtdef.cpp>
#ifndef _MCMAPPER_H_#define _MCMAPPER_H_//#include <wx/dir.h>#include "nbtdef.h"//#include <string>//DATA MAPPINGSenum blocks{	air = 0,	stone,	grass,	dirt,	cobble,	board,	sapling,	bedrock,	water1,	water2,	lava1,	lava2,	sand,	shale,	gold,	iron,	coal,	wood,	leaf,	sponge,	glass,	c_r, c_o, c_y, c_l, c_g, c_ag, c_cy, c_b, c_p, c_in, c_vi, c_ma, c_pi, c_bl, c_gr, c_w, 	f_y, f_r,	m_b, m_r,	gold_b,	iron_b,	dstep,	step,	brick,	tnt,	shelf,	moss,	obsidian,	torch,	fire,	mod,	stair_w,	chest,	wire,	diamond,	diamond_b,	workbench,	crops,	soil,	furnace,	furnace_b,	sign,	door,	ladder,	rail,	stairs_s,	sign_w,	lever,	plate_s,	door_i,	redstone,	redstone_g,	torch_r,	torch_r_o,	button,	snow,	ice,	snow_b,	cactus,	clay,	reed,	phonograph,	fence,	pumpkin,	netherstone,	slow,	lightstone,	portal,	jac_o_lantern};class CHUNK{protected:	int x;	int z;	short blocks[16][16][128]; //X, Z, Ypublic:	CHUNK();};void EnumerateChunks(std::string filename);#endif

// MCmapper.cpp : Defines the entry point for the console application.//##include <wx/dir.h>#include <wx/filefn.h>#include <wx/arrstr.h>#include "MCmapper.h"void EnumerateChunks(std::string fname, wxArrayString &files, size_t &sz){	wxDir dir(wxGetCwd());	if(!dir.IsOpened()){		return;	}	//Enumerate files in directory	wxString filename(fname.c_str(), wxConvUTF8);	if(!dir.Open(filename))		return;	sz = dir.GetAllFiles(filename,&files);	//We now have every chunk file in the string array. We need to open each file	//read the chunk data and build the surface array	//for(int i = 0; i < sz-2; i++){	//	std::cout << std::string(files.mb_str()) << std::endl;	//}	//char a;	//std::cin >> a;}void NBTDUMP(wxString file, size_t sz, std::string fileout){	//READ THE FILE WITH AN NBT FILE	char buf[1024];//MAX 1024 length	strcpy(buf,(const char*) file.mb_str(wxConvUTF8));	std::string str(buf);	nbt_file f;	//f.ReadFile(buf);	f.ReadFile(buf);	std::ofstream files;	files.open(fileout.c_str());	if(files.is_open()){		//Begin dump		std::string str;		for(std::vector<nbt_tag>::iterator iter = f.Begin(); iter != f.End(); ++iter){			//For every tag, print it's string			//files << TypeToString(iter->GetType()) << std::endl;			switch (iter->GetType())    {	case nbt_type::TAG_END:            str = "TAG_END";            break;        case  nbt_type::TAG_BYTE:            str = "TAG_BYTE";            break;        case  nbt_type::TAG_SHORT:            str = "TAG_SHORT";            break;        case  nbt_type::TAG_INT:            str = "TAG_INT";            break;        case  nbt_type::TAG_LONG:            str = "TAG_LONG";            break;        case  nbt_type::TAG_FLOAT:            str = "TAG_FLOAT";            break;        case  nbt_type::TAG_DOUBLE:            str = "TAG_DOUBLE";            break;        case  nbt_type::TAG_BYTE_ARRAY:            str = "TAG_BYTE_ARRAY";            break;        case  nbt_type::TAG_STRING:            str = "TAG_STRING";            break;        case  nbt_type::TAG_LIST:            str = "TAG_LIST";            break;        case  nbt_type::TAG_COMPOUND:            str = "TAG_COMPOUND";            break;        default:            str = "TAG_Unknown";            break;		}			files << str << std::endl;		}		files.close();	}}void ExtractChunk(wxArrayString files, size_t sz, CHUNK** data){	};int main(int argc, char* argv[]){	wxArrayString files;	size_t s;	EnumerateChunks("world",files, s);	NBTDUMP(files[0],s,"dump.txt");	return 0;}

#ifndef NBTDEF_H_#define NBTDEF_H_#include <cstdint>//#define ZLIB_WINAPI#include "gzstream.h"#include <string>#include <list>#include <vector>//#include "endianness.h"#define L_ENDIAN 0#define B_ENDIAN    1int get_endianness();uint64_t swpd(double d);double uswpd(uint64_t d);float swapf(float);double swapd(double);void swaps(uint16_t *x);void swapi(uint32_t *x);void swapl(uint64_t *x);enum nbt_status{    NBT_OK   = 0,    NBT_ERR  = -1,    NBT_EMEM = -2,    NBT_EGZ  = -3};enum nbt_type{   TAG_END        = 0, /* No name, no payload */   TAG_BYTE       = 1, /* char, 8 bits, signed */   TAG_SHORT      = 2, /* short, 16 bits, signed */   TAG_INT        = 3, /* long, 32 bits, signed */   TAG_LONG       = 4, /* long long, 64 bits, signed */   TAG_FLOAT      = 5, /* float, 32 bits, signed */   TAG_DOUBLE     = 6, /* double, 64 bits, signed */   TAG_BYTE_ARRAY = 7, /* char *, 8 bits, unsigned, TAG_INT length */   TAG_STRING     = 8, /* char *, 8 bits, signed, TAG_SHORT length */   TAG_LIST       = 9, /* X *, X bits, TAG_INT length, no names inside */   TAG_COMPOUND   = 10 /* nbt_tag * */};//std::string TypeToString(nbt_type t);class nbt_tag{protected:	//THIS IS A TEMPLATE    nbt_type type; /* Type of the value */    std::string name;    /* tag name */	void *value;public:	nbt_tag();	nbt_tag(nbt_type t);	nbt_tag(nbt_type t, std::string n, void *v);	nbt_tag(const nbt_tag &rhs);	~nbt_tag();	void* GetValue();	nbt_type GetType();	void SetType(nbt_type t);	void SetName(std::string n);	std::string GetName();	void SetValue(void *v);	void SwapEndian();};class nbt_byte_array{protected:    int32_t length;    unsigned char *content;public:	nbt_byte_array();	nbt_byte_array(int32_t l, unsigned char *c);	nbt_byte_array(const nbt_byte_array &rhs);	~nbt_byte_array();	int32_t Size();	unsigned char *Get();};template <typename T>int nbt_read_tag(igzstream &fs, nbt_tag &t);class nbt_file{protected:	int _Read(igzstream &fs, char &t, nbt_tag &tg);	std::vector<nbt_tag> tags;public:	nbt_file();	nbt_file(const nbt_file &rhs);	nbt_file(std::vector<nbt_tag> t);	~nbt_file();	void ReadFile(igzstream &fs);	void ReadFile(std::string filename);	void ReadFile(const char* filename);	nbt_tag First();	std::vector<nbt_tag>::iterator Begin() {return tags.begin();}	std::vector<nbt_tag>::iterator End() {return tags.end();}	void WriteFile(std::string filename);	void AddTag(nbt_tag t, int index);};#endif NBTDEF_H_

#include <cstdint>#include "gzstream.h"#include "nbtdef.h"//#include "endianness.h"#include <string>nbt_tag::nbt_tag(nbt_type t) {type = t; name = ""; value = NULL;}nbt_tag::nbt_tag(){type = nbt_type::TAG_END; name = ""; value = NULL;}nbt_tag::nbt_tag(nbt_type t, std::string n, void *v){type = t; name = n; value = v;} nbt_tag::nbt_tag(const nbt_tag &rhs){type = rhs.type; name = rhs.name; delete value; memcpy(value,rhs.value,sizeof(rhs.value));}nbt_tag::~nbt_tag(){delete value;}void* nbt_tag::GetValue(){return value;}nbt_type nbt_tag::GetType(){return type;}void nbt_tag::SetValue(void *v){delete value; memcpy(value, v, sizeof(v));}void nbt_tag::SetType(nbt_type t){type = t;}void nbt_tag::SetName(std::string n){name= n;}void nbt_tag::SwapEndian(){	switch(type){	case TAG_END:		break;	case TAG_BYTE:		break;	case TAG_SHORT:		if(get_endianness() == L_ENDIAN)			swaps((uint16_t*)value);		break;	case TAG_INT:		if(get_endianness() == L_ENDIAN)			swapi((uint32_t*)value);		break;	case TAG_LONG:		if(get_endianness() == L_ENDIAN)			swapl((uint64_t*)value);		break;	case TAG_FLOAT:		if(get_endianness() == L_ENDIAN)			swapf(*((float*)value));		break;	case TAG_DOUBLE:		if(get_endianness() == L_ENDIAN)			swapd(*((double*)value));		break;	case TAG_BYTE_ARRAY:		break;	}}nbt_byte_array::nbt_byte_array(){content = NULL; length = 0;}nbt_byte_array::nbt_byte_array(int32_t l, unsigned char *c){length = l; delete content; memcpy(content, c, l);}nbt_byte_array::nbt_byte_array(const nbt_byte_array &rhs){length = rhs.length; delete content; memcpy(content, rhs.content, length);}nbt_byte_array::~nbt_byte_array(){delete content;}int32_t nbt_byte_array::Size(){return length;}unsigned char *nbt_byte_array::Get(){return content;}nbt_file::nbt_file(){}nbt_file::nbt_file(const nbt_file &rhs){		tags = rhs.tags;	}nbt_file::nbt_file(std::vector<nbt_tag> t){		tags = t;	}nbt_file::~nbt_file(){}int read_name(igzstream &fs, nbt_tag &t){	char *buffer;    int16_t len;	fs.read((char*)&len, sizeof(len));	if(get_endianness() == L_ENDIAN)	swaps((uint16_t *)&len);	buffer = new char[len];	fs.read(buffer, len);	std::string str(buffer);	delete [] buffer;	buffer = NULL;	t.SetName(str);	return 0;}template <typename T> int nbt_read(igzstream &fs, nbt_tag &t){	t.SetValue((void*)(new T));	read_name(fs, t);	fs.read((char*)t.GetValue(), sizeof(T));	return 1;}	void nbt_file::ReadFile(igzstream &fs){		char t = nbt_type::TAG_END;		int i = 0;		fs.read((char*)&i, t);		nbt_tag tg;		while(_Read(fs, t, tg)){			tags.push_back(tg);		}		tags.push_back(tg);	}	int nbt_file::_Read(igzstream &fs, char &t, nbt_tag &tg){		fs.read(&t, 1);					tg.SetType((nbt_type) t);					switch (t)		{        case TAG_END:			return 0;            break;         case TAG_BYTE:			nbt_read<char>(fs,tg);            break;        case TAG_SHORT:            nbt_read<int16_t>(fs, tg);			            break;        case TAG_INT:            nbt_read<int32_t>(fs,tg);			break;        case TAG_LONG:            nbt_read<int64_t>(fs, tg);            break;        case TAG_FLOAT:            nbt_read<float>(fs, tg);            break;        case TAG_DOUBLE:            nbt_read<double>(fs, tg);            break;        case TAG_STRING:            { /* to make it shut up about the variable declaration */				//This function uses a lot of hackery, we assign the std::string varaible rather than a char array				//because the nbt_tag destructor does not expect an array pointer				read_name(fs, tg);			char *buffer;           // std::string *str = new std::string;            int16_t len;			fs.read((char*)&len, sizeof(len));			if(get_endianness() == L_ENDIAN)				swaps((uint16_t *)&len);			buffer = new char[len];			fs.read(buffer, len);			std::string *str = new std::string(buffer);			delete [] buffer;			buffer = NULL;			tg.SetValue(str);			}            break;        case TAG_BYTE_ARRAY:			{				read_name(fs, tg);				std::list<unsigned char> *lst = new std::list<unsigned char>;            unsigned char *buffer;            //int32_t len = nbt_read_byte_array(nbt, &bytestring);			int32_t len;			fs.read((char*)&len, sizeof(len));			if(get_endianness() == L_ENDIAN)				swapi((uint32_t *)&len);            buffer = new unsigned char[len];			fs.read((char*)buffer, len);			for(int i = 0; i < len; ++i)				lst->push_back(buffer);			tg.SetValue(lst);			delete [] buffer;			buffer = NULL;			}            break;        case TAG_LIST:			{				read_name(fs, tg);				std::list<nbt_tag> *lst = new std::list<nbt_tag>;				char type;				int32_t len;				fs.read(&type,1); //All tags share a type in a list				fs.read((char*)&len, sizeof(len)); //Length of tag seqeuence				for(int i = 0; i < len; ++i){					lst->push_back(nbt_tag());					_Read(fs, type, lst->back());				}				tg.SetValue(lst);			}            break;        case TAG_COMPOUND:			{				//Series of tags of different types				//Create a vector and read in types to the vector until the next TAG END				read_name(fs, tg);				std::list<nbt_tag> *lst = new std::list<nbt_tag>;				char type;				do{					fs.read(&type,1);					lst->push_back(nbt_tag());				} while(_Read(fs, t,lst->back())==1);			}			break;		}		return 1;		}	void  nbt_file::ReadFile(std::string filename){		igzstream fs;		fs.open(filename.c_str(),std::ios::binary | std::ios::in | std::ios::app);		if(fs.good())			ReadFile(fs);	}	void nbt_file::ReadFile(const char* filename){		igzstream fs;		fs.open(filename, std::ios::binary | std::ios::in | std::ios::app);		if(!fs.bad())		ReadFile(fs);		fs.close();	}		nbt_tag  nbt_file::First(){		return tags.front();	}	void  nbt_file::WriteFile(std::string filename){} // Don't worry about this for now	void  nbt_file::AddTag(nbt_tag t, int index){} // Don't worry about this for now	int get_endianness(){    union    {        uint32_t i;        char c[4];    } t = { 0x01020304 };    return t.c[0] == 1;}uint64_t swpd(double d){    int i;    uint64_t res;    unsigned char *dest = (unsigned char *)&res;    unsigned char *src  = (unsigned char *)&d;    for (i = 0; i < 8; ++i)        dest = src[7 - i];    return res;}double uswpd(uint64_t d){    int i;    double res;    unsigned char *src  = (unsigned char *)&res;    unsigned char *dest = (unsigned char *)&d;    for (i = 0; i < 8; ++i)        dest = src[7 - i];    return res;}float swapf(float fx){    float rv;    char *ftc = (char *)&fx;    char *rtf = (char *)&rv;    rtf[0] = ftc[3];    rtf[1] = ftc[2];    rtf[2] = ftc[1];    rtf[3] = ftc[0];    return rv;}double swapd(double dx){    double rv;    char *ftc = (char *)&dx;    char *rtv = (char *)&rv;    rtv[0] = ftc[7];    rtv[1] = ftc[6];    rtv[2] = ftc[5];    rtv[3] = ftc[4];    rtv[4] = ftc[3];    rtv[5] = ftc[2];    rtv[6] = ftc[1];    rtv[7] = ftc[0];    return rv;}void swaps(uint16_t *x){    *x = (*x >> 8) | (*x << 8);}void swapi(uint32_t *x){    *x = (*x >> 24) |         ((*x<<8) & 0x00FF0000) |         ((*x>>8) & 0x0000FF00) |         (*x << 24);}void swapl(uint64_t *x){    *x = (*x>>56) |          ((*x<<40) & 0x00FF000000000000ULL) |         ((*x<<24) & 0x0000FF0000000000ULL) |         ((*x<<8)  & 0x000000FF00000000ULL) |         ((*x>>8)  & 0x00000000FF000000ULL) |         ((*x>>24) & 0x0000000000FF0000ULL) |         ((*x>>40) & 0x000000000000FF00ULL) |         (*x<<56);}


They depend on zlib and gzstream right now, and some of my code is trail-test hardcoding. Anyway, I'm going to go beat my head against a brick wall (attempt to debug) for a while.
___________________________________________________Optimists see the glass as Half FullPessimists See the glass as Half EmptyEngineers See the glass as Twice as big as it needs to be

This topic is closed to new replies.

Advertisement