Skip to content

Commit

Permalink
Merge pull request #388 from LLNL/bug-mcm86-29jul24-fix-botched-ns-merge
Browse files Browse the repository at this point in the history
Fix namescheme tests
  • Loading branch information
markcmiller86 authored Jul 30, 2024
2 parents 5c3732a + 5caa18e commit 69c2dfb
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 48 deletions.
2 changes: 1 addition & 1 deletion src/silo/silo.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -2174,7 +2174,7 @@ SILO_API extern DBgroupelmap * DBGetGroupelmap(DBfile *dbfile, char cons
SILO_API extern DBmrgvar * DBGetMrgvar(DBfile *dbfile, char const *name);
SILO_API extern DBnamescheme * DBMakeNamescheme(char const *fmt, ...);
SILO_API extern char const * DBGetName(DBnamescheme const *ns, long long natnum);
SILO_API long long DBGetIndex(char const *dbns_name_str, int field, int base);
SILO_API long long DBGetIndex(char const *dbns_name_str, int field, int width, int base);
SILO_API extern char const * DBSPrintf(char const *fmt, ...);

/* Multi-block objects and parallel I/O */
Expand Down
67 changes: 43 additions & 24 deletions src/silo/silo_ns.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,41 +609,60 @@ DBGetName(DBnamescheme const *ns, long long natnum)
}

PUBLIC long long
DBGetIndex(char const *dbns_name_str, int fieldSelector, int base)
DBGetIndex(char const *dbns_name_str, int fieldSelector, int minFieldWidth, int base)
{
int currentField = 0;
char const *currentPosition = dbns_name_str;
char const *lastPosition = currentPosition + strlen(dbns_name_str);
char *endPtr;
long long value = LLONG_MAX;

while (*currentPosition != '\0')
/* Note: leading zeros, which are probably quite common in fields in
nameschemes will get treated automatically as octal (base 8) if base
is not explicitly specified by caller. */

while (currentPosition < lastPosition)
{
/* x and X and b and B allow use of hexidecimal and binary numbers as in
0xDeadBeef and 0b101101 though the latter is non-converntional.
Note that leading zeros, which are probably quite common in fields in
nameschemes will get treated automatically as octal (base 8) if base
is not explicitly specified. */
if (isdigit(*currentPosition) || strchr("-+xXbB", *currentPosition))
long long mult = 1;
long long value;

/* skip forward over chars that cannot be part of a number */
if (!strchr("+-0123456789ABCDEFabcdefxX", *currentPosition))
{
errno = 0;
/* Found a digit, attempt to convert it to an integer value */
value = strtoll(currentPosition, &endPtr, base);
if (errno == 0)
{
if (currentField == fieldSelector)
return value;
currentPosition = endPtr; /* moved to end of whatever was parsed by strtol */
currentField++;
}
else
currentPosition++;
} else {
/* Skip non-digit characters */
currentPosition++;
continue;
}

/* walk over any sign if present */
if (*currentPosition == '-')
{
mult = -1;
currentPosition++;
}
else if (*currentPosition == '+')
currentPosition++;

/* Try to detect unconventional '0b' base-2 designator */
if (base == 0 && (!strncmp(currentPosition,"0b0",3) || !strncmp(currentPosition,"0b1",3)))
{
currentPosition += 2;
base = 2; /* explicitly set base to 2 */
}

/* Attempt a conversion. A successful conversion implies its a field. */
errno = 0;
value = strtoll(currentPosition, &endPtr, base);
if (errno == 0 && endPtr >= currentPosition + minFieldWidth)
{
if (currentField == fieldSelector)
return mult * value;
currentPosition = endPtr;
currentField++;
}
else
currentPosition++;
}

return value;
return LLONG_MAX;
}

PUBLIC char const *
Expand Down
57 changes: 34 additions & 23 deletions tests/namescheme.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ be used for advertising or product endorsement purposes.
#include <silo.h>
#include <std.c>
#include <string.h>
#include <limits.h>

#define TEST_GET_NAME(NS,I,EXP) \
if (!NS) \
Expand All @@ -81,20 +82,13 @@ else
} \
}

