📜 ⬆️ ⬇️

Automatic generation of typed data structures for C

If you are programming in C and you do not have enough typed containers that are in high-level languages, welcome to the cat:

Hello!

As you know, a nontrivial program most likely involves working with nontrivial data structures. Modern high-level PL have extensive libraries of typed containers, which greatly simplify working with them. However, when falling from heaven to earth on pure X, all these benefits of civilization are inaccessible. Therefore, often, if you need to write something in C, there is a need for some kind of code that provides processing of complexly structured data.

The need to reinvent the wheel with square wheels every time brought my pampered high-level soul spoiled by narzan to the thought of creating a universal generator of typed structures (part of a more extensive AutoC package) that could solve this problem once and for all.
')
Existing libraries of C containers, for example from GLib , operate on a single type, the untyped gpointer pointers, since an honest solution to this problem in C is possible only with the involvement of a preprocessor and will be a terrible mess of macros that is difficult to understand and debug, as demonstrated existing similar projects. That is, nothing similar in terms of harmony and convenience of STL containers for C ++ and collections of Java and Sharp can be built using standard C tools.

This article introduces an alternative path - the automatic generation of the required data structures for a user-defined specification. The data structures obtained in this way, besides actually ensuring strict typing of elements, are very intuitive and have a simple and intuitive interface, which facilitates their use.

The code generator is written in Ruby. The user-prepared data structure specification is a Ruby script. The result of the generator operation is the C source code, designed as a module (header file and implementation file). The header file is included in custom code using these structures; the implementation file is compiled and linked to the other modules that make up the program.

At the time of this writing, the following data structures are supported:



For each container specialization, an independent source code is created; in fact, this is exactly what C ++ does “behind the scenes” when generating specializations of its template types (for example, for
 std::list  std::list      ). 

, , . , , , copy-on-write .. , - , , , ..

AutoC , std::unordered_set ++.

(set), :
require "autoc" CodeBuilder::CModule.generate!("containers") do |m| m << DataStructBuilder::HashSet.new("IntSet", {:type=>"int"}) end


IntSet :
... typedef struct IntSet IntSet; struct IntSet {...} ... void IntSetCtor(IntSet*); void IntSetDtor(IntSet*); void IntSetPut(IntSet*, int); ...

IntSet :
#include <stdio.h> #include "containers_auto.h" int main(int argc, char** argv) { IntSet set; IntSetCtor(&set); IntSetPut(&set, 0); IntSetPut(&set, 1); IntSetPut(&set, 0); printf("size(set)=%d\n", IntSetSize(&set)); printf("contains(1)==%d\n", IntSetContains(&set, 1)); IntSetDtor(&set); return 0; }

; , , ( API ). , , .
, .

PS
.
std::list std::list ).

, , . , , , copy-on-write .. , - , , , ..

AutoC , std::unordered_set ++.

(set), :
require "autoc" CodeBuilder::CModule.generate!("containers") do |m| m << DataStructBuilder::HashSet.new("IntSet", {:type=>"int"}) end


IntSet :
... typedef struct IntSet IntSet; struct IntSet {...} ... void IntSetCtor(IntSet*); void IntSetDtor(IntSet*); void IntSetPut(IntSet*, int); ...

IntSet :
#include <stdio.h> #include "containers_auto.h" int main(int argc, char** argv) { IntSet set; IntSetCtor(&set); IntSetPut(&set, 0); IntSetPut(&set, 1); IntSetPut(&set, 0); printf("size(set)=%d\n", IntSetSize(&set)); printf("contains(1)==%d\n", IntSetContains(&set, 1)); IntSetDtor(&set); return 0; }

; , , ( API ). , , .
, .

PS
.
 std::list  std::list      ). 

, , . , , , copy-on-write .. , - , , , ..

AutoC , std::unordered_set ++.

(set), :
require "autoc" CodeBuilder::CModule.generate!("containers") do |m| m << DataStructBuilder::HashSet.new("IntSet", {:type=>"int"}) end


IntSet :
... typedef struct IntSet IntSet; struct IntSet {...} ... void IntSetCtor(IntSet*); void IntSetDtor(IntSet*); void IntSetPut(IntSet*, int); ...

IntSet :
#include <stdio.h> #include "containers_auto.h" int main(int argc, char** argv) { IntSet set; IntSetCtor(&set); IntSetPut(&set, 0); IntSetPut(&set, 1); IntSetPut(&set, 0); printf("size(set)=%d\n", IntSetSize(&set)); printf("contains(1)==%d\n", IntSetContains(&set, 1)); IntSetDtor(&set); return 0; }

; , , ( API ). , , .
, .

PS
.
std::list std::list ).

, , . , , , copy-on-write .. , - , , , ..

AutoC , std::unordered_set ++.

(set), :
require "autoc" CodeBuilder::CModule.generate!("containers") do |m| m << DataStructBuilder::HashSet.new("IntSet", {:type=>"int"}) end


IntSet :
... typedef struct IntSet IntSet; struct IntSet {...} ... void IntSetCtor(IntSet*); void IntSetDtor(IntSet*); void IntSetPut(IntSet*, int); ...

IntSet :
#include <stdio.h> #include "containers_auto.h" int main(int argc, char** argv) { IntSet set; IntSetCtor(&set); IntSetPut(&set, 0); IntSetPut(&set, 1); IntSetPut(&set, 0); printf("size(set)=%d\n", IntSetSize(&set)); printf("contains(1)==%d\n", IntSetContains(&set, 1)); IntSetDtor(&set); return 0; }

; , , ( API ). , , .
, .

PS
.
 std::list  std::list      ). 

, , . , , , copy-on-write .. , - , , , ..

AutoC , std::unordered_set ++.

(set), :
require "autoc" CodeBuilder::CModule.generate!("containers") do |m| m << DataStructBuilder::HashSet.new("IntSet", {:type=>"int"}) end


IntSet :
... typedef struct IntSet IntSet; struct IntSet {...} ... void IntSetCtor(IntSet*); void IntSetDtor(IntSet*); void IntSetPut(IntSet*, int); ...

IntSet :
#include <stdio.h> #include "containers_auto.h" int main(int argc, char** argv) { IntSet set; IntSetCtor(&set); IntSetPut(&set, 0); IntSetPut(&set, 1); IntSetPut(&set, 0); printf("size(set)=%d\n", IntSetSize(&set)); printf("contains(1)==%d\n", IntSetContains(&set, 1)); IntSetDtor(&set); return 0; }

; , , ( API ). , , .
, .

PS
.
std::list std::list ).

, , . , , , copy-on-write .. , - , , , ..

AutoC , std::unordered_set ++.

(set), :
require "autoc" CodeBuilder::CModule.generate!("containers") do |m| m << DataStructBuilder::HashSet.new("IntSet", {:type=>"int"}) end


IntSet :
... typedef struct IntSet IntSet; struct IntSet {...} ... void IntSetCtor(IntSet*); void IntSetDtor(IntSet*); void IntSetPut(IntSet*, int); ...

IntSet :
#include <stdio.h> #include "containers_auto.h" int main(int argc, char** argv) { IntSet set; IntSetCtor(&set); IntSetPut(&set, 0); IntSetPut(&set, 1); IntSetPut(&set, 0); printf("size(set)=%d\n", IntSetSize(&set)); printf("contains(1)==%d\n", IntSetContains(&set, 1)); IntSetDtor(&set); return 0; }

; , , ( API ). , , .
, .

PS
.

Source: https://habr.com/ru/post/171339/


All Articles