View Source

[modwtcl]
apreq.h
dist/
libapreq1/
mod_wtcl.c
mod_wtcl.h
setupExclude.txt
util/
win.def
win.mak
wt1.1/
WtAppTable.c
WtAppTable.h
WtBasicCmds.c
WtBasicCmds.h
WtClientRequest.c
WtClientRequest.h
WtCollection.c
WtCollection.h
WtCollectionCmds.c
WtCollectionCmds.h
WtContext.c
WtContext.h
WtContextEvents.c
WtContextEvents.h
WtCookie.c
WtCookie.h
WtDbSession.c
WtDbSession.h
WtExecute.c
WtExecute.h
WtHtmlEntities.c
WtHtmlEntities.h
WtInitCmds.c
WtInitCmds.h
WtMtTable.c
WtMtTable.h
WtMultiTable.c
WtMultiTable.h
WtOS.h
WtProcSession.c
WtProcSession.h
WtResponse.c
WtResponse.h
WtServerCmds.c
WtServerCmds.h
WtSession.c
WtSession.h
WtSettings.c
WtSettings.h
WtTable.c
WtTable.h
WtTableCmds.c
WtTableCmds.h
WtTableUtil.c
WtTableUtil.h
WtUpload.c
WtUpload.h
WtUtil.c
WtUtil.h
WtWebErrors.c
WtWebErrors.h
WtWindows.h
File: / archive / modwtcl / WtCollection.c

Lines Size Modified Created Owner MIME Types
710 15,001 2010/05/08 18:46:41 2011/06/13 15:35:15 BUILTIN\Administrators text/x-csrc

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 "WtCollection.h"
0018
#include "WtUtil.h"
0019
0020
/* Get the underlying collection from a Tcl object */
0021
0022
WtCollection *WtToCln(Tcl_Obj *obj)
0023
{
0024
  return (WtCollection *)(obj->internalRep.twoPtrValue.ptr1);
0025
}
0026
0027
/* Create a new collection object */
0028
0029
Tcl_Obj *WtNewClnObj(Tcl_ObjType *type, WtClnItemType *itemType)
0030
{
0031
  WtCollection *cln;
0032
  Tcl_Obj *obj;
0033
0034
  cln = (WtCollection *)ckalloc(sizeof(WtCollection));
0035
  cln->itemType = itemType;
0036
  cln->list = Tcl_NewListObj(0, NULL);
0037
  Tcl_IncrRefCount(cln->list);
0038
0039
  obj = Tcl_NewObj();
0040
  obj->internalRep.twoPtrValue.ptr1 = cln;
0041
  obj->internalRep.twoPtrValue.ptr2 = NULL;
0042
  obj->typePtr = type ? type : &WtClnType;
0043
  Tcl_InvalidateStringRep(obj);
0044
0045
  return obj;
0046
}
0047
0048
/* Get the size of a collection */
0049
0050
int WtClnSize(Tcl_Obj *cln, int *size, Tcl_Interp *interp)
0051
{
0052
  WtCollection *clnRep = WtToCln(cln);
0053
  return Tcl_ListObjLength(interp, clnRep->list, size) == TCL_OK;
0054
}
0055
0056
/* Get all the items */
0057
0058
Tcl_Obj *WtGetClnItems(Tcl_Obj *cln)
0059
{
0060
  return WtToCln(cln)->list;
0061
}
0062
0063
/* Get all item keys */
0064
0065
int WtGetClnKeys(Tcl_Obj *cln, Tcl_Obj **keys, Tcl_Interp *interp)
0066
{
0067
  int ok = 1, size;
0068
  Tcl_Obj *item, *obj;
0069
  int i;
0070
0071
  if (!WtClnSize(cln, &size, interp)) {
0072
    return 0;
0073
  }
0074
0075
  *keys = Tcl_NewListObj(0, NULL);
0076
0077
  for (i = 0; i < size; i++) {
0078
    if (!WtGetClnItemAtIndex(cln, i, &item, interp) ||
0079
        !WtGetClnItemKey(cln, item, &obj, interp) ||
0080
        Tcl_ListObjAppendElement(interp, *keys, obj) !=
0081
            TCL_OK) {
0082
      ok = 0;
0083
      break;
0084
    }
0085
  }
0086
0087
  if (!ok) {
0088
    Tcl_DecrRefCount(*keys);
0089
    *keys = NULL;
0090
  }
0091
0092
  return ok;
0093
}
0094
0095
/* Get all item values */
0096
0097
int WtGetClnValues(Tcl_Obj *cln, Tcl_Obj **values,
0098
    Tcl_Interp *interp)
