summaryrefslogtreecommitdiffstats
path: root/doc/AbstractListObj.3
blob: ff3329c9a84e303ed20dff15b0de45857e6f22dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
'\"
'\" Copyright (c) 2022 Brian Griffin.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_AbstractListType 3 8.7 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_AbstractListObjNew,
Tcl_AbsstractListObjCopy,
Tcl_AbstractListGetConcreteRep,
Tcl_AbstractListGetElements,
Tcl_AbstractListGetType,
Tcl_AbstractListObjIndex,
Tcl_AbstractListObjLength,
Tcl_AbstractListObjRange,
Tcl_AbstractListObjReverse,
Tcl_AbstractListSetConcreteRep,
\- manipulate Tcl values as abstract lists.
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_AbstractListObjNew\fR(\fIinterp, abstractListType\fR)
Tcl_AbstractListType *
\fBTcl_AbstractListGetType\fR(\fIlistPtr\fR)
void
\fBTcl_AbstractListSetConcreteRep\fR(\fIlistPtr, repPtr\fR)
void *
\fBTcl_AbstractListGetConcreteRep\fR(\fIlistPtr\fR)
Tcl_WideInt
\fBTcl_AbstractListObjLength\fR(\fIlistPtr\fR)
int
\fBTcl_AbstractListObjIndex\fR(\fIinterp\fR, \fIlistPtr, index\fR, \fIelemObjPtr*\fR)
int
\fBTcl_AbstractListObjRange\fR(\fIinterp\fR, \fIlistPtr, fromIdx, toIdx\fR, \fInewObjPtr\fR)
int
\fBTcl_AbstractListObjReverse(\fIinterp\fR, \fIlistPtr\fR, \fInewObjPtr\fR)
int
\fBTcl_AbstraceListObjGetElements\fR(\fIinterp\fR, \fIlistPtr\fR, \fIobjcPtr\fR, \fIobjvPtr\fR)
Tcl_Obj *
\fBTcl_AbstractListObjCopy\fR(\fIinterp\fR, \fIlistPtr\fR);
typedef Tcl_Obj* (Tcl_ALNewObjProc) (int objc, Tcl_Obj * const objv[]);
typedef void (Tcl_ALDupRepProc) (Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
typedef Tcl_WideInt (Tcl_ALLengthProc) (Tcl_Obj *listPtr);
typedef int (Tcl_ALIndexProc) (Tcl_Interp *interp, Tcl_Obj *listPtr,
                               Tcl_WideInt index, Tcl_Obj** elemObj);
typedef int (Tcl_ALSliceProc) (Tcl_Interp *interp, Tcl_Obj *listPtr,
                               Tcl_WideInt fromIdx, Tcl_WideInt toIdx,
                               Tcl_Obj **newObjPtr);
typedef int (Tcl_ALReverseProc) (Tcl_Interp *interp, Tcl_Obj *listPtr,
                                 Tcl_Obj **newObjPtr);
typedef int (Tcl_ALGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr,
                                 int *objcptr, Tcl_Obj ***objvptr);
typedef void (Tcl_ALFreeConcreteRep) (Tcl_Obj *listPtr);
typedef void (Tcl_ALToStringRep) (Tcl_Obj *listPtr);
.SH ARGUMENTS
.AS
.AP Tcl_Interp *interp in
If an error occurs while converting a value to be a list value,
an error message is left in the interpreter's result value
unless \fIinterp\fR is NULL.
.AP Tcl_AbstractListType *abstractListType in
This structure defines the behavior for the \fBAbstractList\fR for a
given concrete \fBAbstractList\fR type. The struct provides the name
plus a collection of functions that implement the various List
operations on the AbstractType value.  \fBTcl_AbstractListObjNew\fR
call creates a new Tcl_Obj based on a preinitilized AbstractList
struct.
.AP Tcl_Obj *listPtr in/out
A Tcl_Obj of type AbstractList. Use to read or modify the type or
value content an AbstractList type.
.AP void *repPtr in
A reference to the concrete type representation storage. Specific
concrete types allocate and use this space to store whatever details
of value are needed.
.AP Tcl_WideInt index in
Index of the list element that \fBTcl_AbstractListObjIndex\fR
is to return.
The first element has index 0.
.AP Tcl_Obj **elemObjPtr
A location where the returned reference to an element Obj is to be
stored.
.AP Tcl_WideInt fromIdx in
The starting index of the list element for the slice that
\fBTcl_AbstractListObjRange\fR is to return.
.AP Tcl_WideInt toIdx in
The ending index of the list element for the slice that
\fBTcl_AbstractListObjRange\fR is to return.
.AP Tcl_Obj **newObjPtr in
A location where the new slice or reversed Obj reference is to be
stored.
.AP (Tcl_ALNewObjProc) in
Function pointer for a function used to create new instances of the
custom AbstractList listPtr.
.AP (Tcl_ALDupRepProc) in
Function pointer for a function used to duplicate (make a copy) of the
custom AbstractList listPtr.
.AP (Tcl_ALLengthProc) in
Function pointer for a function used to return the length of the
custom AbstractList.
.AP (Tcl_ALIndexProc) in
Function pointer for a function used to return an element listPtr for
the given index value.
.AP (Tcl_ALSliceProc) in
Function pointer for a function used to create a new slice from an
existing AbstractList.
.AP (Tcl_ALReverseProc) in
Function pointer for a function used to create a new AbstractList with
the element order reversed.
.BE

.SH DESCRIPTION
.PP
The AbstractList type provides an interface for creating new List type
representations. An AbstractList behaves like a List when using script
level list commands.  How the values are stored or produced is up to
the implementation.  A simple example of an AbstractList is the [lseq]
command which produces a list of numeric values in sequence.  The
underlying implementation does not store a list of numeric values.
Instead, it produces values on demand based on the index using an
arithmetic expression: "value = start + (step * index)".
.PP
An AbstractList is created by defining an internal storage
representation for the list along with a set of functions that manage
and manipulate the list value(s).  These functions provide
"List" like results from the List family of commands.

.SH ABSTRACTLIST C API
.PP
\fBTcl_AbstractListObjNew\fR returns a new Tcl_Obj based on the
concrete type definition given. The caller must then complete the
initialization of the Obj by setting the concrete represtation. (see
\fBTcl_AbstractListSetConcreteRep\fR())

\fBTcl_AbstractListGetType\fR returns the Tcl_AbstractList struct for
the given Obj.  This function is used internally to access the
implementation functions.  It can also be used in a specific
implementation to confirm that the Obj is of the expected AbstractList
type.

\fBTcl_AbstractListSetConcreteRep\fR is called when creating an
instance of an AbstractList. It stores the repPtr, to the allocated
value Representation, in the Tcl_Obj.

\fBTcl_AbstractListGetConcreteRep\fR returns the previously stored
repPtr for a given Obj value.

\fBTcl_AbstractListObjLength\fR returns the list length, i.e., number
of elements in the given AbstractList. This function is typically used
internally by when evaluating various List operations.  It would not
typically be used by an AbstractList concrete implementaion since the
internal representation is readily available within the
implementation, presumably.

\fBTcl_AbstractListObjIndex\fR returns the element Tcl_Obj for a given
index location.

\fBTcl_AbstractListObjRange\fR returns a new Obj value constructed
from a slice of the original AbstractList value, ranging from
\fIfromIdx\fR to the \fItoIdx\fR. If this function is not provided,
the default behavior will be to construct a traditional List using the
Index function.

\fBTcl_AbstractListObjReverse\fR returns a new Obj value constructed by
reversing the index order. If this function is not provided, the
default behavior will be to construct a traditional List using the
Index function.

\fBTcl_AbstraceListObjGetElements\fR returns an objv array containing
all elements of the AbstractList. (*** need words about memory
ownership ***)

\fBTcl_AbstractListObjCopy\fR returns a duplicate Obj from the original.

.SH ABSTRACTLIST IMPLEMENTATION FUNCTIONS
The following functions are to be defined by a specific implementation
to provide full or parcial List compatible behavior. The Length and
Index functions are required, and the rest are optional.
Unimplemented functions will either use a default implementation that
relies on Length and Index functions, or, the AbstractList will
"shimmer" into a formal List value.
.PP
.CS
typedef Tcl_Obj* (Tcl_ALNewObjProc) (int objc, Tcl_Obj * const objv[]);
typedef void (Tcl_ALDupRepProc) (Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
typedef Tcl_WideInt  (Tcl_ALLengthProc) (Tcl_Obj *listPtr);
typedef int (Tcl_ALIndexProc)  (Tcl_Interp *interp, Tcl_Obj *listPtr,
                                 Tcl_WideInt index, Tcl_Obj** elemObj);
typedef int (Tcl_ALSliceProc)  (Tcl_Interp *interp, Tcl_Obj *listPtr,
                                Tcl_WideInt fromIdx, Tcl_WideInt toIdx,
                                Tcl_Obj **newObjPtr);
typedef int (Tcl_ALReverseProc) (Tcl_Interp *interp, Tcl_Obj *listPtr,
                                 Tcl_Obj **newObjPtr);
typedef int (Tcl_ALGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr,
                                 int *objcptr, Tcl_Obj ***objvptr);
typedef void (Tcl_ALFreeConcreteRep) (Tcl_Obj *listPtr);
typedef void (Tcl_ALToStringRep) (Tcl_Obj *listPtr);
.CE
.PP
.SH AbstractList Example
.PP
\fBTcl_AbstractListObjNew\fR is used to create an object with a custom
List representation.
.PP
.CS
/*
** Define the AbstractList type callbacks
*/
static \fBTcl_AbstractListType\fR arithSeriesType = {
    TCL_ABSTRACTLIST_VERSION_1,
    "arithseries",
    Tcl_NewArithSeriesObj,
    DupArithSeriesRep,
    TclArithSeriesObjLength,
    TclArithSeriesObjIndex,
    TclArithSeriesObjRange,
    TclArithSeriesObjReverse,
    TclArithSeriesGetElements,
    FreeArithSeriesRep,
    UpdateStringOfArithSeries
};
.CE
.PP
The Index and Length procs must be defined. The others are optional.
If an optional proc is not defined, it may use a default routine that
makes use of Length and Index, or the value will be converted to a
List, and then the operation will proceed normally, and note: this
will permanently change the value representation to a \fBList\fR
representation.
.PP
.CS
/*
** Define the concrete representation for the ArithSeries type
*/
typedef struct ArithSeries {
    int start,
    int end,
    int step,
    int length
} ArithSeries;

/*
** Allocate and initialize the concrete repdresentation.
*/
arithSeriesRepPtr = (ArithSeries*)\fBTcl_Alloc\fR(sizeof (ArithSeries));
arithSeriesRepPtr->isDouble = 0;
arithSeriesRepPtr->start = 0;
arithSeriesRepPtr->end = 15;
arithSeriesRepPtr->step = 1;
arithSeriesRepPtr->len = 15;
arithSeriesRepPtr->elements = NULL;

/*
** Create an instance Tcl_Obj
*/
\fBTcl_Obj\fR *arithObj = \fBTcl_AbstractListObjNew\fR(interp, &arithSeriesType);

/*
** Set the concrete value for the Obj.
*/
\fBTcl_AbstractListSetConcreteRep\fR(arithObj, arithSeriesRepPtr);

return arithObj;
.CE
.PP
If any List operation is used to modify the AbstractList, for example
[lset $abstraceList 3 17], it will first be converted to a List before
completing the change.
.PP
.CS
/* Example functions */
Tcl_Obj*
ArithSeriesObjIndex(Tcl_Obj *arithSeriesObjPtr, Tcl_WideInt index)
{
    ArithSeries *arithSeriesRepPtr;
    Tcl_WideInt element;
    if (arithSeriesObjPtr->typePtr != &tclAbstractListType) {
        Tcl_Panic("ArithSeriesObjIndex called with a not ArithSeries Obj.");
    }
    arithSeriesRepPtr = ArithSeriesRepPtr(arithSeriesObjPtr);

    if (index < 0 || index >= arithSeriesRepPtr->length) {
        return NULL;
    }

    /* List[i] = Start + (Step * i) */
    element = (arithSeriesRepPtr->start + (index) * arithSeriesRepPtr->step);

    return Tcl_NewWideIntObj(element);
}

Tcl_WideInt ArithSeriesObjLength(Tcl_Obj *arithSeriesObjPtr)
{
    ArithSeries *arithSeriesRepPtr = ArithSeriesRepPtr(arithSeriesObjPtr);
    return arithSeriesRepPtr->length;
}

.CE
.PP
The functions \fBTcl_AbstractListObjLength\fR,
\fBTcl_AbstractListObjIndex\fR, \fBTcl_AbstractListObjRange\fR, and
\fBTcl_AbstractListObjReverse\fR can be used to interact with a known
AbstatractList Tcl_Obj value, as well as \fBTcl_ListObjLength\fR,
\fBTcl_ListObjIndex\fR, without causing the obj value to converted to
a \fBList\fR.  Tcl_ListObjGetElements can also be used on an
AbstractList, just note that this call may result in new element
objects being created for every element in the abstract list.  Since
an abstract list can be arbitrarily large and not consume space, this
call may have undesired consequences.
.PP
.SH "SEE ALSO"
Tcl_NewListObj(3), Tcl_NewObj(3), Tcl_DecrRefCount(3), Tcl_IncrRefCount(3), Tcl_GetObjResult(3)
.SH KEYWORDS
index, internal representation, length, list, list value,
list type, value, value type, replace, string representation