IOT-2274 : Json2Cbor support for swagger files - introspection
authorSrikrishna Gurugubelli <srikguru@microsoft.com>
Fri, 19 May 2017 23:46:07 +0000 (16:46 -0700)
committerRandeep Singh <randeep.s@samsung.com>
Mon, 22 May 2017 11:52:50 +0000 (11:52 +0000)
Change-Id: I0ae46770b08fb6b8c2d632189a060dc14e0e94c0
Signed-off-by: Srikrishna Gurugubelli <srikguru@microsoft.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/19541
Reviewed-by: Alex Kelley <alexke@microsoft.com>
Reviewed-by: Kevin Kane <kkane@microsoft.com>
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
resource/csdk/security/tool/json2cbor.c

index 978e026dd40aa015d2705f931236c3ccce2a8c84..ebc0a0879660d9a0061faa628cf36870f62caaed 100644 (file)
@@ -47,6 +47,7 @@
 //SVR database buffer block size
 
 #define DB_FILE_SIZE_BLOCK 1023
+#define DELTA_ERROR 0.0000001
 
 static OicSecPstat_t* JSONToPstatBin(const char * jsonStr);
 static OicSecDoxm_t* JSONToDoxmBin(const char * jsonStr);
@@ -79,44 +80,239 @@ static size_t GetJSONFileSize(const char *jsonFileName)
     return size;
 }
 
