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