0001 |
/* |
0002 |
* Copyright 2001 Alexander Boverman and the original authors. |
0003 |
* |
0004 |
* Licensed under the Apache License, Version 2.0 (the "License"); |
0005 |
* you may not use this file except in compliance with the License. |
0006 |
* You may obtain a copy of the License at |
0007 |
* |
0008 |
* http://www.apache.org/licenses/LICENSE-2.0 |
0009 |
* |
0010 |
* Unless required by applicable law or agreed to in writing, software |
0011 |
* distributed under the License is distributed on an "AS IS" BASIS, |
0012 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
0013 |
* See the License for the specific language governing permissions and |
0014 |
* limitations under the License. |
0015 |
*/ |
0016 |
|
0017 |
#include "WtMultiTable.h" |
0018 |
#include "WtTableCmds.h" |
0019 |
#include "WtContext.h" |
0020 |
#include "WtUtil.h" |
0021 |
#include "WtTable.h" |
0022 |
#include "WtTableUtil.h" |
0023 |
|
0024 |
/* Create a custom command that operates on a table */ |
0025 |
|
0026 |
Tcl_Command WtCreateMultiTableCmd(const char *cmdName, |
0027 |
Tcl_Obj **tblPtr, Tcl_ObjType *type, Tcl_Interp *interp) |
0028 |
{ |
0029 |
WtTableCmdData *tcd = (WtTableCmdData *)ckalloc(sizeof(WtTableCmdData)); |
0030 |
tcd->tablePtr = tblPtr; |
0031 |
tcd->type = type; |
0032 |
return Tcl_CreateObjCommand(interp, cmdName, WtNamedMultiTableCmd, |
0033 |
(ClientData)tcd, WtDeleteMultiTableCmdProc); |
0034 |
} |
0035 |
|
0036 |
void WtDeleteMultiTableCmdProc(ClientData clientData) |
0037 |
{ |
0038 |
if (clientData) { |
0039 |
ckfree(clientData); |
0040 |
} |
0041 |
} |
0042 |
|
0043 |
/* The custom table command procedure */ |
0044 |
|
0045 |
int WtNamedMultiTableCmd(ClientData clientData, Tcl_Interp *interp, |
0046 |
int objc, Tcl_Obj *const objv[]) |
0047 |
{ |
0048 |
int ret; |
0049 |
WtTableCmdData *tcd = (WtTableCmdData *)clientData; |
0050 |
WtMultiTableMethodHelper(clientData, interp, objc, objv, &ret, |
0051 |
tcd->tablePtr, tcd->type, 0, 1); |
0052 |
return ret; |
0053 |
} |
0054 |
|
0055 |
WtTableCmdStatus WtMultiTableMethodHelper(ClientData clientData, |
0056 |
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], |
0057 |
int *tclRet, Tcl_Obj **tblPtr, Tcl_ObjType *type, int readOnly, |
0058 |
int appendUsage) |
0059 |
{ |
0060 |
int status = WT_TBL_CMD_DONE, ret = TCL_ERROR, error = 0, listLen; |
0061 |
WtContext *w = WtGetAssocContext(interp); |
0062 |
char *subCmd; |
0063 |
Tcl_Obj *tbl, *obj, *list; |
0064 |
|
0065 |
if (objc < 2) { |
0066 |
if (appendUsage) { |
0067 |
WtMultiTableMethodUsageError(interp, objv[0], readOnly); |
0068 |
} |
0069 |
|
0070 |
*tclRet = TCL_ERROR; |
0071 |
|
0072 |
return WT_TBL_CMD_MISSING; |
0073 |
} |
0074 |
|
0075 |
subCmd = WtToString(objv[1]); |
0076 |
tbl = *tblPtr; |
0077 |
|
0078 |
if (!strcmp(subCmd, "count")) { |
0079 |
|
0080 |
/* count command */ |
0081 |
|
0082 |
if (objc != 2) { |
0083 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0084 |
WtToString(objv[0]), " ", WtToString(objv[1]), NULL); |
0085 |
} else if (WtConvertToTableObj(tbl, type, interp)) { |
0086 |
Tcl_SetObjResult(interp, Tcl_NewIntObj(WtTableSize(tbl))); |
0087 |
ret = TCL_OK; |
0088 |
} |
0089 |
|
0090 |
} else if (!strcmp(subCmd, "has")) { |
0091 |
|
0092 |
/* has command */ |
0093 |
|
0094 |
if (objc != 3) { |
0095 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0096 |
WtToString(objv[0]), " ", WtToString(objv[1]), " ", |
0097 |
" key", NULL); |
0098 |
} else if (WtConvertToTableObj(tbl, type, interp)) { |
0099 |
obj = WtTableGet(tbl, objv[2]); |
0100 |
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(obj != NULL)); |
0101 |
ret = TCL_OK; |
0102 |
} |
0103 |
|
0104 |
} else if (!strcmp(subCmd, "keys")) { |
0105 |
|
0106 |
/* keys command */ |
0107 |
|
0108 |
if (objc != 2) { |
0109 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0110 |
WtToString(objv[0]), " ", WtToString(objv[1]), NULL); |
0111 |
} else if (WtConvertToTableObj(tbl, type, interp) && |
0112 |
WtTableKeys(tbl, &list, interp)) { |
0113 |
Tcl_SetObjResult(interp, list); |
0114 |
ret = TCL_OK; |
0115 |
} |
0116 |
|
0117 |
} else if (!strcmp(subCmd, "values")) { |
0118 |
|
0119 |
/* values command */ |
0120 |
|
0121 |
if (objc != 2) { |
0122 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0123 |
WtToString(objv[0]), " ", WtToString(objv[1]), NULL); |
0124 |
} else if (WtConvertToTableObj(tbl, type, interp) && |
0125 |
WtTableFirstValues(tbl, &list, interp)) { |
0126 |
Tcl_SetObjResult(interp, list); |
0127 |
ret = TCL_OK; |
0128 |
} |
0129 |
|
0130 |
} else if (!strcmp(subCmd, "allValues")) { |
0131 |
|
0132 |
/* allValues command */ |
0133 |
|
0134 |
if (objc != 2) { |
0135 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0136 |
WtToString(objv[0]), " ", WtToString(objv[1]), NULL); |
0137 |
} else if (WtConvertToTableObj(tbl, type, interp) && |
0138 |
WtTableValues(tbl, &list, interp)) { |
0139 |
Tcl_SetObjResult(interp, list); |
0140 |
ret = TCL_OK; |
0141 |
} |
0142 |
|
0143 |
} else if (!strcmp(subCmd, "get")) { |
0144 |
|
0145 |
/* get command */ |
0146 |
|
0147 |
if (objc < 3 || objc > 4) { |
0148 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0149 |
WtToString(objv[0]), " ", |
0150 |
WtToString(objv[1]), " key ?defaultValue?", NULL); |
0151 |
} else if (WtConvertToTableObj(tbl, type, interp) && |
0152 |
WtTableGetFirst(tbl, objv[2], &obj, interp)) { |
0153 |
if (obj) { |
0154 |
Tcl_SetObjResult(interp, obj); |
0155 |
ret = TCL_OK; |
0156 |
} else if (objc > 3) { |
0157 |
Tcl_SetObjResult(interp, objv[3]); |
0158 |
ret = TCL_OK; |
0159 |
} else { |
0160 |
Tcl_AppendResult(interp, "No entry with key \"", |
0161 |
WtToString(objv[2]), "\" found.", NULL); |
0162 |
} |
0163 |
} |
0164 |
|
0165 |
} else if (!strcmp(subCmd, "getAll")) { |
0166 |
|
0167 |
/* getAll command */ |
0168 |
|
0169 |
if (objc != 3 && objc != 4) { |
0170 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0171 |
WtToString(objv[0]), " ", WtToString(objv[1]), |
0172 |
" key ?defaultValue?", NULL); |
0173 |
} else if (WtConvertToTableObj(tbl, type, interp)) { |
0174 |
list = WtTableGet(tbl, objv[2]); |
0175 |
if (list) { |
0176 |
Tcl_SetObjResult(interp, list); |
0177 |
ret = TCL_OK; |
0178 |
} else if (objc > 3) { |
0179 |
Tcl_SetObjResult(interp, objv[3]); |
0180 |
ret = TCL_OK; |
0181 |
} else { |
0182 |
Tcl_AppendResult(interp, "No entry with key \"", |
0183 |
WtToString(objv[2]), "\" found.", NULL); |
0184 |
} |
0185 |
} |
0186 |
|
0187 |
} else if (!strcmp(subCmd, "set") && !readOnly) { |
0188 |
|
0189 |
/* set command */ |
0190 |
|
0191 |
if (objc != 4) { |
0192 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0193 |
WtToString(objv[0]), " ", WtToString(objv[1]), |
0194 |
" key value", NULL); |
0195 |
} else if (WtOwnTableObj(tblPtr, type, interp)) { |
0196 |
tbl = *tblPtr; |
0197 |
WtTableSetOneValueList(tbl, objv[2], objv[3], &obj); |
0198 |
Tcl_SetObjResult(interp, obj); |
0199 |
ret = TCL_OK; |
0200 |
} |
0201 |
|
0202 |
} else if (!strcmp(subCmd, "setDefault") && !readOnly) { |
0203 |
|
0204 |
/* setDefault command */ |
0205 |
|
0206 |
if (objc != 4) { |
0207 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0208 |
WtToString(objv[0]), " ", WtToString(objv[1]), " ", |
0209 |
" key value", NULL); |
0210 |
} else if (WtConvertToTableObj(tbl, type, interp)) { |
0211 |
if (WtTableGetFirst(tbl, objv[2], &obj, interp)) { |
0212 |
if (obj) { |
0213 |
Tcl_SetObjResult(interp, obj); |
0214 |
ret = TCL_OK; |
0215 |
} else if (WtOwnTableObj(tblPtr, type, interp)) { |
0216 |
tbl = *tblPtr; |
0217 |
WtTableSetOneValueList(tbl, objv[2], objv[3], &obj); |
0218 |
Tcl_SetObjResult(interp, obj); |
0219 |
ret = TCL_OK; |
0220 |
} |
0221 |
} |
0222 |
} |
0223 |
|
0224 |
} else if (!strcmp(subCmd, "setAll") && !readOnly) { |
0225 |
|
0226 |
/* setAll command */ |
0227 |
|
0228 |
if (objc != 4) { |
0229 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0230 |
WtToString(objv[0]), " ", WtToString(objv[1]), |
0231 |
" key list", NULL); |
0232 |
} else { |
0233 |
if (Tcl_ListObjLength(interp, objv[3], &listLen) != TCL_OK) { |
0234 |
Tcl_AppendResult(interp, |
0235 |
"Value must be a list. Usage: ", WtToString(objv[0]), |
0236 |
" ", WtToString(objv[1]), " key list", NULL); |
0237 |
} else if (WtOwnTableObj(tblPtr, type, interp)) { |
0238 |
WtTableSet(tbl, objv[2], objv[3]); |
0239 |
Tcl_SetObjResult(interp, objv[3]); |
0240 |
ret = TCL_OK; |
0241 |
} |
0242 |
} |
0243 |
|
0244 |
} else if (!strcmp(subCmd, "setAllDefault") && !readOnly) { |
0245 |
|
0246 |
/* setAllDefault command */ |
0247 |
|
0248 |
if (objc != 4) { |
0249 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0250 |
WtToString(objv[0]), " ", WtToString(objv[1]), |
0251 |
" key list", NULL); |
0252 |
} else { |
0253 |
if (Tcl_ListObjLength(interp, objv[3], &listLen) != TCL_OK) { |
0254 |
Tcl_AppendResult(interp, |
0255 |
"Value must be a list. Usage: ", |
0256 |
WtToString(objv[0]), " ", WtToString(objv[1]), |
0257 |
" key list", NULL); |
0258 |
} else if (WtConvertToTableObj(tbl, type, interp)) { |
0259 |
if (WtTableGetList(tbl, objv[2], &list, interp)) { |
0260 |
if (list) { |
0261 |
Tcl_SetObjResult(interp, list); |
0262 |
} else if (WtOwnTableObj(tblPtr, type, interp)) { |
0263 |
tbl = *tblPtr; |
0264 |
WtTableSet(tbl, objv[2], objv[3]); |
0265 |
Tcl_SetObjResult(interp, objv[3]); |
0266 |
} |
0267 |
ret = TCL_OK; |
0268 |
} |
0269 |
} |
0270 |
} |
0271 |
|
0272 |
} else if (!strcmp(subCmd, "add") && !readOnly) { |
0273 |
|
0274 |
/* add command */ |
0275 |
|
0276 |
if (objc != 4) { |
0277 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0278 |
WtToString(objv[0]), " ", WtToString(objv[1]), |
0279 |
" key value", NULL); |
0280 |
} else if (WtOwnTableObj(tblPtr, type, interp)) { |
0281 |
tbl = *tblPtr; |
0282 |
if (WtTableAppendToList(tbl, objv[2], objv[3], &list, interp)) { |
0283 |
Tcl_SetObjResult(interp, list); |
0284 |
ret = TCL_OK; |
0285 |
} |
0286 |
} |
0287 |
|
0288 |
} else if (!strcmp(subCmd, "addList") && !readOnly) { |
0289 |
|
0290 |
/* addList command */ |
0291 |
|
0292 |
if (objc != 4) { |
0293 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0294 |
WtToString(objv[0]), " ", WtToString(objv[1]), |
0295 |
" key list", NULL); |
0296 |
} else { |
0297 |
if (Tcl_ListObjLength(interp, objv[3], &listLen) != TCL_OK) { |
0298 |
Tcl_AppendResult(interp, |
0299 |
"Value is not a list. Usage: ", |
0300 |
WtToString(objv[0]), " ", WtToString(objv[1]), |
0301 |
" key list", NULL); |
0302 |
} else if (WtOwnTableObj(tblPtr, type, interp)) { |
0303 |
tbl = *tblPtr; |
0304 |
if (WtTableAppendListToList(tbl, objv[2], objv[3], &list, interp)) { |
0305 |
Tcl_SetObjResult(interp, list); |
0306 |
ret = TCL_OK; |
0307 |
} |
0308 |
} |
0309 |
} |
0310 |
|
0311 |
} else if (!strcmp(subCmd, "remove") && !readOnly) { |
0312 |
|
0313 |
/* remove command */ |
0314 |
|
0315 |
if (objc != 3) { |
0316 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0317 |
WtToString(objv[0]), " ", WtToString(objv[1]), " key", NULL); |
0318 |
} else if (WtOwnTableObj(tblPtr, type, interp)) { |
0319 |
tbl = *tblPtr; |
0320 |
WtTableRemove(tbl, objv[2]); |
0321 |
ret = TCL_OK; |
0322 |
} |
0323 |
|
0324 |
} else if (!strcmp(subCmd, "removeList") && !readOnly) { |
0325 |
|
0326 |
/* removeList command */ |
0327 |
|
0328 |
if (objc != 3) { |
0329 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0330 |
WtToString(objv[0]), " ", WtToString(objv[1]), " list", NULL); |
0331 |
} else { |
0332 |
if (Tcl_ListObjLength(interp, objv[2], &listLen) != TCL_OK) { |
0333 |
Tcl_AppendResult(interp, |
0334 |
"Value must be a list. Usage: ", |
0335 |
WtToString(objv[0]), " ", WtToString(objv[1]), " list", NULL); |
0336 |
} else if (WtOwnTableObj(tblPtr, type, interp)) { |
0337 |
tbl = *tblPtr; |
0338 |
if (WtTableRemoveList(tbl, objv[2], interp)) { |
0339 |
ret = TCL_OK; |
0340 |
} |
0341 |
} |
0342 |
} |
0343 |
|
0344 |
} else if (!strcmp(subCmd, "items")) { |
0345 |
|
0346 |
/* items command */ |
0347 |
|
0348 |
if (objc != 2) { |
0349 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0350 |
WtToString(objv[0]), " ", WtToString(objv[1]), NULL); |
0351 |
} else if (WtConvertToTableObj(tbl, type, interp)) { |
0352 |
Tcl_SetObjResult(interp, tbl); |
0353 |
ret = TCL_OK; |
0354 |
} |
0355 |
|
0356 |
} else if (!strcmp(subCmd, "list")) { |
0357 |
|
0358 |
/* list command */ |
0359 |
|
0360 |
if (objc != 2) { |
0361 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0362 |
WtToString(objv[0]), " ", WtToString(objv[1]), NULL); |
0363 |
} else if (WtConvertToTableObj(tbl, type, interp)) { |
0364 |
if (obj = WtTableToList(tbl, 0, interp)) { |
0365 |
Tcl_SetObjResult(interp, obj); |
0366 |
ret = TCL_OK; |
0367 |
} |
0368 |
} |
0369 |
|
0370 |
} else if (!strcmp(subCmd, "array")) { |
0371 |
|
0372 |
/* array command */ |
0373 |
|
0374 |
if (objc != 3) { |
0375 |
Tcl_AppendResult(interp, wtBadUsagePrefix, |
0376 |
WtToString(objv[0]), " ", WtToString(objv[1]), " arrayName", |
0377 |
NULL); |
0378 |
} else if (WtConvertToTableObj(tbl, type, interp)) { |
0379 |
if (WtTableToArray(interp, tbl, objv[2], 0)) { |
0380 |
ret = TCL_OK; |
0381 |
} |
0382 |
} |
0383 |
|
0384 |
} else if (!strcmp(subCmd, "copy")) { |
0385 |
|
0386 |
/* copy command */ |
0387 |
|
0388 |
if (WtConvertToTableObj(tbl, type, interp)) { |
0389 |
Tcl_SetObjResult(interp, Tcl_DuplicateObj(tbl)); |
0390 |
ret = TCL_OK; |
0391 |
} |
0392 |
|
0393 |
} else if (!strcmp(subCmd, "clear") && !readOnly) { |
0394 |
|
0395 |
/* clear command */ |
0396 |
|
0397 |
if (WtOwnTableObj(tblPtr, type, interp)) { |
0398 |
tbl = *tblPtr; |
0399 |
WtClearTable(tbl); |
0400 |
ret = TCL_OK; |
0401 |
} |
0402 |
|
0403 |
} else { |
0404 |
|
0405 |
/* unknown command */ |
0406 |
|
0407 |
status = WT_TBL_CMD_NOT_FOUND; |
0408 |
|
0409 |
if (appendUsage) { |
0410 |
WtMultiTableMethodUsageError(interp, objv[0], readOnly); |
0411 |
} |
0412 |
|
0413 |
} |
0414 |
|
0415 |
*tclRet = ret; |
0416 |
|
0417 |
return status; |
0418 |
} |
0419 |
|
0420 |
/* Multi table usage error */ |
0421 |
|
0422 |
void WtMultiTableMethodUsageError(Tcl_Interp *interp, Tcl_Obj *cmd, |
0423 |
int readOnly) |
0424 |
{ |
0425 |
Tcl_AppendResult(interp, "Usage:\n\n", NULL); |
0426 |
WtMultiTableMethodAppendUsage(interp, cmd, readOnly); |
0427 |
} |
0428 |
|
0429 |
/* Multi table usage */ |
0430 |
|
0431 |
void WtMultiTableMethodAppendUsage(Tcl_Interp *interp, Tcl_Obj *cmd, int readOnly) |
0432 |
{ |
0433 |
Tcl_Obj *res = Tcl_GetObjResult(interp); |
0434 |
char *cmdStr = WtToString(cmd); |
0435 |
|
0436 |
if (readOnly) { |
0437 |
Tcl_AppendStringsToObj(res, |
0438 |
cmdStr, " count\n", |
0439 |
cmdStr, " has key\n", |
0440 |
cmdStr, " get key ?defaultValue?\n", |
0441 |
cmdStr, " getAll key ?defaultValue?\n", |
0442 |
cmdStr, " keys\n", |
0443 |
cmdStr, " values\n", |
0444 |
cmdStr, " allValues\n", |
0445 |
cmdStr, " items\n", |
0446 |
cmdStr, " list\n", |
0447 |
cmdStr, " array arrayName\n", |
0448 |
cmdStr, " copy\n", |
0449 |
NULL); |
0450 |
} else { |
0451 |
Tcl_AppendStringsToObj(res, |
0452 |
cmdStr, " count\n", |
0453 |
cmdStr, " has key\n", |
0454 |
cmdStr, " keys\n", |
0455 |
cmdStr, " values\n", |
0456 |
cmdStr, " allValues\n", |
0457 |
cmdStr, " get key ?defaultValue?\n", |
0458 |
cmdStr, " getAll key ?defaultValue?\n", |
0459 |
cmdStr, " set key value\n", |
0460 |
cmdStr, " setDefault key value\n", |
0461 |
cmdStr, " setAll key list\n", |
0462 |
cmdStr, " setAllDefault key list\n", |
0463 |
cmdStr, " add key value\n", |
0464 |
cmdStr, " addList key list\n", |
0465 |
cmdStr, " remove key\n", |
0466 |
cmdStr, " removeList keys\n", |
0467 |
cmdStr, " items\n", |
0468 |
cmdStr, " list\n", |
0469 |
cmdStr, " array arrayName\n", |
0470 |
cmdStr, " copy\n", |
0471 |
cmdStr, " clear\n", |
0472 |
NULL); |
0473 |
} |
0474 |
} |