File: nad.h

package info (click to toggle)
jabberd2 2.7.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid
  • size: 4,016 kB
  • sloc: ansic: 37,099; sh: 1,108; perl: 656; xml: 561; makefile: 511; python: 238; ruby: 145; sql: 55
file content (199 lines) | stat: -rw-r--r-- 7,532 bytes parent folder | download | duplicates (5)
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
/*
 * jabberd - Jabber Open Source Server
 * Copyright (c) 2002-2004 Jeremie Miller, Thomas Muldowney,
 *                         Ryan Eatmon, Robert Norris
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
 */

/** @file util/nad.h
  * @brief Not A DOM
  * @author Jeremie Miller
  * @author Robert Norris
  * $Date: 2004/05/05 23:49:38 $
  * $Revision: 1.3 $
  *
  * NAD is very simplistic, and requires all string handling to use a length.
  * Apps using this must be aware of the structure and access it directly for
  * most information. NADs can only be built by successively using the _append_
  * functions correctly. After built, they can be modified using other
  * functions, or by direct access. To access cdata on an elem or attr, use
  * nad->cdata + nad->xxx[index].ixxx for the start, and .lxxx for len.
  *
  * Namespace support seems to work, but hasn't been thoroughly tested. in
  * particular, editing the NAD after its creation might have quirks. use at
  * your own risk! Note that nad_add_namespace() brings a namespace into scope
  * for the next element added with nad_append_elem(), nad_insert_elem() or
  * nad_wrap_elem() (and by extension, any of its subelements). This is the
  * same way that Expat does things, so nad_add_namespace() can be driven from
  * Expat's StartNamespaceDeclHandler. See nad_parse() for an example of how to
  * use Expat to drive NAD.
  */

#ifndef INCL_UTIL_NAD_H
#define INCL_UTIL_NAD_H 1

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif

/* jabberd2 Windows DLL */
#ifndef JABBERD2_API
# ifdef _WIN32
#  ifdef JABBERD2_EXPORTS
#   define JABBERD2_API  __declspec(dllexport)
#  else /* JABBERD2_EXPORTS */
#   define JABBERD2_API  __declspec(dllimport)
#  endif /* JABBERD2_EXPORTS */
# else /* _WIN32 */
#  define JABBERD2_API extern
# endif /* _WIN32 */
#endif /* JABBERD2_API */

struct nad_elem_st {
    int parent;
    int iname, lname;
    int icdata, lcdata; /* cdata within this elem (up to first child) */
    int itail, ltail; /* cdata after this elem */
    int attr;
    int ns;
    int my_ns;
    unsigned int depth;
};

struct nad_attr_st {
    int iname, lname;
    int ival, lval;
    int my_ns;
    int next;
};

struct nad_ns_st {
    int iuri, luri;
    int iprefix, lprefix;
    int next;
};

typedef struct nad_st
{
    struct nad_elem_st *elems;
    struct nad_attr_st *attrs;
    struct nad_ns_st *nss;
    char *cdata;
    int *depths; /* for tracking the last elem at a depth */

    /* The size in bytes of the elems, attrs, nss and cdata buffers, respectively. */
    int elen, alen, nlen, clen, dlen;

    /* The number of elements of each type of that data that are actually stored in the elems, attrs, nss and cdata buffers, respectively. */
    int ecur, acur, ncur, ccur;

    int scope; /* currently scoped namespaces, get attached to the next element */
    struct nad_st *next; /* for keeping a list of nads */
} *nad_t;

/** create a new nad */
JABBERD2_API nad_t nad_new(void);

/** copy a nad */
JABBERD2_API nad_t nad_copy(nad_t nad);

/** free that nad */
JABBERD2_API void nad_free(nad_t nad);

/** find the next element with this name/depth */
/** 0 for siblings, 1 for children and so on */
JABBERD2_API int nad_find_elem(nad_t nad, unsigned int elem, int ns, const char *name, int depth);