-static void ConvertJsonToCBOR(const char *jsonFileName, const char *cborFileName)
+static void ReadBufferFromFile(const char *fileName, uint8_t **buffer, size_t *bufferSize)
 {
-    char *jsonStr = NULL;
     FILE *fp = NULL;
-    FILE *fp1 = NULL;
-    uint8_t *aclCbor = NULL;
-    uint8_t *pstatCbor = NULL;
-    uint8_t *doxmCbor = NULL;
-    uint8_t *amaclCbor = NULL;
-    uint8_t *credCbor = NULL;
-    uint8_t *dpCbor = NULL;
-    cJSON *jsonRoot = NULL;
-    OCStackResult ret = OC_STACK_ERROR;
-    OCDeviceProperties *deviceProps = NULL;
+    size_t size = 0;
+    VERIFY_NOT_NULL(TAG, buffer, FATAL);
+    VERIFY_NOT_NULL(TAG, bufferSize, FATAL);
 
-    size_t size = GetJSONFileSize(jsonFileName);
+    size = GetJSONFileSize(fileName);
     if (0 == size)
     {
-        OIC_LOG (ERROR, TAG, "Failed converting to JSON");
+        OIC_LOG(ERROR, TAG, "Unable to get file size");
         return;
     }
 
-    jsonStr = (char *)OICMalloc(size + 1);
-    VERIFY_NOT_NULL(TAG, jsonStr, FATAL);
+    *buffer = (uint8_t *)OICMalloc(size + 1);
+    VERIFY_NOT_NULL(TAG, *buffer, FATAL);
 
-    fp = fopen(jsonFileName, "r");
+    fp = fopen(fileName, "r");
     if (fp)
     {
-        size_t bytesRead = fread(jsonStr, 1, size, fp);
-        jsonStr[bytesRead] = '\0';
+        size_t bytesRead = fread(*buffer, 1, size, fp);
+        (*buffer)[bytesRead] = '\0';
 
         OIC_LOG_V(DEBUG, TAG, "Read %" PRIuPTR " bytes", bytesRead);
         fclose(fp);
         fp = NULL;
+        *bufferSize = bytesRead + 1;
+    }
+    else
+    {
+        OIC_LOG(ERROR, TAG, "Unable to open JSON file!!");
+        OICFree(*buffer);
+        *buffer = NULL;
+        *bufferSize = 0;
+    }
+exit:
+    return;
+}
+
+static void WriteBufferToFile(const char *fileName, uint8_t *buffer, size_t size)
+{
+    if ((fileName == NULL) || (buffer == NULL) || (size == 0))
+    {
+        OIC_LOG(ERROR, TAG, "Invalid Parameters to WriteBufferToFile");
+        return;
+    }
+    FILE *fp = fopen(fileName, "wb");
+    if (fp)
+    {
+        size_t bytesWritten = fwrite(buffer, 1, size, fp);
+        if (bytesWritten == size)
+        {
+            OIC_LOG_V(DEBUG, TAG, "Written %" PRIuPTR " bytes", bytesWritten);
+        }
+        else
+        {
+            OIC_LOG_V(ERROR, TAG, "Failed writing %" PRIuPTR " bytes - Error: %" PRIi64,
+                      size, ferror(fp));
+        }
+        fclose(fp);
+        fp = NULL;
+    }
+    else
+    {
+        OIC_LOG_V(ERROR, TAG, "Error opening file [%s] for Write", fileName);
+    }
+}
+
+CborError EncodeJson(CborEncoder *encoder, cJSON *jsonObj)
+{
+    CborError err = CborNoError;
+    switch (jsonObj->type)
+    {
+    case cJSON_Object:
+        {
+            CborEncoder rootMap;
+            err = cbor_encoder_create_map(encoder, &rootMap, CborIndefiniteLength);
+            if (CborNoError == err)
+            {
+                cJSON *child = jsonObj->child;
+                while (child)
+                {
+                    err = cbor_encode_text_string(&rootMap, child->string, strlen(child->string));
+                    if (CborNoError != err)
+                    {
+                        break;
+                    }
+                    err = EncodeJson(&rootMap, child);
+                    if (CborNoError != err)
+                    {
+                        break;
+                    }
+                    child = child->next;
+                }
+            }
+            if (CborNoError == err)
+            {
+                err = cbor_encoder_close_container(encoder, &rootMap);
+            }
+        }
+        break;
+    case cJSON_Array:
+        {
+            CborEncoder cborArray;
+            err = cbor_encoder_create_array(encoder, &cborArray, CborIndefiniteLength);
+            if (CborNoError == err)
+            {
+                cJSON *child = jsonObj->child;
+                while (child)
+                {
+                    err = EncodeJson(&cborArray, child);
+                    if (CborNoError != err)
+                    {
+                        break;
+                    }
+                    child = child->next;
+                }
+            }
+            if (CborNoError == err)
+            {
+                err = cbor_encoder_close_container(encoder, &cborArray);
+            }
+        }
+        break;
+    case cJSON_String:
+        err = cbor_encode_text_string(encoder, jsonObj->valuestring, 
+                                      strlen(jsonObj->valuestring));
+        break;
+    case cJSON_Number:
+        if ((jsonObj->valuedouble - jsonObj->valueint) > DELTA_ERROR)
+        {
+            err = cbor_encode_double(encoder, jsonObj->valuedouble);
+        }
+        else
+        {
+            err = cbor_encode_int(encoder, jsonObj->valueint);
+        }
+        break;
+    case cJSON_NULL:
+        err = cbor_encode_null(encoder);
+        break;
+    case cJSON_True:
+        err = cbor_encode_boolean(encoder, true);
+        break;
+    case cJSON_False:
+        err = cbor_encode_boolean(encoder, false);
+        break;
+    default:
+        OIC_LOG(ERROR, TAG, "Unknown cjson type");
+        break;
+    }
+    return err;
+}
+
+void GenericConvertToCbor(char *jsonFileName, char *cborFileName)
+{
+    CborEncoder encoder;
+    CborError err;
+    cJSON *jsonObj = NULL;
+    uint8_t *buffer = NULL;
+
+    size_t size = 0;
+    char *jsonString = NULL;
+
+    ReadBufferFromFile(jsonFileName, (uint8_t **)&jsonString, &size);
+
+    if ((size == 0) || !jsonString)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to read from file");
+        goto exit;
+    }
+
+    jsonObj = cJSON_Parse(jsonString);
+    if (jsonObj == NULL)
+    {
+        OIC_LOG(ERROR, TAG, "Unable to parse JSON string");
+        goto exit;
+    }
+    size = strlen(jsonString);
+    size_t bufferSize = 0;
+    buffer = (uint8_t *)OICMalloc(size);
+    if (!buffer)
+    {
+        OIC_LOG(ERROR, TAG, "Unable to allocate enough memory");
+        goto exit;
+    }
+
+    cbor_encoder_init(&encoder, buffer, size, 0);
+    
+    err = EncodeJson(&encoder, jsonObj);
+    if (CborNoError != err)
+    {
+        OIC_LOG(ERROR, TAG, "Error encoding json");
+        goto exit;
     }
     else
     {
-        OIC_LOG (ERROR, TAG, "Unable to open JSON file!!");
+        bufferSize = cbor_encoder_get_buffer_size(&encoder, buffer);
+    }
+    WriteBufferToFile(cborFileName, buffer, bufferSize);
+exit:
+    if (jsonObj)
+    {
+        cJSON_Delete(jsonObj);
+    }
+    if (jsonString)
+    {
+        OICFree(jsonString);
+    }
+    if (buffer)
+    {
+        OICFree(buffer);
+    }
+}
+
+static void ConvertJsonToCBOR(const char *jsonFileName, const char *cborFileName)
+{
+    char *jsonStr = NULL;
+    uint8_t *aclCbor = NULL;
+    uint8_t *pstatCbor = NULL;
+    uint8_t *doxmCbor = NULL;
+    uint8_t *amaclCbor = NULL;
+    uint8_t *credCbor = NULL;
+    uint8_t *dpCbor = NULL;
+    cJSON *jsonRoot = NULL;
+    OCStackResult ret = OC_STACK_ERROR;
+    OCDeviceProperties *deviceProps = NULL;
+    size_t size = 0;
+
+    ReadBufferFromFile(jsonFileName, (uint8_t **)&jsonStr, &size);
+    if ((size == 0) || !jsonStr)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to read from file");
         goto exit;
     }
 
