1 /*
2 * Copyright (c) 1999-2002, Darren Hiebert
3 * Copyright 2009-2011 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
4 *
5 * This source code is released for free distribution under the terms of the
6 * GNU General Public License version 2 or (at your option) any later version.
7 *
8 * Defines external interface to scope nesting levels for tags.
9 */
10
11 /*
12 * INCLUDE FILES
13 */
14 #include "general.h" /* must always come first */
15
16 #include "debug.h"
17 #include "entry.h"
18 #include "routines.h"
19 #include "nestlevel.h"
20
21 #include <string.h>
22
23 /* TODO: Alignment */
24 #define NL_SIZE(nls) (sizeof(NestingLevel) + (nls)->userDataSize)
25 #define NL_NTH(nls,n) (NestingLevel *)(((char *)((nls)->levels)) + ((n) * NL_SIZE (nls)))
26
27 /*
28 * FUNCTION DEFINITIONS
29 */
30
nestingLevelsNewFull(size_t userDataSize,void (* deleteUserData)(NestingLevel *,void *))31 extern NestingLevels *nestingLevelsNewFull(size_t userDataSize,
32 void (* deleteUserData)(NestingLevel *, void *))
33 {
34 NestingLevels *nls = xCalloc (1, NestingLevels);
35 nls->userDataSize = userDataSize;
36 nls->deleteUserData = deleteUserData;
37 return nls;
38 }
39
nestingLevelsNew(size_t userDataSize)40 extern NestingLevels *nestingLevelsNew(size_t userDataSize)
41 {
42 return nestingLevelsNewFull (userDataSize, NULL);
43 }
44
nestingLevelsFreeFull(NestingLevels * nls,void * ctxData)45 extern void nestingLevelsFreeFull(NestingLevels *nls, void *ctxData)
46 {
47 int i;
48 NestingLevel *nl;
49
50 for (i = 0; i < nls->n; i++)
51 {
52 nl = NL_NTH(nls, i);
53 if (nls->deleteUserData)
54 nls->deleteUserData (nl, ctxData);
55 nl->corkIndex = CORK_NIL;
56 }
57 if (nls->levels) eFree(nls->levels);
58 eFree(nls);
59 }
60
nestingLevelsPush(NestingLevels * nls,int corkIndex)61 extern NestingLevel * nestingLevelsPush(NestingLevels *nls, int corkIndex)
62 {
63 NestingLevel *nl = NULL;
64
65 if (nls->n >= nls->allocated)
66 {
67 nls->allocated++;
68 nls->levels = eRealloc(nls->levels,
69 nls->allocated * NL_SIZE (nls));
70 }
71 nl = NL_NTH(nls, nls->n);
72 nls->n++;
73
74 nl->corkIndex = corkIndex;
75 if (nls->userDataSize > 0)
76 memset (nl->userData, 0, nls->userDataSize);
77
78 return nl;
79 }
80
nestingLevelsTruncate(NestingLevels * nls,int depth,int corkIndex)81 extern NestingLevel *nestingLevelsTruncate(NestingLevels *nls, int depth, int corkIndex)
82 {
83 NestingLevel *nl;
84
85 nls->n = depth;
86 nl = nestingLevelsGetCurrent(nls);
87 nl->corkIndex = corkIndex;
88 return nl;
89 }
90
91
nestingLevelsPopFull(NestingLevels * nls,void * ctxData)92 extern void nestingLevelsPopFull(NestingLevels *nls, void *ctxData)
93 {
94 NestingLevel *nl = nestingLevelsGetCurrent(nls);
95
96 Assert (nl != NULL);
97 if (nls->deleteUserData)
98 nls->deleteUserData (nl, ctxData);
99 nl->corkIndex = CORK_NIL;
100 nls->n--;
101 }
102
nestingLevelsGetNthFromRoot(const NestingLevels * nls,int n)103 extern NestingLevel *nestingLevelsGetNthFromRoot (const NestingLevels *nls, int n)
104 {
105 Assert (nls != NULL);
106 if (nls->n > n && n >= 0)
107 return NL_NTH(nls, n);
108 else
109 return NULL;
110 }
111
nestingLevelsGetNthParent(const NestingLevels * nls,int n)112 extern NestingLevel *nestingLevelsGetNthParent (const NestingLevels *nls, int n)
113 {
114 Assert (nls != NULL);
115 return nestingLevelsGetNthFromRoot (nls, nls->n - 1 - n);
116 }
117
nestingLevelGetUserData(const NestingLevel * nl)118 extern void *nestingLevelGetUserData (const NestingLevel *nl)
119 {
120 return (void *)nl->userData;
121 }
122