Skip to content

Commit

Permalink
Fix a few issues with the C generator (part 4) (OpenAPITools#20289)
Browse files Browse the repository at this point in the history
* [C] Deal with binary api parameters

With this change, the bodyParameters array can also be binary, so pass
its length around instead of relying on strlen().

* [C] Fix a few remaining enum issues

* [C] Install headers and include any_type.h header

* [C] Don't require C++ to compile C code

* [C] Test binary bodies and path enums in schemas

* Update samples

---------

Co-authored-by: Sam Bingner <sam@corellium.com>
  • Loading branch information
eafer and Sam Bingner authored Dec 12, 2024
1 parent 24ddb33 commit b7c7ed0
Show file tree
Hide file tree
Showing 38 changed files with 820 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ public void processOpts() {
// root folder
supportingFiles.add(new SupportingFile("CMakeLists.txt.mustache", "", "CMakeLists.txt"));
supportingFiles.add(new SupportingFile("Packing.cmake.mustache", "", "Packing.cmake"));
supportingFiles.add(new SupportingFile("cmake-config.mustache", "", "Config.cmake.in"));
supportingFiles.add(new SupportingFile("libcurl.licence.mustache", "", "libcurl.licence"));
supportingFiles.add(new SupportingFile("uncrustify-rules.cfg.mustache", "", "uncrustify-rules.cfg"));
supportingFiles.add(new SupportingFile("README.md.mustache", "", "README.md"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
cmake_minimum_required (VERSION 2.6...3.10.2)
project (CGenerator)
project (CGenerator C)

cmake_policy(SET CMP0063 NEW)

set(CMAKE_C_VISIBILITY_PRESET default)
set(CMAKE_CXX_VISIBILITY_PRESET default)
set(CMAKE_VISIBILITY_INLINES_HIDDEN OFF)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ end:
list_t *localVarHeaderType = {{#hasProduces}}list_createList();{{/hasProduces}}{{^hasProduces}}NULL;{{/hasProduces}}
list_t *localVarContentType = {{#hasConsumes}}list_createList();{{/hasConsumes}}{{^hasConsumes}}NULL;{{/hasConsumes}}
char *localVarBodyParameters = NULL;
size_t localVarBodyLength = 0;

// clear the error code from the previous api call
apiClient->response_code = 0;
Expand All @@ -121,12 +122,16 @@ end:
if(!{{paramName}})
goto end;
{{/isString}}
{{#isBinary}}
if(!{{paramName}})
goto end;
{{/isBinary}}
{{/pathParams}}

{{#pathParams}}

// Path Params
long sizeOfPathParams_{{{paramName}}} = {{#pathParams}}{{#isLong}}sizeof({{paramName}})+3{{/isLong}}{{#isString}}strlen({{paramName}})+3{{/isString}}{{^-last}} + {{/-last}}{{/pathParams}} + strlen("{ {{baseName}} }");
long sizeOfPathParams_{{{paramName}}} = {{#pathParams}}{{#isLong}}sizeof({{paramName}})+3{{/isLong}}{{#isString}}strlen({{^isEnum}}{{paramName}}{{/isEnum}}{{#isEnum}}{{{operationId}}}_{{enumName}}_ToString({{paramName}}){{/isEnum}})+3{{/isString}}{{^-last}} + {{/-last}}{{/pathParams}} + strlen("{ {{baseName}} }");
{{#isNumeric}}
if({{paramName}} == 0){
goto end;
Expand Down Expand Up @@ -180,13 +185,13 @@ end:

{{/isLong}}
{{#isString}}
if({{paramName}} == NULL) {
if({{paramName}} == {{#isEnum}}0{{/isEnum}}{{^isEnum}}NULL{{/isEnum}}) {
goto end;
}
char* localVarToReplace_{{paramName}} = malloc(sizeOfPathParams_{{paramName}});
sprintf(localVarToReplace_{{paramName}}, "{%s}", "{{baseName}}");

localVarPath = strReplace(localVarPath, localVarToReplace_{{paramName}}, {{paramName}});
localVarPath = strReplace(localVarPath, localVarToReplace_{{paramName}}, {{^isEnum}}{{paramName}}{{/isEnum}}{{#isEnum}}{{{operationId}}}_{{enumName}}_ToString({{paramName}}){{/isEnum}});
{{/isString}}
{{#isUuid}}
if({{paramName}} == NULL) {
Expand Down Expand Up @@ -331,20 +336,30 @@ end:
}
cJSON_AddItemToArray(localVarSingleItemJSON_{{paramName}}, localVar_{{paramName}});
localVarBodyParameters = {{{cJSONPrint}}}(localVarItemJSON_{{paramName}});
localVarBodyLength = strlen(localVarBodyParameters);
}
{{/isArray}}
{{^isArray}}
{{#isString}}
localVarBodyParameters = strdup({{paramName}});
localVarBodyLength = strlen(localVarBodyParameters);
{{/isString}}
{{^isString}}
{{#isBinary}}
localVarBodyParameters = malloc({{paramName}}->len);
memcpy(localVarBodyParameters, {{paramName}}->data, {{paramName}}->len);
localVarBodyLength = {{paramName}}->len;
{{/isBinary}}
{{^isBinary}}
cJSON *localVarSingleItemJSON_{{paramName}} = NULL;
if ({{paramName}} != NULL)
{
//string
//not string, not binary
localVarSingleItemJSON_{{paramName}} = {{dataType}}_convertToJSON({{paramName}});
localVarBodyParameters = {{{cJSONPrint}}}(localVarSingleItemJSON_{{paramName}});
localVarBodyLength = strlen(localVarBodyParameters);
}
{{/isBinary}}
{{/isString}}
{{/isArray}}
{{/bodyParam}}
Expand All @@ -362,6 +377,7 @@ end:
localVarHeaderType,
localVarContentType,
localVarBodyParameters,
localVarBodyLength,
"{{{httpMethod}}}");

{{#responses}}
Expand Down Expand Up @@ -503,10 +519,12 @@ end:
{{/isArray}}
{{^isArray}}
{{^isString}}
{{^isBinary}}
if (localVarSingleItemJSON_{{paramName}}) {
cJSON_Delete(localVarSingleItemJSON_{{paramName}});
localVarSingleItemJSON_{{paramName}} = NULL;
}
{{/isBinary}}
{{/isString}}
free(localVarBodyParameters);
{{/isArray}}
Expand Down Expand Up @@ -644,10 +662,12 @@ end:
free(localVarBodyParameters);
{{/isArray}}
{{^isArray}}
{{^isBinary}}
if (localVarSingleItemJSON_{{paramName}}) {
cJSON_Delete(localVarSingleItemJSON_{{paramName}});
localVarSingleItemJSON_{{paramName}} = NULL;
}
{{/isBinary}}
free(localVarBodyParameters);
{{/isArray}}
{{/bodyParams}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,10 @@ char *assembleHeaderField(char *key, char *value) {
return header;
}

void postData(CURL *handle, const char *bodyParameters) {
void postData(CURL *handle, const char *bodyParameters, size_t bodyParametersLength) {
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, bodyParameters);
curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE_LARGE,
(curl_off_t)strlen(bodyParameters));
(curl_off_t)bodyParametersLength);
}

int lengthOfKeyPair(keyValuePair_t *keyPair) {
Expand All @@ -270,7 +270,8 @@ void apiClient_invoke(apiClient_t *apiClient,
list_t *headerType,
list_t *contentType,
const char *bodyParameters,
const char *requestType) {
size_t bodyParametersLength,
const char *requestType) {
CURL *handle = curl_easy_init();
CURLcode res;
Expand Down Expand Up @@ -550,7 +551,7 @@ void apiClient_invoke(apiClient_t *apiClient,
{{/hasAuthMethods}}

if(bodyParameters != NULL) {
postData(handle, bodyParameters);
postData(handle, bodyParameters, bodyParametersLength);
}

res = curl_easy_perform(handle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ apiClient_t* apiClient_create_with_base_path(const char *basePath

void apiClient_free(apiClient_t *apiClient);

void apiClient_invoke(apiClient_t *apiClient,const char* operationParameter, list_t *queryParameters, list_t *headerParameters, list_t *formParameters,list_t *headerType,list_t *contentType, const char *bodyParameters, const char *requestType);
void apiClient_invoke(apiClient_t *apiClient,const char* operationParameter, list_t *queryParameters, list_t *headerParameters, list_t *formParameters,list_t *headerType,list_t *contentType, const char *bodyParameters, size_t bodyParametersLength, const char *requestType);

sslConfig_t *sslConfig_create(const char *clientCertFile, const char *clientKeyFile, const char *CACertFile, int insecureSkipTlsVerify);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@PACKAGE_INIT@

include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake)

check_required_components("@PROJECT_NAME@")
47 changes: 47 additions & 0 deletions modules/openapi-generator/src/test/resources/2_0/c/petstore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ paths:
required: true
schema:
type: string
format: binary
responses:
'200':
description: successful operation
Expand Down Expand Up @@ -348,6 +349,52 @@ paths:
- petstore_auth:
- 'write:pets'
- 'read:pets'
/store/feedback:
post:
tags:
- store
summary: Send us a feedback message
description: ''
operationId: sendFeedback
parameters:
- in: body
name: feedback
description: The feedback message to send
required: true
schema:
type: string
responses:
'200':
description: successful operation
schema:
type: string
description: Thank you message
'/store/rating/{rating}':
post:
tags:
- store
summary: How would you rate our service?
description: ''
operationId: sendRating
parameters:
- in: path
name: rating
description: The rating to submit
required: true
type: string
enum:
- Excellent
- Great
- Good
- Regular
- Bad
- Awful
responses:
'200':
description: successful operation
schema:
type: string
description: Thank you message
/store/daysWithoutIncident:
get:
tags:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
CMakeLists.txt
Config.cmake.in
Packing.cmake
README.md
api/DefaultAPI.c
Expand Down
3 changes: 1 addition & 2 deletions samples/client/others/c/bearerAuth/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
cmake_minimum_required (VERSION 2.6...3.10.2)
project (CGenerator)
project (CGenerator C)

cmake_policy(SET CMP0063 NEW)

set(CMAKE_C_VISIBILITY_PRESET default)
set(CMAKE_CXX_VISIBILITY_PRESET default)
set(CMAKE_VISIBILITY_INLINES_HIDDEN OFF)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

Expand Down
5 changes: 5 additions & 0 deletions samples/client/others/c/bearerAuth/Config.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@PACKAGE_INIT@

include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake)

check_required_components("@PROJECT_NAME@")
6 changes: 6 additions & 0 deletions samples/client/others/c/bearerAuth/api/DefaultAPI.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ DefaultAPI_privateGet(apiClient_t *apiClient)
list_t *localVarHeaderType = list_createList();
list_t *localVarContentType = NULL;
char *localVarBodyParameters = NULL;
size_t localVarBodyLength = 0;

// clear the error code from the previous api call
apiClient->response_code = 0;
Expand All @@ -46,6 +47,7 @@ DefaultAPI_privateGet(apiClient_t *apiClient)
localVarHeaderType,
localVarContentType,
localVarBodyParameters,
localVarBodyLength,
"GET");

// uncomment below to debug the error response
Expand Down Expand Up @@ -95,6 +97,7 @@ DefaultAPI_publicGet(apiClient_t *apiClient)
list_t *localVarHeaderType = list_createList();
list_t *localVarContentType = NULL;
char *localVarBodyParameters = NULL;
size_t localVarBodyLength = 0;

// clear the error code from the previous api call
apiClient->response_code = 0;
Expand All @@ -116,6 +119,7 @@ DefaultAPI_publicGet(apiClient_t *apiClient)
localVarHeaderType,
localVarContentType,
localVarBodyParameters,
localVarBodyLength,
"GET");

// uncomment below to debug the error response
Expand Down Expand Up @@ -165,6 +169,7 @@ DefaultAPI_usersGet(apiClient_t *apiClient)
list_t *localVarHeaderType = list_createList();
list_t *localVarContentType = NULL;
char *localVarBodyParameters = NULL;
size_t localVarBodyLength = 0;

// clear the error code from the previous api call
apiClient->response_code = 0;
Expand All @@ -186,6 +191,7 @@ DefaultAPI_usersGet(apiClient_t *apiClient)
localVarHeaderType,
localVarContentType,
localVarBodyParameters,
localVarBodyLength,
"GET");

// uncomment below to debug the error response
Expand Down
2 changes: 1 addition & 1 deletion samples/client/others/c/bearerAuth/include/apiClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ apiClient_t* apiClient_create_with_base_path(const char *basePath

void apiClient_free(apiClient_t *apiClient);

void apiClient_invoke(apiClient_t *apiClient,const char* operationParameter, list_t *queryParameters, list_t *headerParameters, list_t *formParameters,list_t *headerType,list_t *contentType, const char *bodyParameters, const char *requestType);
void apiClient_invoke(apiClient_t *apiClient,const char* operationParameter, list_t *queryParameters, list_t *headerParameters, list_t *formParameters,list_t *headerType,list_t *contentType, const char *bodyParameters, size_t bodyParametersLength, const char *requestType);

sslConfig_t *sslConfig_create(const char *clientCertFile, const char *clientKeyFile, const char *CACertFile, int insecureSkipTlsVerify);

Expand Down
9 changes: 5 additions & 4 deletions samples/client/others/c/bearerAuth/src/apiClient.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,10 @@ char *assembleHeaderField(char *key, char *value) {
return header;
}

void postData(CURL *handle, const char *bodyParameters) {
void postData(CURL *handle, const char *bodyParameters, size_t bodyParametersLength) {
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, bodyParameters);
curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE_LARGE,
(curl_off_t)strlen(bodyParameters));
(curl_off_t)bodyParametersLength);
}

int lengthOfKeyPair(keyValuePair_t *keyPair) {
Expand All @@ -186,7 +186,8 @@ void apiClient_invoke(apiClient_t *apiClient,
list_t *headerType,
list_t *contentType,
const char *bodyParameters,
const char *requestType) {
size_t bodyParametersLength,
const char *requestType) {
CURL *handle = curl_easy_init();
CURLcode res;

Expand Down Expand Up @@ -405,7 +406,7 @@ void apiClient_invoke(apiClient_t *apiClient,


if(bodyParameters != NULL) {
postData(handle, bodyParameters);
postData(handle, bodyParameters, bodyParametersLength);
}

res = curl_easy_perform(handle);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
CMakeLists.txt
Config.cmake.in
Packing.cmake
README.md
api/PetAPI.c
Expand Down
3 changes: 1 addition & 2 deletions samples/client/petstore/c-useJsonUnformatted/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
cmake_minimum_required (VERSION 2.6...3.10.2)
project (CGenerator)
project (CGenerator C)

cmake_policy(SET CMP0063 NEW)

set(CMAKE_C_VISIBILITY_PRESET default)
set(CMAKE_CXX_VISIBILITY_PRESET default)
set(CMAKE_VISIBILITY_INLINES_HIDDEN OFF)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

Expand Down
5 changes: 5 additions & 0 deletions samples/client/petstore/c-useJsonUnformatted/Config.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@PACKAGE_INIT@

include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake)

check_required_components("@PROJECT_NAME@")
2 changes: 2 additions & 0 deletions samples/client/petstore/c-useJsonUnformatted/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ Category | Method | HTTP request | Description
*StoreAPI* | [**StoreAPI_getInventory**](docs/StoreAPI.md#StoreAPI_getInventory) | **GET** /store/inventory | Returns pet inventories by status
*StoreAPI* | [**StoreAPI_getOrderById**](docs/StoreAPI.md#StoreAPI_getOrderById) | **GET** /store/order/{orderId} | Find purchase order by ID
*StoreAPI* | [**StoreAPI_placeOrder**](docs/StoreAPI.md#StoreAPI_placeOrder) | **POST** /store/order | Place an order for a pet
*StoreAPI* | [**StoreAPI_sendFeedback**](docs/StoreAPI.md#StoreAPI_sendFeedback) | **POST** /store/feedback | Send us a feedback message
*StoreAPI* | [**StoreAPI_sendRating**](docs/StoreAPI.md#StoreAPI_sendRating) | **POST** /store/rating/{rating} | How would you rate our service?
*UserAPI* | [**UserAPI_createUser**](docs/UserAPI.md#UserAPI_createUser) | **POST** /user | Create user
*UserAPI* | [**UserAPI_createUsersWithArrayInput**](docs/UserAPI.md#UserAPI_createUsersWithArrayInput) | **POST** /user/createWithArray | Creates list of users with given input array
*UserAPI* | [**UserAPI_createUsersWithListInput**](docs/UserAPI.md#UserAPI_createUsersWithListInput) | **POST** /user/createWithList | Creates list of users with given input array
Expand Down
Loading

0 comments on commit b7c7ed0

Please sign in to comment.