0099
{
0100
  int ok = 1, size;
0101
  Tcl_Obj *item, *obj;
0102
  int i;
0103
0104
  if (!WtClnSize(cln, &size, interp)) {
0105
    return 0;
0106
  }
0107
0108
  *values = Tcl_NewListObj(0, NULL);
0109
0110
  for (i = 0; i < size; i++) {
0111
    if (!WtGetClnItemAtIndex(cln, i, &item, interp) ||
0112
        !WtGetClnItemValue(cln, item, &obj, interp) ||
0113
        Tcl_ListObjAppendElement(interp, *values, obj) !=
0114
            TCL_OK) {
0115
      ok = 0;
0116
      break;
0117
    }
0118
  }
0119
0120
  if (!ok) {
0121
    Tcl_DecrRefCount(*values);
0122
    *values = NULL;
0123
  }
0124
0125
  return ok;
0126
}
0127
0128
/* Get a collection item */
0129
0130
int WtGetClnItemAtIndex(Tcl_Obj *cln, int idx, Tcl_Obj **item,
0131
    Tcl_Interp *interp)
0132
{
0133
  WtCollection *clnRep = WtToCln(cln);
0134
  return Tcl_ListObjIndex(interp, clnRep->list, idx, item) ==
0135
    TCL_OK;
0136
}
0137
0138
/* Set a collection item */
0139
0140
int WtSetClnItemAtIndex(Tcl_Obj *cln, int idx, Tcl_Obj *obj,
0141
    Tcl_Interp *interp)
0142
{
0143
  int ok = 1;
0144
  WtCollection *clnRep = WtToCln(cln);
0145
0146
  WtCopyOnWrite(&clnRep->list);
0147
  Tcl_InvalidateStringRep(cln);
0148
  Tcl_IncrRefCount(obj);
0149
0150
  if (Tcl_ListObjReplace(interp, clnRep->list, idx,
0151
      1, 1, &obj) != TCL_OK) {
0152
    ok = 0;
0153
  }
0154
0155
  Tcl_DecrRefCount(obj);
0156
0157
  return ok;
0158
}
0159
0160
/* Add an item to a collection */
0161
0162
int WtAppendClnItem(Tcl_Obj *cln, Tcl_Obj *obj, Tcl_Interp *interp)
0163
{
0164
  WtCollection *clnRep = WtToCln(cln);
0165
  WtCopyOnWrite(&clnRep->list);
0166
  Tcl_InvalidateStringRep(cln);
0167
  return Tcl_ListObjAppendElement(interp, clnRep->list, obj) ==
0168
    TCL_OK;
0169
}
0170
0171
/* Add a list of items to a collection */
0172
0173
int WtAppendClnItemList(Tcl_Obj *cln, Tcl_Obj *list,
0174
    Tcl_Interp *interp)
0175
{
0176
  WtCollection *clnRep = WtToCln(cln);
0177
  WtCopyOnWrite(&clnRep->list);
0178
  Tcl_InvalidateStringRep(cln);
0179
  return Tcl_ListObjAppendList(interp, clnRep->list, list) ==
0180
    TCL_OK;
0181
}
0182
0183
/* Find an item using a key */
0184
0185
int WtFindClnItemIndex(Tcl_Obj *cln, Tcl_Obj *key, int start,
0186
    int *index, Tcl_Obj **item, Tcl_Interp *interp)
0187
{
0188
  int ok = 1, i, size, comp = 0;
0189
0190
  if (!WtClnSize(cln, &size, interp)) {
0191
    return 0;
0192
  }
0193
0194
  for (i = start; i < size; i++) {
0195
    if (!WtGetClnItemAtIndex(cln, i, item, interp) ||
0196
        !WtCompareClnItem(cln, *item, key, &comp, interp)) {
0197
      ok = 0;
0198
      break;
0199
    }
0200
    if (!comp) {
0201
      if (index) {
0202
        *index = i;
0203
      }
0204
      return 1;
0205
    }
0206
  }
0207
0208
  if (index) {
0209
    *index = -1;
0210
  }
0211
  *item = NULL;
0212
0213
  return ok;
0214
}
0215
0216
/* Find an item in reverse order using a key */
0217
0218
int WtFindClnItemIndexReverse(Tcl_Obj *cln, Tcl_Obj *key, int start,
0219
    int *index, Tcl_Obj **item, Tcl_Interp *interp)