/** find the first matching attribute (and optionally value) */
JABBERD2_API int nad_find_attr(nad_t nad, unsigned int elem, int ns, const char *name, const char *val);

/** find the first matching namespace (and optionally prefix) */
JABBERD2_API int nad_find_namespace(nad_t nad, unsigned int elem, const char *uri, const char *prefix);

/** find a namespace in scope (and optionally prefix) */
JABBERD2_API int nad_find_scoped_namespace(nad_t nad, const char *uri, const char *prefix);

/** find elem using XPath like query
 *  name -- "name" for the child tag of that name
 *          "name/name" for a sub child (recurses)
 *          "?attrib" to match the first tag with that attrib defined
 *          "?attrib=value" to match the first tag with that attrib and value
 *          or any combination: "name/name/?attrib", etc
 */
JABBERD2_API int nad_find_elem_path(nad_t nad, unsigned int elem, int ns, const char *name);

/** reset or store the given attribute */
JABBERD2_API void nad_set_attr(nad_t nad, unsigned int elem, int ns, const char *name, const char *val, int vallen);

/** insert and return a new element as a child of this one */
JABBERD2_API int nad_insert_elem(nad_t nad, unsigned int parent, int ns, const char *name, const char *cdata);

/** remove an element (and its subelements) */
JABBERD2_API void nad_drop_elem(nad_t nad, unsigned int elem);

/** wrap an element with another element */
JABBERD2_API void nad_wrap_elem(nad_t nad, unsigned int elem, int ns, const char *name);

/** insert part of a nad into another nad */
JABBERD2_API int nad_insert_nad(nad_t dest, int delem, nad_t src, int selem);

/** append and return a new element */
JABBERD2_API int nad_append_elem(nad_t nad, int ns, const char *name, int depth);

/** append attribs to the last element */
JABBERD2_API int nad_append_attr(nad_t nad, int ns, const char *name, const char *val);

/** append more cdata to the last element */
JABBERD2_API void nad_append_cdata(nad_t nad, const char *cdata, int len, int depth);

/** add a namespace to the next element (ie, called when the namespace comes into scope) */
JABBERD2_API int nad_add_namespace(nad_t nad, const char *uri, const char *prefix);

/** declare a namespace on an already existing element */
JABBERD2_API int nad_append_namespace(nad_t nad, unsigned int elem, const char *uri, const char *prefix);

/** create a string representation of the given element (and children), point references to it */
JABBERD2_API void nad_print(nad_t nad, unsigned int elem, const char **xml, int *len);

/** serialize and deserialize a nad */
JABBERD2_API void nad_serialize(nad_t nad, char **buf, int *len);
JABBERD2_API nad_t nad_deserialize(const char *buf);

/** create a nad from raw xml */
JABBERD2_API nad_t nad_parse(const char *buf, int len);

/* these are some helpful macros */
#define NAD_ENAME(N,E) (N->cdata + N->elems[E].iname)
#define NAD_ENAME_L(N,E) (N->elems[E].lname)
#define NAD_CDATA(N,E) (N->cdata + N->elems[E].icdata)
#define NAD_CDATA_L(N,E) (N->elems[E].lcdata)
#define NAD_ANAME(N,A) (N->cdata + N->attrs[A].iname)
#define NAD_ANAME_L(N,A) (N->attrs[A].lname)
#define NAD_AVAL(N,A) (N->cdata + N->attrs[A].ival)
#define NAD_AVAL_L(N,A) (N->attrs[A].lval)
#define NAD_NURI(N,NS) (N->cdata + N->nss[NS].iuri)
#define NAD_NURI_L(N,NS) (N->nss[NS].luri)
#define NAD_NPREFIX(N,NS) (N->cdata + N->nss[NS].iprefix)
#define NAD_NPREFIX_L(N,NS) (N->nss[NS].lprefix)

#define NAD_ENS(N,E) (N->elems[E].my_ns)
#define NAD_ANS(N,A) (N->attrs[A].my_ns)

#endif