1 /*
2 * This file is part of Hubbub.
3 * Licensed under the MIT License,
4 * http://www.opensource.org/licenses/mit-license.php
5 * Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org>
6 */
7
8 #include "utils/utils.h"
9 #include "tokeniser/entities.h"
10
11 /** Node in our entity tree */
12 typedef struct hubbub_entity_node {
13 /* Do not reorder this without fixing make-entities.pl */
14 uint8_t split; /**< Data to split on */
15 int32_t lt; /**< Subtree for data less than split */
16 int32_t eq; /**< Subtree for data equal to split */
17 int32_t gt; /**< Subtree for data greater than split */
18 uint32_t value; /**< Data for this node */
19 } hubbub_entity_node;
20
21 #include "entities.inc"
22
23 /**
24 * Step-wise search for a key in our entity tree
25 *
26 * \param c Character to look for
27 * \param result Pointer to location for result
28 * \param context Pointer to location for search context
29 * \return HUBBUB_OK if key found,
30 * HUBBUB_NEEDDATA if more steps are required
31 * HUBBUB_INVALID if nothing matches
32 *
33 * The value pointed to by \p context must be NULL for the first call.
34 * Thereafter, pass in the same value as returned by the previous call.
35 * The context is opaque to the caller and should not be inspected.
36 *
37 * The location pointed to by \p result will be set to NULL unless a match
38 * is found.
39 */
hubbub_entity_tree_search_step(uint8_t c,uint32_t * result,int32_t * context)40 static hubbub_error hubbub_entity_tree_search_step(uint8_t c,
41 uint32_t *result, int32_t *context)
42 {
43 bool match = false;
44 int32_t p;
45
46 if (result == NULL || context == NULL)
47 return HUBBUB_BADPARM;
48
49 if (*context == -1) {
50 p = dict_root;
51 } else {
52 p = *context;
53 }
54
55 while (p != -1) {
56 if (c < dict[p].split) {
57 p = dict[p].lt;
58 } else if (c == dict[p].split) {
59 if (dict[p].split == '\0') {
60 match = true;
61 p = -1;
62 } else if (dict[p].eq != -1 && dict[dict[p].eq].split == '\0') {
63 match = true;
64 *result = dict[dict[p].eq].value;
65 p = dict[p].eq;
66 } else if (dict[p].value != 0) {
67 match = true;
68 *result = dict[p].value;
69 p = dict[p].eq;
70 } else {
71 p = dict[p].eq;
72 }
73
74 break;
75 } else {
76 p = dict[p].gt;
77 }
78 }
79
80 *context = p;
81
82 return (match) ? HUBBUB_OK :
83 (p == -1) ? HUBBUB_INVALID : HUBBUB_NEEDDATA;
84 }
85
86 /**
87 * Step-wise search for an entity in the dictionary
88 *
89 * \param c Character to look for
90 * \param result Pointer to location for result
91 * \param context Pointer to location for search context
92 * \return HUBBUB_OK if key found,
93 * HUBBUB_NEEDDATA if more steps are required
94 * HUBBUB_INVALID if nothing matches
95 *
96 * The value pointed to by \p context should be -1 for the first call.
97 * Thereafter, pass in the same value as returned by the previous call.
98 * The context is opaque to the caller and should not be inspected.
99 *
100 * The location pointed to by \p result will be set to U+FFFD unless a match
101 * is found.
102 */
hubbub_entities_search_step(uint8_t c,uint32_t * result,int32_t * context)103 hubbub_error hubbub_entities_search_step(uint8_t c, uint32_t *result,
104 int32_t *context)
105 {
106 if (result == NULL)
107 return HUBBUB_BADPARM;
108
109 *result = 0xFFFD;
110
111 return hubbub_entity_tree_search_step(c, result, context);
112 }
113