OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [generic/] [tclStringObj.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tclStringObj.c --
3
 *
4
 *      This file contains procedures that implement string operations
5
 *      on Tcl objects.  To do this efficiently (i.e. to allow many
6
 *      appends to be done to an object without constantly reallocating
7
 *      the space for the string representation) we overallocate the
8
 *      space for the string and use the internal representation to keep
9
 *      track of the extra space.  Objects with this internal
10
 *      representation are called "expandable string objects".
11
 *
12
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
13
 *
14
 * See the file "license.terms" for information on usage and redistribution
15
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
 *
17
 * RCS: @(#) $Id: tclStringObj.c,v 1.1.1.1 2002-01-16 10:25:29 markom Exp $
18
 */
19
 
20
#include "tclInt.h"
21
 
22
/*
23
 * Prototypes for procedures defined later in this file:
24
 */
25
 
26
static void             ConvertToStringType _ANSI_ARGS_((Tcl_Obj *objPtr));
27
static void             DupStringInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr,
28
                            Tcl_Obj *copyPtr));
29
static int              SetStringFromAny _ANSI_ARGS_((Tcl_Interp *interp,
30
                            Tcl_Obj *objPtr));
31
static void             UpdateStringOfString _ANSI_ARGS_((Tcl_Obj *objPtr));
32
 
33
/*
34
 * The structure below defines the string Tcl object type by means of
35
 * procedures that can be invoked by generic object code.
36
 */
37
 
38
Tcl_ObjType tclStringType = {
39
    "string",                           /* name */
40
    (Tcl_FreeInternalRepProc *) NULL,   /* freeIntRepProc */
41
    DupStringInternalRep,               /* dupIntRepProc */
42
    UpdateStringOfString,               /* updateStringProc */
43
    SetStringFromAny                    /* setFromAnyProc */
44
};
45
 
46
/*
47
 *----------------------------------------------------------------------
48
 *
49
 * Tcl_NewStringObj --
50
 *
51
 *      This procedure is normally called when not debugging: i.e., when
52
 *      TCL_MEM_DEBUG is not defined. It creates a new string object and
53
 *      initializes it from the byte pointer and length arguments.
54
 *
55
 *      When TCL_MEM_DEBUG is defined, this procedure just returns the
56
 *      result of calling the debugging version Tcl_DbNewStringObj.
57
 *
58
 * Results:
59
 *      A newly created string object is returned that has ref count zero.
60
 *
61
 * Side effects:
62
 *      The new object's internal string representation will be set to a
63
 *      copy of the length bytes starting at "bytes". If "length" is
64
 *      negative, use bytes up to the first NULL byte; i.e., assume "bytes"
65
 *      points to a C-style NULL-terminated string. The object's type is set
66
 *      to NULL. An extra NULL is added to the end of the new object's byte
67
 *      array.
68
 *
69
 *----------------------------------------------------------------------
70
 */
71
 
72
#ifdef TCL_MEM_DEBUG
73
#undef Tcl_NewStringObj
74
 
75
Tcl_Obj *
76
Tcl_NewStringObj(bytes, length)
77
    register char *bytes;       /* Points to the first of the length bytes
78
                                 * used to initialize the new object. */
79
    register int length;        /* The number of bytes to copy from "bytes"
80
                                 * when initializing the new object. If
81
                                 * negative, use bytes up to the first
82
                                 * NULL byte. */
83
{
84
    return Tcl_DbNewStringObj(bytes, length, "unknown", 0);
85
}
86
 
87
#else /* if not TCL_MEM_DEBUG */
88
 
89
Tcl_Obj *
90
Tcl_NewStringObj(bytes, length)
91
    register char *bytes;       /* Points to the first of the length bytes
92
                                 * used to initialize the new object. */
93
    register int length;        /* The number of bytes to copy from "bytes"
94
                                 * when initializing the new object. If
95
                                 * negative, use bytes up to the first
96
                                 * NULL byte. */
97
{
98
    register Tcl_Obj *objPtr;
99
 
100
    if (length < 0) {
101
        length = (bytes? strlen(bytes) : 0);
102
    }
103
    TclNewObj(objPtr);
104
    TclInitStringRep(objPtr, bytes, length);
105
    return objPtr;
106
}
107
#endif /* TCL_MEM_DEBUG */
108
 