#define TEST_GET_INDEX(NS,I,IND) \
if (!NS) \
/* Uses a hard-coded min field width of 3 */
#define TEST_GET_INDEX(STR, FLD, BASE, EXP) \
if (DBGetIndex(STR, FLD, 3, BASE) != (long long) EXP) \
{ \
fprintf(stderr, "Got NULL namescheme from DBMakeNamescheme at line %d\n", __LINE__); \
fprintf(stderr, "DBGetIndex() at line %d failed for field %d of \"%s\". Expected %lld, got %lld\n", \
__LINE__, FLD, STR, (long long) EXP, DBGetIndex(STR,FLD,3,BASE)); \
return 1; \
} \
else \
{ \
if (DBGetIndex(NS, I) != IND) \
{ \
fprintf(stderr, "DBGetIndex() at line %d failed for field %d of \"%s\". Expected %lld, got %lld\n",\
__LINE__, FLD, STR, (long long) IND, DBGetIndex(STR,FLD,BASE)); \
return 1; \
} \
}

#define TEST_STR(A,B) \
Expand Down Expand Up @@ -412,11 +406,11 @@ int main(int argc, char **argv)

/* Test using namescheme as a simple integer mapping */
ns = DBMakeNamescheme("|chemA_%04X|n%3");
TEST_GET_INDEX(ns, 0, 0);
TEST_GET_INDEX(ns, 1, 1);
TEST_GET_INDEX(ns, 2, 2);
TEST_GET_INDEX(ns, 3, 0);
TEST_GET_INDEX(ns, 4, 1);
TEST_GET_INDEX(DBGetName(ns, 0), 0, 0, 0);
TEST_GET_INDEX(DBGetName(ns, 1), 0, 0, 1);
TEST_GET_INDEX(DBGetName(ns, 2), 0, 0, 2);
TEST_GET_INDEX(DBGetName(ns, 3), 0, 0, 0);
TEST_GET_INDEX(DBGetName(ns, 4), 0, 0, 1);
DBFreeNamescheme(ns);

/* simple offset by -2 mapping */
Expand All @@ -430,10 +424,10 @@ int main(int argc, char **argv)

/* Get different fields as indices from nameschemed strings */
ns = DBMakeNamescheme("|foo_%03d_%03d|n/5|n%5");
TEST_GET_INDEX(DBGetName(ns,0), 0, 0, 0);
TEST_GET_INDEX(DBGetName(ns,0), 1, 0, 0);
TEST_GET_INDEX(DBGetName(ns,18), 0, 2, 0);
TEST_GET_INDEX(DBGetName(ns,18), 1, 3, 0);
TEST_GET_INDEX(DBGetName(ns,0), 0, 0, 0);
TEST_GET_INDEX(DBGetName(ns,0), 1, 0, 0);
TEST_GET_INDEX(DBGetName(ns,18), 0, 0, 3);
TEST_GET_INDEX(DBGetName(ns,17), 1, 0, 2);
DBFreeNamescheme(ns);

/* Case where index is bigger than an int */
Expand All @@ -442,13 +436,30 @@ int main(int argc, char **argv)
TEST_GET_INDEX(DBGetName(ns,0x7FFFFFFFF), 0, 0, 0x7FFFFFFFF); /* make sure another `F` works */
DBFreeNamescheme(ns);

/* Test inferring base 2 (binary, leading '0b') */
TEST_GET_INDEX("block_0b0101", 0, 0, 5);
TEST_GET_INDEX("block_0b0101_0b1100", 1, 0, 12);

/* Test inferring base 8 (octal, leading '0') */
TEST_GET_INDEX("slice1_035", 0, 0, 29);

/* Test non-standard base 5 */
TEST_GET_INDEX("VisIt_docs_section_0002_chapter_1234", 1, 5, 194);

/* Test negative values */
TEST_GET_INDEX("block_-0b0101", 0, 0, -5);

/* Test some cases that could lead to error */
TEST_GET_INDEX("block_0b0", 1, 0, LLONG_MAX);
TEST_GET_INDEX("block_+", 1, 0, LLONG_MAX);
TEST_GET_INDEX("block_0x", 1, 0, LLONG_MAX);
TEST_GET_INDEX("VisIt_docs_section_0002_chapter_1234", 5, 5, LLONG_MAX);

/* Test the convenience method, DBSPrintf */
#if 0
snprintf(teststr, sizeof(teststr), "%s, %s",
DBSPrintf("block_%d,level_%04d", 505, 17),
DBSPrintf("side_%s_%cx%g", "master",'z',1.0/3));
TEST_STR(teststr, "block_505,level_0017, side_master_zx0.333333")
#endif

/* Test case where fewer expressions that conversion specs */
ns = DBMakeNamescheme("|/domain_%03d/laser_beam_power_%d|n/1|");
Expand Down

0 comments on commit 69c2dfb

Please sign in to comment.