summaryrefslogtreecommitdiff
path: root/FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/aws/common/src/aws_iot_doc_parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/aws/common/src/aws_iot_doc_parser.c')
-rw-r--r--FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/aws/common/src/aws_iot_doc_parser.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/aws/common/src/aws_iot_doc_parser.c b/FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/aws/common/src/aws_iot_doc_parser.c
new file mode 100644
index 000000000..a4322840b
--- /dev/null
+++ b/FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/aws/common/src/aws_iot_doc_parser.c
@@ -0,0 +1,294 @@
+/*
+ * AWS IoT Common V1.0.0
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file aws_iot_doc_parser.c
+ * @brief Implements the functions in aws_iot_doc_parser.h
+ */
+
+/* The config header is always included first. */
+#include "iot_config.h"
+
+/* Standard includes. */
+#include <string.h>
+
+/* JSON utilities include. */
+#include "aws_iot_doc_parser.h"
+
+#define IS_QUOTE( str, idx ) \
+ ( ( str )[ ( idx ) ] == '"' && ( ( idx ) == 0 || ( str )[ ( idx ) - 1 ] != '\\' ) )
+#define IS_WHITESPACE( str, idx ) \
+ ( ( str )[ ( idx ) ] == ' ' || ( str )[ ( idx ) ] == '\n' || ( str )[ ( idx ) ] == '\r' || ( str )[ ( idx ) ] == '\t' )
+
+/*-----------------------------------------------------------*/
+
+bool AwsIotDocParser_FindValue( const char * pAwsIotJsonDocument,
+ size_t awsIotJsonDocumentLength,
+ const char * pAwsIotJsonKey,
+ size_t awsIotJsonKeyLength,
+ const char ** pAwsIotJsonValue,
+ size_t * pAwsIotJsonValueLength )
+{
+ size_t i = 0;
+ size_t jsonValueLength = 0;
+ char openCharacter = '\0', closeCharacter = '\0';
+ int nestingLevel = 0;
+ bool isWithinQuotes = false;
+
+ /* Validate all the arguments.*/
+ if( ( pAwsIotJsonDocument == NULL ) || ( pAwsIotJsonKey == NULL ) ||
+ ( awsIotJsonDocumentLength == 0 ) || ( awsIotJsonKeyLength == 0 ) )
+ {
+ return false;
+ }
+
+ /* Ensure the JSON document is long enough to contain the key/value pair. At
+ * the very least, a JSON key/value pair must contain the key and the 6
+ * characters {":""} */
+ if( awsIotJsonDocumentLength < awsIotJsonKeyLength + 6 )
+ {
+ return false;
+ }
+
+ /* Search the characters in the JSON document for the key. The end of the JSON
+ * document does not have to be searched once too few characters remain to hold a
+ * value. */
+ while( i < awsIotJsonDocumentLength - awsIotJsonKeyLength - 3 )
+ {
+ /* If the first character in the key is found and there's an unescaped double
+ * quote after the key length, do a string compare for the key. */
+ if( ( IS_QUOTE( pAwsIotJsonDocument, i ) ) &&
+ ( IS_QUOTE( pAwsIotJsonDocument, i + 1 + awsIotJsonKeyLength ) ) &&
+ ( pAwsIotJsonDocument[ i + 1 ] == pAwsIotJsonKey[ 0 ] ) &&
+ ( strncmp( pAwsIotJsonDocument + i + 1,
+ pAwsIotJsonKey,
+ awsIotJsonKeyLength ) == 0 ) )
+ {
+ /* Key found; this is a potential match. */
+
+ /* Skip the characters in the JSON key and closing double quote. */
+ /* While loop guarantees that i < awsIotJsonDocumentLength - 1 */
+ i += awsIotJsonKeyLength + 2;
+
+ /* Skip all whitespace characters between the closing " and the : */
+ while( IS_WHITESPACE( pAwsIotJsonDocument, i ) )
+ {
+ i++;
+
+ /* If the end of the document is reached, this isn't a match. */
+ if( i >= awsIotJsonDocumentLength )
+ {
+ return false;
+ }
+ }
+
+ /* The character immediately following a key (and any whitespace) must be a :
+ * If it's another character, then this string is a JSON value; skip it. */
+ if( pAwsIotJsonDocument[ i ] != ':' )
+ {
+ continue;
+ }
+ else
+ {
+ /* Skip the : */
+ i++;
+ }
+
+ /* If the end of the document is reached, this isn't a match. */
+ if( i >= awsIotJsonDocumentLength )
+ {
+ return false;
+ }
+
+ /* Skip all whitespace characters between : and the first character in the value. */
+ while( IS_WHITESPACE( pAwsIotJsonDocument, i ) )
+ {
+ i++;
+
+ /* If the end of the document is reached, this isn't a match. */
+ if( i >= awsIotJsonDocumentLength )
+ {
+ return false;
+ }
+ }
+
+ /* Value found. Set the output parameter. */
+ if( pAwsIotJsonValue != NULL )
+ {
+ *pAwsIotJsonValue = pAwsIotJsonDocument + i;
+ }
+
+ /* Calculate the value's length. */
+ switch( pAwsIotJsonDocument[ i ] )
+ {
+ /* Calculate length of a JSON string. */
+ case '\"':
+ /* Include the length of the opening and closing double quotes. */
+ jsonValueLength = 2;
+
+ /* Skip the opening double quote. */
+ i++;
+
+ /* If the end of the document is reached, this isn't a match. */
+ if( i >= awsIotJsonDocumentLength )
+ {
+ return false;
+ }
+
+ /* Add the length of all characters in the JSON string. */
+ while( pAwsIotJsonDocument[ i ] != '\"' )
+ {
+ /* Ignore escaped double quotes. */
+ if( ( pAwsIotJsonDocument[ i ] == '\\' ) &&
+ ( i + 1 < awsIotJsonDocumentLength ) &&
+ ( pAwsIotJsonDocument[ i + 1 ] == '\"' ) )
+ {
+ /* Skip the characters \" */
+ i += 2;
+ jsonValueLength += 2;
+ }
+ else
+ {
+ /* Add the length of a single character. */
+ i++;
+ jsonValueLength++;
+ }
+
+ /* If the end of the document is reached, this isn't a match. */
+ if( i >= awsIotJsonDocumentLength )
+ {
+ return false;
+ }
+ }
+
+ break;
+
+ /* Set the matching opening and closing characters of a JSON object or array.
+ * The length calculation is performed below. */
+ case '{':
+ openCharacter = '{';
+ closeCharacter = '}';
+ break;
+
+ case '[':
+ openCharacter = '[';
+ closeCharacter = ']';
+ break;
+
+ /* Calculate the length of a JSON primitive. */
+ default:
+
+ /* Skip the characters in the JSON value. The JSON value ends with a , or } */
+ while( pAwsIotJsonDocument[ i ] != ',' &&
+ pAwsIotJsonDocument[ i ] != '}' )
+ {
+ /* Any whitespace before a , or } means the JSON document is invalid. */
+ if( IS_WHITESPACE( pAwsIotJsonDocument, i ) )
+ {
+ return false;
+ }
+
+ i++;
+ jsonValueLength++;
+
+ /* If the end of the document is reached, this isn't a match. */
+ if( i >= awsIotJsonDocumentLength )
+ {
+ return false;
+ }
+ }
+
+ break;
+ }
+
+ /* Calculate the length of a JSON object or array. */
+ if( ( openCharacter != '\0' ) && ( closeCharacter != '\0' ) )
+ {
+ /* Include the length of the opening and closing characters. */
+ jsonValueLength = 2;
+
+ /* Skip the opening character. */
+ i++;
+
+ /* If the end of the document is reached, this isn't a match. */
+ if( i >= awsIotJsonDocumentLength )
+ {
+ return false;
+ }
+
+ /* Add the length of all characters in the JSON object or array. This
+ * includes the length of nested objects. */
+ while( pAwsIotJsonDocument[ i ] != closeCharacter ||
+ ( pAwsIotJsonDocument[ i ] == closeCharacter && ( nestingLevel != 0 || isWithinQuotes ) ) )
+ {
+ /* Check if its a quote so as to avoid considering the
+ * nested levels for opening and closing characters within
+ * quotes.
+ */
+ if( IS_QUOTE( pAwsIotJsonDocument, i ) )
+ {
+ /*Toggle the flag*/
+ isWithinQuotes = !isWithinQuotes;
+ }
+
+ /* Calculate the nesting levels only if not in quotes. */
+ if( !isWithinQuotes )
+ {
+ /* An opening character starts a nested object. */
+ if( pAwsIotJsonDocument[ i ] == openCharacter )
+ {
+ nestingLevel++;
+ }
+ /* A closing character ends a nested object. */
+ else if( pAwsIotJsonDocument[ i ] == closeCharacter )
+ {
+ nestingLevel--;
+ }
+ }
+
+ i++;
+ jsonValueLength++;
+
+ /* If the end of the document is reached, this isn't a match. */
+ if( i >= awsIotJsonDocumentLength )
+ {
+ return false;
+ }
+ }
+ }
+
+ /* JSON value length calculated; set the output parameter. */
+ if( pAwsIotJsonValueLength != NULL )
+ {
+ *pAwsIotJsonValueLength = jsonValueLength;
+ }
+
+ return true;
+ }
+
+ i++;
+ }
+
+ return false;
+}
+
+/*-----------------------------------------------------------*/