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; } }
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 }