GoatError goat_message_get_tag_value( const GoatMessage *message, const char *key, char *value, size_t *size ) { if (NULL == message) return EINVAL; if (NULL == key) return EINVAL; if (NULL == value) return EINVAL; if (NULL == size) return EINVAL; const MessageTags *tags = message->m_tags; if (NULL == tags || 0 == strlen(tags->m_bytes)) return GOAT_E_NOTAG; const char *p, *v, *end; p = _find_tag(tags->m_bytes, key); if (NULL == p) return GOAT_E_NOTAG; v = _find_value(p); if (NULL == v) return GOAT_E_NOTAGVAL; end = _next_tag(v); if ('\0' != *end) end--; // account for separator char unescaped[GOAT_MESSAGE_MAX_TAGS]; size_t unescaped_len = sizeof(unescaped); _unescape_value(v, unescaped, &unescaped_len); if (*size <= unescaped_len) return EOVERFLOW; memset(value, 0, *size); strncpy(value, unescaped, unescaped_len); *size = unescaped_len; return 0; }
int goat_message_has_tag(const GoatMessage *message, const char *key) { if (NULL == message) return 0; if (NULL == key) return 0; const MessageTags *tags = message->m_tags; if (NULL == tags || 0 == strlen(tags->m_bytes)) return 0; return _find_tag(tags->m_bytes, key) ? 1 : 0; }
GoatError goat_message_set_tag(GoatMessage *message, const char *key, const char *value) { if (NULL == message) return EINVAL; if (NULL == key) return EINVAL; if (NULL == message->m_tags) { return tags_init(&message->m_tags, key, value); } if (_find_tag(message->m_tags->m_bytes, key)) { // tag already exists, discard the old one goat_message_unset_tag(message, key); } char buf[GOAT_MESSAGE_MAX_TAGS] = {0}; char *p = buf; if (message->m_tags->m_len + strlen(key) + 1 > GOAT_MESSAGE_MAX_TAGS) { return GOAT_E_MSGLEN; } if (message->m_tags->m_len > 0) { // separator if there's already tag data *p++ = ';'; } p = stpcpy(p, key); if (value) { char escaped_value[GOAT_MESSAGE_MAX_TAGS] = {0}; size_t escaped_value_len = sizeof(escaped_value); _escape_value(value, escaped_value, &escaped_value_len); if (message->m_tags->m_len + strlen(buf) + escaped_value_len + 1 > GOAT_MESSAGE_MAX_TAGS) { return GOAT_E_MSGLEN; } *p++ = '='; p = stpcpy(p, escaped_value); } strcat(message->m_tags->m_bytes, buf); message->m_tags->m_len += strlen(buf); return 0; }
GoatError goat_message_unset_tag(GoatMessage *message, const char *key) { if (NULL == message) return EINVAL; if (NULL == key) return EINVAL; MessageTags *tags = message->m_tags; if (NULL == tags || 0 == strlen(tags->m_bytes)) return 0; char *p1, *p2, *end; end = &tags->m_bytes[tags->m_len]; p1 = (char *) _find_tag(tags->m_bytes, key); if (p1[0] == '\0') return 0; // => p1 is the start of the tag to be replaced p2 = (char *) _next_tag(p1); // => p2 is the start of the rest of the string (if any) if (p2[0] != '\0') { memmove(p1, p2, end - p2); tags->m_len -= (p2 - p1); memset(&tags->m_bytes[tags->m_len], 0, sizeof(tags->m_bytes) - tags->m_len); } else { tags->m_len = p1 - tags->m_bytes; memset(p1, 0, sizeof(tags->m_bytes) - tags->m_len); } // may be a trailing semicolon if tag removed from end, chomp it if (tags->m_bytes[tags->m_len - 1] == ';') { tags->m_bytes[-- tags->m_len] = '\0'; } return 0; }
int st_asn1_tlv_find_tag(unsigned short tag, unsigned char* data, unsigned short data_length, unsigned char** value, unsigned short* value_length) { return _find_tag(tag, &data, &data_length, value, value_length); }