0220
{
0221
  int ok = 1, size, i, comp;
0222
0223
  if (start == -1) {
0224
    if (!WtClnSize(cln, &size, interp)) {
0225
      return 0;
0226
    }
0227
    start = size;
0228
  }
0229
0230
  for (i = start; i >= 0; i--) {
0231
    if (!WtGetClnItemAtIndex(cln, i, item, interp) ||
0232
        !WtCompareClnItem(cln, *item, key, &comp, interp)) {
0233
      ok = 0;
0234
      break;
0235
    }
0236
    if (!comp) {
0237
      if (index) {
0238
        *index = i;
0239
      }
0240
      return 1;
0241
    }
0242
  }
0243
0244
  if (index) {
0245
    *index = -1;
0246
  }
0247
  *item = NULL;
0248
0249
  return ok;
0250
}
0251
0252
/* Find the first matching item */
0253
0254
int WtFindClnItem(Tcl_Obj *cln, Tcl_Obj *key, Tcl_Obj **item,
0255
    Tcl_Interp *interp)
0256
{
0257
  return WtFindClnItemIndex(cln, key, 0, NULL, item, interp);
0258
}
0259
0260
/* Get all items matching the key */
0261
0262
int WtFindAllClnItems(Tcl_Obj *cln, Tcl_Obj *key,
0263
    Tcl_Obj **items, Tcl_Interp *interp)
0264
{
0265
  int ok = 1;
0266
  Tcl_Obj *item;
0267
  int start = 0;
0268
0269
  *items = Tcl_NewListObj(0, NULL);
0270
0271
  for (;;) {
0272
    if (!WtFindClnItemIndex(cln, key, start, &start, &item, interp)) {
0273
      ok = 0;
0274
      break;
0275
    }
0276
    if (!item) {
0277
      break;
0278
    }
0279
    if (Tcl_ListObjAppendElement(interp, *items, item) != TCL_OK) {
0280
      ok = 0;
0281
      break;
0282
    }
0283
  }
0284
0285
  if (!ok) {
0286
    Tcl_DecrRefCount(*items);
0287
    *items = NULL;
0288
  }
0289
0290
  return ok;
0291
}
0292
0293
/* Get the key from all items that match the search key */
0294
0295
int WtFindAllClnKeys(Tcl_Obj *cln, Tcl_Obj *key, Tcl_Obj **keys,
0296
    Tcl_Interp *interp)
0297
{
0298
  int ok = 1;
0299
  Tcl_Obj *item, *itemKey;
0300
  int start = 0;
0301
0302
  *keys = Tcl_NewListObj(0, NULL);
0303
0304
  for (;;) {
0305
    if (!WtFindClnItemIndex(cln, key, start, &start, &item, interp)) {
0306
      ok = 0;
0307
      break;
0308
    }
0309
    if (!item) {
0310
      break;
0311
    }
0312
    if (!WtGetClnItemKey(cln, item, &itemKey, interp)) {
0313
      ok = 0;
0314
      break;
0315
    }
0316
    if (Tcl_ListObjAppendElement(interp, *keys, itemKey) != TCL_OK) {
0317
      ok = 0;
0318
      break;
0319
    }
0320
  }
0321
0322
  if (!ok) {
0323
    Tcl_DecrRefCount(*keys);
0324
    *keys = NULL;
0325
  }
0326
0327
  return ok;
0328
}
0329
0330
/* Get the value from all items that match the search key */
0331
0332
int WtFindAllClnValues(Tcl_Obj *cln, Tcl_Obj *key,
0333
    Tcl_Obj **values, Tcl_Interp *interp)
