|
1 | 1 | /****************************************************************************
|
2 | 2 | **
|
3 |
| -** Copyright (C) 2016 Intel Corporation |
| 3 | +** Copyright (C) 2017 Intel Corporation |
4 | 4 | **
|
5 | 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 | 6 | ** of this software and associated documentation files (the "Software"), to deal
|
@@ -932,14 +932,154 @@ CborError cbor_value_get_int_checked(const CborValue *value, int *result)
|
932 | 932 | * CborErrorDataTooLarge if the stream indicates a length that is too big to
|
933 | 933 | * fit in 32-bit.
|
934 | 934 | *
|
935 |
| - * \sa cbor_value_get_string_length(), cbor_value_copy_string(), cbor_value_is_length_known() |
| 935 | + * \sa cbor_value_get_string_length(), cbor_value_copy_text_string(), cbor_value_copy_byte_string(), cbor_value_is_length_known() |
936 | 936 | */
|
937 | 937 | CborError cbor_value_calculate_string_length(const CborValue *value, size_t *len)
|
938 | 938 | {
|
939 | 939 | *len = SIZE_MAX;
|
940 | 940 | return _cbor_value_copy_string(value, NULL, len, NULL);
|
941 | 941 | }
|
942 | 942 |
|
| 943 | +static CborError get_string_chunk(CborValue *it, const void **bufferptr, size_t *len) |
| 944 | +{ |
| 945 | + CborError err; |
| 946 | + |
| 947 | + /* Possible states: |
| 948 | + * length known | iterating | meaning |
| 949 | + * no | no | before the first chunk of a chunked string |
| 950 | + * yes | no | at a non-chunked string |
| 951 | + * no | yes | second or later chunk |
| 952 | + * yes | yes | after a non-chunked string |
| 953 | + */ |
| 954 | + if (it->flags & CborIteratorFlag_IteratingStringChunks) { |
| 955 | + /* already iterating */ |
| 956 | + if (cbor_value_is_length_known(it)) { |
| 957 | + /* if the length was known, it wasn't chunked, so finish iteration */ |
| 958 | + goto last_chunk; |
| 959 | + } |
| 960 | + } else if (!cbor_value_is_length_known(it)) { |
| 961 | + /* chunked string, we're before the first chunk */ |
| 962 | + ++it->ptr; |
| 963 | + } |
| 964 | + |
| 965 | + /* are we at the end? */ |
| 966 | + if (it->ptr == it->parser->end) |
| 967 | + return CborErrorUnexpectedEOF; |
| 968 | + |
| 969 | + if (*it->ptr == BreakByte) { |
| 970 | + /* last chunk */ |
| 971 | + ++it->ptr; |
| 972 | +last_chunk: |
| 973 | + *bufferptr = NULL; |
| 974 | + return preparse_next_value(it); |
| 975 | + } else if ((uint8_t)(*it->ptr & MajorTypeMask) == it->type) { |
| 976 | + err = extract_length(it->parser, &it->ptr, len); |
| 977 | + if (err) |
| 978 | + return err; |
| 979 | + if (*len > (size_t)(it->parser->end - it->ptr)) |
| 980 | + return CborErrorUnexpectedEOF; |
| 981 | + |
| 982 | + *bufferptr = it->ptr; |
| 983 | + it->ptr += *len; |
| 984 | + } else { |
| 985 | + return CborErrorIllegalType; |
| 986 | + } |
| 987 | + |
| 988 | + it->flags |= CborIteratorFlag_IteratingStringChunks; |
| 989 | + return CborNoError; |
| 990 | +} |
| 991 | + |
| 992 | +/** |
| 993 | + * \fn CborError cbor_value_get_text_string_chunk(const CborValue *value, const char **bufferptr, size_t *len, CborValue *next) |
| 994 | + * |
| 995 | + * Extracts one text string chunk pointed to by \a value and stores a pointer |
| 996 | + * to the data in \a buffer and the size in \a len, which must not be null. If |
| 997 | + * no more chunks are available, then \a bufferptr will be set to null. This |
| 998 | + * function may be used to iterate over any string without causing its contents |
| 999 | + * to be copied to a separate buffer, like the convenience function |
| 1000 | + * cbor_value_copy_text_string() does. |
| 1001 | + * |
| 1002 | + * It is designed to be used in code like: |
| 1003 | + * |
| 1004 | + * \code |
| 1005 | + * if (cbor_value_is_text_string(value)) { |
| 1006 | + * char *ptr; |
| 1007 | + * size_t len; |
| 1008 | + * while (1) { |
| 1009 | + * err = cbor_value_get_text_string_chunk(value, &ptr, &len, &value)); |
| 1010 | + * if (err) return err; |
| 1011 | + * if (ptr == NULL) return CborNoError; |
| 1012 | + * consume(ptr, len); |
| 1013 | + * } |
| 1014 | + * } |
| 1015 | + * \endcode |
| 1016 | + * |
| 1017 | + * If the iterator \a value does not point to a text string, the behaviour is |
| 1018 | + * undefined, so checking with \ref cbor_value_get_type or \ref |
| 1019 | + * cbor_value_is_text_string is recommended. |
| 1020 | + * |
| 1021 | + * The \a next pointer, if not null, will be updated to point to the next item |
| 1022 | + * after this string. During iteration, the pointer must only be passed back |
| 1023 | + * again to this function; passing it to any other function in this library |
| 1024 | + * results in undefined behavior. If there are no more chunks to be read from |
| 1025 | + * \a value, then \a next will be set to the next item after this string; if \a |
| 1026 | + * value points to the last item, then \a next will be invalid. |
| 1027 | + * |
| 1028 | + * \note This function does not perform UTF-8 validation on the incoming text |
| 1029 | + * string. |
| 1030 | + * |
| 1031 | + * \sa cbor_value_dup_text_string(), cbor_value_copy_text_string(), cbor_value_caculate_string_length(), cbor_value_get_byte_string_chunk() |
| 1032 | + */ |
| 1033 | + |
| 1034 | +/** |
| 1035 | + * \fn CborError cbor_value_get_byte_string_chunk(const CborValue *value, const char **bufferptr, size_t *len, CborValue *next) |
| 1036 | + * |
| 1037 | + * Extracts one byte string chunk pointed to by \a value and stores a pointer |
| 1038 | + * to the data in \a buffer and the size in \a len, which must not be null. If |
| 1039 | + * no more chunks are available, then \a bufferptr will be set to null. This |
| 1040 | + * function may be used to iterate over any string without causing its contents |
| 1041 | + * to be copied to a separate buffer, like the convenience function |
| 1042 | + * cbor_value_copy_byte_string() does. |
| 1043 | + * |
| 1044 | + * It is designed to be used in code like: |
| 1045 | + * |
| 1046 | + * \code |
| 1047 | + * if (cbor_value_is_byte_string(value)) { |
| 1048 | + * char *ptr; |
| 1049 | + * size_t len; |
| 1050 | + * while (1) { |
| 1051 | + * err = cbor_value_get_byte_string_chunk(value, &ptr, &len, &value)); |
| 1052 | + * if (err) return err; |
| 1053 | + * if (ptr == NULL) return CborNoError; |
| 1054 | + * consume(ptr, len); |
| 1055 | + * } |
| 1056 | + * } |
| 1057 | + * \endcode |
| 1058 | + * |
| 1059 | + * If the iterator \a value does not point to a byte string, the behaviour is |
| 1060 | + * undefined, so checking with \ref cbor_value_get_type or \ref |
| 1061 | + * cbor_value_is_byte_string is recommended. |
| 1062 | + * |
| 1063 | + * The \a next pointer, if not null, will be updated to point to the next item |
| 1064 | + * after this string. During iteration, the pointer must only be passed back |
| 1065 | + * again to this function; passing it to any other function in this library |
| 1066 | + * results in undefined behavior. If there are no more chunks to be read from |
| 1067 | + * \a value, then \a next will be set to the next item after this string; if \a |
| 1068 | + * value points to the last item, then \a next will be invalid. |
| 1069 | + * |
| 1070 | + * \sa cbor_value_dup_byte_string(), cbor_value_copy_byte_string(), cbor_value_caculate_string_length(), cbor_value_get_text_string_chunk() |
| 1071 | + */ |
| 1072 | + |
| 1073 | +CborError _cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr, |
| 1074 | + size_t *len, CborValue *next) |
| 1075 | +{ |
| 1076 | + CborValue tmp; |
| 1077 | + if (!next) |
| 1078 | + next = &tmp; |
| 1079 | + *next = *value; |
| 1080 | + return get_string_chunk(next, bufferptr, len); |
| 1081 | +} |
| 1082 | + |
943 | 1083 | /* We return uintptr_t so that we can pass memcpy directly as the iteration
|
944 | 1084 | * function. The choice is to optimize for memcpy, which is used in the base
|
945 | 1085 | * parser API (cbor_value_copy_string), while memcmp is used in convenience API
|
@@ -1066,7 +1206,7 @@ static CborError iterate_string_chunks(const CborValue *value, char *buffer, siz
|
1066 | 1206 | * \note This function does not perform UTF-8 validation on the incoming text
|
1067 | 1207 | * string.
|
1068 | 1208 | *
|
1069 |
| - * \sa cbor_value_dup_text_string(), cbor_value_copy_byte_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() |
| 1209 | + * \sa cbor_value_get_text_string_chunk() cbor_value_dup_text_string(), cbor_value_copy_byte_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() |
1070 | 1210 | */
|
1071 | 1211 |
|
1072 | 1212 | /**
|
@@ -1097,7 +1237,7 @@ static CborError iterate_string_chunks(const CborValue *value, char *buffer, siz
|
1097 | 1237 | * This function may not run in constant time (it will run in O(n) time on the
|
1098 | 1238 | * number of chunks). It requires constant memory (O(1)).
|
1099 | 1239 | *
|
1100 |
| - * \sa cbor_value_dup_text_string(), cbor_value_copy_text_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() |
| 1240 | + * \sa cbor_value_get_byte_string_chunk(), cbor_value_dup_text_string(), cbor_value_copy_text_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() |
1101 | 1241 | */
|
1102 | 1242 |
|
1103 | 1243 | CborError _cbor_value_copy_string(const CborValue *value, void *buffer,
|
|
0 commit comments