109
/*
110
 *----------------------------------------------------------------------
111
 *
112
 * Tcl_DbNewStringObj --
113
 *
114
 *      This procedure is normally called when debugging: i.e., when
115
 *      TCL_MEM_DEBUG is defined. It creates new string objects. It is the
116
 *      same as the Tcl_NewStringObj procedure above except that it calls
117
 *      Tcl_DbCkalloc directly with the file name and line number from its
118
 *      caller. This simplifies debugging since then the checkmem command
119
 *      will report the correct file name and line number when reporting
120
 *      objects that haven't been freed.
121
 *
122
 *      When TCL_MEM_DEBUG is not defined, this procedure just returns the
123
 *      result of calling Tcl_NewStringObj.
124
 *
125
 * Results:
126
 *      A newly created string object is returned that has ref count zero.
127
 *
128
 * Side effects:
129
 *      The new object's internal string representation will be set to a
130
 *      copy of the length bytes starting at "bytes". If "length" is
131
 *      negative, use bytes up to the first NULL byte; i.e., assume "bytes"
132
 *      points to a C-style NULL-terminated string. The object's type is set
133
 *      to NULL. An extra NULL is added to the end of the new object's byte
134
 *      array.
135
 *
136
 *----------------------------------------------------------------------
137
 */
138
 
139
#ifdef TCL_MEM_DEBUG
140
 
141
Tcl_Obj *
142
Tcl_DbNewStringObj(bytes, length, file, line)
143
    register char *bytes;       /* Points to the first of the length bytes
144
                                 * used to initialize the new object. */
145
    register int length;        /* The number of bytes to copy from "bytes"
146
                                 * when initializing the new object. If
147
                                 * negative, use bytes up to the first
148
                                 * NULL byte. */
149
    char *file;                 /* The name of the source file calling this
150
                                 * procedure; used for debugging. */
151
    int line;                   /* Line number in the source file; used
152
                                 * for debugging. */
153
{
154
    register Tcl_Obj *objPtr;
155
 
156
    if (length < 0) {
157
        length = (bytes? strlen(bytes) : 0);
158
    }
159
    TclDbNewObj(objPtr, file, line);
160
    TclInitStringRep(objPtr, bytes, length);
161
    return objPtr;
162
}
163
 
164
#else /* if not TCL_MEM_DEBUG */
165
 
166
Tcl_Obj *
167
Tcl_DbNewStringObj(bytes, length, file, line)
168
    register char *bytes;       /* Points to the first of the length bytes
169
                                 * used to initialize the new object. */
170
    register int length;        /* The number of bytes to copy from "bytes"
171
                                 * when initializing the new object. If
172
                                 * negative, use bytes up to the first
173
                                 * NULL byte. */
174
    char *file;                 /* The name of the source file calling this
175
                                 * procedure; used for debugging. */
176
    int line;                   /* Line number in the source file; used
177
                                 * for debugging. */
178
{
179
    return Tcl_NewStringObj(bytes, length);
180
}
181
#endif /* TCL_MEM_DEBUG */
182
 
183
/*
184
 *----------------------------------------------------------------------
185
 *
186
 * Tcl_SetStringObj --
187
 *
188
 *      Modify an object to hold a string that is a copy of the bytes
189
 *      indicated by the byte pointer and length arguments.
190
 *
191
 * Results:
192
 *      None.
193
 *
194
 * Side effects:
195
 *      The object's string representation will be set to a copy of
196
 *      the "length" bytes starting at "bytes". If "length" is negative, use
197
 *      bytes up to the first NULL byte; i.e., assume "bytes" points to a
198
 *      C-style NULL-terminated string. The object's old string and internal
199
 *      representations are freed and the object's type is set NULL.
200
 *
201
 *----------------------------------------------------------------------
202
 */
203
 
204
void
205
Tcl_SetStringObj(objPtr, bytes, length)
206
    register Tcl_Obj *objPtr;   /* Object whose internal rep to init. */
207
    char *bytes;                /* Points to the first of the length bytes
208
                                 * used to initialize the object. */
