Changeset 3713 for trunk/packages/vizservers/nanovis/CmdProc.cpp
- Timestamp:
- Jun 26, 2013 8:12:09 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/packages/vizservers/nanovis/CmdProc.cpp
r3502 r3713 10 10 #include "CmdProc.h" 11 11 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 *------------------------------------------------------------------------------- 12 using 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. 28 23 */ 29 24 static int 30 BinaryOpSearch( 31 Rappture::CmdSpec *specs, 32 int nSpecs, 33 char *string) /* Name of minor operation to search for */ 25 LinearOpSearch(CmdSpec *specs, int low, int high, const char *string, 26 int length) 34 27 { 28 CmdSpec *specPtr; 35 29 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 operation80 * specifications to find a partial, anchored match for the given81 * operation string.82 *83 * Results:84 * If the string matches unambiguously the index of the specification in85 * the array is returned. If the string does not match, even as an86 * abbreviation, any operation, -1 is returned. If the string matches,87 * but ambiguously -2 is returned.88 *89 *-------------------------------------------------------------------------------90 */91 static int92 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;100 30 int nMatches, last; 101 31 int i; 102 32 103 33 c = string[0]; 104 length = strlen(string);105 34 nMatches = 0; 106 35 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 } 116 45 } 117 46 if (nMatches > 1) { 118 return -2; /* Ambiguous operation name */47 return -2; /* Ambiguous operation name */ 119 48 } 120 49 if (nMatches == 0) { 121 return -1; /* Can't find operation */50 return -1; /* Can't find operation */ 122 51 } 123 52 return last; /* Op found. */ 124 53 } 125 54 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 */ 68 static int 69 BinaryOpSearch(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. 140 115 */ 141 116 Tcl_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) 117 Rappture::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) 153 127 { 154 128 CmdSpec *specPtr; 155 129 char *string; 130 int length; 156 131 int n; 157 132 158 133 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); 177 154 if (flags & CMDSPEC_LINEAR_SEARCH) { 178 n = LinearOpSearch(specs, nSpecs, string);155 n = LinearOpSearch(specs, 0, nSpecs - 1, string, length); 179 156 } else { 180 n = BinaryOpSearch(specs, nSpecs, string);157 n = BinaryOpSearch(specs, 0, nSpecs - 1, string, length); 181 158 } 182 159 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; 204 182 205 183 } 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; 213 194 } 214 195 specPtr = specs + n; 215 196 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; 227 210 } 228 211 return specPtr->proc;
Note: See TracChangeset
for help on using the changeset viewer.