source: trunk/packages/vizservers/vtkvis/CmdProc.cpp @ 2238

Last change on this file since 2238 was 2123, checked in by ldelgass, 14 years ago
  • First pass at making dataSetName optional in commands, pass 'all' to methods

in this case (can pass literal 'all' or leave name out). Currently implemented
for delete subcommands.

  • Return bool from rendering legend if color map not found - fixes crash
  • Delete DataSets? after graphics objects, since they hold pointers to their

DataSet?. (TODO: use TR1 shared pointers?)

  • Make hash keys (std::string) const reference parameters in methods
  • Add some debug traces to destructors
  • Fix indentation in CmdProc?.cpp
  • Property svn:eol-style set to native
File size: 6.6 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2011, Purdue Research Foundation
4 *
5 * Author: ?
6 */
7
8#include <cstring>
9#include <tcl.h>
10
11#include "CmdProc.h"
12
13/**
14 * Performs a binary search on the array of command operation
15 * specifications to find a partial, anchored match for the given
16 * operation string.
17 *
18 * \return If the string matches unambiguously the index of the specification in
19 * the array is returned.  If the string does not match, even as an
20 * abbreviation, any operation, -1 is returned.  If the string matches,
21 * but ambiguously -2 is returned.
22 */
23static int
24BinaryOpSearch(Rappture::CmdSpec *specs,
25               int nSpecs,
26               char *string)       /* Name of minor operation to search for */
27{
28    char c;
29    int high, low;
30    size_t length;
31
32    low = 0;
33    high = nSpecs - 1;
34    c = string[0];
35    length = strlen(string);
36    while (low <= high) {
37        Rappture::CmdSpec *specPtr;
38        int compare;
39        int median;
40   
41        median = (low + high) >> 1;
42        specPtr = specs + median;
43
44        /* Test the first character */
45        compare = c - specPtr->name[0];
46        if (compare == 0) {
47            /* Now test the entire string */
48            compare = strncmp(string, specPtr->name, length);
49            if (compare == 0) {
50                if ((int)length < specPtr->minChars) {
51                    return -2;  /* Ambiguous operation name */
52                }
53            }
54        }
55        if (compare < 0) {
56            high = median - 1;
57        } else if (compare > 0) {
58            low = median + 1;
59        } else {
60            return median;  /* Op found. */
61        }
62    }
63    return -1;          /* Can't find operation */
64}
65
66
67/**
68 * Performs a binary search on the array of command operation
69 * specifications to find a partial, anchored match for the given
70 * operation string.
71 *
72 * \return If the string matches unambiguously the index of the specification in
73 * the array is returned.  If the string does not match, even as an
74 * abbreviation, any operation, -1 is returned.  If the string matches,
75 * but ambiguously -2 is returned.
76 */
77static int
78LinearOpSearch(Rappture::CmdSpec *specs,
79               int nSpecs,
80               char *string)       /* Name of minor operation to search for */
81{
82    Rappture::CmdSpec *specPtr;
83    char c;
84    size_t length;
85    int nMatches, last;
86    int i;
87
88    c = string[0];
89    length = strlen(string);
90    nMatches = 0;
91    last = -1;
92    for (specPtr = specs, i = 0; i < nSpecs; i++, specPtr++) {
93        if ((c == specPtr->name[0]) &&
94            (strncmp(string, specPtr->name, length) == 0)) {
95            last = i;
96            nMatches++;
97            if ((int)length == specPtr->minChars) {
98                break;
99            }
100        }
101    }
102    if (nMatches > 1) {
103        return -2;      /* Ambiguous operation name */
104    }
105    if (nMatches == 0) {
106        return -1;      /* Can't find operation */
107    }
108    return last;        /* Op found. */
109}
110
111/**
112 * \brief Find the command operation given a string name.
113 *
114 * This is useful where a group of command operations have the same argument
115 * signature.
116 *
117 * \return If found, a pointer to the procedure (function pointer) is returned.
118 * Otherwise NULL is returned and an error message containing a list of
119 * the possible commands is returned in interp->result.
120 */
121Tcl_ObjCmdProc *
122Rappture::GetOpFromObj(Tcl_Interp *interp,              /* Interpreter to report errors to */
123                       int nSpecs,                      /* Number of specifications in array */
124                       Rappture::CmdSpec *specs,        /* Op specification array */
125                       int operPos,                     /* Position of operation in argument
126                                                         * list. */
127                       int objc,                        /* Number of arguments in the argument
128                                                         * vector.  This includes any prefixed
129                                                         * arguments */
130                       Tcl_Obj *const *objv,            /* Argument vector */
131                       int flags)
132{
133    CmdSpec *specPtr;
134    char *string;
135    int n;
136
137    if (objc <= operPos) {  /* No operation argument */
138        Tcl_AppendResult(interp, "wrong # args: ", (char *)NULL);
139usage:
140        Tcl_AppendResult(interp, "should be one of...", (char *)NULL);
141        for (n = 0; n < nSpecs; n++) {
142            int i;
143
144            Tcl_AppendResult(interp, "\n  ", (char *)NULL);
145            for (i = 0; i < operPos; i++) {
146                Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
147                                 (char *)NULL);
148            }
149            specPtr = specs + n;
150            Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage,
151                             (char *)NULL);
152        }
153        return NULL;
154    }
155    string = Tcl_GetString(objv[operPos]);
156    if (flags & CMDSPEC_LINEAR_SEARCH) {
157        n = LinearOpSearch(specs, nSpecs, string);
158    } else {
159        n = BinaryOpSearch(specs, nSpecs, string);
160    }
161    if (n == -2) {
162        char c;
163        size_t length;
164
165        Tcl_AppendResult(interp, "ambiguous", (char *)NULL);
166        if (operPos > 2) {
167            Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
168                             (char *)NULL);
169        }
170        Tcl_AppendResult(interp, " operation \"", string, "\" matches: ",
171                         (char *)NULL);
172
173        c = string[0];
174        length = strlen(string);
175        for (n = 0; n < nSpecs; n++) {
176            specPtr = specs + n;
177            if ((c == specPtr->name[0]) &&
178                (strncmp(string, specPtr->name, length) == 0)) {
179                Tcl_AppendResult(interp, " ", specPtr->name, (char *)NULL);
180            }
181        }
182        return NULL;
183
184    } else if (n == -1) {   /* Can't find operation, display help */
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    specPtr = specs + n;
194    if ((objc < specPtr->minArgs) ||
195        ((specPtr->maxArgs > 0) && (objc > specPtr->maxArgs))) {
196        int i;
197
198        Tcl_AppendResult(interp, "wrong # args: should be \"", (char *)NULL);
199        for (i = 0; i < operPos; i++) {
200            Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
201                             (char *)NULL);
202        }
203        Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage, "\"",
204                         (char *)NULL);
205        return NULL;
206    }
207    return specPtr->proc;
208}
Note: See TracBrowser for help on using the repository browser.