From b9f47cb3ab13e18a2cff6a7698af8797711626d2 Mon Sep 17 00:00:00 2001 From: Hemant Zope <42613258+zhemant@users.noreply.github.com> Date: Tue, 4 Sep 2018 09:59:28 +0200 Subject: [PATCH] Add string replace function for C generator (#908) * Add string replace function for C generator * Fixed replacement for variable only * Fixed problem for different datatypes of paramName * store return value of modified path * set str_replace variable to be same as original variable. * [C] Fixed coding style issues --- .../src/main/resources/C-libcurl/api.mustache | 76 ++- .../resources/C-libcurl/apiClient.c.mustache | 536 ++++++++++-------- 2 files changed, 339 insertions(+), 273 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/C-libcurl/api.mustache b/modules/openapi-generator/src/main/resources/C-libcurl/api.mustache index f96800649d61..660f1286239f 100644 --- a/modules/openapi-generator/src/main/resources/C-libcurl/api.mustache +++ b/modules/openapi-generator/src/main/resources/C-libcurl/api.mustache @@ -7,6 +7,11 @@ {{/imports}} #define MAX_BUFFER_LENGTH 4096 +#define intToStr(dst, src) \ + do {\ + char dst[64];\ + snprintf(dst, 64, "%ld", (long int)(src));\ +}while(0) {{#operations}} {{#operation}} @@ -19,19 +24,30 @@ // {{/notes}} {{#returnType}}{{{.}}}_t{{/returnType}}{{^returnType}}void{{/returnType}} *{{{classname}}}_{{{operationId}}}(apiClient_t *apiClient{{#allParams}}, {{{dataType}}} {{paramName}}{{/allParams}}) { - list_t *localVarQueryParameters, - list_t *localVarHeaderParameters, - list_t *localVarFormParameters, - char *localVarBodyParameters, + list_t *localVarQueryParameters, + list_t *localVarHeaderParameters, + list_t *localVarFormParameters, + char *localVarBodyParameters, // create the path - char *localVarPath = malloc(MAX_BUFFER_LENGTH); - snprintf(localVarPath, MAX_BUFFER_LENGTH, "{{{path}}}"); + char *localVarPath = malloc(MAX_BUFFER_LENGTH); + snprintf(localVarPath, MAX_BUFFER_LENGTH, "{{{path}}}"); {{#pathParams}} // TODO path parameter {{paramName}} ({{baseName}}) not yet supported // TODO base path = {{{basePath}}} - replace_str(localVarPath, "{" + "{{baseName}}" + "}", {{paramName}})// TODO need to revise + char* baseNameMod = malloc(strlen({{baseName}})+2); //baseNameMod free not yet implemented + snprintf(baseNameMod, strlen(baseName)+3, "%s%s%s", "{", {{baseName}}, "}"); + {{#paramName}} + {{#isLong}} + char buff[64]; + intToStr(buf, {{paramName}}); + localVarPath = strReplace(localVarPath, baseNameMod, buff); + {{/isLong}} + {{#isString}} + localVarPath = strReplace(localVarPath, baseNameMod, {{paramName}}); + {{/isString}} + {{/paramName}} {{/pathParams}} {{#headerParams}} @@ -57,25 +73,25 @@ localVarBodyParameters = cJSON_Print({{{paramName}}}JSONObject); {{/bodyParam}} - apiClient_invoke(apiClient, - "pet", - localVarPath, - localVarQueryParameters, - localVarHeaderParameters, - localVarFormParameters, - localVarBodyParameters, - "{{{httpMethod}}}"); + apiClient_invoke(apiClient, + "pet", + localVarPath, + localVarQueryParameters, + localVarHeaderParameters, + localVarFormParameters, + localVarBodyParameters, + "{{{httpMethod}}}"); - free(apiClient->dataReceived); - {{#allParams}} - {{^bodyParam}} - free({{{paramName}}}String); - {{/bodyParam}} - {{#bodyParam}} + free(apiClient->dataReceived); + {{#allParams}} + {{^bodyParam}} + free({{{paramName}}}String); + {{/bodyParam}} + {{#bodyParam}} free(localVarBodyParameters); - cJSON_Delete() - {{/bodyParam}} - {{/allParams}} + cJSON_Delete() + {{/bodyParam}} + {{/allParams}} {{#returnType}} localVar{{{returnType}}} = {{complexType}}_parseFromJSON(apiClient->dataReceived); if(localVar{{{returnType}}} == NULL) { @@ -85,13 +101,15 @@ cJSON_Delete(jsonObject); } - return localVar{{{returnType}}}; - {{/returnType}} + return localVar{{{returnType}}}; + {{/returnType}} {{^returnType}} - return; - {{/returnType}} + return; + {{/returnType}} } {{/operation}} -{{/operations}} \ No newline at end of file +{{/operations}} + + diff --git a/modules/openapi-generator/src/main/resources/C-libcurl/apiClient.c.mustache b/modules/openapi-generator/src/main/resources/C-libcurl/apiClient.c.mustache index 58a593e28f27..9cd6e1b32397 100644 --- a/modules/openapi-generator/src/main/resources/C-libcurl/apiClient.c.mustache +++ b/modules/openapi-generator/src/main/resources/C-libcurl/apiClient.c.mustache @@ -8,270 +8,318 @@ size_t writeDataCallback(void *buffer, size_t size, size_t nmemb, void *userp); apiClient_t *apiClient_create() { - curl_global_init(CURL_GLOBAL_ALL); - apiClient_t *apiClient = malloc(sizeof(apiClient_t)); - apiClient->basePath = "http://petstore.swagger.io:80/v2/"; - #ifdef BASIC_AUTH - apiClient->username = NULL; - apiClient->password = NULL; - #endif // BASIC_AUTH - #ifdef OAUTH2 - apiClient->accessToken = NULL; - #endif // OAUTH2 - return apiClient; + curl_global_init(CURL_GLOBAL_ALL); + apiClient_t *apiClient = malloc(sizeof(apiClient_t)); + apiClient->basePath = "http://petstore.swagger.io:80/v2/"; + #ifdef BASIC_AUTH + apiClient->username = NULL; + apiClient->password = NULL; + #endif // BASIC_AUTH + #ifdef OAUTH2 + apiClient->accessToken = NULL; + #endif // OAUTH2 + return apiClient; } void apiClient_free(apiClient_t *apiClient) { - free(apiClient); - curl_global_cleanup(); + free(apiClient); + curl_global_cleanup(); } void replaceSpaceWithPlus(char *stringToProcess) { - for(int i = 0; i < strlen(stringToProcess); i++) { - if(stringToProcess[i] == ' ') { - stringToProcess[i] = '+'; - } - } + for(int i = 0; i < strlen(stringToProcess); i++) { + if(stringToProcess[i] == ' ') { + stringToProcess[i] = '+'; + } + } } -char *assembleTargetUrl(char *basePath, - char *operationName, - char *operationParameter, - list_t *queryParameters) { - int neededBufferSizeForQueryParameters = 0; - listEntry_t *listEntry; - - if(queryParameters != NULL) { - list_ForEach(listEntry, queryParameters) { - keyValuePair_t *pair = listEntry->data; - neededBufferSizeForQueryParameters += - strlen(pair->key) + strlen(pair->value); - } - - neededBufferSizeForQueryParameters += - (queryParameters->count * 2); // each keyValuePair is separated by a = and a & except the last, but this makes up for the ? at the beginning - } - - int operationParameterLength = 0; - int basePathLength = strlen(basePath); - bool slashNeedsToBeAppendedToBasePath = false; - - if(operationParameter != NULL) { - operationParameterLength = (1 + strlen(operationParameter)); - } - if(basePath[strlen(basePath) - 1] != '/') { - slashNeedsToBeAppendedToBasePath = true; - basePathLength++; - } - - char *targetUrl = - malloc(strlen( - operationName) + neededBufferSizeForQueryParameters + basePathLength + operationParameterLength + 1 - ); - strcpy(targetUrl, basePath); - if(slashNeedsToBeAppendedToBasePath) { - strcat(targetUrl, "/"); - } - strcat(targetUrl, operationName); - if(operationParameter != NULL) { - strcat(targetUrl, "/"); - strcat(targetUrl, operationParameter); - } - - if(queryParameters != NULL) { - strcat(targetUrl, "?"); - list_ForEach(listEntry, queryParameters) { - keyValuePair_t *pair = listEntry->data; - replaceSpaceWithPlus(pair->key); - strcat(targetUrl, pair->key); - strcat(targetUrl, "="); - replaceSpaceWithPlus(pair->value); - strcat(targetUrl, pair->value); - if(listEntry->nextListEntry != NULL) { - strcat(targetUrl, "&"); - } - } - } - - return targetUrl; +char *assembleTargetUrl(char *basePath, + char *operationName, + char *operationParameter, + list_t *queryParameters) { + int neededBufferSizeForQueryParameters = 0; + listEntry_t *listEntry; + + if(queryParameters != NULL) { + list_ForEach(listEntry, queryParameters) { + keyValuePair_t *pair = listEntry->data; + neededBufferSizeForQueryParameters += + strlen(pair->key) + strlen(pair->value); + } + + neededBufferSizeForQueryParameters += + (queryParameters->count * 2); // each keyValuePair is separated by a = and a & except the last, but this makes up for the ? at the beginning + } + + int operationParameterLength = 0; + int basePathLength = strlen(basePath); + bool slashNeedsToBeAppendedToBasePath = false; + + if(operationParameter != NULL) { + operationParameterLength = (1 + strlen(operationParameter)); + } + if(basePath[strlen(basePath) - 1] != '/') { + slashNeedsToBeAppendedToBasePath = true; + basePathLength++; + } + + char *targetUrl = + malloc(strlen( + operationName) + neededBufferSizeForQueryParameters + basePathLength + operationParameterLength + 1 + ); + strcpy(targetUrl, basePath); + if(slashNeedsToBeAppendedToBasePath) { + strcat(targetUrl, "/"); + } + strcat(targetUrl, operationName); + if(operationParameter != NULL) { + strcat(targetUrl, "/"); + strcat(targetUrl, operationParameter); + } + + if(queryParameters != NULL) { + strcat(targetUrl, "?"); + list_ForEach(listEntry, queryParameters) { + keyValuePair_t *pair = listEntry->data; + replaceSpaceWithPlus(pair->key); + strcat(targetUrl, pair->key); + strcat(targetUrl, "="); + replaceSpaceWithPlus(pair->value); + strcat(targetUrl, pair->value); + if(listEntry->nextListEntry != NULL) { + strcat(targetUrl, "&"); + } + } + } + + return targetUrl; } char *assembleHeaderField(char *key, char *value) { - char *header = malloc(strlen(key) + strlen(value) + 3); + char *header = malloc(strlen(key) + strlen(value) + 3); - strcpy(header, key), - strcat(header, ": "); - strcat(header, value); + strcpy(header, key), + strcat(header, ": "); + strcat(header, value); - return header; + return header; } void postData(CURL *handle, char *bodyParameters) { - curl_easy_setopt(handle, CURLOPT_POSTFIELDS, bodyParameters); - curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE_LARGE, - strlen(bodyParameters)); + curl_easy_setopt(handle, CURLOPT_POSTFIELDS, bodyParameters); + curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE_LARGE, + strlen(bodyParameters)); } -void apiClient_invoke(apiClient_t *apiClient, - char *operationName, - char *operationParameter, - list_t *queryParameters, - list_t *headerParameters, - list_t *formParameters, - char *bodyParameters, - char *requestType) { - CURL *handle = curl_easy_init(); - CURLcode res; - - if(handle) { - listEntry_t *listEntry; - curl_mime *mime = NULL; - struct curl_slist *headers = NULL; - - headers = - curl_slist_append(headers, "accept: application/json"); - headers = curl_slist_append(headers, - "Content-Type: application/json"); - if(requestType != NULL) { - curl_easy_setopt(handle, - CURLOPT_CUSTOMREQUEST, - requestType); - } - if(formParameters != NULL) { - mime = curl_mime_init(handle); - - list_ForEach(listEntry, formParameters) { - keyValuePair_t *keyValuePair = listEntry->data; - if((keyValuePair->key != NULL) && - (keyValuePair->value != NULL) ) - { - curl_mimepart *part = curl_mime_addpart( - mime); - curl_mime_data(part, - keyValuePair->key, - CURL_ZERO_TERMINATED); - curl_mime_name(part, - keyValuePair->value); - } - } - - curl_easy_setopt(handle, CURLOPT_MIMEPOST, mime); - } - - list_ForEach(listEntry, headerParameters) { - keyValuePair_t *keyValuePair = listEntry->data; - if((keyValuePair->key != NULL) && - (keyValuePair->value != NULL) ) - { - char *headerValueToWrite = - assembleHeaderField( - keyValuePair->key, - keyValuePair->value); - curl_slist_append(headers, headerValueToWrite); - free(headerValueToWrite); - } - } - // this would only be generated for apiKey authentication - #ifdef API_KEY - list_ForEach(listEntry, apiClient->apiKeys) { - keyValuePair_t *apiKey = listEntry->data; - if((apiKey->key != NULL) && - (apiKey->value != NULL) ) - { - char *headerValueToWrite = - assembleHeaderField( - apiKey->key, - apiKey->value); - curl_slist_append(headers, headerValueToWrite); - free(headerValueToWrite); - } - } - #endif // API_KEY - - char *targetUrl = - assembleTargetUrl(apiClient->basePath, - operationName, - operationParameter, - queryParameters); - - curl_easy_setopt(handle, CURLOPT_URL, targetUrl); - curl_easy_setopt(handle, - CURLOPT_WRITEFUNCTION, - writeDataCallback); - curl_easy_setopt(handle, - CURLOPT_WRITEDATA, - &apiClient->dataReceived); - curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); - - // this would only be generated for OAuth2 authentication - #ifdef OAUTH2 - if(apiClient->accessToken != NULL) { - // curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_BEARER); - curl_easy_setopt(handle, - CURLOPT_XOAUTH2_BEARER, - apiClient->accessToken); - } - #endif - - - // this would only be generated for basic authentication: - #ifdef BASIC_AUTH - char *authenticationToken; - - if((apiClient->username != NULL) && - (apiClient->password != NULL) ) - { - authenticationToken = malloc(strlen( - apiClient->username) + - strlen( - apiClient->password) + - 2); - sprintf(authenticationToken, - "%s:%s", - apiClient->username, - apiClient->password); - - curl_easy_setopt(handle, - CURLOPT_HTTPAUTH, - CURLAUTH_BASIC); - curl_easy_setopt(handle, - CURLOPT_USERPWD, - authenticationToken); - } - - #endif // BASIC_AUTH - - if(bodyParameters != NULL) { - postData(handle, bodyParameters); - } - - res = curl_easy_perform(handle); - - curl_slist_free_all(headers); - - free(targetUrl); - - if(res != CURLE_OK) { - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); - } - #ifdef BASIC_AUTH - if((apiClient->username != NULL) && - (apiClient->password != NULL) ) - { - free(authenticationToken); - } - #endif // BASIC_AUTH - curl_easy_cleanup(handle); - if(formParameters != NULL) { - curl_mime_free(mime); - } - } +void apiClient_invoke(apiClient_t *apiClient, + char *operationName, + char *operationParameter, + list_t *queryParameters, + list_t *headerParameters, + list_t *formParameters, + char *bodyParameters, + char *requestType) { + CURL *handle = curl_easy_init(); + CURLcode res; + + if(handle) { + listEntry_t *listEntry; + curl_mime *mime = NULL; + struct curl_slist *headers = NULL; + + headers = + curl_slist_append(headers, "accept: application/json"); + headers = curl_slist_append(headers, + "Content-Type: application/json"); + if(requestType != NULL) { + curl_easy_setopt(handle, + CURLOPT_CUSTOMREQUEST, + requestType); + } + if(formParameters != NULL) { + mime = curl_mime_init(handle); + + list_ForEach(listEntry, formParameters) { + keyValuePair_t *keyValuePair = listEntry->data; + if((keyValuePair->key != NULL) && + (keyValuePair->value != NULL) ) + { + curl_mimepart *part = curl_mime_addpart( + mime); + curl_mime_data(part, + keyValuePair->key, + CURL_ZERO_TERMINATED); + curl_mime_name(part, + keyValuePair->value); + } + } + + curl_easy_setopt(handle, CURLOPT_MIMEPOST, mime); + } + + list_ForEach(listEntry, headerParameters) { + keyValuePair_t *keyValuePair = listEntry->data; + if((keyValuePair->key != NULL) && + (keyValuePair->value != NULL) ) + { + char *headerValueToWrite = + assembleHeaderField( + keyValuePair->key, + keyValuePair->value); + curl_slist_append(headers, headerValueToWrite); + free(headerValueToWrite); + } + } + // this would only be generated for apiKey authentication + #ifdef API_KEY + list_ForEach(listEntry, apiClient->apiKeys) { + keyValuePair_t *apiKey = listEntry->data; + if((apiKey->key != NULL) && + (apiKey->value != NULL) ) + { + char *headerValueToWrite = + assembleHeaderField( + apiKey->key, + apiKey->value); + curl_slist_append(headers, headerValueToWrite); + free(headerValueToWrite); + } + } + #endif // API_KEY + + char *targetUrl = + assembleTargetUrl(apiClient->basePath, + operationName, + operationParameter, + queryParameters); + + curl_easy_setopt(handle, CURLOPT_URL, targetUrl); + curl_easy_setopt(handle, + CURLOPT_WRITEFUNCTION, + writeDataCallback); + curl_easy_setopt(handle, + CURLOPT_WRITEDATA, + &apiClient->dataReceived); + curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); + + // this would only be generated for OAuth2 authentication + #ifdef OAUTH2 + if(apiClient->accessToken != NULL) { + // curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_BEARER); + curl_easy_setopt(handle, + CURLOPT_XOAUTH2_BEARER, + apiClient->accessToken); + } + #endif + + + // this would only be generated for basic authentication: + #ifdef BASIC_AUTH + char *authenticationToken; + + if((apiClient->username != NULL) && + (apiClient->password != NULL) ) + { + authenticationToken = malloc(strlen( + apiClient->username) + + strlen( + apiClient->password) + + 2); + sprintf(authenticationToken, + "%s:%s", + apiClient->username, + apiClient->password); + + curl_easy_setopt(handle, + CURLOPT_HTTPAUTH, + CURLAUTH_BASIC); + curl_easy_setopt(handle, + CURLOPT_USERPWD, + authenticationToken); + } + + #endif // BASIC_AUTH + + if(bodyParameters != NULL) { + postData(handle, bodyParameters); + } + + res = curl_easy_perform(handle); + + curl_slist_free_all(headers); + + free(targetUrl); + + if(res != CURLE_OK) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + } + #ifdef BASIC_AUTH + if((apiClient->username != NULL) && + (apiClient->password != NULL) ) + { + free(authenticationToken); + } + #endif // BASIC_AUTH + curl_easy_cleanup(handle); + if(formParameters != NULL) { + curl_mime_free(mime); + } + } } size_t writeDataCallback(void *buffer, size_t size, size_t nmemb, void *userp) { - *(char **) userp = strdup(buffer); + *(char **) userp = strdup(buffer); + + return size * nmemb; +} + +char *strReplace(char *orig, char *rep, char *with) { + char *result; // the return string + char *ins; // the next insert point + char *tmp; // varies + int lenRep; // length of rep (the string to remove) + int lenWith; // length of with (the string to replace rep with) + int lenFront; // distance between rep and end of last rep + int count; // number of replacements + + // sanity checks and initialization + if (!orig || !rep) + return NULL; + lenRep = strlen(rep); + if (lenRep == 0) + return NULL; // empty rep causes infinite loop during count + if (!with) + with = ""; + lenWith = strlen(with); + + // count the number of replacements needed + ins = orig; + for (count = 0; tmp = strstr(ins, rep); ++count) { + ins = tmp + lenRep; + } + + tmp = result = malloc(strlen(orig) + (lenWith - lenRep) * count + 1); + + if (!result) + return NULL; + + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) { + ins = strstr(orig, rep); + lenFront = ins - orig; + tmp = strncpy(tmp, orig, lenFront) + lenFront; + tmp = strcpy(tmp, with) + lenWith; + orig += lenFront + lenRep; // move to next "end of rep" + } + strcpy(tmp, orig); + return result; +} + - return size * nmemb; -} \ No newline at end of file