int main() { int i; int P[100], U[4]; const char *N[3] = { "red", "green", "blue" }; const char *FileNumbers[] = {"1","2","3"}; // Test a somewhat complex expression Namescheme *ns = new Namescheme("@foo_%+03d@3-((n % 3)*(4+1)+1/2)+1"); if (strcmp(ns->GetName(25), "foo_+01") != 0) return 1; delete ns; // Test ?:: operator ns = new Namescheme("@foo_%d@(n-5)?14:77:"); if (strcmp(ns->GetName(6), "foo_14") != 0) return 1; delete ns; // Example of AMR-like naming convention where we have the following // assignment of pathces to levels starting with the patches on // level 0 and ending with the patches on level 3... // // level: 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 // | | | // 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 // patch: 0 1 0 1 2 3 4 5 6 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 0 1 2 3 4 // | | | // 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 // n: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 // A B C D E F G H // // 2 patches at level 0 // 7 patches at level 1 // 17 patches at level 2 // 5 patches at level 3 ns = new Namescheme("@level%d,patch%d" "@(n/2)?((n/9)?((n/26)?3:2:):1:):0:" // level part (1rst %d) "@(n/2)?((n/9)?((n/26)?n-26:n-9:):n-2:):n:" // patch part (2nd %d) ); if (strcmp(ns->GetName( 1), "level0,patch1") != 0) return 1; // A if (strcmp(ns->GetName( 3), "level1,patch1") != 0) return 1; // B if (strcmp(ns->GetName( 8), "level1,patch6") != 0) return 1; // C if (strcmp(ns->GetName( 9), "level2,patch0") != 0) return 1; // D if (strcmp(ns->GetName(20), "level2,patch11") != 0) return 1; // E if (strcmp(ns->GetName(25), "level2,patch16") != 0) return 1; // F if (strcmp(ns->GetName(26), "level3,patch0") != 0) return 1; // G if (strcmp(ns->GetName(30), "level3,patch4") != 0) return 1; // H delete ns; // Test multiple conversion specifiers ns = new Namescheme("|foo_%03dx%03d|n/5|n%5"); if (strcmp(ns->GetName(17), "foo_003x002") != 0) return 1; if (strcmp(ns->GetName(20), "foo_004x000") != 0) return 1; if (strcmp(ns->GetName(3), "foo_000x003") != 0) return 1; delete ns; // Test embedded string value results ns = new Namescheme("#foo_%s#(n-5)?'master':'slave':"); if (strcmp(ns->GetName(6), "foo_master") != 0) return 1; delete ns; // Test array-based references in a name scheme for (i = 0; i < 100; i++) P[i] = i*5; for (i = 0; i < 4; i++) U[i] = i*i; ns = new Namescheme("@foo_%03dx%03d@#P[n]@#U[n%4]", P, U); if (strcmp(ns->GetName(17), "foo_085x001") != 0) return 1; if (strcmp(ns->GetName(18), "foo_090x004") != 0) return 1; if (strcmp(ns->GetName(19), "foo_095x009") != 0) return 1; if (strcmp(ns->GetName(20), "foo_100x000") != 0) return 1; if (strcmp(ns->GetName(21), "foo_105x001") != 0) return 1; delete ns; // Test array-based references to char* valued array ns = new Namescheme("Hfoo_%sH$N[n%3]", N); if (strcmp(ns->GetName(17), "foo_blue") != 0) return 1; if (strcmp(ns->GetName(6), "foo_red") != 0) return 1; delete ns; // Test McCandless' example ns = new Namescheme("@%s%s@(n/4)?'myfilename.':'':@(n/4)?$/arr_dir/FileNumbers[n/4-1]:'':",FileNumbers); if (strcmp(ns->GetName(0), "") != 0) return 1; if (strcmp(ns->GetName(1), "") != 0) return 1; if (strcmp(ns->GetName(4), "myfilename.1") != 0) return 1; if (strcmp(ns->GetName(15), "myfilename.3") != 0) return 1; delete ns; return 0; }
const char *NameschemeAttributes::GetName(int n) const { // First, determine if this is FIRST call to GetName on this object map<const void*, bool>::const_iterator cit4 = getNameCalledMap.find(this); if (cit4 == getNameCalledMap.end()) { // This is first call. Indicate that in the map. getNameCalledMap[this] = true; } // First, see if we have ALL explicit names defined and, if so, // ensure 'n' is in correct range for it. if ((size_t)n < allExplicitNames.size()) return allExplicitNames[n].c_str(); // Next, see if we have an explicit names map for this object. if (explicitIds.size()) { // If there is an explicit name for this entry, return it. for (size_t i = 0; i < explicitIds.size(); i++) { if (explicitIds[i] == n) return explicitNames[i].c_str(); } } // If we get here, we didn't have an explicit name, so // use our Namescheme class to compute the name. static char tmpname[128]; if (namescheme == "") { SNPRINTF(tmpname, sizeof(tmpname), "unknown_name_%d", n); return tmpname; } // First, lets see if we've already got one constructed for this object. Namescheme *ns = 0; map<const void*, Namescheme*>::const_iterator cit3 = nameschemesMap.find(this); if (cit3 != nameschemesMap.end()) { ns = cit3->second; } else { // We didn't find a Namescheme object. That means we've yet to create // it for this object. Create it now. // We could make this switch larger to accomodate a larger number // of external array references. But, for now, we're setting a // limit at 4. If we want to increase it, we need to make sure the // cooresponding Namescheme class can support it. switch(externalArrayNames.size()) { case 0: ns = new Namescheme(namescheme.c_str()); break; case 1: ns = new Namescheme(namescheme.c_str(), EA(0)); break; case 2: ns = new Namescheme(namescheme.c_str(), EA(0), EA(1)); break; case 3: ns = new Namescheme(namescheme.c_str(), EA(0), EA(1), EA(2)); break; case 4: ns = new Namescheme(namescheme.c_str(), EA(0), EA(1), EA(2), EA(3)); break; default: { EXCEPTION0(StateObjectException); } } // Store the Namescheme pointer in the map for this object so // we can find it again when we need to. nameschemesMap[this] = ns; } // Compute the name from the Namescheme const char *retval = ns ? ns->GetName(n) : 0; if (retval && retval[0] != '\0') return retval; // Ok, we can't compute a name. Make one up. SNPRINTF(tmpname, sizeof(tmpname), "unknown_name_%d", n); return tmpname; }