1*d073aa1aSkasunath #include "bej_dictionary.h" 2*d073aa1aSkasunath 3*d073aa1aSkasunath #include <stdbool.h> 4*d073aa1aSkasunath #include <stdio.h> 5*d073aa1aSkasunath 6*d073aa1aSkasunath /** 7*d073aa1aSkasunath * @brief Get the index for a property offset. First property will be at index 8*d073aa1aSkasunath * 0. 9*d073aa1aSkasunath * 10*d073aa1aSkasunath * @param[in] propertyOffset - a valid property offset. 11*d073aa1aSkasunath * @return index of the property. 12*d073aa1aSkasunath */ 13*d073aa1aSkasunath static uint16_t bejGetPropertyEntryIndex(uint16_t propertyOffset) 14*d073aa1aSkasunath { 15*d073aa1aSkasunath return (propertyOffset - bejDictGetPropertyHeadOffset()) / 16*d073aa1aSkasunath sizeof(struct BejDictionaryProperty); 17*d073aa1aSkasunath } 18*d073aa1aSkasunath 19*d073aa1aSkasunath /** 20*d073aa1aSkasunath * @brief Validate a property offset. 21*d073aa1aSkasunath * 22*d073aa1aSkasunath * @param[in] propertyOffset - offset needed to be validated. 23*d073aa1aSkasunath * @return true if propertyOffset is a valid offset. 24*d073aa1aSkasunath */ 25*d073aa1aSkasunath static bool bejValidatePropertyOffset(uint16_t propertyOffset) 26*d073aa1aSkasunath { 27*d073aa1aSkasunath // propertyOffset should be greater than or equal to first property offset. 28*d073aa1aSkasunath if (propertyOffset < bejDictGetPropertyHeadOffset()) 29*d073aa1aSkasunath { 30*d073aa1aSkasunath fprintf( 31*d073aa1aSkasunath stderr, 32*d073aa1aSkasunath "Invalid property offset. Pointing to Dictionary header data\n"); 33*d073aa1aSkasunath return false; 34*d073aa1aSkasunath } 35*d073aa1aSkasunath 36*d073aa1aSkasunath // propertyOffset should be a multiple of sizeof(BejDictionaryProperty) 37*d073aa1aSkasunath // starting from first property within the dictionary. 38*d073aa1aSkasunath if ((propertyOffset - bejDictGetPropertyHeadOffset()) % 39*d073aa1aSkasunath sizeof(struct BejDictionaryProperty)) 40*d073aa1aSkasunath { 41*d073aa1aSkasunath fprintf(stderr, "Invalid property offset. Does not point to beginning " 42*d073aa1aSkasunath "of property\n"); 43*d073aa1aSkasunath return false; 44*d073aa1aSkasunath } 45*d073aa1aSkasunath 46*d073aa1aSkasunath return true; 47*d073aa1aSkasunath } 48*d073aa1aSkasunath 49*d073aa1aSkasunath uint16_t bejDictGetPropertyHeadOffset() 50*d073aa1aSkasunath { 51*d073aa1aSkasunath // First property is present soon after the dictionary header. 52*d073aa1aSkasunath return sizeof(struct BejDictionaryHeader); 53*d073aa1aSkasunath } 54*d073aa1aSkasunath 55*d073aa1aSkasunath uint16_t bejDictGetFirstAnnotatedPropertyOffset() 56*d073aa1aSkasunath { 57*d073aa1aSkasunath // The first property available is the "Annotations" set which is the parent 58*d073aa1aSkasunath // for all properties. Next immediate property is the first property we 59*d073aa1aSkasunath // need. 60*d073aa1aSkasunath return sizeof(struct BejDictionaryHeader) + 61*d073aa1aSkasunath sizeof(struct BejDictionaryProperty); 62*d073aa1aSkasunath } 63*d073aa1aSkasunath 64*d073aa1aSkasunath int bejDictGetProperty(const uint8_t* dictionary, 65*d073aa1aSkasunath uint16_t startingPropertyOffset, uint16_t sequenceNumber, 66*d073aa1aSkasunath const struct BejDictionaryProperty** property) 67*d073aa1aSkasunath { 68*d073aa1aSkasunath uint16_t propertyOffset = startingPropertyOffset; 69*d073aa1aSkasunath const struct BejDictionaryHeader* header = 70*d073aa1aSkasunath (const struct BejDictionaryHeader*)dictionary; 71*d073aa1aSkasunath 72*d073aa1aSkasunath if (!bejValidatePropertyOffset(propertyOffset)) 73*d073aa1aSkasunath { 74*d073aa1aSkasunath return bejErrorInvalidPropertyOffset; 75*d073aa1aSkasunath } 76*d073aa1aSkasunath uint16_t propertyIndex = bejGetPropertyEntryIndex(propertyOffset); 77*d073aa1aSkasunath 78*d073aa1aSkasunath for (uint16_t index = propertyIndex; index < header->entryCount; ++index) 79*d073aa1aSkasunath { 80*d073aa1aSkasunath const struct BejDictionaryProperty* p = 81*d073aa1aSkasunath (const struct BejDictionaryProperty*)(dictionary + propertyOffset); 82*d073aa1aSkasunath if (p->sequenceNumber == sequenceNumber) 83*d073aa1aSkasunath { 84*d073aa1aSkasunath *property = p; 85*d073aa1aSkasunath return 0; 86*d073aa1aSkasunath } 87*d073aa1aSkasunath propertyOffset += sizeof(struct BejDictionaryProperty); 88*d073aa1aSkasunath } 89*d073aa1aSkasunath return bejErrorUnknownProperty; 90*d073aa1aSkasunath } 91*d073aa1aSkasunath 92*d073aa1aSkasunath const char* bejDictGetPropertyName(const uint8_t* dictionary, 93*d073aa1aSkasunath uint16_t nameOffset, uint8_t nameLength) 94*d073aa1aSkasunath { 95*d073aa1aSkasunath if (nameLength == 0) 96*d073aa1aSkasunath { 97*d073aa1aSkasunath return ""; 98*d073aa1aSkasunath } 99*d073aa1aSkasunath return (const char*)(dictionary + nameOffset); 100*d073aa1aSkasunath } 101