コード例 #1
0
static int check_for_dupid(ListBase *lb, ID *id, char *name)
{
	ID *idtest;
	int nr= 0, nrtest, a, left_len;
	char left[32], leftest[32], in_use[32];

	/* make sure input name is terminated properly */
	/* if( strlen(name) > 21 ) name[21]= 0; */
	/* removed since this is only ever called from one place - campbell */

	while (1) {

		/* phase 1: id already exists? */
		idtest = is_dupid(lb, id, name);

		/* if there is no double, done */
		if( idtest == NULL ) return 0;

		/* we have a dup; need to make a new name */
		/* quick check so we can reuse one of first 32 ids if vacant */
		memset(in_use, 0, sizeof(in_use));

		/* get name portion, number portion ("name.number") */
		left_len= BLI_split_name_num(left, &nr, name, '.');

		/* if new name will be too long, truncate it */
		if(nr > 999 && left_len > 16) {
			left[16]= 0;
			left_len= 16;
		}
		else if(left_len > 17) {
			left[17]= 0;
			left_len= 17;
		}

		for(idtest= lb->first; idtest; idtest= idtest->next) {
			if(		(id != idtest) &&
					(idtest->lib == NULL) &&
					(*name == *(idtest->name+2)) &&
					(strncmp(name, idtest->name+2, left_len)==0) &&
					(BLI_split_name_num(leftest, &nrtest, idtest->name+2, '.') == left_len)
			) {
				if(nrtest < sizeof(in_use))
					in_use[nrtest]= 1;	/* mark as used */
				if(nr <= nrtest)
					nr= nrtest+1;		/* track largest unused */
			}
		}

		/* decide which value of nr to use */
		for(a=0; a < sizeof(in_use); a++) {
			if(a>=nr) break;	/* stop when we've check up to biggest */
			if( in_use[a]==0 ) { /* found an unused value */
				nr = a;
				break;
			}
		}

		/* If the original name has no numeric suffix, 
		 * rather than just chopping and adding numbers, 
		 * shave off the end chars until we have a unique name.
		 * Check the null terminators match as well so we dont get Cube.000 -> Cube.00 */
		if (nr==0 && name[left_len]== '\0') {
			int len = left_len-1;
			idtest= is_dupid(lb, id, name);
			
			while (idtest && len> 1) {
				name[len--] = '\0';
				idtest= is_dupid(lb, id, name);
			}
			if (idtest == NULL) return 1;
			/* otherwise just continue and use a number suffix */
		}
		
		if(nr > 999 && left_len > 16) {
			/* this would overflow name buffer */
			left[16] = 0;
			/* left_len = 16; */ /* for now this isnt used again */
			memcpy(name, left, sizeof(char) * 17);
			continue;
		}
		/* this format specifier is from hell... */
		BLI_snprintf(name, sizeof(id->name) - 2,"%s.%.3d", left, nr);

		return 1;
	}
}
コード例 #2
0
ファイル: library.c プロジェクト: manwapastorelli/blender-git
static bool check_for_dupid(ListBase *lb, ID *id, char *name)
{
	ID *idtest;
	int nr = 0, a, left_len;
#define MAX_IN_USE 64
	bool in_use[MAX_IN_USE];
	/* to speed up finding unused numbers within [1 .. MAX_IN_USE - 1] */

	char left[MAX_ID_NAME + 8], leftest[MAX_ID_NAME + 8];

	while (true) {

		/* phase 1: id already exists? */
		idtest = is_dupid(lb, id, name);

		/* if there is no double, done */
		if (idtest == NULL) return false;

		/* we have a dup; need to make a new name */
		/* quick check so we can reuse one of first MAX_IN_USE - 1 ids if vacant */
		memset(in_use, false, sizeof(in_use));

		/* get name portion, number portion ("name.number") */
		left_len = BLI_split_name_num(left, &nr, name, '.');

		/* if new name will be too long, truncate it */
		if (nr > 999 && left_len > (MAX_ID_NAME - 8)) {  /* assumption: won't go beyond 9999 */
			left[MAX_ID_NAME - 8] = 0;
			left_len = MAX_ID_NAME - 8;
		}
		else if (left_len > (MAX_ID_NAME - 7)) {
			left[MAX_ID_NAME - 7] = 0;
			left_len = MAX_ID_NAME - 7;
		}

		for (idtest = lb->first; idtest; idtest = idtest->next) {
			int nrtest;
			if ( (id != idtest) &&
			     (idtest->lib == NULL) &&
			     (*name == *(idtest->name + 2)) &&
			     (strncmp(name, idtest->name + 2, left_len) == 0) &&
			     (BLI_split_name_num(leftest, &nrtest, idtest->name + 2, '.') == left_len)
			     )
			{
				/* will get here at least once, otherwise is_dupid call above would have returned NULL */
				if (nrtest < MAX_IN_USE)
					in_use[nrtest] = true;  /* mark as used */
				if (nr <= nrtest)
					nr = nrtest + 1;    /* track largest unused */
			}
		}
		/* At this point, 'nr' will typically be at least 1. (but not always) */
		// BLI_assert(nr >= 1);

		/* decide which value of nr to use */
		for (a = 0; a < MAX_IN_USE; a++) {
			if (a >= nr) break;  /* stop when we've checked up to biggest */  /* redundant check */
			if (!in_use[a]) { /* found an unused value */
				nr = a;
				/* can only be zero if all potential duplicate names had
				 * nonzero numeric suffixes, which means name itself has
				 * nonzero numeric suffix (else no name conflict and wouldn't
				 * have got here), which means name[left_len] is not a null */
				break;
			}
		}
		/* At this point, nr is either the lowest unused number within [0 .. MAX_IN_USE - 1],
		 * or 1 greater than the largest used number if all those low ones are taken.
		 * We can't be bothered to look for the lowest unused number beyond (MAX_IN_USE - 1). */

		/* If the original name has no numeric suffix, 
		 * rather than just chopping and adding numbers, 
		 * shave off the end chars until we have a unique name.
		 * Check the null terminators match as well so we don't get Cube.000 -> Cube.00 */
		if (nr == 0 && name[left_len] == '\0') {
			int len;
			/* FIXME: this code will never be executed, because either nr will be
			 * at least 1, or name will not end at left_len! */
			BLI_assert(0);

			len = left_len - 1;
			idtest = is_dupid(lb, id, name);
			
			while (idtest && len > 1) {
				name[len--] = '\0';
				idtest = is_dupid(lb, id, name);
			}
			if (idtest == NULL) return true;
			/* otherwise just continue and use a number suffix */
		}
		
		if (nr > 999 && left_len > (MAX_ID_NAME - 8)) {
			/* this would overflow name buffer */
			left[MAX_ID_NAME - 8] = 0;
			/* left_len = MAX_ID_NAME - 8; */ /* for now this isn't used again */
			memcpy(name, left, sizeof(char) * (MAX_ID_NAME - 7));
			continue;
		}
		/* this format specifier is from hell... */
		BLI_snprintf(name, sizeof(id->name) - 2, "%s.%.3d", left, nr);

		return true;
	}

#undef MAX_IN_USE
}