Changeset 3712 for trunk/packages


Ignore:
Timestamp:
Jun 26, 2013 7:10:30 AM (11 years ago)
Author:
ldelgass
Message:

Update CmdProc? with command search functions from blt4 branch: permits having
a command which is a substring of another command.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/vizservers/vtkvis/CmdProc.cpp

    r3177 r3712  
    1414
    1515/**
    16  * Performs a binary search on the array of command operation
     16 * Performs a linear search on the array of command operation
    1717 * specifications to find a partial, anchored match for the given
    1818 * operation string.
     
    2424 */
    2525static int
    26 BinaryOpSearch(CmdSpec *specs,
    27                int nSpecs,
    28                char *string)       /* Name of minor operation to search for */
     26LinearOpSearch(CmdSpec *specs, int low, int high, const char *string,
     27               int length)
     28{
     29    CmdSpec *specPtr;
     30    char c;
     31    int nMatches, last;
     32    int i;
     33
     34    c = string[0];
     35    nMatches = 0;
     36    last = -1;
     37    for (specPtr = specs+low, i = low; i <= high; i++, specPtr++) {
     38        if ((c == specPtr->name[0]) &&
     39            (strncmp(string, specPtr->name, length) == 0)) {
     40            last = i;
     41            nMatches++;
     42            if (length == specPtr->minChars) {
     43                break;
     44            }
     45        }
     46    }
     47    if (nMatches > 1) {
     48        return -2;      /* Ambiguous operation name */
     49    }
     50    if (nMatches == 0) {
     51        return -1;      /* Can't find operation */
     52    }
     53    return last;        /* Op found. */
     54}
     55
     56/**
     57 * Performs a binary search on the array of command operation
     58 * specifications to find a partial, anchored match for the given
     59 * operation string.  If we get to a point where the sample string
     60 * partially matches an entry, we then revert to a linear search
     61 * over the given range to check if it's an exact match or
     62 * ambiguous (example: "color" with commands color and colormode).
     63 *
     64 * \return If the string matches unambiguously the index of the specification in
     65 * the array is returned.  If the string does not match, even as an
     66 * abbreviation, any operation, -1 is returned.  If the string matches,
     67 * but ambiguously -2 is returned.
     68 */
     69static int
     70BinaryOpSearch(CmdSpec *specs, int low, int high, const char *string,
     71               int length)
    2972{
    3073    char c;
    31     int high, low;
    32     size_t length;
    33 
    34     low = 0;
    35     high = nSpecs - 1;
     74
    3675    c = string[0];
    37     length = strlen(string);
    3876    while (low <= high) {
    3977        CmdSpec *specPtr;
     
    4987            /* Now test the entire string */
    5088            compare = strncmp(string, specPtr->name, length);
    51             if (compare == 0) {
    52                 if ((int)length < specPtr->minChars) {
    53                     return -2;  /* Ambiguous operation name */
    54                 }
    55             }
    5689        }
    5790        if (compare < 0) {
     
    6093            low = median + 1;
    6194        } else {
     95            if (length < specPtr->minChars) {
     96                /* Verify that the string is either ambiguous or an exact
     97                 * match of another command by doing a linear search over the
     98                 * given interval. */
     99                return LinearOpSearch(specs, low, high, string, length);
     100            }
    62101            return median;  /* Op found. */
    63102        }
    64103    }
    65104    return -1;          /* Can't find operation */
    66 }
    67 
    68 
    69 /**
    70  * Performs a binary search on the array of command operation
    71  * specifications to find a partial, anchored match for the given
    72  * operation string.
    73  *
    74  * \return If the string matches unambiguously the index of the specification in
    75  * the array is returned.  If the string does not match, even as an
    76  * abbreviation, any operation, -1 is returned.  If the string matches,
    77  * but ambiguously -2 is returned.
    78  */
    79 static int
    80 LinearOpSearch(CmdSpec *specs,
    81                int nSpecs,
    82                char *string)       /* Name of minor operation to search for */
    83 {
    84     CmdSpec *specPtr;
    85     char c;
    86     size_t length;
    87     int nMatches, last;
    88     int i;
    89 
    90     c = string[0];
    91     length = strlen(string);
    92     nMatches = 0;
    93     last = -1;
    94     for (specPtr = specs, i = 0; i < nSpecs; i++, specPtr++) {
    95         if ((c == specPtr->name[0]) &&
    96             (strncmp(string, specPtr->name, length) == 0)) {
    97             last = i;
    98             nMatches++;
    99             if ((int)length == specPtr->minChars) {
    100                 break;
    101             }
    102         }
    103     }
    104     if (nMatches > 1) {
    105         return -2;      /* Ambiguous operation name */
    106     }
    107     if (nMatches == 0) {
    108         return -1;      /* Can't find operation */
    109     }
    110     return last;        /* Op found. */
    111105}
    112106
     
    135129    CmdSpec *specPtr;
    136130    char *string;
     131    int length;
    137132    int n;
    138133
    139134    if (objc <= operPos) {  /* No operation argument */
    140         Tcl_AppendResult(interp, "wrong # args: ", (char *)NULL);
    141 usage:
    142         Tcl_AppendResult(interp, "should be one of...", (char *)NULL);
    143         for (n = 0; n < nSpecs; n++) {
    144             int i;
    145 
    146             Tcl_AppendResult(interp, "\n  ", (char *)NULL);
    147             for (i = 0; i < operPos; i++) {
    148                 Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
    149                                  (char *)NULL);
    150             }
    151             specPtr = specs + n;
    152             Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage,
     135        if (interp != NULL) {
     136            Tcl_AppendResult(interp, "wrong # args: ", (char *)NULL);
     137        usage:
     138            Tcl_AppendResult(interp, "should be one of...", (char *)NULL);
     139            for (n = 0; n < nSpecs; n++) {
     140                int i;
     141
     142                Tcl_AppendResult(interp, "\n  ", (char *)NULL);
     143                for (i = 0; i < operPos; i++) {
     144                    Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
     145                                     (char *)NULL);
     146                }
     147                specPtr = specs + n;
     148                Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage,
     149                                 (char *)NULL);
     150            }
     151        }
     152        return NULL;
     153    }
     154    string = Tcl_GetStringFromObj(objv[operPos], &length);
     155    if (flags & CMDSPEC_LINEAR_SEARCH) {
     156        n = LinearOpSearch(specs, 0, nSpecs - 1, string, length);
     157    } else {
     158        n = BinaryOpSearch(specs, 0, nSpecs - 1, string, length);
     159    }
     160    if (n == -2) {
     161        if (interp != NULL) {
     162            char c;
     163
     164            Tcl_AppendResult(interp, "ambiguous", (char *)NULL);
     165            if (operPos > 2) {
     166                Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
     167                                 (char *)NULL);
     168            }
     169            Tcl_AppendResult(interp, " operation \"", string, "\" matches: ",
    153170                             (char *)NULL);
    154         }
    155         return NULL;
    156     }
    157     string = Tcl_GetString(objv[operPos]);
    158     if (flags & CMDSPEC_LINEAR_SEARCH) {
    159         n = LinearOpSearch(specs, nSpecs, string);
    160     } else {
    161         n = BinaryOpSearch(specs, nSpecs, string);
    162     }
    163     if (n == -2) {
    164         char c;
    165         size_t length;
    166 
    167         Tcl_AppendResult(interp, "ambiguous", (char *)NULL);
    168         if (operPos > 2) {
    169             Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
    170                              (char *)NULL);
    171         }
    172         Tcl_AppendResult(interp, " operation \"", string, "\" matches: ",
    173                          (char *)NULL);
    174 
    175         c = string[0];
    176         length = strlen(string);
    177         for (n = 0; n < nSpecs; n++) {
    178             specPtr = specs + n;
    179             if ((c == specPtr->name[0]) &&
    180                 (strncmp(string, specPtr->name, length) == 0)) {
    181                 Tcl_AppendResult(interp, " ", specPtr->name, (char *)NULL);
     171
     172            c = string[0];
     173            length = strlen(string);
     174            for (n = 0; n < nSpecs; n++) {
     175                specPtr = specs + n;
     176                if ((c == specPtr->name[0]) &&
     177                    (strncmp(string, specPtr->name, length) == 0)) {
     178                    Tcl_AppendResult(interp, " ", specPtr->name, (char *)NULL);
     179                }
    182180            }
    183181        }
     
    185183
    186184    } else if (n == -1) {   /* Can't find operation, display help */
    187         Tcl_AppendResult(interp, "bad", (char *)NULL);
    188         if (operPos > 2) {
    189             Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
    190                              (char *)NULL);
    191         }
    192         Tcl_AppendResult(interp, " operation \"", string, "\": ", (char *)NULL);
    193         goto usage;
     185        if (interp != NULL) {
     186            Tcl_AppendResult(interp, "bad", (char *)NULL);
     187            if (operPos > 2) {
     188                Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
     189                                 (char *)NULL);
     190            }
     191            Tcl_AppendResult(interp, " operation \"", string, "\": ", (char *)NULL);
     192            goto usage;
     193        }
     194        return NULL;
    194195    }
    195196    specPtr = specs + n;
    196197    if ((objc < specPtr->minArgs) ||
    197198        ((specPtr->maxArgs > 0) && (objc > specPtr->maxArgs))) {
    198         int i;
    199 
    200         Tcl_AppendResult(interp, "wrong # args: should be \"", (char *)NULL);
    201         for (i = 0; i < operPos; i++) {
    202             Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
     199        if (interp != NULL) {
     200            int i;
     201
     202            Tcl_AppendResult(interp, "wrong # args: should be \"", (char *)NULL);
     203            for (i = 0; i < operPos; i++) {
     204                Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
     205                                 (char *)NULL);
     206            }
     207            Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage, "\"",
    203208                             (char *)NULL);
    204209        }
    205         Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage, "\"",
    206                          (char *)NULL);
    207210        return NULL;
    208211    }
Note: See TracChangeset for help on using the changeset viewer.