209
    register int length;        /* The number of bytes to copy from "bytes"
210
                                 * when initializing the object. If
211
                                 * negative, use bytes up to the first
212
                                 * NULL byte.*/
213
{
214
    register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
215
 
216
    /*
217
     * Free any old string rep, then set the string rep to a copy of
218
     * the length bytes starting at "bytes".
219
     */
220
 
221
    if (Tcl_IsShared(objPtr)) {
222
        panic("Tcl_SetStringObj called with shared object");
223
    }
224
 
225
    Tcl_InvalidateStringRep(objPtr);
226
    if (length < 0) {
227
        length = strlen(bytes);
228
    }
229
    TclInitStringRep(objPtr, bytes, length);
230
 
231
    /*
232
     * Set the type to NULL and free any internal rep for the old type.
233
     */
234
 
235
    if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
236
        oldTypePtr->freeIntRepProc(objPtr);
237
    }
238
    objPtr->typePtr = NULL;
239
}
240
 
241
/*
242
 *----------------------------------------------------------------------
243
 *
244
 * Tcl_SetObjLength --
245
 *
246
 *      This procedure changes the length of the string representation
247
 *      of an object.
248
 *
249
 * Results:
250
 *      None.
251
 *
252
 * Side effects:
253
 *      If the size of objPtr's string representation is greater than
254
 *      length, then it is reduced to length and a new terminating null
255
 *      byte is stored in the strength.  If the length of the string
256
 *      representation is greater than length, the storage space is
257
 *      reallocated to the given length; a null byte is stored at the
258
 *      end, but other bytes past the end of the original string
259
 *      representation are undefined.  The object's internal
260
 *      representation is changed to "expendable string".
261
 *
262
 *----------------------------------------------------------------------
263
 */
264
 
265
void
266
Tcl_SetObjLength(objPtr, length)
267
    register Tcl_Obj *objPtr;   /* Pointer to object.  This object must
268
                                 * not currently be shared. */
269
    register int length;        /* Number of bytes desired for string
270
                                 * representation of object, not including
271
                                 * terminating null byte. */
272
{
273
    char *new;
274
 
275
    if (Tcl_IsShared(objPtr)) {
276
        panic("Tcl_SetObjLength called with shared object");
277
    }
278
    if (objPtr->typePtr != &tclStringType) {
279
        ConvertToStringType(objPtr);
280
    }
281
 
282
    if ((long)length > objPtr->internalRep.longValue) {
283
        /*
284
         * Not enough space in current string. Reallocate the string
285
         * space and free the old string.
286
         */
287
 
288
        new = (char *) ckalloc((unsigned) (length+1));
289
        if (objPtr->bytes != NULL) {
290
            memcpy((VOID *) new, (VOID *) objPtr->bytes,
291
                    (size_t) objPtr->length);
292
            Tcl_InvalidateStringRep(objPtr);
293
        }
294
        objPtr->bytes = new;
295
        objPtr->internalRep.longValue = (long) length;
296
    }
297
    objPtr->length = length;
298
    if ((objPtr->bytes != NULL) && (objPtr->bytes != tclEmptyStringRep)) {
299
        objPtr->bytes[length] = 0;
300
    }
301
}
302
 
303
/*
304
 *----------------------------------------------------------------------
305
 *
306
 * Tcl_AppendToObj --
307
 *
308
 *      This procedure appends a sequence of bytes to an object.
309
 *
310
 * Results:
311
 *      None.
312
 *
313
 * Side effects:
314
 *      The bytes at *bytes are appended to the string representation
315
 *      of objPtr.
316
 *
317
 *----------------------------------------------------------------------
318
 */
319
 
320
void
321
Tcl_AppendToObj(objPtr, bytes, length)
322
    register Tcl_Obj *objPtr;   /* Points to the object to append to. */
323
    char *bytes;                /* Points to the bytes to append to the
324
                                 * object. */
325
    register int length;        /* The number of bytes to append from
326
                                 * "bytes". If < 0, then append all bytes
327
                                 * up to NULL byte. */