0334
{
0335
  int ok = 1;
0336
  Tcl_Obj *item, *itemValue;
0337
  int start = 0;
0338
0339
  *values = Tcl_NewListObj(0, NULL);
0340
0341
  for (;;) {
0342
    if (!WtFindClnItemIndex(cln, key, start, &start, &item, interp)) {
0343
      ok = 0;
0344
      break;
0345
    }
0346
    if (!item) {
0347
      break;
0348
    }
0349
    if (!WtGetClnItemValue(cln, item, &itemValue, interp)) {
0350
      ok = 0;
0351
      break;
0352
    }
0353
    if (Tcl_ListObjAppendElement(interp, *values, itemValue) !=
0354
        TCL_OK) {
0355
      ok = 0;
0356
      break;
0357
    }
0358
  }
0359
0360
  if (!ok) {
0361
    Tcl_DecrRefCount(*values);
0362
    *values = NULL;
0363
  }
0364
0365
  return ok;
0366
}
0367
0368
/* Remove a collection item */
0369
0370
int WtRemoveFromCln(Tcl_Obj *cln, Tcl_Obj *target, int limit,
0371
    Tcl_Interp *interp)
0372
{
0373
  int ok = 1, size, i, count = 0;
0374
  Tcl_Obj *item;
0375
  WtCollection *clnRep = WtToCln(cln);
0376
0377
  if (limit == 0) {
0378
    return ok;
0379
  }
0380
0381
  if (!WtClnSize(cln, &size, interp)) {
0382
    return 0;
0383
  }
0384
0385
  for (i = size; i >= 0; i--) {
0386
    if (!WtGetClnItemAtIndex(cln, i, &item, interp)) {
0387
      ok = 0;
0388
      break;
0389
    }
0390
    if (item == target) {
0391
      WtCopyOnWrite(&clnRep->list);
0392
      Tcl_InvalidateStringRep(cln);
0393
      if (Tcl_ListObjReplace(interp, clnRep->list, i, 1, 0, NULL) !=
0394
          TCL_OK) {
0395
        ok = 0;
0396
        break;
0397
      }
0398
      if (++count == limit && limit != -1) {
0399
        break;
0400
      }
0401
    }
0402
  }
0403
0404
  return ok;
0405
}
0406
0407
/* Remove a collection item at an index */
0408
0409
int RemoveFromClnByIndex(Tcl_Obj *cln, int idx, Tcl_Interp *interp)
0410
{
0411
  WtCollection *clnRep = WtToCln(cln);
0412
  WtCopyOnWrite(&clnRep->list);
0413
  Tcl_InvalidateStringRep(cln);
0414
  return Tcl_ListObjReplace(interp, clnRep->list, idx, 1, 0, NULL) ==
0415
      TCL_OK;
0416
}
0417
0418
/* Remove a collection item by key */
0419
0420
int WtRemoveFromClnByKey(Tcl_Obj *cln, Tcl_Obj *key, int limit,
0421
    Tcl_Interp *interp)
0422
{
0423
  int ok = 1, size, i, comp, count = 0;
0424
  Tcl_Obj *item;
0425
  WtCollection *clnRep = WtToCln(cln);
0426
0427
  if (limit == 0) {
0428
    return ok;
0429
  }
0430
0431
  if (!WtClnSize(cln, &size, interp)) {
0432
    return 0;
0433
  }
0434
0435
  for (i = size; i >= 0; i--) {
0436
    if (!WtGetClnItemAtIndex(cln, i, &item, interp) ||
0437
        !WtCompareClnItem(cln, item, key, &comp, interp)) {
0438
      ok = 0;
0439
      break;
0440
    }
0441
    if (!comp) {
0442
      WtCopyOnWrite(&clnRep->list);
0443
      Tcl_InvalidateStringRep(cln);
0444
      if (Tcl_ListObjReplace(interp, clnRep->list, i, 1, 0, NULL) !=
0445
          TCL_OK) {
0446
        ok = 0;
0447
        break;
0448
      }
0449
      if (++count == limit && limit != -1) {
0450
        break;
0451
      }
0452
    }
0453
  }
0454
0455
  return ok;
0456
}
0457
0458
/* Remove a list of collection items by key */
0459
0460
int WtRemoveFromClnByKeyList(Tcl_Obj *cln, Tcl_Obj *list,
0461
    int limit, Tcl_Interp *interp)
