// XMIInspect global blocks methods

#include "stdafx.h"

/* read a small global data block 
 * These are currently only defined for EnumCompressor, which is why we can print the internal data
 *
 * structure:
 *  index[curglobal] times an lstring 
 */
int XMIInspect::readSmallGlobalBlock()
{
	int stat = 0;

	/* get memory to store small global data meta-info */
	trydela(statesize);
	statesize = new long[numglobals];
	trydela(index);
	index = new long[numglobals];

	/* read indexes and sizes */
	for (int j = 0; j < numglobals; j++) {
		/* read dictionary size for this run */
		index[j] = Load::UInt32(curptr);
#if 0
		/* set total dictionary size */
		dictionarysizes[j] += index[j];
#endif
		/* read # strings in this block */
		statesize[j] = Load::UInt32(curptr);
		/* Calculate globaldatasize. this size is implementation dependent, unfortunately... 
			This size is used for checking the totaldatasize number stored in the run header 
		 */
		globaldatasize += sizeof(EnumDictItem)*index[j] +          // The size of the dictionary directoy
								WordAlignUInt(statesize[j]);				  // The size of the string space (word-aligned)
		if (level >= XMIINS_REPORT_MOREINFO) {
			printf(" state %ld/%ld size: %ld, total string length: %ld\n", j+1, numglobals, index[j], statesize[j]);
		}
	}

	/* read enum values for small global blocks */
	for (int j = 0; j < numglobals; j++) {
		if (statesize[j] < SMALLCOMPRESS_THRESHOLD) {
			if (level >= XMIINS_REPORT_CONTENTS) {
				printf(" state %ld/%ld values:\n", j+1, numglobals);
			}
			for (int k = 0; k < index[j]; k++) {
				if (level >= XMIINS_REPORT_CONTENTS) {
					printf("  index %ld/%ld: '", k+1, index[j]);
				}
				delete[] printlstring(curptr);
				if (level >= XMIINS_REPORT_CONTENTS) {
					printf("'\n");
				}
			}
		} else {
			numlargeglobals++;
		}
	}

	/* some size administration */
	smallglobalsize = bytesleft;
	bytesleft = len - (long)curptr + (long)buffer;
	smallglobalsize -= bytesleft;
	if (level >= XMIINS_REPORT_INFO) {
		printf("small global data: %ld Bytes\nrun header now contains %ld Bytes (== total small container data size)\n", 
			smallglobalsize, bytesleft);
	}

cleanup:
	return stat;
}

/* read a large global data block 
 * These are currently only defined for EnumCompressor, which is why we can print the internal data
 *
 * structure:
 *  index[curglobal] times an lstring 
 */
int XMIInspect::readLargeGlobalBlock()
{
	int stat = 0;

	/* decode global block # curglobal */
	if (level >= XMIINS_REPORT_INFO) {
		printf("reading large global data block %ld/%ld\n", curglobal+1, numlargeglobals);
	}

	/* find the next large container */
	while (curglobal < numlargeglobals && statesize[curglobal] < SMALLCOMPRESS_THRESHOLD) {
		curglobal++;
	}
	if (curglobal >= numlargeglobals) {
		if (level >= XMIINS_REPORT_ERRORS) {
			printf("global not found!\n");
		}
		stat = XMIINS_ERR_GLOBALNOTFOUND;
		goto cleanup;
	}
	globalsfound++;

	/* check buffer size */
	if (len != statesize[curglobal]) {
		if (level >= XMIINS_REPORT_ERRORS) {
			printf("size of uncompressed buffer (%ld Bytes) is not equal to global block %ld/%ld (%ld Bytes)!\n",
					len, curglobal+1, numlargeglobals, statesize[curglobal]);
		}
		stat = XMIINS_ERR_GLOBALSIZE;
		goto cleanup;
	}

	/* print enum values */
	if (level >= XMIINS_REPORT_CONTENTS) {
		printf(" state %ld values:\n", curglobal);
	}
	for (int k = 0; k < index[curglobal]; k++) {
		if (level >= XMIINS_REPORT_CONTENTS) {
			printf("  index %ld/%ld: '", k+1, index[curglobal]);
		}
		delete[] printlstring(curptr);
		if (level >= XMIINS_REPORT_CONTENTS) {
			printf("'\n");
		}
	}

	/* check if all data was consumed */
	bytesleft = len - (long)curptr + (long)buffer;
	if (bytesleft != 0) {
		if (level >= XMIINS_REPORT_WARNINGS) {
			printf("global block now contains %ld Bytes, should be 0!\n", bytesleft);
		}
	} else if (level >= XMIINS_REPORT_MOREINFO) {
		printf ("global block is OK\n");
	}

	/* next global data block */
	curglobal++;

	/* do more large global blocks follow? */
	if (globalsfound == numlargeglobals) {
		/* we're done, next state please */
		if (level >= XMIINS_REPORT_INFO) {
			printf ("all %ld large global blocks done, now follow the %ld containers\n", 
				numlargeglobals, expectedcontainers);
		}
		state = XMIINS_READ_CONTAINER_BLOCK;
		curcontainer = 0;
		curblock = 0;
	}

cleanup:
	return stat;
}