328
{
329
    int newLength, oldLength;
330
 
331
    if (Tcl_IsShared(objPtr)) {
332
        panic("Tcl_AppendToObj called with shared object");
333
    }
334
    if (objPtr->typePtr != &tclStringType) {
335
        ConvertToStringType(objPtr);
336
    }
337
    if (length < 0) {
338
        length = strlen(bytes);
339
    }
340
    if (length == 0) {
341
        return;
342
    }
343
    oldLength = objPtr->length;
344
    newLength = length + oldLength;
345
    if ((long)newLength > objPtr->internalRep.longValue) {
346
        /*
347
         * There isn't currently enough space in the string
348
         * representation so allocate additional space.  In fact,
349
         * overallocate so that there is room for future growth without
350
         * having to reallocate again.
351
         */
352
 
353
        Tcl_SetObjLength(objPtr, 2*newLength);
354
    }
355
    if (length > 0) {
356
        memcpy((VOID *) (objPtr->bytes + oldLength), (VOID *) bytes,
357
               (size_t) length);
358
        objPtr->length = newLength;
359
        objPtr->bytes[objPtr->length] = 0;
360
    }
361
}
362
 
363
/*
364
 *----------------------------------------------------------------------
365
 *
366
 * Tcl_AppendStringsToObj --
367
 *
368
 *      This procedure appends one or more null-terminated strings
369
 *      to an object.
370
 *
371
 * Results:
372
 *      None.
373
 *
374
 * Side effects:
375
 *      The contents of all the string arguments are appended to the
376
 *      string representation of objPtr.
377
 *
378
 *----------------------------------------------------------------------
379
 */
380
 
381
void
382
Tcl_AppendStringsToObj TCL_VARARGS_DEF(Tcl_Obj *,arg1)
383
{
384
    va_list argList;
385
    register Tcl_Obj *objPtr;
386
    int newLength, oldLength;
387
    register char *string, *dst;
388
 
389
    objPtr = (Tcl_Obj *) TCL_VARARGS_START(Tcl_Obj *,arg1,argList);
390
    if (Tcl_IsShared(objPtr)) {
391
        panic("Tcl_AppendStringsToObj called with shared object");
392
    }
393
    if (objPtr->typePtr != &tclStringType) {
394
        ConvertToStringType(objPtr);
395
    }
396
 
397
    /*
398
     * Figure out how much space is needed for all the strings, and
399
     * expand the string representation if it isn't big enough. If no
400
     * bytes would be appended, just return.
401
     */
402
 
403
    newLength = oldLength = objPtr->length;
404
    while (1) {
405
        string = va_arg(argList, char *);
406
        if (string == NULL) {
407
            break;
408
        }
409
        newLength += strlen(string);
410
    }
411
    if (newLength == oldLength) {
412
        return;
413
    }
414
 
415
    if ((long)newLength > objPtr->internalRep.longValue) {
416
        /*
417
         * There isn't currently enough space in the string
418
         * representation so allocate additional space.  If the current
419
         * string representation isn't empty (i.e. it looks like we're
420
         * doing a series of appends) then overallocate the space so
421
         * that we won't have to do as much reallocation in the future.
422
         */
423
 
424
        Tcl_SetObjLength(objPtr,
425
                (objPtr->length == 0) ? newLength : 2*newLength);
426
    }
427
 
428
    /*
429
     * Make a second pass through the arguments, appending all the
430
     * strings to the object.
431
     */
432
 
433
    TCL_VARARGS_START(Tcl_Obj *,arg1,argList);
434
    dst = objPtr->bytes + oldLength;
435
    while (1) {
436
        string = va_arg(argList, char *);
437
        if (string == NULL) {
438
            break;
439
        }
440
        while (*string != 0) {
441
            *dst = *string;
442
            dst++;
443
            string++;
444
        }
445
    }
446
 
447
    /*
448
     * Add a null byte to terminate the string.  However, be careful:
449
     * it's possible that the object is totally empty (if it was empty
450
     * originally and there was nothing to append).  In this case dst is
451
     * NULL; just leave everything alone.
452
     */
453
 
454
    if (dst != NULL) {
455
        *dst = 0;
456
    }
457
    objPtr->length = newLength;
458
    va_end(argList);
459
}
460
 