0462
{
0463
  int ok = 1, i, j, comp, count = 0, len;
0464
  Tcl_Obj *item, *key;
0465
  WtCollection *clnRep = WtToCln(cln);
0466
0467
  if (limit == 0) {
0468
    return ok;
0469
  }
0470
0471
  if (Tcl_ListObjLength(interp, list, &len) != TCL_OK ||
0472
      !WtClnSize(cln, &i, interp)) {
0473
    ok = 0;
0474
  } else {
0475
    for (; i >= 0; i--) {
0476
      if (!WtGetClnItemAtIndex(cln, i, &item, interp)) {
0477
        ok = 0;
0478
        break;
0479
      } else {
0480
        for (j = 0; j < len; j++) {
0481
          if (!Tcl_ListObjIndex(interp, list, i, &key)) {
0482
            ok = 0;
0483
            break;
0484
          } else if (!WtCompareClnItem(cln, item, key, &comp, interp)) {
0485
            ok = 0;
0486
            break;
0487
          }
0488
          if (!comp) {
0489
            WtCopyOnWrite(&clnRep->list);
0490
            Tcl_InvalidateStringRep(cln);
0491
            if (Tcl_ListObjReplace(interp, clnRep->list, i, 1, 0, NULL) !=
0492
                TCL_OK) {
0493
              ok = 0;
0494
              break;
0495
            }
0496
            ++count;
0497
            break;
0498
          }
0499
        }
0500
        if (!ok) {
0501
          break;
0502
        }
0503
        if (count == limit && limit != -1) {
0504
          break;
0505
        }
0506
      }
0507
    }
0508
  }
0509
0510
  return ok;
0511
}
0512
0513
/* Clear the contents of a collection */
0514
0515
void WtClearCollection(Tcl_Obj *cln)
0516
{
0517
  WtCollection *clnRep = WtToCln(cln);
0518
  WtCopyOnWrite(&clnRep->list);
0519
  Tcl_DecrRefCount(clnRep->list);
0520
  clnRep->list = Tcl_NewListObj(0, NULL);
0521
  Tcl_IncrRefCount(clnRep->list);
0522
  Tcl_InvalidateStringRep(cln);
0523
}
0524
0525
/* Update a Tcl array from a collection object */
0526
0527
int WtClnToArray(Tcl_Interp *interp, Tcl_Obj *cln,
0528
    Tcl_Obj *arrName, int multiVals)
0529
{
0530
  int ok = 1, size, i;
0531
  WtCollection *clnRep = WtToCln(cln);
0532
  Tcl_Obj *item, *key, *val, *slot, *list;
0533
  Tcl_ObjType *listType = Tcl_GetObjType("list");
0534
0535
  if (!WtClnSize(cln, &size, interp)) {
0536
    return 0;
0537
  }
0538
  
0539
  for (i = 0; i < size; ++i) {
0540
    if (!WtGetClnItemAtIndex(cln, i, &item, interp)) {
0541
      ok = 0;
0542
      break;
0543
    }
0544
    if (!WtGetClnItemKey(cln, item, &key, interp) ||
0545
        !WtGetClnItemValue(cln, item, &val, interp)) {
0546
      ok = 0;
0547
      break;
0548
    }
0549
0550
    slot = Tcl_ObjGetVar2(interp, arrName, key, 0);
0551
0552
    if (multiVals) {
0553
      if (!slot) {
0554
        list = Tcl_NewListObj(1, &val);
0555
        if (!Tcl_ObjSetVar2(interp, arrName, key, list,
0556
            TCL_LEAVE_ERR_MSG)) {
0557
          ok = 0;
0558
          break;
0559
        }
0560
      } else {
0561
        if (Tcl_IsShared(slot)) {
0562
          list = Tcl_DuplicateObj(slot);
0563
          Tcl_IncrRefCount(list);
0564
        } else {
0565
          list = slot;
0566
        }
0567
        if (Tcl_ListObjAppendElement(interp, list, val) != TCL_OK) {
0568
          ok = 0;
0569
        } else if (!Tcl_ObjSetVar2(interp, arrName, key, list,
0570
            TCL_LEAVE_ERR_MSG)) {
0571
          ok = 0;
0572
        }
0573
        if (list != slot) {
0574
          Tcl_DecrRefCount(list);
0575
        }
0576
        if (!ok) {
0577
          break;
0578
        }
0579
      }
0580
    } else if (!Tcl_ObjSetVar2(interp, arrName, key, val,
0581
        TCL_LEAVE_ERR_MSG)) {
0582
      ok = 0;
0583
      break;
0584
    }
0585
  }
0586
0587
  return ok;
0588
}
0589
0590
int WtConvertToClnObj(Tcl_Obj *obj, Tcl_ObjType *type,
0591
    Tcl_Interp *interp)
