Skip to content

Commit 5fd724f

Browse files
C client generator improvements to support petstore. Solves #5836 (#5837)
* C client generator improvement to support: openapi-generator/modules/openapi-generator/src/test/resources/3_0/petstore.yaml * Improvements to the C client generator: - moved base64* from apiClient.c to binary.h/binary.c - changed CR/LF to LF in binary.h/binary.c * C client generator: better support for base64encode / base64decode
1 parent ff0c730 commit 5fd724f

File tree

25 files changed

+216
-131
lines changed

25 files changed

+216
-131
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CLibcurlClientCodegen.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,12 @@ public void processOpts() {
223223
supportingFiles.add(new SupportingFile("apiClient.c.mustache", "src", "apiClient.c"));
224224
supportingFiles.add(new SupportingFile("apiKey.c.mustache", "src", "apiKey.c"));
225225
supportingFiles.add(new SupportingFile("list.c.mustache", "src", "list.c"));
226+
supportingFiles.add(new SupportingFile("binary.c.mustache", "src", "binary.c"));
226227
// include folder
227228
supportingFiles.add(new SupportingFile("apiClient.h.mustache", "include", "apiClient.h"));
228229
supportingFiles.add(new SupportingFile("keyValuePair.h.mustache", "include", "keyValuePair.h"));
229230
supportingFiles.add(new SupportingFile("list.h.mustache", "include", "list.h"));
231+
supportingFiles.add(new SupportingFile("binary.h.mustache", "include", "binary.h"));
230232
// external folder
231233
supportingFiles.add(new SupportingFile("cJSON.licence.mustache", "external", "cJSON.licence"));
232234
supportingFiles.add(new SupportingFile("cJSON.c.mustache", "external", "cJSON.c"));
@@ -377,14 +379,14 @@ public String toExampleValue(Schema schema) {
377379
example = "\"2013-10-20T19:20:30+01:00\"";
378380
return example;
379381
} else if (ModelUtils.isBinarySchema(schema)) {
380-
example = "bytes(b'blah')";
382+
example = "instantiate_binary_t(\"blah\", 5)";
381383
return example;
382384
} else if (ModelUtils.isByteArraySchema(schema)) {
383385
example = "YQ==";
384386
} else if (ModelUtils.isStringSchema(schema)) {
385387
// a BigDecimal:
386388
if ("Number".equalsIgnoreCase(schema.getFormat())) {return "1";}
387-
if (StringUtils.isNotBlank(schema.getPattern())) return "'a'"; // I cheat here, since it would be too complicated to generate a string from a regexp
389+
if (StringUtils.isNotBlank(schema.getPattern())) return "\"a\""; // I cheat here, since it would be too complicated to generate a string from a regexp
388390
int len = 0;
389391
if (null != schema.getMinLength()) len = schema.getMinLength().intValue();
390392
if (len < 1) len = 1;

modules/openapi-generator/src/main/resources/C-libcurl/CMakeLists.txt.mustache

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@ set(CMAKE_CXX_VISIBILITY_PRESET default)
88
set(CMAKE_VISIBILITY_INLINES_HIDDEN OFF)
99
set(CMAKE_BUILD_TYPE Debug)
1010

11+
find_package(OpenSSL)
12+
13+
if (OPENSSL_FOUND)
14+
message (STATUS "OPENSSL found")
15+
set (CMAKE_C_FLAGS "-DOPENSSL")
16+
include_directories(${OPENSSL_INCLUDE_DIR})
17+
include_directories(${OPENSSL_INCLUDE_DIRS})
18+
link_directories(${OPENSSL_LIBRARIES})
19+
message(STATUS "Using OpenSSL ${OPENSSL_VERSION}")
20+
else()
21+
message (STATUS "OpenSSL Not found.")
22+
endif()
23+
1124
set(pkgName "{{projectName}}")
1225

1326
find_package(CURL 7.58.0 REQUIRED)
@@ -22,6 +35,7 @@ set(SRCS
2235
src/list.c
2336
src/apiKey.c
2437
src/apiClient.c
38+
src/binary.c
2539
external/cJSON.c
2640
model/object.c
2741
{{#models}}
@@ -42,6 +56,7 @@ set(SRCS
4256
set(HDRS
4357
include/apiClient.h
4458
include/list.h
59+
include/binary.h
4560
include/keyValuePair.h
4661
external/cJSON.h
4762
model/object.h

modules/openapi-generator/src/main/resources/C-libcurl/api-header.mustache

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "../include/list.h"
55
#include "../external/cJSON.h"
66
#include "../include/keyValuePair.h"
7+
#include "../include/binary.h"
78
{{#imports}}{{{import}}}
89
{{/imports}}
910

modules/openapi-generator/src/main/resources/C-libcurl/apiClient.c.mustache

Lines changed: 12 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
#include <string.h>
44
#include <stdio.h>
55
#include "../include/apiClient.h"
6-
#ifdef OPENSSL
7-
#include "openssl/pem.h"
8-
#endif
96

107
size_t writeDataCallback(void *buffer, size_t size, size_t nmemb, void *userp);
118

@@ -26,7 +23,7 @@ apiClient_t *apiClient_create() {
2623
apiClient->accessToken = NULL;
2724
{{/isOAuth}}
2825
{{#isApiKey}}
29-
apiClient->apiKeys = NULL;
26+
apiClient->apiKeys_{{name}} = NULL;
3027
{{/isApiKey}}
3128
{{/authMethods}}
3229
{{/hasAuthMethods}}
@@ -39,7 +36,7 @@ apiClient_t *apiClient_create_with_base_path(const char *basePath
3936
{{#hasAuthMethods}}
4037
{{#authMethods}}
4138
{{#isApiKey}}
42-
, list_t *apiKeys
39+
, list_t *apiKeys_{{name}}
4340
{{/isApiKey}}
4441
{{/authMethods}}
4542
{{/hasAuthMethods}}
@@ -70,16 +67,16 @@ apiClient_t *apiClient_create_with_base_path(const char *basePath
7067
apiClient->accessToken = NULL;
7168
{{/isOAuth}}
7269
{{#isApiKey}}
73-
if(apiKeys!= NULL) {
74-
apiClient->apiKeys = list_create();
70+
if(apiKeys_{{name}}!= NULL) {
71+
apiClient->apiKeys_{{name}} = list_create();
7572
listEntry_t *listEntry = NULL;
76-
list_ForEach(listEntry, apiKeys) {
73+
list_ForEach(listEntry, apiKeys_{{name}}) {
7774
keyValuePair_t *pair = listEntry->data;
7875
keyValuePair_t *pairDup = keyValuePair_create(strdup(pair->key), strdup(pair->value));
79-
list_addElement(apiClient->apiKeys, pairDup);
76+
list_addElement(apiClient->apiKeys_{{name}}, pairDup);
8077
}
8178
}else{
82-
apiClient->apiKeys = NULL;
79+
apiClient->apiKeys_{{name}} = NULL;
8380
}
8481
{{/isApiKey}}
8582
{{/authMethods}}
@@ -108,9 +105,9 @@ void apiClient_free(apiClient_t *apiClient) {
108105
}
109106
{{/isOAuth}}
110107
{{#isApiKey}}
111-
if(apiClient->apiKeys) {
108+
if(apiClient->apiKeys_{{name}}) {
112109
listEntry_t *listEntry = NULL;
113-
list_ForEach(listEntry, apiClient->apiKeys) {
110+
list_ForEach(listEntry, apiClient->apiKeys_{{name}}) {
114111
keyValuePair_t *pair = listEntry->data;
115112
if(pair->key){
116113
free(pair->key);
@@ -120,7 +117,7 @@ void apiClient_free(apiClient_t *apiClient) {
120117
}
121118
keyValuePair_free(pair);
122119
}
123-
list_free(apiClient->apiKeys);
120+
list_free(apiClient->apiKeys_{{name}});
124121
}
125122
{{/isApiKey}}
126123
{{/authMethods}}
@@ -440,9 +437,9 @@ void apiClient_invoke(apiClient_t *apiClient,
440437
{{#authMethods}}
441438
{{#isApiKey}}
442439
// this would only be generated for apiKey authentication
443-
if (apiClient->apiKeys != NULL)
440+
if (apiClient->apiKeys_{{name}} != NULL)
444441
{
445-
list_ForEach(listEntry, apiClient->apiKeys) {
442+
list_ForEach(listEntry, apiClient->apiKeys_{{name}}) {
446443
keyValuePair_t *apiKey = listEntry->data;
447444
if((apiKey->key != NULL) &&
448445
(apiKey->value != NULL) )
@@ -616,40 +613,3 @@ char *strReplace(char *orig, char *rep, char *with) {
616613
return result;
617614
}
618615

619-
char *base64encode (const void *b64_encode_this, int encode_this_many_bytes){
620-
#ifdef OPENSSL
621-
BIO *b64_bio, *mem_bio; //Declares two OpenSSL BIOs: a base64 filter and a memory BIO.
622-
BUF_MEM *mem_bio_mem_ptr; //Pointer to a "memory BIO" structure holding our base64 data.
623-
b64_bio = BIO_new(BIO_f_base64()); //Initialize our base64 filter BIO.
624-
mem_bio = BIO_new(BIO_s_mem()); //Initialize our memory sink BIO.
625-
BIO_push(b64_bio, mem_bio); //Link the BIOs by creating a filter-sink BIO chain.
626-
BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); //No newlines every 64 characters or less.
627-
BIO_write(b64_bio, b64_encode_this, encode_this_many_bytes); //Records base64 encoded data.
628-
BIO_flush(b64_bio); //Flush data. Necessary for b64 encoding, because of pad characters.
629-
BIO_get_mem_ptr(mem_bio, &mem_bio_mem_ptr); //Store address of mem_bio's memory structure.
630-
BIO_set_close(mem_bio, BIO_NOCLOSE); //Permit access to mem_ptr after BIOs are destroyed.
631-
BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one).
632-
BUF_MEM_grow(mem_bio_mem_ptr, (*mem_bio_mem_ptr).length + 1); //Makes space for end null.
633-
(*mem_bio_mem_ptr).data[(*mem_bio_mem_ptr).length] = '\0'; //Adds null-terminator to tail.
634-
return (*mem_bio_mem_ptr).data; //Returns base-64 encoded data. (See: "buf_mem_st" struct).
635-
#endif
636-
}
637-
638-
char *base64decode (const void *b64_decode_this, int decode_this_many_bytes, int *decoded_bytes){
639-
#ifdef OPENSSL
640-
BIO *b64_bio, *mem_bio; //Declares two OpenSSL BIOs: a base64 filter and a memory BIO.
641-
char *base64_decoded = calloc( (decode_this_many_bytes*3)/4+1, sizeof(char) ); //+1 = null.
642-
b64_bio = BIO_new(BIO_f_base64()); //Initialize our base64 filter BIO.
643-
mem_bio = BIO_new(BIO_s_mem()); //Initialize our memory source BIO.
644-
BIO_write(mem_bio, b64_decode_this, decode_this_many_bytes); //Base64 data saved in source.
645-
BIO_push(b64_bio, mem_bio); //Link the BIOs by creating a filter-source BIO chain.
646-
BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines.
647-
int decoded_byte_index = 0; //Index where the next base64_decoded byte should be written.
648-
while ( 0 < BIO_read(b64_bio, base64_decoded+decoded_byte_index, 1) ){ //Read byte-by-byte.
649-
decoded_byte_index++; //Increment the index until read of BIO decoded data is complete.
650-
} //Once we're done reading decoded data, BIO_read returns -1 even though there's no error.
651-
BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one).
652-
*decoded_bytes = decoded_byte_index;
653-
return base64_decoded; //Returns base-64 decoded data with trailing null terminator.
654-
#endif
655-
}

modules/openapi-generator/src/main/resources/C-libcurl/apiClient.h.mustache

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <stdint.h>
99
#include "../include/list.h"
1010
#include "../include/keyValuePair.h"
11+
#include "../include/binary.h"
1112

1213
typedef struct sslConfig_t {
1314
char *clientCertFile; /* client certificate */
@@ -32,26 +33,20 @@ typedef struct apiClient_t {
3233
char *accessToken;
3334
{{/isOAuth}}
3435
{{#isApiKey}}
35-
list_t *apiKeys;
36+
list_t *apiKeys_{{name}};
3637
{{/isApiKey}}
3738
{{/authMethods}}
3839
{{/hasAuthMethods}}
3940
} apiClient_t;
4041

41-
typedef struct binary_t
42-
{
43-
uint8_t* data;
44-
unsigned int len;
45-
} binary_t;
46-
4742
apiClient_t* apiClient_create();
4843

4944
apiClient_t* apiClient_create_with_base_path(const char *basePath
5045
, sslConfig_t *sslConfig
5146
{{#hasAuthMethods}}
5247
{{#authMethods}}
5348
{{#isApiKey}}
54-
, list_t *apiKeys
49+
, list_t *apiKeys_{{name}}
5550
{{/isApiKey}}
5651
{{/authMethods}}
5752
{{/hasAuthMethods}}
@@ -67,8 +62,4 @@ void sslConfig_free(sslConfig_t *sslConfig);
6762

6863
char *strReplace(char *orig, char *rep, char *with);
6964

70-
char *base64encode(const void *b64_encode_this, int encode_this_many_bytes);
71-
72-
char *base64decode(const void *b64_decode_this, int decode_this_many_bytes);
73-
7465
#endif // INCLUDE_API_CLIENT_H
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include <stdlib.h>
2+
#include <string.h>
3+
#include "../include/binary.h"
4+
#ifdef OPENSSL
5+
#include "openssl/pem.h"
6+
#endif
7+
8+
binary_t* instantiate_binary_t(char* data, int len) {
9+
binary_t* ret = malloc(sizeof(struct binary_t));
10+
ret->len=len;
11+
ret->data = malloc(len);
12+
memcpy(ret->data, data, len);
13+
return ret;
14+
}
15+
16+
char *base64encode (const void *b64_encode_this, int encode_this_many_bytes){
17+
#ifdef OPENSSL
18+
BIO *b64_bio, *mem_bio; //Declares two OpenSSL BIOs: a base64 filter and a memory BIO.
19+
BUF_MEM *mem_bio_mem_ptr; //Pointer to a "memory BIO" structure holding our base64 data.
20+
b64_bio = BIO_new(BIO_f_base64()); //Initialize our base64 filter BIO.
21+
mem_bio = BIO_new(BIO_s_mem()); //Initialize our memory sink BIO.
22+
BIO_push(b64_bio, mem_bio); //Link the BIOs by creating a filter-sink BIO chain.
23+
BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); //No newlines every 64 characters or less.
24+
BIO_write(b64_bio, b64_encode_this, encode_this_many_bytes); //Records base64 encoded data.
25+
BIO_flush(b64_bio); //Flush data. Necessary for b64 encoding, because of pad characters.
26+
BIO_get_mem_ptr(mem_bio, &mem_bio_mem_ptr); //Store address of mem_bio's memory structure.
27+
BIO_set_close(mem_bio, BIO_NOCLOSE); //Permit access to mem_ptr after BIOs are destroyed.
28+
BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one).
29+
BUF_MEM_grow(mem_bio_mem_ptr, (*mem_bio_mem_ptr).length + 1); //Makes space for end null.
30+
(*mem_bio_mem_ptr).data[(*mem_bio_mem_ptr).length] = '\0'; //Adds null-terminator to tail.
31+
return (*mem_bio_mem_ptr).data; //Returns base-64 encoded data. (See: "buf_mem_st" struct).
32+
#else // OPENSSL
33+
#warning Data will not be encoded. If you want to use function "base64encode", please define "-DOPENSSL" when building the library.
34+
return NULL;
35+
#endif // OPENSSL
36+
}
37+
38+
char *base64decode (const void *b64_decode_this, int decode_this_many_bytes, int *decoded_bytes){
39+
#ifdef OPENSSL
40+
BIO *b64_bio, *mem_bio; //Declares two OpenSSL BIOs: a base64 filter and a memory BIO.
41+
char *base64_decoded = calloc( (decode_this_many_bytes*3)/4+1, sizeof(char) ); //+1 = null.
42+
b64_bio = BIO_new(BIO_f_base64()); //Initialize our base64 filter BIO.
43+
mem_bio = BIO_new(BIO_s_mem()); //Initialize our memory source BIO.
44+
BIO_write(mem_bio, b64_decode_this, decode_this_many_bytes); //Base64 data saved in source.
45+
BIO_push(b64_bio, mem_bio); //Link the BIOs by creating a filter-source BIO chain.
46+
BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines.
47+
int decoded_byte_index = 0; //Index where the next base64_decoded byte should be written.
48+
while ( 0 < BIO_read(b64_bio, base64_decoded+decoded_byte_index, 1) ){ //Read byte-by-byte.
49+
decoded_byte_index++; //Increment the index until read of BIO decoded data is complete.
50+
} //Once we're done reading decoded data, BIO_read returns -1 even though there's no error.
51+
BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one).
52+
*decoded_bytes = decoded_byte_index;
53+
return base64_decoded; //Returns base-64 decoded data with trailing null terminator.
54+
#else // OPENSSL
55+
#warning Data will not be decoded. If you want to use function "base64decode", please define "-DOPENSSL" when building the library.
56+
return NULL;
57+
#endif // OPENSSL
58+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef INCLUDE_BINARY_H
2+
#define INCLUDE_BINARY_H
3+
4+
#include <stdint.h>
5+
6+
typedef struct binary_t
7+
{
8+
uint8_t* data;
9+
unsigned int len;
10+
} binary_t;
11+
12+
binary_t* instantiate_binary_t(char* data, int len);
13+
14+
char *base64encode(const void *b64_encode_this, int encode_this_many_bytes);
15+
16+
char *base64decode(const void *b64_decode_this, int decode_this_many_bytes, int *decoded_bytes);
17+
18+
#endif // INCLUDE_BINARY_H

modules/openapi-generator/src/main/resources/C-libcurl/model-body.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ fail:
534534
}
535535
{{/isByteArray}}
536536
{{#isBinary}}
537-
binary_t* decoded_str_{{{name}}};
537+
binary_t* decoded_str_{{{name}}} = malloc(sizeof(struct binary_t));
538538
{{^required}}if ({{{name}}}) { {{/required}}
539539
if(!cJSON_IsString({{{name}}}))
540540
{

modules/openapi-generator/src/main/resources/C-libcurl/model-header.mustache

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "../external/cJSON.h"
1212
#include "../include/list.h"
1313
#include "../include/keyValuePair.h"
14+
#include "../include/binary.h"
1415

1516
typedef struct {{classname}}_t {{classname}}_t;
1617

modules/openapi-generator/src/main/resources/C-libcurl/object-header.mustache

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "../external/cJSON.h"
1010
#include "../include/list.h"
1111
#include "../include/keyValuePair.h"
12+
#include "../include/binary.h"
1213

1314

1415
typedef struct object_t {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
4.3.0-SNAPSHOT
1+
4.3.1-SNAPSHOT

samples/client/petstore/c/api/PetAPI.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "../include/list.h"
55
#include "../external/cJSON.h"
66
#include "../include/keyValuePair.h"
7+
#include "../include/binary.h"
78
#include "../model/api_response.h"
89
#include "../model/pet.h"
910

samples/client/petstore/c/api/StoreAPI.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "../include/list.h"
55
#include "../external/cJSON.h"
66
#include "../include/keyValuePair.h"
7+
#include "../include/binary.h"
78
#include "../model/order.h"
89

910

samples/client/petstore/c/api/UserAPI.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "../include/list.h"
55
#include "../external/cJSON.h"
66
#include "../include/keyValuePair.h"
7+
#include "../include/binary.h"
78
#include "../model/user.h"
89

910

0 commit comments

Comments
 (0)