Graphviz 12.0.1~dev.20240716.0800
Loading...
Searching...
No Matches
tclhandle.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11/*
12 * tclhandle.c --
13 *
14 * adapted from tclXhandles.c tclXutil.c and tclExtend.h
15 */
16
17/*
18 *
19 * tclXhandles.c --
20 *
21 * Tcl handles. Provides a mechanism for managing expandable tables that are
22 * addressed by textual handles.
23 *-----------------------------------------------------------------------------
24 * Copyright 1991-1994 Karl Lehenbauer and Mark Diekhans.
25 *
26 * Permission to use, copy, modify, and distribute this software and its
27 * documentation for any purpose and without fee is hereby granted, provided
28 * that the above copyright notice appear in all copies. Karl Lehenbauer and
29 * Mark Diekhans make no representations about the suitability of this
30 * software for any purpose. It is provided "as is" without express or
31 * implied warranty.
32 *-----------------------------------------------------------------------------
33 * $Id$
34 *-----------------------------------------------------------------------------
35 */
36
37#include "tclhandle.h"
38#include <cgraph/agxbuf.h>
39#include <inttypes.h>
40#include <stdint.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44
45/*
46 * Alignment factor (in bytes) for this machine.
47 */
48enum {
49 tclhandleEntryAlignment =
50 sizeof(void *) > sizeof(uint64_t)
51 ? (sizeof(double) > sizeof(void *) ? sizeof(double) : sizeof(void *))
52 : (sizeof(double) > sizeof(uint64_t) ? sizeof(double)
53 : sizeof(uint64_t))
54};
55
56/*=============================================================================
57 * tclhandleLinkInNewEntries --
58 * Build free links through the newly allocated part of a table.
59 *
60 * Parameters:
61 * o tblHdrPtr (I) - A pointer to the table header.
62 * o newIdx (I) - Index of the first new entry.
63 * o numEntries (I) - The number of new entries.
64 *-----------------------------------------------------------------------------
65 */
66static void tclhandleLinkInNewEntries(tblHeader_pt tblHdrPtr, uint64_t newIdx,
67 uint64_t numEntries) {
68 uint64_t entIdx, lastIdx;
69 entryHeader_pt entryPtr;
70
71 lastIdx = newIdx + numEntries - 1;
72
73 for (entIdx = newIdx; entIdx < lastIdx; entIdx++) {
74 entryPtr = TBL_INDEX(tblHdrPtr, entIdx);
75 entryPtr->freeLink = entIdx + 1;
76 }
77 entryPtr = TBL_INDEX(tblHdrPtr, lastIdx);
78 entryPtr->freeLink = tblHdrPtr->freeHeadIdx;
79 tblHdrPtr->freeHeadIdx = newIdx;
80}
81
82/*=============================================================================
83 * tclhandleExpandTable --
84 * Expand a handle table, doubling its size.
85 * Parameters:
86 * o tblHdrPtr (I) - A pointer to the table header.
87 * o neededIdx (I) - If positive, then the table will be expanded so that
88 * this entry is available. If -1, then just expand by the number of
89 * entries specified on table creation. MUST be smaller than this size.
90 *-----------------------------------------------------------------------------
91 */
92static void tclhandleExpandTable(tblHeader_pt tblHdrPtr, uint64_t neededIdx) {
93 ubyte_pt oldbodyPtr = tblHdrPtr->bodyPtr;
94 uint64_t numNewEntries;
95 uint64_t newSize;
96
97 if (neededIdx == NULL_IDX || neededIdx == ALLOCATED_IDX)
98 numNewEntries = tblHdrPtr->tableSize;
99 else
100 numNewEntries = neededIdx - tblHdrPtr->tableSize + 1;
101 newSize = (tblHdrPtr->tableSize + numNewEntries) * tblHdrPtr->entrySize;
102
103 tblHdrPtr->bodyPtr = malloc(newSize);
104 memcpy(tblHdrPtr->bodyPtr, oldbodyPtr,
105 tblHdrPtr->tableSize * tblHdrPtr->entrySize);
106 tclhandleLinkInNewEntries(tblHdrPtr, tblHdrPtr->tableSize, numNewEntries);
107 tblHdrPtr->tableSize += numNewEntries;
108 free(oldbodyPtr);
109}
110
111/*=============================================================================
112 * tclhandleAlloc --
113 * Allocate a table entry, expanding if necessary.
114 *
115 * Parameters:
116 * o headerPtr (I) - A pointer to the table header.
117 * o handle (O) - If not NULL, the handle is returned here.
118 * o entryIdxPtr (O) - If not NULL, the index is returned here.
119 * Returns:
120 * The a pointer to the entry.
121 *-----------------------------------------------------------------------------
122 */
124 uint64_t *entryIdxPtr) {
125 tblHeader_pt tblHdrPtr = headerPtr;
126 entryHeader_pt entryPtr;
127 uint64_t entryIdx;
128
129 if (tblHdrPtr->freeHeadIdx == NULL_IDX)
130 tclhandleExpandTable(tblHdrPtr, NULL_IDX);
131
132 entryIdx = tblHdrPtr->freeHeadIdx;
133 entryPtr = TBL_INDEX(tblHdrPtr, entryIdx);
134 tblHdrPtr->freeHeadIdx = entryPtr->freeLink;
135 entryPtr->freeLink = ALLOCATED_IDX;
136
137 if (handle) {
138 agxbuf buf = {0};
139 agxbprint(&buf, tblHdrPtr->handleFormat, entryIdx);
140 *handle = agxbdisown(&buf);
141 }
142 if (entryIdxPtr)
143 *entryIdxPtr = entryIdx;
144 return USER_AREA(entryPtr);
145}
146
147/*=============================================================================
148 * tclhandleInit --
149 * Create and initialize a Tcl dynamic handle table.
150 * Parameters:
151 * o prefix (I) - The character string prefix to be used.
152 * o entrySize (I) - The size of an entry, in bytes.
153 * o initEntries (I) - Initial size of the table, in entries.
154 * Returns:
155 * A pointer to the table header.
156 *-----------------------------------------------------------------------------
157 */
158tblHeader_pt tclhandleInit(char *prefix, uint64_t entrySize,
159 uint64_t initEntries) {
160 tblHeader_pt tblHdrPtr;
161
162 /*
163 * Set up the table entry.
164 */
165 tblHdrPtr = malloc(sizeof(tblHeader_t));
166
167 /*
168 * Calculate entry size, including header, rounded up to sizeof (void *).
169 */
170 tblHdrPtr->entrySize = ENTRY_HEADER_SIZE + ROUND_ENTRY_SIZE(entrySize);
171 tblHdrPtr->freeHeadIdx = NULL_IDX;
172 tblHdrPtr->tableSize = initEntries;
173 tblHdrPtr->handleFormat = malloc(strlen(prefix) + strlen("%" PRIu64) + 1);
174 strcpy(tblHdrPtr->handleFormat, prefix);
175 strcat(tblHdrPtr->handleFormat, "%" PRIu64);
176 tblHdrPtr->bodyPtr = malloc(initEntries * tblHdrPtr->entrySize);
177 tclhandleLinkInNewEntries(tblHdrPtr, 0, initEntries);
178
179 return tblHdrPtr;
180}
181
182/*=============================================================================
183 * tclhandleIndex --
184 * Translate a string handle to a handleTable Index.
185 *
186 * Parameters:
187 * o headerPtr (I) - A pointer to the table header.
188 * o handle (I) - The handle string -- <prefix><int>
189 * o entryIdxPtr (O) - If not NULL, the index is returned here.
190 * Returns:
191 * TCL_OK if the handle was valid.
192 * TCL_ERROR if the handle was invalid.
193 *-----------------------------------------------------------------------------
194 */
195int tclhandleIndex(tblHeader_pt tblHdrPtr, char *handle,
196 uint64_t *entryIdxPtr) {
197 uint64_t entryIdx;
198
199 if (sscanf(handle, tblHdrPtr->handleFormat, &entryIdx) != 1)
200 return TCL_ERROR;
201 if (entryIdxPtr)
202 *entryIdxPtr = entryIdx;
203 return TCL_OK;
204}
205
206/*=============================================================================
207 * tclhandleXlateIndex --
208 * Translate an index to an entry pointer.
209 *
210 * Parameters:
211 * o headerPtr (I) - A pointer to the table header.
212 * o index (I) - The index of an entry.
213 * Returns:
214 * A pointer to the entry, or NULL if an error occurred.
215 *-----------------------------------------------------------------------------
216 */
217void *tclhandleXlateIndex(tblHeader_pt headerPtr, uint64_t entryIdx) {
218 tblHeader_pt tblHdrPtr = headerPtr;
219 entryHeader_pt entryPtr;
220
221 entryPtr = TBL_INDEX(tblHdrPtr, entryIdx);
222
223 if (entryIdx >= tblHdrPtr->tableSize || entryPtr->freeLink != ALLOCATED_IDX) {
224 return NULL;
225 }
226
227 return USER_AREA(entryPtr);
228}
229
230/*=============================================================================
231 * tclhandleXlate --
232 * Translate a string handle to an entry pointer.
233 *
234 * Parameters:
235 * o headerPtr (I) - A pointer to the table header.
236 * o handle (I) - The handle string -- <prefix><int>
237 * Returns:
238 * A pointer to the entry, or NULL if an error occurred.
239 *-----------------------------------------------------------------------------
240 */
241void *tclhandleXlate(tblHeader_pt tblHdrPtr, char *handle) {
242 uint64_t entryIdx;
243
244 if (tclhandleIndex(tblHdrPtr, handle, &entryIdx) != TCL_OK)
245 return NULL;
246 return tclhandleXlateIndex(tblHdrPtr, entryIdx);
247}
248
249/*============================================================================
250 * tclhandleFreeIndex --
251 * Frees a handle table entry by index.
252 *
253 * Parameters:
254 * o headerPtr (I) - A pointer to the table header.
255 * o index (I) - The index of an entry.
256 *----------------------------------------------------------------------------
257 * Returns:
258 * The contents of the entry, if success, or NULL if an error occurred.
259 *----------------------------------------------------------------------------
260 */
261void *tclhandleFreeIndex(tblHeader_pt headerPtr, uint64_t entryIdx) {
262 tblHeader_pt tblHdrPtr = headerPtr;
263 entryHeader_pt entryPtr, freeentryPtr;
264
265 entryPtr = TBL_INDEX(tblHdrPtr, entryIdx);
266
267 if (entryIdx >= tblHdrPtr->tableSize || entryPtr->freeLink != ALLOCATED_IDX) {
268 return NULL;
269 }
270
271 entryPtr = USER_AREA(entryPtr);
272 freeentryPtr = HEADER_AREA(entryPtr);
273 freeentryPtr->freeLink = tblHdrPtr->freeHeadIdx;
274 tblHdrPtr->freeHeadIdx =
275 ((uint64_t)((uintptr_t)entryPtr - (uintptr_t)tblHdrPtr->bodyPtr)) /
276 tblHdrPtr->entrySize;
277
278 return entryPtr;
279}
280
281/*============================================================================
282 * tclhandleFree --
283 * Frees a handle table entry by handle.
284 *
285 * Parameters:
286 * o headerPtr (I) - A pointer to the table header.
287 * o handle (I) - The handle of an entry.
288 *----------------------------------------------------------------------------
289 * Returns:
290 * The contents of the entry, if success, or NULL if an error occurred.
291 *----------------------------------------------------------------------------
292 */
293void *tclhandleFree(tblHeader_pt tblHdrPtr, char *handle) {
294 uint64_t entryIdx;
295
296 if (tclhandleIndex(tblHdrPtr, handle, &entryIdx) != TCL_OK)
297 return NULL;
298 return tclhandleFreeIndex(tblHdrPtr, entryIdx);
299}
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:213
static char * agxbdisown(agxbuf *xb)
Definition agxbuf.h:299
void * malloc(YYSIZE_T)
void free(void *)
require define api prefix
Definition gmlparse.y:17
node NULL
Definition grammar.y:149
uint64_t freeLink
Definition tclhandle.h:52
uint64_t tableSize
Definition tclhandle.h:44
ubyte_pt bodyPtr
Definition tclhandle.h:47
uint64_t freeHeadIdx
Definition tclhandle.h:45
uint64_t entrySize
Definition tclhandle.h:43
char * handleFormat
Definition tclhandle.h:46
void * tclhandleXlateIndex(tblHeader_pt headerPtr, uint64_t entryIdx)
Definition tclhandle.c:217
entryHeader_pt tclhandleAlloc(tblHeader_pt headerPtr, char **handle, uint64_t *entryIdxPtr)
Definition tclhandle.c:123
void * tclhandleFreeIndex(tblHeader_pt headerPtr, uint64_t entryIdx)
Definition tclhandle.c:261
void * tclhandleXlate(tblHeader_pt tblHdrPtr, char *handle)
Definition tclhandle.c:241
void * tclhandleFree(tblHeader_pt tblHdrPtr, char *handle)
Definition tclhandle.c:293
int tclhandleIndex(tblHeader_pt tblHdrPtr, char *handle, uint64_t *entryIdxPtr)
Definition tclhandle.c:195
static void tclhandleExpandTable(tblHeader_pt tblHdrPtr, uint64_t neededIdx)
Definition tclhandle.c:92
tblHeader_pt tclhandleInit(char *prefix, uint64_t entrySize, uint64_t initEntries)
Definition tclhandle.c:158
static void tclhandleLinkInNewEntries(tblHeader_pt tblHdrPtr, uint64_t newIdx, uint64_t numEntries)
Definition tclhandle.c:66
#define ROUND_ENTRY_SIZE(size)
Definition tclhandle.h:22
#define ALLOCATED_IDX
Definition tclhandle.h:27
ubyte_t * ubyte_pt
Definition tclhandle.h:30
#define USER_AREA(entryPtr)
Definition tclhandle.h:68
#define TBL_INDEX(hdrPtr, idx)
Definition tclhandle.h:61
#define ENTRY_HEADER_SIZE
Definition tclhandle.h:56
#define NULL_IDX
Definition tclhandle.h:26
#define HEADER_AREA(entryPtr)
Definition tclhandle.h:69