Hi. Here is a proposed fix for this problem.
The original code was using gzseek/gzeof/gztell to figure out the uncompressed size of a compressed instrument bank file, to preallocate the buffer for reading its contents, and something in zlib has broken that. I know this is supposed to work, but it’s going to be slow anyway. So this patch replaces that with incremental buffer allocation and reading, in increments of 1 kiB. Looking at the existing bank files, which seem to be only a few kiB in size, this should work OK in terms of both speed and RAM usage. Lawrence D’Oliveiro
--- src/Misc/XMLwrapper.cpp-orig 2009-07-16 07:48:41.000000000 +1200 +++ src/Misc/XMLwrapper.cpp 2012-04-24 16:42:11.968157362 +1200 @@ -300,50 +300,70 @@ return(0); }; +/* wrappers with more convenient and consistent signatures than direct gzread and fread calls */ +static ssize_t read_compressed + ( + void * thefile, + char * buffer, + size_t bufsize + ) + { + return + gzread((gzFile)thefile, buffer, bufsize); + } /*gz_read*/ + +static ssize_t read_uncompressed + ( + void * thefile, + char * buffer, + size_t bufsize + ) + { + return + fread(buffer, bufsize, 1, (FILE *)thefile); + } /*read_uncompressed*/ char *XMLwrapper::doloadfile(const string &filename) { char *xmldata=NULL; - int filesize=-1; + size_t datasize = 0; + void * thefile; + ssize_t (*thefile_read)(void * thefile, char * buffer, size_t bufsize); + int (*thefile_close)(void * thefile); + + thefile = gzopen(filename.c_str(),"rb"); + if (thefile != NULL) + { + thefile_read = read_compressed; + thefile_close = (int (*)(void *))gzclose; + } + else + { + thefile = fopen(filename.c_str(),"rb"); + if (thefile==NULL) return(NULL); + thefile_read = read_uncompressed; + thefile_close = (int (*)(void *))fclose; + } /*if*/ + for (;;) + { + const size_t increment = 1024; /* something convenient */ + const size_t prevdatasize = datasize; + datasize += increment; + xmldata = (char *)realloc(xmldata, datasize + 1); + if (xmldata == NULL) return(NULL); + const ssize_t bytesread = thefile_read(thefile, xmldata + prevdatasize, increment); + if (bytesread < 0) return(NULL); + if (bytesread < increment) + { + datasize = prevdatasize + bytesread; + xmldata = (char *)realloc(xmldata, datasize + 1); /* assume shrinking buffer won't fail! */ + xmldata[datasize] = 0; /* terminating null */ + break; + } /*if*/ + } /*for*/ - //try get filesize as gzip data (first) - gzFile gzfile=gzopen(filename.c_str(),"rb"); - if (gzfile!=NULL) {//this is a gzip file - // first check it's size - while (!gzeof(gzfile)) { - gzseek (gzfile,1024*1024,SEEK_CUR); - if (gztell(gzfile)>10000000) { - gzclose(gzfile); - goto notgzip;//the file is too big - }; - }; - filesize=gztell(gzfile); - - //rewind the file and load the data - xmldata=new char[filesize+1]; - ZERO(xmldata,filesize+1); - - gzrewind(gzfile); - gzread(gzfile,xmldata,filesize); - - gzclose(gzfile); - return (xmldata); - } else {//this is not a gzip file -notgzip: - FILE *file=fopen(filename.c_str(),"rb"); - if (file==NULL) return(NULL); - fseek(file,0,SEEK_END); - filesize=ftell(file); - - xmldata=new char [filesize+1]; - ZERO(xmldata,filesize+1); - - rewind(file); - fread(xmldata,filesize,1,file); - - fclose(file); - return(xmldata); - }; + thefile_close(thefile); + return(xmldata); }; bool XMLwrapper::putXMLdata(const char *xmldata)