461
/*
462
 *----------------------------------------------------------------------
463
 *
464
 * ConvertToStringType --
465
 *
466
 *      This procedure converts the internal representation of an object
467
 *      to "expandable string" type.
468
 *
469
 * Results:
470
 *      None.
471
 *
472
 * Side effects:
473
 *      Any old internal reputation for objPtr is freed and the
474
 *      internal representation is set to that for an expandable string
475
 *      (the field internalRep.longValue holds 1 less than the allocated
476
 *      length of objPtr's string representation).
477
 *
478
 *----------------------------------------------------------------------
479
 */
480
 
481
static void
482
ConvertToStringType(objPtr)
483
    register Tcl_Obj *objPtr;   /* Pointer to object.  Must have a
484
                                 * typePtr that isn't &tclStringType. */
485
{
486
    if (objPtr->typePtr != NULL) {
487
        if (objPtr->bytes == NULL) {
488
            objPtr->typePtr->updateStringProc(objPtr);
489
        }
490
        if (objPtr->typePtr->freeIntRepProc != NULL) {
491
            objPtr->typePtr->freeIntRepProc(objPtr);
492
        }
493
    }
494
    objPtr->typePtr = &tclStringType;
495
    if (objPtr->bytes != NULL) {
496
        objPtr->internalRep.longValue = (long)objPtr->length;
497
    } else {
498
        objPtr->internalRep.longValue = 0;
499
        objPtr->length = 0;
500
    }
501
}
502
 
503
/*
504
 *----------------------------------------------------------------------
505
 *
506
 * DupStringInternalRep --
507
 *
508
 *      Initialize the internal representation of a new Tcl_Obj to a
509
 *      copy of the internal representation of an existing string object.
510
 *
511
 * Results:
512
 *      None.
513
 *
514
 * Side effects:
515
 *      copyPtr's internal rep is set to a copy of srcPtr's internal
516
 *      representation.
517
 *
518
 *----------------------------------------------------------------------
519
 */
520
 
521
static void
522
DupStringInternalRep(srcPtr, copyPtr)
523
    register Tcl_Obj *srcPtr;   /* Object with internal rep to copy.  Must
524
                                 * have an internal representation of type
525
                                 * "expandable string". */
526
    register Tcl_Obj *copyPtr;  /* Object with internal rep to set.  Must
527
                                 * not currently have an internal rep.*/
528
{
529
    /*
530
     * Tricky point: the string value was copied by generic object
531
     * management code, so it doesn't contain any extra bytes that
532
     * might exist in the source object.
533
     */
534
 
535
    copyPtr->internalRep.longValue = (long)copyPtr->length;
536
    copyPtr->typePtr = &tclStringType;
537
}
538
 
539
/*
540
 *----------------------------------------------------------------------
541
 *
542
 * SetStringFromAny --
543
 *
544
 *      Create an internal representation of type "expandable string"
545
 *      for an object.
546
 *
547
 * Results:
548
 *      This operation always succeeds and returns TCL_OK.
549
 *
550
 * Side effects:
551
 *      This procedure does nothing; there is no advantage in converting
552
 *      the internal representation now, so we just defer it.
553
 *
554
 *----------------------------------------------------------------------
555
 */
556
 
557
static int
558
SetStringFromAny(interp, objPtr)
559
    Tcl_Interp *interp;         /* Used for error reporting if not NULL. */
560
    Tcl_Obj *objPtr;            /* The object to convert. */
561
{
562
    return TCL_OK;
563
}
564
 
565
/*
566
 *----------------------------------------------------------------------
567
 *
568
 * UpdateStringOfString --
569
 *
570
 *      Update the string representation for an object whose internal
571
 *      representation is "expandable string".
572
 *
573
 * Results:
574
 *      None.
575
 *
576
 * Side effects:
577
 *      None.
578
 *
579
 *----------------------------------------------------------------------
580
 */
581
 
582
static void
583
UpdateStringOfString(objPtr)
584
    Tcl_Obj *objPtr;            /* Object with string rep to update. */
585
{
586
    /*
587
     * The string is almost always valid already, in which case there's
588
     * nothing for us to do. The only case we have to worry about is if
589
     * the object is totally null. In this case, set the string rep to
590
     * an empty string.
591
     */
592
 
593
    if (objPtr->bytes == NULL) {
594
        objPtr->bytes = tclEmptyStringRep;
595
        objPtr->length = 0;
596
    }
597
    return;
598
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.