@@ -313,22 +509,7 @@ static void ConvertJsonToCBOR(const char *jsonFileName, const char *cborFileName
 
     size_t s = cbor_encoder_get_buffer_size(&encoder, outPayload);
     OIC_LOG_V(DEBUG, TAG, "Payload size %" PRIuPTR, s);
-
-    fp1 = fopen(cborFileName, "w");
-    if (fp1)
-    {
-        size_t bytesWritten = fwrite(outPayload, 1, s, fp1);
-        if (bytesWritten == s)
-        {
-            OIC_LOG_V(DEBUG, TAG, "Written %" PRIuPTR " bytes", bytesWritten);
-        }
-        else
-        {
-            OIC_LOG_V(ERROR, TAG, "Failed writing %" PRIuPTR " bytes", s);
-        }
-        fclose(fp1);
-        fp1 = NULL;
-    }
+    WriteBufferToFile(cborFileName, outPayload, s);
 exit:
 
     cJSON_Delete(jsonRoot);
@@ -1266,11 +1447,18 @@ int main(int argc, char* argv[])
         printf("JSON File Name: %s\n CBOR File Name: %s \n", argv[1], argv[2]);
         ConvertJsonToCBOR(argv[1], argv[2]);
     }
+    else if (argc == 4)
+    {
+        printf("Encoding Introspection File\n");
+        printf("JSON File Name: %s\n CBOR File Name: %s \n", argv[1], argv[2]);
+        GenericConvertToCbor(argv[1], argv[2]);
+    }
     else
     {
         printf("This program requires two inputs:\n");
         printf("1. First input is a json file tha will be converted to cbor. \n");
         printf("2. Second input is a resulting cbor file that will store converted cbor. \n");
-        printf("\t json2cbor <json_file_name> <cbor_file_name>. \n");
+        printf("3. Third input is a flag [-i] that indicates that encoding is for introspection file. \n");
+        printf("\t json2cbor <json_file_name> <cbor_file_name> [-i]. \n");
     }
 }