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 "main.h"
17 #include "debug.h"
18 #include "routines.h"
19 #include "nestlevel.h"
20 
21 /* TODO: Alignment */
22 #define NL_SIZE(nls) (sizeof(NestingLevel) + (nls)->userDataSize)
23 #define NL_NTH(nls,n) (NestingLevel *)(((char *)((nls)->levels)) + ((n) * NL_SIZE (nls)))
24 
25 /*
26 *   FUNCTION DEFINITIONS
27 */
28 
nestingLevelsNew(size_t userDataSize)29 extern NestingLevels *nestingLevelsNew(size_t userDataSize)
30 {
31 	NestingLevels *nls = xCalloc (1, NestingLevels);
32 	nls->userDataSize = userDataSize;
33 	return nls;
34 }
35 
nestingLevelsFree(NestingLevels * nls)36 extern void nestingLevelsFree(NestingLevels *nls)
37 {
38 	int i;
39 	NestingLevel *nl;
40 
41 	for (i = 0; i < nls->allocated; i++)
42 	{
43 		nl = NL_NTH(nls, i);
44 		nl->corkIndex = CORK_NIL;
45 	}
46 	if (nls->levels) eFree(nls->levels);
47 	eFree(nls);
48 }
49 
nestingLevelsPush(NestingLevels * nls,int corkIndex)50 extern NestingLevel * nestingLevelsPush(NestingLevels *nls, int corkIndex)
51 {
52 	NestingLevel *nl = NULL;
53 
54 	if (nls->n >= nls->allocated)
55 	{
56 		nls->allocated++;
57 		nls->levels = eRealloc(nls->levels,
58 				       nls->allocated * NL_SIZE (nls));
59 	}
60 	nl = NL_NTH(nls, nls->n);
61 	nls->n++;
62 
63 	nl->corkIndex = corkIndex;
64 	return nl;
65 }
66 
nestingLevelsTruncate(NestingLevels * nls,int depth,int corkIndex)67 extern NestingLevel *nestingLevelsTruncate(NestingLevels *nls, int depth, int corkIndex)
68 {
69 	NestingLevel *nl;
70 
71 	nls->n = depth;
72 	nl = nestingLevelsGetCurrent(nls);
73 	nl->corkIndex = corkIndex;
74 	return nl;
75 }
76 
77 
nestingLevelsPop(NestingLevels * nls)78 extern void nestingLevelsPop(NestingLevels *nls)
79 {
80 	NestingLevel *nl = nestingLevelsGetCurrent(nls);
81 
82 	Assert (nl != NULL);
83 	nl->corkIndex = CORK_NIL;
84 	nls->n--;
85 }
86 
nestingLevelsGetCurrent(const NestingLevels * nls)87 extern NestingLevel *nestingLevelsGetCurrent(const NestingLevels *nls)
88 {
89 	Assert (nls != NULL);
90 
91 	if (nls->n < 1)
92 		return NULL;
93 
94 	return NL_NTH(nls, (nls->n - 1));
95 }
96 
nestingLevelsGetNth(const NestingLevels * nls,int n)97 extern NestingLevel *nestingLevelsGetNth(const NestingLevels *nls, int n)
98 {
99 	Assert (nls != NULL);
100 	if (nls->n > n && n >= 0)
101 		return  NL_NTH(nls, n);
102 	else
103 		return NULL;
104 }
105 
nestingLevelGetUserData(const NestingLevel * nl)106 extern void *nestingLevelGetUserData (const NestingLevel *nl)
107 {
108 	return (void *)nl->userData;
109 }
110