Changeset 3713


Ignore:
Timestamp:
Jun 26, 2013, 11:12:09 AM (6 years ago)
Author:
ldelgass
Message:

Apply CmdProc? updates to nanovis.

File:
1 edited

Legend:

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

    r3502 r3713  
    1010#include "CmdProc.h"
    1111
    12 /*
    13  *-------------------------------------------------------------------------------
    14  *
    15  * BinaryOpSearch --
    16  *
    17  *      Performs a binary search on the array of command operation
    18  *      specifications to find a partial, anchored match for the given
    19  *      operation string.
    20  *
    21  * Results:
    22  *  If the string matches unambiguously the index of the specification in
    23  *  the array is returned.  If the string does not match, even as an
    24  *  abbreviation, any operation, -1 is returned.  If the string matches,
    25  *  but ambiguously -2 is returned.
    26  *
    27  *-------------------------------------------------------------------------------
     12using namespace Rappture;
     13
     14/**
     15 * Performs a linear search on the array of command operation
     16 * specifications to find a partial, anchored match for the given
     17 * operation string.
     18 *
     19 * \return If the string matches unambiguously the index of the specification in
     20 * the array is returned.  If the string does not match, even as an
     21 * abbreviation, any operation, -1 is returned.  If the string matches,
     22 * but ambiguously -2 is returned.
    2823 */
    2924static int
    30 BinaryOpSearch(
    31     Rappture::CmdSpec *specs,
    32     int nSpecs,
    33     char *string)       /* Name of minor operation to search for */
     25LinearOpSearch(CmdSpec *specs, int low, int high, const char *string,
     26               int length)
    3427{
     28    CmdSpec *specPtr;
    3529    char c;
    36     int high, low;
    37     size_t length;
    38 
    39     low = 0;
    40     high = nSpecs - 1;
    41     c = string[0];
    42     length = strlen(string);
    43     while (low <= high) {
    44     Rappture::CmdSpec *specPtr;
    45     int compare;
    46     int median;
    47    
    48     median = (low + high) >> 1;
    49     specPtr = specs + median;
    50 
    51     /* Test the first character */
    52     compare = c - specPtr->name[0];
    53     if (compare == 0) {
    54         /* Now test the entire string */
    55         compare = strncmp(string, specPtr->name, length);
    56         if (compare == 0) {
    57         if ((int)length < specPtr->minChars) {
    58             return -2;  /* Ambiguous operation name */
    59         }
    60         }
    61     }
    62     if (compare < 0) {
    63         high = median - 1;
    64     } else if (compare > 0) {
    65         low = median + 1;
    66     } else {
    67         return median;  /* Op found. */
    68     }
    69     }
    70     return -1;          /* Can't find operation */
    71 }
    72 
    73 
    74 /*
    75  *-------------------------------------------------------------------------------
    76  *
    77  * LinearOpSearch --
    78  *
    79  *      Performs a binary search on the array of command operation
    80  *      specifications to find a partial, anchored match for the given
    81  *      operation string.
    82  *
    83  * Results:
    84  *  If the string matches unambiguously the index of the specification in
    85  *  the array is returned.  If the string does not match, even as an
    86  *  abbreviation, any operation, -1 is returned.  If the string matches,
    87  *  but ambiguously -2 is returned.
    88  *
    89  *-------------------------------------------------------------------------------
    90  */
    91 static int
    92 LinearOpSearch(
    93     Rappture::CmdSpec *specs,
    94     int nSpecs,
    95     char *string)       /* Name of minor operation to search for */
    96 {
    97     Rappture::CmdSpec *specPtr;
    98     char c;
    99     size_t length;
    10030    int nMatches, last;
    10131    int i;
    10232
    10333    c = string[0];
    104     length = strlen(string);
    10534    nMatches = 0;
    10635    last = -1;
    107     for (specPtr = specs, i = 0; i < nSpecs; i++, specPtr++) {
    108     if ((c == specPtr->name[0]) &&
    109         (strncmp(string, specPtr->name, length) == 0)) {
    110         last = i;
    111         nMatches++;
    112         if ((int)length == specPtr->minChars) {
    113         break;
    114         }
    115     }
     36    for (specPtr = specs+low, i = low; i <= high; i++, specPtr++) {
     37        if ((c == specPtr->name[0]) &&
     38            (strncmp(string, specPtr->name, length) == 0)) {
     39            last = i;
     40            nMatches++;
     41            if (length == specPtr->minChars) {
     42                break;
     43            }
     44        }
    11645    }
    11746    if (nMatches > 1) {
    118     return -2;      /* Ambiguous operation name */
     47        return -2;      /* Ambiguous operation name */
    11948    }
    12049    if (nMatches == 0) {
    121     return -1;      /* Can't find operation */
     50        return -1;      /* Can't find operation */
    12251    }
    12352    return last;        /* Op found. */
    12453}
    12554
    126 /*
    127  *-------------------------------------------------------------------------------
    128  *
    129  * GetOpFromObj --
    130  *
    131  *      Find the command operation given a string name.  This is useful where
    132  *      a group of command operations have the same argument signature.
    133  *
    134  * Results:
    135  *      If found, a pointer to the procedure (function pointer) is returned.
    136  *      Otherwise NULL is returned and an error message containing a list of
    137  *      the possible commands is returned in interp->result.
    138  *
    139  *-------------------------------------------------------------------------------
     55/**
     56 * Performs a binary search on the array of command operation
     57 * specifications to find a partial, anchored match for the given
     58 * operation string.  If we get to a point where the sample string
     59 * partially matches an entry, we then revert to a linear search
     60 * over the given range to check if it's an exact match or
     61 * ambiguous (example: "color" with commands color and colormode).
     62 *
     63 * \return If the string matches unambiguously the index of the specification in
     64 * the array is returned.  If the string does not match, even as an
     65 * abbreviation, any operation, -1 is returned.  If the string matches,
     66 * but ambiguously -2 is returned.
     67 */
     68static int
     69BinaryOpSearch(CmdSpec *specs, int low, int high, const char *string,
     70               int length)
     71{
     72    char c;
     73
     74    c = string[0];
     75    while (low <= high) {
     76        CmdSpec *specPtr;
     77        int compare;
     78        int median;
     79   
     80        median = (low + high) >> 1;
     81        specPtr = specs + median;
     82
     83        /* Test the first character */
     84        compare = c - specPtr->name[0];
     85        if (compare == 0) {
     86            /* Now test the entire string */
     87            compare = strncmp(string, specPtr->name, length);
     88        }
     89        if (compare < 0) {
     90            high = median - 1;
     91        } else if (compare > 0) {
     92            low = median + 1;
     93        } else {
     94            if (length < specPtr->minChars) {
     95                /* Verify that the string is either ambiguous or an exact
     96                 * match of another command by doing a linear search over the
     97                 * given interval. */
     98                return LinearOpSearch(specs, low, high, string, length);
     99            }
     100            return median;  /* Op found. */
     101        }
     102    }
     103    return -1;          /* Can't find operation */
     104}
     105
     106/**
     107 * \brief Find the command operation given a string name.
     108 *
     109 * This is useful where a group of command operations have the same argument
     110 * signature.
     111 *
     112 * \return If found, a pointer to the procedure (function pointer) is returned.
     113 * Otherwise NULL is returned and an error message containing a list of
     114 * the possible commands is returned in interp->result.
    140115 */
    141116Tcl_ObjCmdProc *
    142 Rappture::GetOpFromObj(
    143     Tcl_Interp *interp,                 /* Interpreter to report errors to */
    144     int nSpecs,                         /* Number of specifications in array */
    145     CmdSpec *specs,                     /* Op specification array */
    146     int operPos,                        /* Position of operation in argument
    147                                          * list. */
    148     int objc,                           /* Number of arguments in the argument
    149                                          * vector.  This includes any prefixed
    150                                          * arguments */
    151     Tcl_Obj *CONST *objv,               /* Argument vector */
    152     int flags)
     117Rappture::GetOpFromObj(Tcl_Interp *interp,      /* Interpreter to report errors to */
     118                       int nSpecs,              /* Number of specifications in array */
     119                       CmdSpec *specs,          /* Op specification array */
     120                       int operPos,             /* Position of operation in argument
     121                                                 * list. */
     122                       int objc,                /* Number of arguments in the argument
     123                                                 * vector.  This includes any prefixed
     124                                                 * arguments */
     125                       Tcl_Obj *const *objv,    /* Argument vector */
     126                       int flags)
    153127{
    154128    CmdSpec *specPtr;
    155129    char *string;
     130    int length;
    156131    int n;
    157132
    158133    if (objc <= operPos) {  /* No operation argument */
    159     Tcl_AppendResult(interp, "wrong # args: ", (char *)NULL);
    160       usage:
    161     Tcl_AppendResult(interp, "should be one of...", (char *)NULL);
    162     for (n = 0; n < nSpecs; n++) {
    163         int i;
    164 
    165         Tcl_AppendResult(interp, "\n  ", (char *)NULL);
    166         for (i = 0; i < operPos; i++) {
    167         Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
    168              (char *)NULL);
    169         }
    170         specPtr = specs + n;
    171         Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage,
    172         (char *)NULL);
    173     }
    174     return NULL;
    175     }
    176     string = Tcl_GetString(objv[operPos]);
     134        if (interp != NULL) {
     135            Tcl_AppendResult(interp, "wrong # args: ", (char *)NULL);
     136        usage:
     137            Tcl_AppendResult(interp, "should be one of...", (char *)NULL);
     138            for (n = 0; n < nSpecs; n++) {
     139                int i;
     140
     141                Tcl_AppendResult(interp, "\n  ", (char *)NULL);
     142                for (i = 0; i < operPos; i++) {
     143                    Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
     144                                     (char *)NULL);
     145                }
     146                specPtr = specs + n;
     147                Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage,
     148                                 (char *)NULL);
     149            }
     150        }
     151        return NULL;
     152    }
     153    string = Tcl_GetStringFromObj(objv[operPos], &length);
    177154    if (flags & CMDSPEC_LINEAR_SEARCH) {
    178     n = LinearOpSearch(specs, nSpecs, string);
     155        n = LinearOpSearch(specs, 0, nSpecs - 1, string, length);
    179156    } else {
    180     n = BinaryOpSearch(specs, nSpecs, string);
     157        n = BinaryOpSearch(specs, 0, nSpecs - 1, string, length);
    181158    }
    182159    if (n == -2) {
    183     char c;
    184     size_t length;
    185 
    186     Tcl_AppendResult(interp, "ambiguous", (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, "\" matches: ",
    192         (char *)NULL);
    193 
    194     c = string[0];
    195     length = strlen(string);
    196     for (n = 0; n < nSpecs; n++) {
    197         specPtr = specs + n;
    198         if ((c == specPtr->name[0]) &&
    199         (strncmp(string, specPtr->name, length) == 0)) {
    200         Tcl_AppendResult(interp, " ", specPtr->name, (char *)NULL);
    201         }
    202     }
    203     return NULL;
     160        if (interp != NULL) {
     161            char c;
     162
     163            Tcl_AppendResult(interp, "ambiguous", (char *)NULL);
     164            if (operPos > 2) {
     165                Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
     166                                 (char *)NULL);
     167            }
     168            Tcl_AppendResult(interp, " operation \"", string, "\" matches: ",
     169                             (char *)NULL);
     170
     171            c = string[0];
     172            length = strlen(string);
     173            for (n = 0; n < nSpecs; n++) {
     174                specPtr = specs + n;
     175                if ((c == specPtr->name[0]) &&
     176                    (strncmp(string, specPtr->name, length) == 0)) {
     177                    Tcl_AppendResult(interp, " ", specPtr->name, (char *)NULL);
     178                }
     179            }
     180        }
     181        return NULL;
    204182
    205183    } else if (n == -1) {   /* Can't find operation, display help */
    206     Tcl_AppendResult(interp, "bad", (char *)NULL);
    207     if (operPos > 2) {
    208         Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
    209         (char *)NULL);
    210     }
    211     Tcl_AppendResult(interp, " operation \"", string, "\": ", (char *)NULL);
    212     goto usage;
     184        if (interp != NULL) {
     185            Tcl_AppendResult(interp, "bad", (char *)NULL);
     186            if (operPos > 2) {
     187                Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
     188                                 (char *)NULL);
     189            }
     190            Tcl_AppendResult(interp, " operation \"", string, "\": ", (char *)NULL);
     191            goto usage;
     192        }
     193        return NULL;
    213194    }
    214195    specPtr = specs + n;
    215196    if ((objc < specPtr->minArgs) ||
    216     ((specPtr->maxArgs > 0) && (objc > specPtr->maxArgs))) {
    217     int i;
    218 
    219     Tcl_AppendResult(interp, "wrong # args: should be \"", (char *)NULL);
    220     for (i = 0; i < operPos; i++) {
    221         Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
    222         (char *)NULL);
    223     }
    224     Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage, "\"",
    225         (char *)NULL);
    226     return NULL;
     197        ((specPtr->maxArgs > 0) && (objc > specPtr->maxArgs))) {
     198        if (interp != NULL) {
     199            int i;
     200
     201            Tcl_AppendResult(interp, "wrong # args: should be \"", (char *)NULL);
     202            for (i = 0; i < operPos; i++) {
     203                Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
     204                                 (char *)NULL);
     205            }
     206            Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage, "\"",
     207                             (char *)NULL);
     208        }
     209        return NULL;
    227210    }
    228211    return specPtr->proc;
Note: See TracChangeset for help on using the changeset viewer.