| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2008-01-07 19:13:47 +00:00
										 |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							| 
									
										
										
										
											2006-11-29 23:31:46 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							| 
									
										
										
										
											2008-01-07 19:13:47 +00:00
										 |  |  |  * of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2006-11-29 23:31:46 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							| 
									
										
										
										
											2010-02-12 13:34:04 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2006-11-29 23:31:46 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Joseph Eagar | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2008-01-07 19:13:47 +00:00
										 |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							| 
									
										
										
										
											2006-11-29 23:31:46 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-02-27 20:40:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** \file blender/blenkernel/intern/idprop.c
 | 
					
						
							|  |  |  |  *  \ingroup bke | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-24 18:38:03 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2010-08-13 06:30:04 +00:00
										 |  |  | #include <stddef.h>
 | 
					
						
							| 
									
										
										
										
											2007-12-24 18:38:03 +00:00
										 |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-08 06:00:27 +00:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | #include "BLI_string.h"
 | 
					
						
							|  |  |  | #include "BLI_listbase.h"
 | 
					
						
							| 
									
										
										
										
											2014-04-24 16:46:54 +02:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2012-07-08 06:00:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | #include "BKE_idprop.h"
 | 
					
						
							|  |  |  | #include "BKE_library.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* IDPropertyTemplate is a union in DNA_ID.h */ | 
					
						
							| 
									
										
										
										
											2007-04-19 22:49:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*local size table.*/ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | static char idp_size_table[] = { | 
					
						
							| 
									
										
										
										
											2007-04-19 22:49:48 +00:00
										 |  |  | 	1, /*strings*/ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	sizeof(int), | 
					
						
							|  |  |  | 	sizeof(float), | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	sizeof(float) * 3, /*Vector type, deprecated*/ | 
					
						
							|  |  |  | 	sizeof(float) * 16, /*Matrix type, deprecated*/ | 
					
						
							| 
									
										
										
										
											2007-04-19 22:49:48 +00:00
										 |  |  | 	0, /*arrays don't have a fixed size*/ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	sizeof(ListBase), /*Group type*/ | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	sizeof(void *), | 
					
						
							| 
									
										
										
										
											2008-07-24 19:22:17 +00:00
										 |  |  | 	sizeof(double) | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* Array Functions */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \name IDP Array API
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | #define GETPROP(prop, i) (((IDProperty *)(prop)->data.pointer) + (i))
 | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | /* --------- property array type -------------*/ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * \note as a start to move away from the stupid IDP_New function, this type | 
					
						
							|  |  |  |  * has it's own allocation function. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | IDProperty *IDP_NewIDPArray(const char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	IDProperty *prop = MEM_callocN(sizeof(IDProperty), "IDProperty prop array"); | 
					
						
							|  |  |  | 	prop->type = IDP_IDPARRAY; | 
					
						
							|  |  |  | 	prop->len = 0; | 
					
						
							|  |  |  | 	BLI_strncpy(prop->name, name, MAX_IDPROP_NAME); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return prop; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | IDProperty *IDP_CopyIDPArray(const IDProperty *array) | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  | 	/* don't use MEM_dupallocN because this may be part of an array */ | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	IDProperty *narray, *tmp; | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2011-04-19 23:52:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(array->type == IDP_IDPARRAY); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	narray = MEM_mallocN(sizeof(IDProperty), __func__); | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	*narray = *array; | 
					
						
							| 
									
										
										
										
											2011-04-19 23:52:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 	narray->data.pointer = MEM_dupallocN(array->data.pointer); | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	for (i = 0; i < narray->len; i++) { | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  | 		/* ok, the copy functions always allocate a new structure,
 | 
					
						
							|  |  |  | 		 * which doesn't work here.  instead, simply copy the | 
					
						
							|  |  |  | 		 * contents of the new structure into the array cell, | 
					
						
							|  |  |  | 		 * then free it.  this makes for more maintainable | 
					
						
							|  |  |  | 		 * code than simply reimplementing the copy functions | 
					
						
							|  |  |  | 		 * in this loop.*/ | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 		tmp = IDP_CopyProperty(GETPROP(narray, i)); | 
					
						
							|  |  |  | 		memcpy(GETPROP(narray, i), tmp, sizeof(IDProperty)); | 
					
						
							|  |  |  | 		MEM_freeN(tmp); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return narray; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void IDP_FreeIDPArray(IDProperty *prop) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(prop->type == IDP_IDPARRAY); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	for (i = 0; i < prop->len; i++) | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 		IDP_FreeProperty(GETPROP(prop, i)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (prop->data.pointer) | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 		MEM_freeN(prop->data.pointer); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*shallow copies item*/ | 
					
						
							|  |  |  | void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	IDProperty *old; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_assert(prop->type == IDP_IDPARRAY); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	old = GETPROP(prop, index); | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 	if (index >= prop->len || index < 0) return; | 
					
						
							|  |  |  | 	if (item != old) IDP_FreeProperty(old); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	memcpy(GETPROP(prop, index), item, sizeof(IDProperty)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IDProperty *IDP_GetIndexArray(IDProperty *prop, int index) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(prop->type == IDP_IDPARRAY); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 	return GETPROP(prop, index); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-08 06:00:27 +00:00
										 |  |  | void IDP_AppendArray(IDProperty *prop, IDProperty *item) | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(prop->type == IDP_IDPARRAY); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	IDP_ResizeIDPArray(prop, prop->len + 1); | 
					
						
							|  |  |  | 	IDP_SetIndexArray(prop, prop->len - 1, item); | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void IDP_ResizeIDPArray(IDProperty *prop, int newlen) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 	int newsize; | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(prop->type == IDP_IDPARRAY); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 	/* first check if the array buffer size has room */ | 
					
						
							|  |  |  | 	/* if newlen is 200 items less then totallen, reallocate anyway */ | 
					
						
							| 
									
										
										
										
											2013-05-15 14:36:58 +00:00
										 |  |  | 	if (newlen <= prop->totallen) { | 
					
						
							|  |  |  | 		if (newlen < prop->len && prop->totallen - newlen < 200) { | 
					
						
							|  |  |  | 			int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (i = newlen; i < prop->len; i++) | 
					
						
							|  |  |  | 				IDP_FreeProperty(GETPROP(prop, i)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			prop->len = newlen; | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (newlen >= prop->len) { | 
					
						
							|  |  |  | 			prop->len = newlen; | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 	/* free trailing items */ | 
					
						
							|  |  |  | 	if (newlen < prop->len) { | 
					
						
							|  |  |  | 		/* newlen is smaller */ | 
					
						
							|  |  |  | 		int i; | 
					
						
							|  |  |  | 		for (i = newlen; i < prop->len; i++) { | 
					
						
							|  |  |  | 			IDP_FreeProperty(GETPROP(prop, i)); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-25 16:04:03 +00:00
										 |  |  | 	/* - Note: This code comes from python, here's the corresponding comment. - */ | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 	/* This over-allocates proportional to the list size, making room
 | 
					
						
							|  |  |  | 	 * for additional growth.  The over-allocation is mild, but is | 
					
						
							|  |  |  | 	 * enough to give linear-time amortized behavior over a long | 
					
						
							|  |  |  | 	 * sequence of appends() in the presence of a poorly-performing | 
					
						
							|  |  |  | 	 * system realloc(). | 
					
						
							|  |  |  | 	 * The growth pattern is:  0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 	newsize = newlen; | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 	newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize; | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 	prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * newsize); | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 	prop->len = newlen; | 
					
						
							|  |  |  | 	prop->totallen = newsize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ----------- Numerical Array Type ----------- */ | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (prop->subtype != IDP_GROUP) | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (newlen >= prop->len) { | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 		/* bigger */ | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 		IDProperty **array = newarr; | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 		IDPropertyTemplate val; | 
					
						
							|  |  |  | 		int a; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 		for (a = prop->len; a < newlen; a++) { | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 			val.i = 0; /* silence MSVC warning about uninitialized var when debugging */ | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 			array[a] = IDP_New(IDP_GROUP, &val, "IDP_ResizeArray group"); | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		/* smaller */ | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 		IDProperty **array = prop->data.pointer; | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 		int a; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 		for (a = newlen; a < prop->len; a++) { | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 			IDP_FreeProperty(array[a]); | 
					
						
							|  |  |  | 			MEM_freeN(array[a]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | /*this function works for strings too!*/ | 
					
						
							|  |  |  | void IDP_ResizeArray(IDProperty *prop, int newlen) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 	int newsize; | 
					
						
							|  |  |  | 	const bool is_grow = newlen >= prop->len; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 	/* first check if the array buffer size has room */ | 
					
						
							|  |  |  | 	/* if newlen is 200 chars less then totallen, reallocate anyway */ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	if (newlen <= prop->totallen && prop->totallen - newlen < 200) { | 
					
						
							| 
									
										
										
										
											2009-01-23 20:36:47 +00:00
										 |  |  | 		idp_resize_group_array(prop, newlen, prop->data.pointer); | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 		prop->len = newlen; | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-25 16:04:03 +00:00
										 |  |  | 	/* - Note: This code comes from python, here's the corresponding comment. - */ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	/* This over-allocates proportional to the list size, making room
 | 
					
						
							|  |  |  | 	 * for additional growth.  The over-allocation is mild, but is | 
					
						
							|  |  |  | 	 * enough to give linear-time amortized behavior over a long | 
					
						
							|  |  |  | 	 * sequence of appends() in the presence of a poorly-performing | 
					
						
							|  |  |  | 	 * system realloc(). | 
					
						
							|  |  |  | 	 * The growth pattern is:  0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 	newsize = newlen; | 
					
						
							|  |  |  | 	newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;\ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 	if (is_grow == false) | 
					
						
							|  |  |  | 		idp_resize_group_array(prop, newlen, prop->data.pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	prop->data.pointer = MEM_recallocN(prop->data.pointer, idp_size_table[(int)prop->subtype] * newsize); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (is_grow == true) | 
					
						
							|  |  |  | 		idp_resize_group_array(prop, newlen, prop->data.pointer); | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	prop->len = newlen; | 
					
						
							|  |  |  | 	prop->totallen = newsize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | void IDP_FreeArray(IDProperty *prop) | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 	if (prop->data.pointer) { | 
					
						
							|  |  |  | 		idp_resize_group_array(prop, 0, NULL); | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 		MEM_freeN(prop->data.pointer); | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | static IDProperty *idp_generic_copy(const IDProperty *prop) | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | 	IDProperty *newp = MEM_callocN(sizeof(IDProperty), "IDProperty array dup"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 	BLI_strncpy(newp->name, prop->name, MAX_IDPROP_NAME); | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | 	newp->type = prop->type; | 
					
						
							|  |  |  | 	newp->flag = prop->flag; | 
					
						
							|  |  |  | 	newp->data.val = prop->data.val; | 
					
						
							| 
									
										
										
										
											2008-10-05 01:15:58 +00:00
										 |  |  | 	newp->data.val2 = prop->data.val2; | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return newp; | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | static IDProperty *IDP_CopyArray(const IDProperty *prop) | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	IDProperty *newp = idp_generic_copy(prop); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 	if (prop->data.pointer) { | 
					
						
							|  |  |  | 		newp->data.pointer = MEM_dupallocN(prop->data.pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 		if (prop->type == IDP_GROUP) { | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 			IDProperty **array = newp->data.pointer; | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 			int a; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 			for (a = 0; a < prop->len; a++) | 
					
						
							|  |  |  | 				array[a] = IDP_CopyProperty(array[a]); | 
					
						
							| 
									
										
										
											
												RNA:
* Added support for using pointers + collections as operator properties,
  but with the restriction that they must point to other type derived from
  ID property groups. The "add" function for these properties will allocate
  a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
	float loc[2];
	RNA_float_get_array(&itemptr, "loc", loc);
	printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
											
										 
											2008-12-26 20:38:52 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | 	newp->len = prop->len; | 
					
						
							|  |  |  | 	newp->subtype = prop->subtype; | 
					
						
							|  |  |  | 	newp->totallen = prop->totallen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return newp; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* String Functions */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \name IDProperty String API
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \param st  The string to assign. | 
					
						
							|  |  |  |  * \param name  The property name. | 
					
						
							|  |  |  |  * \param maxlen  The size of the new string (including the \0 terminator) | 
					
						
							|  |  |  |  * \return | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-06-12 17:30:21 +00:00
										 |  |  | IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	IDProperty *prop = MEM_callocN(sizeof(IDProperty), "IDProperty string"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (st == NULL) { | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 		prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1"); | 
					
						
							|  |  |  | 		*IDP_String(prop) = '\0'; | 
					
						
							| 
									
										
										
										
											2010-06-12 17:30:21 +00:00
										 |  |  | 		prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS; | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 		prop->len = 1;  /* NULL string, has len of 1 to account for null byte. */ | 
					
						
							| 
									
										
										
										
											2010-06-12 17:30:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2014-02-15 12:31:58 +11:00
										 |  |  | 		/* include null terminator '\0' */ | 
					
						
							|  |  |  | 		int stlen = strlen(st) + 1; | 
					
						
							| 
									
										
										
										
											2010-06-12 17:30:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 		if (maxlen > 0 && maxlen < stlen) | 
					
						
							| 
									
										
										
										
											2010-06-12 17:30:21 +00:00
										 |  |  | 			stlen = maxlen; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 		prop->data.pointer = MEM_mallocN(stlen, "id property string 2"); | 
					
						
							| 
									
										
										
										
											2010-06-12 17:30:21 +00:00
										 |  |  | 		prop->len = prop->totallen = stlen; | 
					
						
							|  |  |  | 		BLI_strncpy(prop->data.pointer, st, stlen); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	prop->type = IDP_STRING; | 
					
						
							|  |  |  | 	BLI_strncpy(prop->name, name, MAX_IDPROP_NAME); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return prop; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | static IDProperty *IDP_CopyString(const IDProperty *prop) | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	IDProperty *newp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_assert(prop->type == IDP_STRING); | 
					
						
							|  |  |  | 	newp = idp_generic_copy(prop); | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	if (prop->data.pointer) | 
					
						
							|  |  |  | 		newp->data.pointer = MEM_dupallocN(prop->data.pointer); | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | 	newp->len = prop->len; | 
					
						
							|  |  |  | 	newp->subtype = prop->subtype; | 
					
						
							|  |  |  | 	newp->totallen = prop->totallen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return newp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-19 02:14:18 +00:00
										 |  |  | void IDP_AssignString(IDProperty *prop, const char *st, int maxlen) | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	int stlen; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(prop->type == IDP_STRING); | 
					
						
							|  |  |  | 	stlen = strlen(st); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (maxlen > 0 && maxlen < stlen) | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 		stlen = maxlen; | 
					
						
							| 
									
										
										
										
											2010-06-12 17:30:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-15 09:12:10 +00:00
										 |  |  | 	if (prop->subtype == IDP_STRING_SUB_BYTE) { | 
					
						
							|  |  |  | 		IDP_ResizeArray(prop, stlen); | 
					
						
							|  |  |  | 		memcpy(prop->data.pointer, st, stlen); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 		stlen++; | 
					
						
							| 
									
										
										
										
											2011-11-15 09:12:10 +00:00
										 |  |  | 		IDP_ResizeArray(prop, stlen); | 
					
						
							|  |  |  | 		BLI_strncpy(prop->data.pointer, st, stlen); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-19 02:14:18 +00:00
										 |  |  | void IDP_ConcatStringC(IDProperty *prop, const char *st) | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int newlen; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(prop->type == IDP_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	newlen = prop->len + strlen(st); | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  | 	/* we have to remember that prop->len includes the null byte for strings.
 | 
					
						
							|  |  |  | 	 * so there's no need to add +1 to the resize function.*/ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	IDP_ResizeArray(prop, newlen); | 
					
						
							|  |  |  | 	strcat(prop->data.pointer, st); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void IDP_ConcatString(IDProperty *str1, IDProperty *append) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int newlen; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(append->type == IDP_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  | 	/* since ->len for strings includes the NULL byte, we have to subtract one or
 | 
					
						
							| 
									
										
										
										
											2012-03-04 04:35:12 +00:00
										 |  |  | 	 * we'll get an extra null byte after each concatenation operation.*/ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	newlen = str1->len + append->len - 1; | 
					
						
							|  |  |  | 	IDP_ResizeArray(str1, newlen); | 
					
						
							|  |  |  | 	strcat(str1->data.pointer, append->data.pointer); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void IDP_FreeString(IDProperty *prop) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(prop->type == IDP_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (prop->data.pointer) | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 		MEM_freeN(prop->data.pointer); | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | /** \} */ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* ID Type (not in use yet) */ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | /** \name IDProperty ID API (unused)
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | void IDP_LinkID(IDProperty *prop, ID *id) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	if (prop->data.pointer) ((ID *)prop->data.pointer)->us--; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	prop->data.pointer = id; | 
					
						
							|  |  |  | 	id_us_plus(id); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void IDP_UnlinkID(IDProperty *prop) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	((ID *)prop->data.pointer)->us--; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* Group Functions */ | 
					
						
							| 
									
										
										
										
											2007-05-22 04:41:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | /** \name IDProperty Group API
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Checks if a property with the same name as prop exists, and if so replaces it. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | static IDProperty *IDP_CopyGroup(const IDProperty *prop) | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	IDProperty *newp, *link; | 
					
						
							| 
									
										
										
										
											2008-02-11 18:26:19 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(prop->type == IDP_GROUP); | 
					
						
							|  |  |  | 	newp = idp_generic_copy(prop); | 
					
						
							|  |  |  | 	newp->len = prop->len; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	for (link = prop->data.group.first; link; link = link->next) { | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | 		BLI_addtail(&newp->data.group, IDP_CopyProperty(link)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return newp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-15 18:43:54 +00:00
										 |  |  | /* use for syncing proxies.
 | 
					
						
							|  |  |  |  * When values name and types match, copy the values, else ignore */ | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src) | 
					
						
							| 
									
										
										
										
											2010-02-15 18:43:54 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-05-01 06:34:40 +00:00
										 |  |  | 	IDProperty *other, *prop; | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BLI_assert(dest->type == IDP_GROUP); | 
					
						
							|  |  |  | 	BLI_assert(src->type == IDP_GROUP); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	for (prop = src->data.group.first; prop; prop = prop->next) { | 
					
						
							|  |  |  | 		other = BLI_findstring(&dest->data.group, prop->name, offsetof(IDProperty, name)); | 
					
						
							|  |  |  | 		if (other && prop->type == other->type) { | 
					
						
							| 
									
										
										
										
											2011-05-01 06:34:40 +00:00
										 |  |  | 			switch (prop->type) { | 
					
						
							|  |  |  | 				case IDP_INT: | 
					
						
							|  |  |  | 				case IDP_FLOAT: | 
					
						
							|  |  |  | 				case IDP_DOUBLE: | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 					other->data = prop->data; | 
					
						
							| 
									
										
										
										
											2011-05-01 06:34:40 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				case IDP_GROUP: | 
					
						
							|  |  |  | 					IDP_SyncGroupValues(other, prop); | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 					IDProperty *tmp = other; | 
					
						
							|  |  |  | 					IDProperty *copy = IDP_CopyProperty(prop); | 
					
						
							| 
									
										
										
										
											2011-05-01 06:34:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					BLI_insertlinkafter(&dest->data.group, other, copy); | 
					
						
							|  |  |  | 					BLI_remlink(&dest->data.group, tmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					IDP_FreeProperty(tmp); | 
					
						
							|  |  |  | 					MEM_freeN(tmp); | 
					
						
							| 
									
										
										
										
											2013-07-21 08:16:37 +00:00
										 |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2010-02-15 18:43:54 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-13 00:28:35 +11:00
										 |  |  | void IDP_SyncGroupTypes(IDProperty *dst, const IDProperty *src, const bool do_arraylen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	IDProperty *prop_dst, *prop_dst_next; | 
					
						
							|  |  |  | 	const IDProperty *prop_src; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (prop_dst = dst->data.group.first; prop_dst; prop_dst = prop_dst_next) { | 
					
						
							|  |  |  | 		prop_dst_next = prop_dst->next; | 
					
						
							|  |  |  | 		if ((prop_src = IDP_GetPropertyFromGroup((IDProperty *)src, prop_dst->name))) { | 
					
						
							|  |  |  | 			/* check of we should replace? */ | 
					
						
							|  |  |  | 			if ((prop_dst->type != prop_src->type || prop_dst->subtype != prop_src->subtype) || | 
					
						
							|  |  |  | 			    (do_arraylen && ELEM(prop_dst->type, IDP_ARRAY, IDP_IDPARRAY) && (prop_src->len != prop_dst->len))) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				IDP_FreeFromGroup(dst, prop_dst); | 
					
						
							|  |  |  | 				prop_dst = IDP_CopyProperty(prop_src); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				dst->len++; | 
					
						
							|  |  |  | 				BLI_insertlinkbefore(&dst->data.group, prop_dst_next, prop_dst); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else if (prop_dst->type == IDP_GROUP) { | 
					
						
							|  |  |  | 				IDP_SyncGroupTypes(prop_dst, prop_src, do_arraylen); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			IDP_FreeFromGroup(dst, prop_dst); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Replaces all properties with the same name in a destination group from a source group. | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src) | 
					
						
							| 
									
										
										
										
											2010-01-05 03:29:41 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	IDProperty *loop, *prop; | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BLI_assert(dest->type == IDP_GROUP); | 
					
						
							|  |  |  | 	BLI_assert(src->type == IDP_GROUP); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	for (prop = src->data.group.first; prop; prop = prop->next) { | 
					
						
							|  |  |  | 		for (loop = dest->data.group.first; loop; loop = loop->next) { | 
					
						
							| 
									
										
										
										
											2013-03-10 06:18:03 +00:00
										 |  |  | 			if (STREQ(loop->name, prop->name)) { | 
					
						
							| 
									
										
										
										
											2010-01-21 21:01:18 +00:00
										 |  |  | 				IDProperty *copy = IDP_CopyProperty(prop); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-22 14:12:55 +00:00
										 |  |  | 				BLI_insertlinkafter(&dest->data.group, loop, copy); | 
					
						
							| 
									
										
										
										
											2010-01-05 03:29:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				BLI_remlink(&dest->data.group, loop); | 
					
						
							|  |  |  | 				IDP_FreeProperty(loop); | 
					
						
							|  |  |  | 				MEM_freeN(loop); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-21 21:01:18 +00:00
										 |  |  | 		/* only add at end if not added yet */ | 
					
						
							|  |  |  | 		if (loop == NULL) { | 
					
						
							|  |  |  | 			IDProperty *copy = IDP_CopyProperty(prop); | 
					
						
							|  |  |  | 			dest->len++; | 
					
						
							|  |  |  | 			BLI_addtail(&dest->data.group, copy); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-01-05 03:29:41 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Checks if a property with the same name as prop exists, and if so replaces it. | 
					
						
							|  |  |  |  * Use this to preserve order! | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-05-22 04:41:21 +00:00
										 |  |  | void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	IDProperty *loop; | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BLI_assert(group->type == IDP_GROUP); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	if ((loop = IDP_GetPropertyFromGroup(group, prop->name))) { | 
					
						
							| 
									
										
										
										
											2013-02-22 14:12:55 +00:00
										 |  |  | 		BLI_insertlinkafter(&group->data.group, loop, prop); | 
					
						
							| 
									
										
										
										
											2010-08-13 06:30:04 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		BLI_remlink(&group->data.group, loop); | 
					
						
							|  |  |  | 		IDP_FreeProperty(loop); | 
					
						
							| 
									
										
										
										
											2012-09-16 04:58:18 +00:00
										 |  |  | 		MEM_freeN(loop); | 
					
						
							| 
									
										
										
										
											2010-08-13 06:30:04 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		group->len++; | 
					
						
							|  |  |  | 		BLI_addtail(&group->data.group, prop); | 
					
						
							| 
									
										
										
										
											2007-05-22 04:41:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2012-10-31 19:07:25 +00:00
										 |  |  |  * If a property is missing in \a dest, add it. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite) | 
					
						
							| 
									
										
										
										
											2012-10-31 19:07:25 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	IDProperty *prop; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(dest->type == IDP_GROUP); | 
					
						
							|  |  |  | 	BLI_assert(src->type == IDP_GROUP); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-31 19:07:25 +00:00
										 |  |  | 	if (do_overwrite) { | 
					
						
							|  |  |  | 		for (prop = src->data.group.first; prop; prop = prop->next) { | 
					
						
							|  |  |  | 			IDProperty *copy = IDP_CopyProperty(prop); | 
					
						
							|  |  |  | 			IDP_ReplaceInGroup(dest, copy); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		for (prop = src->data.group.first; prop; prop = prop->next) { | 
					
						
							|  |  |  | 			if (IDP_GetPropertyFromGroup(dest, prop->name) == NULL) { | 
					
						
							|  |  |  | 				IDProperty *copy = IDP_CopyProperty(prop); | 
					
						
							|  |  |  | 				dest->len++; | 
					
						
							|  |  |  | 				BLI_addtail(&dest->data.group, copy); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * This function has a sanity check to make sure ID properties with the same name don't | 
					
						
							|  |  |  |  * get added to the group. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The sanity check just means the property is not added to the group if another property | 
					
						
							|  |  |  |  * exists with the same name; the client code using ID properties then needs to detect this | 
					
						
							|  |  |  |  * (the function that adds new properties to groups, IDP_AddToGroup,returns 0 if a property can't | 
					
						
							|  |  |  |  * be added to the group, and 1 if it can) and free the property. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Currently the code to free ID properties is designed to leave the actual struct | 
					
						
							|  |  |  |  * you pass it un-freed, this is needed for how the system works.  This means | 
					
						
							|  |  |  |  * to free an ID property, you first call IDP_FreeProperty then MEM_freeN the | 
					
						
							|  |  |  |  * struct.  In the future this will just be IDP_FreeProperty and the code will | 
					
						
							|  |  |  |  * be reorganized to work properly. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(group->type == IDP_GROUP); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-27 10:35:39 +00:00
										 |  |  | 	if (IDP_GetPropertyFromGroup(group, prop->name) == NULL) { | 
					
						
							| 
									
										
										
										
											2010-08-13 06:30:04 +00:00
										 |  |  | 		group->len++; | 
					
						
							|  |  |  | 		BLI_addtail(&group->data.group, prop); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							| 
									
										
										
										
											2006-11-17 08:19:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-13 06:30:04 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * This is the same as IDP_AddToGroup, only you pass an item | 
					
						
							|  |  |  |  * in the group list to be inserted after. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | bool IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew) | 
					
						
							| 
									
										
										
										
											2006-12-16 23:54:45 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(group->type == IDP_GROUP); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-27 10:35:39 +00:00
										 |  |  | 	if (IDP_GetPropertyFromGroup(group, pnew->name) == NULL) { | 
					
						
							| 
									
										
										
										
											2010-08-13 06:30:04 +00:00
										 |  |  | 		group->len++; | 
					
						
							| 
									
										
										
										
											2013-02-22 14:12:55 +00:00
										 |  |  | 		BLI_insertlinkafter(&group->data.group, previous, pnew); | 
					
						
							| 
									
										
										
										
											2010-08-13 06:30:04 +00:00
										 |  |  | 		return 1; | 
					
						
							| 
									
										
										
										
											2006-12-16 23:54:45 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-10-06 10:24:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-13 06:30:04 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2006-12-16 23:54:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * \note this does not free the property!! | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * To free the property, you have to do: | 
					
						
							|  |  |  |  * IDP_FreeProperty(prop); //free all subdata
 | 
					
						
							|  |  |  |  * MEM_freeN(prop); //free property struct itself
 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-10-16 05:29:28 +00:00
										 |  |  | void IDP_RemoveFromGroup(IDProperty *group, IDProperty *prop) | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(group->type == IDP_GROUP); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	group->len--; | 
					
						
							|  |  |  | 	BLI_remlink(&group->data.group, prop); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-16 05:29:28 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Removes the property from the group and frees it. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void IDP_FreeFromGroup(IDProperty *group, IDProperty *prop) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	IDP_RemoveFromGroup(group, prop); | 
					
						
							|  |  |  | 	IDP_FreeProperty(prop); | 
					
						
							|  |  |  | 	MEM_freeN(prop); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-18 20:01:35 +00:00
										 |  |  | IDProperty *IDP_GetPropertyFromGroup(IDProperty *prop, const char *name) | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	BLI_assert(prop->type == IDP_GROUP); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-13 06:30:04 +00:00
										 |  |  | 	return (IDProperty *)BLI_findstring(&prop->data.group, name, offsetof(IDProperty, name)); | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /** same as above but ensure type match */ | 
					
						
							| 
									
										
										
										
											2011-02-07 05:05:41 +00:00
										 |  |  | IDProperty *IDP_GetPropertyTypeFromGroup(IDProperty *prop, const char *name, const char type) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	IDProperty *idprop = IDP_GetPropertyFromGroup(prop, name); | 
					
						
							| 
									
										
										
										
											2011-02-07 05:05:41 +00:00
										 |  |  | 	return (idprop && idprop->type == type) ? idprop : NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | typedef struct IDPIter { | 
					
						
							|  |  |  | 	void *next; | 
					
						
							|  |  |  | 	IDProperty *parent; | 
					
						
							|  |  |  | } IDPIter; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Get an iterator to iterate over the members of an id property group. | 
					
						
							|  |  |  |  * Note that this will automatically free the iterator once iteration is complete; | 
					
						
							|  |  |  |  * if you stop the iteration before hitting the end, make sure to call | 
					
						
							|  |  |  |  * IDP_FreeIterBeforeEnd(). | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | void *IDP_GetGroupIterator(IDProperty *prop) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 	IDPIter *iter; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_assert(prop->type == IDP_GROUP); | 
					
						
							|  |  |  | 	iter = MEM_mallocN(sizeof(IDPIter), "IDPIter"); | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	iter->next = prop->data.group.first; | 
					
						
							|  |  |  | 	iter->parent = prop; | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	return (void *) iter; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Returns the next item in the iteration.  To use, simple for a loop like the following: | 
					
						
							|  |  |  |  * while (IDP_GroupIterNext(iter) != NULL) { | 
					
						
							|  |  |  |  *     ... | 
					
						
							|  |  |  |  * } | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-12-06 19:20:06 +00:00
										 |  |  | IDProperty *IDP_GroupIterNext(void *vself) | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	IDPIter *self = (IDPIter *) vself; | 
					
						
							|  |  |  | 	Link *next = (Link *) self->next; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	if (self->next == NULL) { | 
					
						
							|  |  |  | 		MEM_freeN(self); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	self->next = next->next; | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	return (void *) next; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Frees the iterator pointed to at vself, only use this if iteration is stopped early; | 
					
						
							|  |  |  |  * when the iterator hits the end of the list it'll automatically free itself.\ | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | void IDP_FreeIterBeforeEnd(void *vself) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	MEM_freeN(vself); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  | /* Ok, the way things work, Groups free the ID Property structs of their children.
 | 
					
						
							|  |  |  |  * This is because all ID Property freeing functions free only direct data (not the ID Property | 
					
						
							|  |  |  |  * struct itself), but for Groups the child properties *are* considered | 
					
						
							|  |  |  |  * direct data. */ | 
					
						
							| 
									
										
										
										
											2008-09-29 17:08:11 +00:00
										 |  |  | static void IDP_FreeGroup(IDProperty *prop) | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-21 21:01:18 +00:00
										 |  |  | 	IDProperty *loop; | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BLI_assert(prop->type == IDP_GROUP); | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	for (loop = prop->data.group.first; loop; loop = loop->next) { | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 		IDP_FreeProperty(loop); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-01-21 21:01:18 +00:00
										 |  |  | 	BLI_freelistN(&prop->data.group); | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | /** \} */ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* Main Functions */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \name IDProperty Main API
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | IDProperty *IDP_CopyProperty(const IDProperty *prop) | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	switch (prop->type) { | 
					
						
							|  |  |  | 		case IDP_GROUP: return IDP_CopyGroup(prop); | 
					
						
							|  |  |  | 		case IDP_STRING: return IDP_CopyString(prop); | 
					
						
							|  |  |  | 		case IDP_ARRAY: return IDP_CopyArray(prop); | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 		case IDP_IDPARRAY: return IDP_CopyIDPArray(prop); | 
					
						
							| 
									
										
										
										
											2007-07-09 20:42:14 +00:00
										 |  |  | 		default: return idp_generic_copy(prop); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Get the Group property that contains the id properties for ID id.  Set create_if_needed | 
					
						
							|  |  |  |  * to create the Group property and attach it to id if it doesn't exist; otherwise | 
					
						
							|  |  |  |  * the function will return NULL if there's no Group property attached to the ID. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | IDProperty *IDP_GetProperties(ID *id, const bool create_if_needed) | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-08 17:08:27 +00:00
										 |  |  | 	if (id->properties) { | 
					
						
							|  |  |  | 		return id->properties; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		if (create_if_needed) { | 
					
						
							|  |  |  | 			id->properties = MEM_callocN(sizeof(IDProperty), "IDProperty"); | 
					
						
							|  |  |  | 			id->properties->type = IDP_GROUP; | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  | 			/* don't overwrite the data's name and type
 | 
					
						
							| 
									
										
										
										
											2008-10-08 09:27:26 +00:00
										 |  |  | 			 * some functions might need this if they | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  | 			 * don't have a real ID, should be named elsewhere - Campbell */ | 
					
						
							| 
									
										
										
										
											2008-10-08 09:27:26 +00:00
										 |  |  | 			/* strcpy(id->name, "top_level_group");*/ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return id->properties; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-31 20:29:32 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2014-04-01 11:34:00 +11:00
										 |  |  |  * \param is_strict When false treat missing items as a match */ | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is_strict) | 
					
						
							| 
									
										
										
										
											2009-01-28 23:29:27 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	if (prop1 == NULL && prop2 == NULL) | 
					
						
							| 
									
										
										
										
											2009-01-28 23:29:27 +00:00
										 |  |  | 		return 1; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	else if (prop1 == NULL || prop2 == NULL) | 
					
						
							| 
									
										
										
										
											2012-10-31 20:29:32 +00:00
										 |  |  | 		return is_strict ? 0 : 1; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 	else if (prop1->type != prop2->type) | 
					
						
							| 
									
										
										
										
											2009-01-28 23:29:27 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-31 19:42:02 +00:00
										 |  |  | 	switch (prop1->type) { | 
					
						
							|  |  |  | 		case IDP_INT: | 
					
						
							|  |  |  | 			return (IDP_Int(prop1) == IDP_Int(prop2)); | 
					
						
							|  |  |  | 		case IDP_FLOAT: | 
					
						
							| 
									
										
										
										
											2014-04-24 16:46:54 +02:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				float p1 = IDP_Float(prop1); | 
					
						
							|  |  |  | 				float p2 = IDP_Float(prop2); | 
					
						
							| 
									
										
										
										
											2014-04-25 03:18:19 +10:00
										 |  |  | 				if ((p1 != p2) && ((fabsf(p1 - p2) / max_ff(p1, p2)) < 0.001f)) { | 
					
						
							| 
									
										
										
										
											2014-04-24 16:46:54 +02:00
										 |  |  | 					printf("WARNING: Comparing two float properties that have nearly the same value (%f vs. %f)\n", p1, p2); | 
					
						
							|  |  |  | 					printf("    p1: "); | 
					
						
							|  |  |  | 					IDP_spit(prop1); | 
					
						
							|  |  |  | 					printf("    p2: "); | 
					
						
							|  |  |  | 					IDP_spit(prop2); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-10-31 19:42:02 +00:00
										 |  |  | 			return (IDP_Float(prop1) == IDP_Float(prop2)); | 
					
						
							|  |  |  | 		case IDP_DOUBLE: | 
					
						
							|  |  |  | 			return (IDP_Double(prop1) == IDP_Double(prop2)); | 
					
						
							|  |  |  | 		case IDP_STRING: | 
					
						
							|  |  |  | 			return ((prop1->len == prop2->len) && strncmp(IDP_String(prop1), IDP_String(prop2), prop1->len) == 0); | 
					
						
							|  |  |  | 		case IDP_ARRAY: | 
					
						
							|  |  |  | 			if (prop1->len == prop2->len && prop1->subtype == prop2->subtype) { | 
					
						
							|  |  |  | 				return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[(int)prop1->subtype] * prop1->len); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-07-21 08:16:37 +00:00
										 |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2012-10-31 19:42:02 +00:00
										 |  |  | 		case IDP_GROUP: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			IDProperty *link1, *link2; | 
					
						
							| 
									
										
										
										
											2009-01-28 23:29:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-14 12:02:10 +00:00
										 |  |  | 			if (is_strict && prop1->len != prop2->len) | 
					
						
							| 
									
										
										
										
											2012-10-31 19:42:02 +00:00
										 |  |  | 				return 0; | 
					
						
							| 
									
										
										
										
											2009-01-28 23:29:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-31 19:42:02 +00:00
										 |  |  | 			for (link1 = prop1->data.group.first; link1; link1 = link1->next) { | 
					
						
							|  |  |  | 				link2 = IDP_GetPropertyFromGroup(prop2, link1->name); | 
					
						
							| 
									
										
										
										
											2009-01-28 23:29:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-31 20:29:32 +00:00
										 |  |  | 				if (!IDP_EqualsProperties_ex(link1, link2, is_strict)) | 
					
						
							| 
									
										
										
										
											2012-10-31 19:42:02 +00:00
										 |  |  | 					return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-01-28 23:29:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-31 19:42:02 +00:00
										 |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		case IDP_IDPARRAY: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			IDProperty *array1 = IDP_IDPArray(prop1); | 
					
						
							|  |  |  | 			IDProperty *array2 = IDP_IDPArray(prop2); | 
					
						
							|  |  |  | 			int i; | 
					
						
							| 
									
										
										
										
											2009-01-28 23:29:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-31 19:42:02 +00:00
										 |  |  | 			if (prop1->len != prop2->len) | 
					
						
							| 
									
										
										
										
											2009-01-28 23:29:27 +00:00
										 |  |  | 				return 0; | 
					
						
							| 
									
										
										
										
											2012-10-31 19:42:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			for (i = 0; i < prop1->len; i++) | 
					
						
							|  |  |  | 				if (!IDP_EqualsProperties(&array1[i], &array2[i])) | 
					
						
							|  |  |  | 					return 0; | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			/* should never get here */ | 
					
						
							|  |  |  | 			BLI_assert(0); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-01-28 23:29:27 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-10-31 19:42:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 23:29:27 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-12 21:57:37 +11:00
										 |  |  | bool IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) | 
					
						
							| 
									
										
										
										
											2012-10-31 20:29:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-01 11:34:00 +11:00
										 |  |  | 	return IDP_EqualsProperties_ex(prop1, prop2, true); | 
					
						
							| 
									
										
										
										
											2012-10-31 20:29:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Allocate a new ID. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This function takes three arguments: the ID property type, a union which defines | 
					
						
							|  |  |  |  * it's initial value, and a name. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The union is simple to use; see the top of this header file for its definition. | 
					
						
							|  |  |  |  * An example of using this function: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     IDPropertyTemplate val; | 
					
						
							|  |  |  |  *     IDProperty *group, *idgroup, *color; | 
					
						
							|  |  |  |  *     group = IDP_New(IDP_GROUP, val, "group1"); //groups don't need a template.
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     val.array.len = 4 | 
					
						
							|  |  |  |  *     val.array.type = IDP_FLOAT; | 
					
						
							|  |  |  |  *     color = IDP_New(IDP_ARRAY, val, "color1"); | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     idgroup = IDP_GetProperties(some_id, 1); | 
					
						
							|  |  |  |  *     IDP_AddToGroup(idgroup, color); | 
					
						
							|  |  |  |  *     IDP_AddToGroup(idgroup, group); | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Note that you MUST either attach the id property to an id property group with | 
					
						
							|  |  |  |  * IDP_AddToGroup or MEM_freeN the property, doing anything else might result in | 
					
						
							|  |  |  |  * a memory leak. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-11-15 09:22:52 +00:00
										 |  |  | IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name) | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 	IDProperty *prop = NULL; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch (type) { | 
					
						
							|  |  |  | 		case IDP_INT: | 
					
						
							|  |  |  | 			prop = MEM_callocN(sizeof(IDProperty), "IDProperty int"); | 
					
						
							| 
									
										
										
										
											2011-11-15 09:22:52 +00:00
										 |  |  | 			prop->data.val = val->i; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		case IDP_FLOAT: | 
					
						
							|  |  |  | 			prop = MEM_callocN(sizeof(IDProperty), "IDProperty float"); | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 			*(float *)&prop->data.val = val->f; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2008-07-24 19:22:17 +00:00
										 |  |  | 		case IDP_DOUBLE: | 
					
						
							|  |  |  | 			prop = MEM_callocN(sizeof(IDProperty), "IDProperty float"); | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 			*(double *)&prop->data.val = val->d; | 
					
						
							| 
									
										
										
										
											2012-09-16 04:58:18 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 		case IDP_ARRAY: | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2012-08-17 14:43:20 +00:00
										 |  |  | 			/* for now, we only support float and int and double arrays */ | 
					
						
							| 
									
										
										
										
											2011-12-22 00:03:20 +00:00
										 |  |  | 			if ( (val->array.type == IDP_FLOAT) || | 
					
						
							|  |  |  | 			     (val->array.type == IDP_INT) || | 
					
						
							|  |  |  | 			     (val->array.type == IDP_DOUBLE) || | 
					
						
							|  |  |  | 			     (val->array.type == IDP_GROUP) ) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 				prop = MEM_callocN(sizeof(IDProperty), "IDProperty array"); | 
					
						
							| 
									
										
										
										
											2011-11-15 09:22:52 +00:00
										 |  |  | 				prop->subtype = val->array.type; | 
					
						
							|  |  |  | 				if (val->array.len) | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 					prop->data.pointer = MEM_callocN(idp_size_table[val->array.type] * val->array.len, "id property array"); | 
					
						
							| 
									
										
										
										
											2011-11-15 09:22:52 +00:00
										 |  |  | 				prop->len = prop->totallen = val->array.len; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-07-21 08:16:37 +00:00
										 |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		case IDP_STRING: | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2011-11-15 09:22:52 +00:00
										 |  |  | 			const char *st = val->string.str; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			prop = MEM_callocN(sizeof(IDProperty), "IDProperty string"); | 
					
						
							| 
									
										
										
										
											2011-11-15 09:22:52 +00:00
										 |  |  | 			if (val->string.subtype == IDP_STRING_SUB_BYTE) { | 
					
						
							| 
									
										
										
										
											2011-11-15 09:12:10 +00:00
										 |  |  | 				/* note, intentionally not null terminated */ | 
					
						
							|  |  |  | 				if (st == NULL) { | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 					prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1"); | 
					
						
							|  |  |  | 					*IDP_String(prop) = '\0'; | 
					
						
							| 
									
										
										
										
											2011-11-15 09:12:10 +00:00
										 |  |  | 					prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS; | 
					
						
							|  |  |  | 					prop->len = 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							| 
									
										
										
										
											2011-11-15 09:22:52 +00:00
										 |  |  | 					prop->data.pointer = MEM_mallocN(val->string.len, "id property string 2"); | 
					
						
							|  |  |  | 					prop->len = prop->totallen = val->string.len; | 
					
						
							|  |  |  | 					memcpy(prop->data.pointer, st, val->string.len); | 
					
						
							| 
									
										
										
										
											2011-11-15 09:12:10 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 				prop->subtype = IDP_STRING_SUB_BYTE; | 
					
						
							| 
									
										
										
										
											2011-11-15 09:12:10 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				if (st == NULL) { | 
					
						
							| 
									
										
										
										
											2013-09-05 04:26:08 +00:00
										 |  |  | 					prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1"); | 
					
						
							|  |  |  | 					*IDP_String(prop) = '\0'; | 
					
						
							| 
									
										
										
										
											2011-11-15 09:12:10 +00:00
										 |  |  | 					prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS; | 
					
						
							|  |  |  | 					prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/ | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					int stlen = strlen(st) + 1; | 
					
						
							|  |  |  | 					prop->data.pointer = MEM_mallocN(stlen, "id property string 3"); | 
					
						
							|  |  |  | 					prop->len = prop->totallen = stlen; | 
					
						
							|  |  |  | 					memcpy(prop->data.pointer, st, stlen); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-05-06 17:22:54 +00:00
										 |  |  | 				prop->subtype = IDP_STRING_SUB_UTF8; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		case IDP_GROUP: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			prop = MEM_callocN(sizeof(IDProperty), "IDProperty group"); | 
					
						
							|  |  |  | 			/* heh I think all needed values are set properly by calloc anyway :) */ | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			prop = MEM_callocN(sizeof(IDProperty), "IDProperty array"); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	prop->type = type; | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 	BLI_strncpy(prop->name, name, MAX_IDPROP_NAME); | 
					
						
							| 
									
										
										
										
											2008-07-24 19:22:17 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	return prop; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * \note this will free all child properties of list arrays and groups! | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |  * Also, note that this does NOT unlink anything!  Plus it doesn't free | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  |  * the actual struct IDProperty struct either. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | void IDP_FreeProperty(IDProperty *prop) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	switch (prop->type) { | 
					
						
							|  |  |  | 		case IDP_ARRAY: | 
					
						
							|  |  |  | 			IDP_FreeArray(prop); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IDP_STRING: | 
					
						
							|  |  |  | 			IDP_FreeString(prop); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IDP_GROUP: | 
					
						
							|  |  |  | 			IDP_FreeGroup(prop); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2008-12-31 13:16:37 +00:00
										 |  |  | 		case IDP_IDPARRAY: | 
					
						
							|  |  |  | 			IDP_FreeIDPArray(prop); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-02 23:10:14 +00:00
										 |  |  | void IDP_ClearProperty(IDProperty *prop) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	IDP_FreeProperty(prop); | 
					
						
							|  |  |  | 	prop->data.pointer = NULL; | 
					
						
							|  |  |  | 	prop->len = prop->totallen = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-24 01:51:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Unlinks any struct IDProperty<->ID linkage that might be going on. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note currently unused | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | void IDP_UnlinkProperty(IDProperty *prop) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	switch (prop->type) { | 
					
						
							|  |  |  | 		case IDP_ID: | 
					
						
							|  |  |  | 			IDP_UnlinkID(prop); | 
					
						
							| 
									
										
										
										
											2013-07-21 08:16:37 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2006-11-17 04:46:48 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-09-30 11:27:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** \} */ |