0592
{
0593
  return WtClnObjSetFromAny(interp, obj, type) == TCL_OK;
0594
}
0595
0596
/* Collection object type */
0597
0598
struct Tcl_ObjType WtClnType =
0599
{
0600
  "collection",
0601
  WtClnFree,
0602
  WtClnDup,
0603
  WtClnUpdateString,
0604
  WtClnSetFromAny
0605
};
0606
0607
/* Collection object procs */
0608
0609
void WtClnFree(Tcl_Obj *cln)
0610
{
0611
  WtClnObjFree(cln);
0612
}
0613
0614
void WtClnDup(Tcl_Obj *src, Tcl_Obj *dest)
0615
{
0616
  WtClnObjDup(src, dest);
0617
}
0618
0619
void WtClnUpdateString(Tcl_Obj *cln)
0620
{
0621
  WtClnObjUpdateString(cln);
0622
}
0623
0624
int WtClnSetFromAny(Tcl_Interp *interp, Tcl_Obj *obj)
0625
{
0626
  return WtClnObjSetFromAny(interp, obj, &WtClnType);
0627
}
0628
0629
void WtClnObjFree(Tcl_Obj *cln)
0630
{
0631
  WtCollection *clnRep = WtToCln(cln);
0632
  Tcl_DecrRefCount(clnRep->list);
0633
  ckfree((char *)clnRep);
0634
}
0635
0636
void WtClnObjDup(Tcl_Obj *src, Tcl_Obj *dest)
0637
{
0638
  WtCollection *srcRep = WtToCln(src);
0639
  WtCollection *destRep = (WtCollection *)ckalloc(sizeof(WtCollection));
0640
  destRep->list = Tcl_DuplicateObj(srcRep->list);
0641
  Tcl_IncrRefCount(destRep->list);
0642
  destRep->itemType = srcRep->itemType;
0643
  dest->typePtr = src->typePtr;
0644
  dest->internalRep.twoPtrValue.ptr1 = destRep;
0645
  dest->internalRep.twoPtrValue.ptr2 = NULL;
0646
}
0647
0648
void WtClnObjUpdateString(Tcl_Obj *cln)
0649
{
0650
  WtUpdateProtectedObjString(cln);
0651
}
0652
0653
int WtClnObjSetFromAny(Tcl_Interp *interp, Tcl_Obj *obj, Tcl_ObjType *type)
0654
{
0655
  return WtSetProtectedObjFromAny(interp, obj, type);
0656
}
0657
0658
/* Compare an item to a search key */
0659
0660
int WtCompareClnItem(Tcl_Obj *cln, Tcl_Obj *item, Tcl_Obj *key,
0661
    int *result, Tcl_Interp *interp)
0662
{
0663
  int ok = 1;
0664
  WtCollection *clnRep = WtToCln(cln);
0665
  char *itemStr, *keyStr;
0666
0667
  if (item == key) {
0668
    *result = 0;
0669
  } else if (clnRep->itemType && clnRep->itemType->compare) {
0670
    if (!clnRep->itemType->compare(item, key, result, interp)) {
0671
      ok = 0;
0672
    }
0673
  } else {
0674
    itemStr = WtToString(item);
0675
    keyStr = WtToString(key);
0676
    *result = strcmp(itemStr, keyStr);
0677
  }
0678
0679
  return ok;
0680
}
0681
0682
/* Get the key from an item */
0683
0684
int WtGetClnItemKey(Tcl_Obj *cln, Tcl_Obj *item,
0685
    Tcl_Obj **key, Tcl_Interp *interp)
0686
{
0687
  int ok = 1;
0688
  WtCollection *clnRep = WtToCln(cln);
0689
  if (clnRep->itemType && clnRep->itemType->getKey) {
0690
    ok = clnRep->itemType->getKey(item, key, interp);
0691
  } else {
0692
    *key = item;
0693
  }
0694
  return ok;
0695
}
0696
0697
/* Get the value from an item */
0698
0699
int WtGetClnItemValue(Tcl_Obj *cln, Tcl_Obj *item,
0700
    Tcl_Obj **value, Tcl_Interp *interp)
0701
{
0702
  int ok = 1;
0703
  WtCollection *clnRep = WtToCln(cln);
0704
  if (clnRep->itemType && clnRep->itemType->getValue) {
0705
    ok = clnRep->itemType->getValue(item, value, interp);
0706
  } else {
0707
    *value = item;
0708
  }
0709
  return ok;
0710
}