Exemple #1
0
void BLI_endian_switch_int16_array(short *val, const int size)
{
	if (size > 0) {
		int i = size;
		val = val + (size - 1);
		while (i--) {
			BLI_endian_switch_int16(val--);
		}
	}
}
Exemple #2
0
/**
 * In sdna->data the data, now we convert that to something understandable
 */
static bool init_structDNA(
        SDNA *sdna, bool do_endian_swap,
        const char **r_error_message)
{
	int *data, *verg, gravity_fix = -1;
	short *sp;
	char str[8];
	
	verg = (int *)str;
	data = (int *)sdna->data;

	/* clear pointers incase of error */
	sdna->names = NULL;
	sdna->types = NULL;
	sdna->structs = NULL;
#ifdef WITH_DNA_GHASH
	sdna->structs_map = NULL;
#endif

	strcpy(str, "SDNA");
	if (*data != *verg) {
		*r_error_message = "SDNA error in SDNA file";
		return false;
	}
	else {
		const char *cp;

		data++;
		
		/* load names array */
		strcpy(str, "NAME");
		if (*data == *verg) {
			data++;
			
			sdna->nr_names = *data;
			if (do_endian_swap) {
				BLI_endian_switch_int32(&sdna->nr_names);
			}
			
			data++;
			sdna->names = MEM_callocN(sizeof(void *) * sdna->nr_names, "sdnanames");
		}
		else {
			*r_error_message = "NAME error in SDNA file";
			return false;
		}
		
		cp = (char *)data;
		for (int nr = 0; nr < sdna->nr_names; nr++) {
			sdna->names[nr] = cp;

			/* "float gravity [3]" was parsed wrong giving both "gravity" and
			 * "[3]"  members. we rename "[3]", and later set the type of
			 * "gravity" to "void" so the offsets work out correct */
			if (*cp == '[' && strcmp(cp, "[3]") == 0) {
				if (nr && strcmp(sdna->names[nr - 1], "Cvi") == 0) {
					sdna->names[nr] = "gravity[3]";
					gravity_fix = nr;
				}
			}

			while (*cp) cp++;
			cp++;
		}

		cp = pad_up_4(cp);
		
		/* load type names array */
		data = (int *)cp;
		strcpy(str, "TYPE");
		if (*data == *verg) {
			data++;

			sdna->nr_types = *data;
			if (do_endian_swap) {
				BLI_endian_switch_int32(&sdna->nr_types);
			}
			
			data++;
			sdna->types = MEM_callocN(sizeof(void *) * sdna->nr_types, "sdnatypes");
		}
		else {
			*r_error_message = "TYPE error in SDNA file";
			return false;
		}
		
		cp = (char *)data;
		for (int nr = 0; nr < sdna->nr_types; nr++) {
			sdna->types[nr] = cp;
			
			/* this is a patch, to change struct names without a conflict with SDNA */
			/* be careful to use it, in this case for a system-struct (opengl/X) */
			
			if (*cp == 'b') {
				/* struct Screen was already used by X, 'bScreen' replaces the old IrisGL 'Screen' struct */
				if (strcmp("bScreen", cp) == 0) sdna->types[nr] = cp + 1;
			}
			
			while (*cp) cp++;
			cp++;
		}

		cp = pad_up_4(cp);
		
		/* load typelen array */
		data = (int *)cp;
		strcpy(str, "TLEN");
		if (*data == *verg) {
			data++;
			sp = (short *)data;
			sdna->typelens = sp;
			
			if (do_endian_swap) {
				BLI_endian_switch_int16_array(sp, sdna->nr_types);
			}
			
			sp += sdna->nr_types;
		}
		else {
			*r_error_message = "TLEN error in SDNA file";
			return false;
		}
		if (sdna->nr_types & 1) sp++;   /* prevent BUS error */

		/* load struct array */
		data = (int *)sp;
		strcpy(str, "STRC");
		if (*data == *verg) {
			data++;
			
			sdna->nr_structs = *data;
			if (do_endian_swap) {
				BLI_endian_switch_int32(&sdna->nr_structs);
			}
			
			data++;
			sdna->structs = MEM_callocN(sizeof(void *) * sdna->nr_structs, "sdnastrcs");
		}
		else {
			*r_error_message = "STRC error in SDNA file";
			return false;
		}
		
		sp = (short *)data;
		for (int nr = 0; nr < sdna->nr_structs; nr++) {
			sdna->structs[nr] = sp;
			
			if (do_endian_swap) {
				short a;
				
				BLI_endian_switch_int16(&sp[0]);
				BLI_endian_switch_int16(&sp[1]);
				
				a = sp[1];
				sp += 2;
				while (a--) {
					BLI_endian_switch_int16(&sp[0]);
					BLI_endian_switch_int16(&sp[1]);
					sp += 2;
				}
			}
			else {
				sp += 2 * sp[1] + 2;
			}
		}
	}

	{
		/* second part of gravity problem, setting "gravity" type to void */
		if (gravity_fix > -1) {
			for (int nr = 0; nr < sdna->nr_structs; nr++) {
				sp = sdna->structs[nr];
				if (strcmp(sdna->types[sp[0]], "ClothSimSettings") == 0)
					sp[10] = SDNA_TYPE_VOID;
			}
		}
	}

#ifdef WITH_DNA_GHASH
	{
		/* create a ghash lookup to speed up */
		sdna->structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->nr_structs);

		for (intptr_t nr = 0; nr < sdna->nr_structs; nr++) {
			sp = sdna->structs[nr];
			BLI_ghash_insert(sdna->structs_map, (void *)sdna->types[sp[0]], SET_INT_IN_POINTER(nr));
		}
	}
#endif

	/* Calculate 'sdna->pointerlen' */
	{
		intptr_t nr = DNA_struct_find_nr(sdna, "ListBase");

		/* should never happen, only with corrupt file for example */
		if (UNLIKELY(nr == -1)) {
			*r_error_message = "ListBase struct error! Not found.";
			return false;
		}

		/* finally pointerlen: use struct ListBase to test it, never change the size of it! */
		sp = sdna->structs[nr];
		/* weird; i have no memory of that... I think I used sizeof(void *) before... (ton) */

		sdna->pointerlen = sdna->typelens[sp[0]] / 2;

		if (sp[1] != 2 || (sdna->pointerlen != 4 && sdna->pointerlen != 8)) {
			*r_error_message = "ListBase struct error! Needs it to calculate pointerize.";
			/* well, at least sizeof(ListBase) is error proof! (ton) */
			return false;
		}
	}

	return true;
}