blob: b4d99ae56f5c12add11f974f7b9a9a5688ce97a7 [file] [log] [blame]
kasunathd073aa12022-05-12 16:08:49 -07001#include "bej_dictionary.h"
2
3#include <stdbool.h>
4#include <stdio.h>
kasunathf68be952023-08-01 17:29:58 -07005#include <string.h>
kasunathd073aa12022-05-12 16:08:49 -07006
7/**
8 * @brief Get the index for a property offset. First property will be at index
9 * 0.
10 *
11 * @param[in] propertyOffset - a valid property offset.
12 * @return index of the property.
13 */
14static uint16_t bejGetPropertyEntryIndex(uint16_t propertyOffset)
15{
16 return (propertyOffset - bejDictGetPropertyHeadOffset()) /
17 sizeof(struct BejDictionaryProperty);
18}
19
20/**
21 * @brief Validate a property offset.
22 *
kasunathf68be952023-08-01 17:29:58 -070023 * @param[in] dictionary - pointer to the dictionary.
kasunathd073aa12022-05-12 16:08:49 -070024 * @param[in] propertyOffset - offset needed to be validated.
25 * @return true if propertyOffset is a valid offset.
26 */
kasunathf68be952023-08-01 17:29:58 -070027static bool bejValidatePropertyOffset(const uint8_t* dictionary,
28 uint16_t propertyOffset)
kasunathd073aa12022-05-12 16:08:49 -070029{
30 // propertyOffset should be greater than or equal to first property offset.
31 if (propertyOffset < bejDictGetPropertyHeadOffset())
32 {
33 fprintf(
34 stderr,
35 "Invalid property offset. Pointing to Dictionary header data\n");
36 return false;
37 }
38
39 // propertyOffset should be a multiple of sizeof(BejDictionaryProperty)
40 // starting from first property within the dictionary.
41 if ((propertyOffset - bejDictGetPropertyHeadOffset()) %
42 sizeof(struct BejDictionaryProperty))
43 {
44 fprintf(stderr, "Invalid property offset. Does not point to beginning "
45 "of property\n");
46 return false;
47 }
48
kasunathf68be952023-08-01 17:29:58 -070049 const struct BejDictionaryHeader* header =
50 (const struct BejDictionaryHeader*)dictionary;
51 uint16_t propertyIndex = bejGetPropertyEntryIndex(propertyOffset);
52 if (propertyIndex >= header->entryCount)
53 {
54 fprintf(stderr,
55 "Invalid property offset %u. It falls outside of dictionary "
56 "properties\n",
57 propertyOffset);
58 return false;
59 }
60
kasunathd073aa12022-05-12 16:08:49 -070061 return true;
62}
63
64uint16_t bejDictGetPropertyHeadOffset()
65{
66 // First property is present soon after the dictionary header.
67 return sizeof(struct BejDictionaryHeader);
68}
69
70uint16_t bejDictGetFirstAnnotatedPropertyOffset()
71{
72 // The first property available is the "Annotations" set which is the parent
73 // for all properties. Next immediate property is the first property we
74 // need.
75 return sizeof(struct BejDictionaryHeader) +
76 sizeof(struct BejDictionaryProperty);
77}
78
79int bejDictGetProperty(const uint8_t* dictionary,
80 uint16_t startingPropertyOffset, uint16_t sequenceNumber,
81 const struct BejDictionaryProperty** property)
82{
83 uint16_t propertyOffset = startingPropertyOffset;
84 const struct BejDictionaryHeader* header =
85 (const struct BejDictionaryHeader*)dictionary;
86
kasunathf68be952023-08-01 17:29:58 -070087 if (!bejValidatePropertyOffset(dictionary, propertyOffset))
kasunathd073aa12022-05-12 16:08:49 -070088 {
89 return bejErrorInvalidPropertyOffset;
90 }
91 uint16_t propertyIndex = bejGetPropertyEntryIndex(propertyOffset);
92
93 for (uint16_t index = propertyIndex; index < header->entryCount; ++index)
94 {
95 const struct BejDictionaryProperty* p =
96 (const struct BejDictionaryProperty*)(dictionary + propertyOffset);
97 if (p->sequenceNumber == sequenceNumber)
98 {
99 *property = p;
100 return 0;
101 }
102 propertyOffset += sizeof(struct BejDictionaryProperty);
103 }
104 return bejErrorUnknownProperty;
105}
106
107const char* bejDictGetPropertyName(const uint8_t* dictionary,
108 uint16_t nameOffset, uint8_t nameLength)
109{
110 if (nameLength == 0)
111 {
112 return "";
113 }
114 return (const char*)(dictionary + nameOffset);
115}
kasunathf68be952023-08-01 17:29:58 -0700116
117int bejDictGetPropertyByName(const uint8_t* dictionary,
118 uint16_t startingPropertyOffset,
119 const char* propertyName,
120 const struct BejDictionaryProperty** property,
121 uint16_t* propertyOffset)
122{
123 NULL_CHECK(property, "property in bejDictGetPropertyByName");
124
125 uint16_t curPropertyOffset = startingPropertyOffset;
126 const struct BejDictionaryHeader* header =
127 (const struct BejDictionaryHeader*)dictionary;
128
129 if (!bejValidatePropertyOffset(dictionary, curPropertyOffset))
130 {
131 return bejErrorInvalidPropertyOffset;
132 }
133 uint16_t propertyIndex = bejGetPropertyEntryIndex(curPropertyOffset);
134
135 for (uint16_t index = propertyIndex; index < header->entryCount; ++index)
136 {
137 const struct BejDictionaryProperty* p =
138 (const struct BejDictionaryProperty*)(dictionary +
139 curPropertyOffset);
140 if (strcmp(propertyName,
141 bejDictGetPropertyName(dictionary, p->nameOffset,
142 p->nameLength)) == 0)
143 {
144 *property = p;
145 // propertyOffset is an optional output.
146 if (propertyOffset != NULL)
147 {
148 *propertyOffset = curPropertyOffset;
149 }
150 return 0;
151 }
152 curPropertyOffset += sizeof(struct BejDictionaryProperty);
153 }
154 return bejErrorUnknownProperty;
155}