Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_avro.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
27#include "nilorea/n_common.h"
28#include "nilorea/n_log.h"
29#include "nilorea/n_str.h"
30#include "nilorea/n_avro.h"
31
32#include <stdio.h>
33#include <string.h>
34
35int main(int argc, char* argv[]) {
37
38 if (argc == 5) {
39 /* file-based mode: ex_avro <encode|decode> <schema.json> <input> <output> */
40 if (strcmp(argv[1], "encode") == 0) {
41 n_log(LOG_INFO, "Encoding JSON to Avro: %s + %s -> %s", argv[3], argv[2], argv[4]);
42 if (avro_json_to_file(argv[4], argv[2], argv[3]) == TRUE) {
43 n_log(LOG_INFO, "Success!");
44 } else {
45 n_log(LOG_ERR, "Encoding failed!");
46 return 1;
47 }
48 } else if (strcmp(argv[1], "decode") == 0) {
49 n_log(LOG_INFO, "Decoding Avro to JSON: %s + %s -> %s", argv[3], argv[2], argv[4]);
50 if (avro_file_to_json(argv[3], argv[2], argv[4]) == TRUE) {
51 n_log(LOG_INFO, "Success!");
52 } else {
53 n_log(LOG_ERR, "Decoding failed!");
54 return 1;
55 }
56 } else {
57 n_log(LOG_ERR, "Unknown command: %s (use 'encode' or 'decode')", argv[1]);
58 return 1;
59 }
60 return 0;
61 }
62
63 /* default: in-memory demo with embedded data */
64 n_log(LOG_INFO, "=== Avro In-Memory Demo ===");
65
66 /* define a schema */
67 const char* schema_json =
68 "{"
69 " \"type\": \"record\","
70 " \"name\": \"User\","
71 " \"namespace\": \"com.example\","
72 " \"fields\": ["
73 " {\"name\": \"name\", \"type\": \"string\"},"
74 " {\"name\": \"age\", \"type\": \"int\"},"
75 " {\"name\": \"email\", \"type\": [\"null\", \"string\"]},"
76 " {\"name\": \"score\", \"type\": \"double\"},"
77 " {\"name\": \"active\", \"type\": \"boolean\"}"
78 " ]"
79 "}";
80
81 /* define some JSON records */
82 const char* json_data =
83 "["
84 " {"
85 " \"name\": \"Alice\","
86 " \"age\": 30,"
87 " \"email\": \"alice@example.com\","
88 " \"score\": 95.5,"
89 " \"active\": true"
90 " },"
91 " {"
92 " \"name\": \"Bob\","
93 " \"age\": 25,"
94 " \"email\": null,"
95 " \"score\": 87.3,"
96 " \"active\": false"
97 " },"
98 " {"
99 " \"name\": \"Charlie\","
100 " \"age\": 35,"
101 " \"email\": \"charlie@example.com\","
102 " \"score\": 92.1,"
103 " \"active\": true"
104 " }"
105 "]";
106
107 /* convert to N_STR for the N_STR-based API */
108 N_STR* schema_nstr = char_to_nstr(schema_json);
109 N_STR* json_nstr = char_to_nstr(json_data);
110
111 /* encode JSON -> Avro using N_STR API */
112 n_log(LOG_INFO, "Encoding JSON to Avro (in-memory)...");
113 N_STR* avro_nstr = avro_nstr_json_to_avro(schema_nstr, json_nstr);
114 if (!avro_nstr) {
115 n_log(LOG_ERR, "Encoding failed!");
116 free_nstr(&schema_nstr);
117 free_nstr(&json_nstr);
118 return 1;
119 }
120 n_log(LOG_INFO, "Avro data size: %zu bytes (from %zu bytes JSON)", avro_nstr->written, json_nstr->written);
121
122 /* decode Avro -> JSON using N_STR API */
123 n_log(LOG_INFO, "Decoding Avro to JSON (in-memory)...");
124 N_STR* result_json = avro_nstr_avro_to_json(schema_nstr, avro_nstr);
125 if (!result_json) {
126 n_log(LOG_ERR, "Decoding failed!");
127 free_nstr(&schema_nstr);
128 free_nstr(&json_nstr);
129 free_nstr(&avro_nstr);
130 return 1;
131 }
132
133 n_log(LOG_INFO, "Decoded JSON:\n%s", result_json->data);
134
135 /* also test the schema parse/serialize round-trip */
136 n_log(LOG_INFO, "--- Schema round-trip test ---");
137 AVRO_SCHEMA* schema = avro_schema_parse_nstr(schema_nstr);
138 if (schema) {
139 char* schema_back = avro_schema_to_json(schema);
140 if (schema_back) {
141 n_log(LOG_INFO, "Schema round-trip: %s", schema_back);
142 Free(schema_back);
143 }
144 avro_schema_free(&schema);
145 }
146
147 /* also demo the file-based round-trip */
148 n_log(LOG_INFO, "--- File-based round-trip test ---");
149 nstr_to_file(schema_nstr, (char*)"/tmp/test_avro_schema.json");
150 nstr_to_file(json_nstr, (char*)"/tmp/test_avro_input.json");
151
152 if (avro_json_to_file("/tmp/test_output.avro", "/tmp/test_avro_schema.json", "/tmp/test_avro_input.json") == TRUE) {
153 n_log(LOG_INFO, "File encoding succeeded");
154
155 if (avro_file_to_json("/tmp/test_output.avro", "/tmp/test_avro_schema.json", "/tmp/test_avro_output.json") == TRUE) {
156 n_log(LOG_INFO, "File decoding succeeded");
157 N_STR* output = file_to_nstr((char*)"/tmp/test_avro_output.json");
158 if (output) {
159 n_log(LOG_INFO, "File round-trip JSON:\n%s", output->data);
160 free_nstr(&output);
161 }
162 }
163 }
164
165 /* cleanup */
166 free_nstr(&schema_nstr);
167 free_nstr(&json_nstr);
168 free_nstr(&avro_nstr);
169 free_nstr(&result_json);
170
171 n_log(LOG_INFO, "=== Done ===");
172 return 0;
173}
int main(void)
N_STR * avro_nstr_json_to_avro(const N_STR *schema_nstr, const N_STR *json_nstr)
Convert JSON N_STR to Avro N_STR using schema N_STR (all in-memory)
Definition n_avro.c:1279
int avro_file_to_json(const char *avro_filename, const char *schema_filename, const char *json_filename)
Read an Avro object container file and produce a JSON file using a schema file.
Definition n_avro.c:1210
AVRO_SCHEMA * avro_schema_parse_nstr(const N_STR *schema_nstr)
Parse schema from N_STR.
Definition n_avro.c:1272
N_STR * avro_nstr_avro_to_json(const N_STR *schema_nstr, const N_STR *avro_nstr)
Convert Avro N_STR to JSON N_STR using schema N_STR (all in-memory)
Definition n_avro.c:1315
char * avro_schema_to_json(const AVRO_SCHEMA *schema)
Convert an Avro schema back to JSON string (caller must free)
Definition n_avro.c:258
void avro_schema_free(AVRO_SCHEMA **schema_ptr)
Free an Avro schema.
Definition n_avro.c:222
int avro_json_to_file(const char *avro_filename, const char *schema_filename, const char *json_filename)
Write an Avro object container file from a JSON file and schema file.
Definition n_avro.c:1146
Avro schema definition.
Definition n_avro.h:84
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:262
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:88
#define LOG_DEBUG
debug-level messages
Definition n_log.h:83
#define LOG_ERR
error conditions
Definition n_log.h:75
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
Definition n_log.c:120
#define LOG_INFO
informational
Definition n_log.h:81
size_t written
size of the written data inside the string
Definition n_str.h:66
char * data
the string
Definition n_str.h:62
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition n_str.h:201
int nstr_to_file(N_STR *str, char *filename)
Write a N_STR content into a file.
Definition n_str.c:416
N_STR * char_to_nstr(const char *src)
Convert a char into a N_STR, short version.
Definition n_str.c:254
N_STR * file_to_nstr(char *filename)
Load a whole file into a N_STR.
Definition n_str.c:286
A box including a string and his lenght.
Definition n_str.h:60
Avro binary format encoding/decoding with JSON conversion.
Common headers and low-level functions & define.
Generic log system.
N_STR and string function declaration.