Import source to librtti
Summary: - Import initial source Test Plan: NA
This commit is contained in:
commit
c8c1749347
23 changed files with 969 additions and 0 deletions
36
.clang-format
Normal file
36
.clang-format
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
BasedOnStyle: webkit
|
||||||
|
ColumnLimit: 80
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignArrayOfStructures: Left
|
||||||
|
AlignConsecutiveAssignments:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignConsecutiveBitFields:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignConsecutiveDeclarations:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignConsecutiveMacros:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignConsecutiveShortCaseStatements:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: true
|
||||||
|
AcrossComments: true
|
||||||
|
AlignCaseColons: true
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: AlignAfterOperator
|
||||||
|
AlignTrailingComments:
|
||||||
|
Kind: Always
|
||||||
|
OverEmptyLines: 2
|
||||||
|
AllowAllArgumentsOnNextLine: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
|
||||||
|
---
|
||||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
*~
|
||||||
|
result
|
||||||
9
LICENSE
Normal file
9
LICENSE
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 rshen
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
3
README.md
Normal file
3
README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# rtti
|
||||||
|
|
||||||
|
runtime type information library for c
|
||||||
18
examples/meson.build
Normal file
18
examples/meson.build
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#
|
||||||
|
#app_c_srcs=[
|
||||||
|
# 'app.c',
|
||||||
|
#]
|
||||||
|
#
|
||||||
|
#app_srcs= app_c_srcs
|
||||||
|
#
|
||||||
|
#incdir = include_directories('../include', '.')
|
||||||
|
#
|
||||||
|
#app_deps = [
|
||||||
|
# dep_librtti,
|
||||||
|
#]
|
||||||
|
#
|
||||||
|
#app = executable('app',
|
||||||
|
# app_srcs,
|
||||||
|
# include_directories: incdir,
|
||||||
|
# dependencies: app_deps,
|
||||||
|
# install: true)
|
||||||
131
flake.lock
generated
Normal file
131
flake.lock
generated
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_2": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1764950072,
|
||||||
|
"narHash": "sha256-BmPWzogsG2GsXZtlT+MTcAWeDK5hkbGRZTeZNW42fwA=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "f61125a668a320878494449750330ca58b78c557",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1764667669,
|
||||||
|
"narHash": "sha256-7WUCZfmqLAssbDqwg9cUDAXrSoXN79eEEq17qhTNM/Y=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "418468ac9527e799809c900eda37cbff999199b6",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"xbuild": "xbuild"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"xbuild": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1769064169,
|
||||||
|
"narHash": "sha256-Tqb8E8vw6WtP5KPCzwWAVBzMwv+UH0gduR2ZWkkYM9g=",
|
||||||
|
"owner": "shen390s",
|
||||||
|
"repo": "my-nix-channel",
|
||||||
|
"rev": "d6e6711f401446ebfec291ad1a3fbb58fd33720d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "shen390s",
|
||||||
|
"ref": "master",
|
||||||
|
"repo": "my-nix-channel",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
42
flake.nix
Normal file
42
flake.nix
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
description = "Flake for librtti";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
xbuild.url = "github:shen390s/my-nix-channel?ref=master";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
{
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
flake-utils,
|
||||||
|
xbuild,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
supportedSystems = [ "x86_64-linux" ];
|
||||||
|
in
|
||||||
|
flake-utils.lib.eachSystem supportedSystems (
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
mypkgs = xbuild.packages.${system};
|
||||||
|
overlays = [
|
||||||
|
(final: prev: mypkgs // prev)
|
||||||
|
];
|
||||||
|
pkgs = import nixpkgs { inherit overlays system; };
|
||||||
|
xpkgs = import ./nixSupport/default.nix {
|
||||||
|
inherit pkgs;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
rec {
|
||||||
|
packages = pkgs // xpkgs;
|
||||||
|
defaultPackage = xpkgs.librtti_debug;
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
nativeBuildInputs = xpkgs.librtti.nativeBuildInputs;
|
||||||
|
};
|
||||||
|
|
||||||
|
devShell = self.devShells.${system}.default;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
8
include/rtti.h
Normal file
8
include/rtti.h
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#if !defined(_LIBRTTI_RTTI_H_)
|
||||||
|
|
||||||
|
#define _LIBRTTI_RTTI_H_ 1
|
||||||
|
|
||||||
|
#include "rtti/typeinfo.h"
|
||||||
|
#include "rtti/utils.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
142
include/rtti/typeinfo.h
Normal file
142
include/rtti/typeinfo.h
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
#if !defined(_RTTI_TYPEINFO_H_)
|
||||||
|
|
||||||
|
#define _RTTI_TYPEINFO_H_ 1
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#define var void*
|
||||||
|
|
||||||
|
#define SIZE_ROUNDUP(sz) \
|
||||||
|
((((sz + sizeof(void*) - 1)) / (sizeof(void*))) * sizeof(void*))
|
||||||
|
|
||||||
|
#define OBJ_HEADER_SIZE SIZE_ROUNDUP(sizeof(meta_obj_t))
|
||||||
|
|
||||||
|
/** Object format
|
||||||
|
**
|
||||||
|
** +=====================+===================+===================+
|
||||||
|
** | <private data> | <object header> | <- public data > |
|
||||||
|
** +=====================+===================+===================+
|
||||||
|
**
|
||||||
|
**/
|
||||||
|
#define OBJ_TO_DATA(T, obj) ((T*)(((char*)obj) + OBJ_HEADER_SIZE))
|
||||||
|
#define DATA_TO_OBJ(v) ((meta_obj_t*)(((char*)v) - OBJ_HEADER_SIZE))
|
||||||
|
#define OBJ_TO_PRIV(obj) \
|
||||||
|
((void*)(((char*)obj) - SIZE_ROUNDUP((obj)->type->privateSize)))
|
||||||
|
|
||||||
|
struct meta_obj_;
|
||||||
|
struct typeinfo_;
|
||||||
|
|
||||||
|
typedef struct meta_obj_ meta_obj_t;
|
||||||
|
typedef struct typeinfo_ typeinfo_t;
|
||||||
|
|
||||||
|
/* calculate the size of data */
|
||||||
|
typedef size_t (*datasize_fn_t)(va_list);
|
||||||
|
|
||||||
|
/* object life cycle */
|
||||||
|
typedef int (*obj_init_fn_t)(typeinfo_t*, va_list);
|
||||||
|
typedef void (*obj_destroy_fn_t)(var);
|
||||||
|
|
||||||
|
/* lock/unlock */
|
||||||
|
typedef int (*lock_fn_t)(var, uint64_t);
|
||||||
|
typedef void (*unlock_fn_t)(var);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
lock_fn_t lock;
|
||||||
|
unlock_fn_t unlock;
|
||||||
|
} intf_lock_t;
|
||||||
|
|
||||||
|
/* convert to string */
|
||||||
|
typedef char* (*to_string_fn_t)(var, va_list);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
to_string_fn_t toString;
|
||||||
|
} intf_tostring_t;
|
||||||
|
|
||||||
|
/* iterator function */
|
||||||
|
|
||||||
|
#define ITER_NO_DATA (0)
|
||||||
|
#define ITER_OK (1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
var v;
|
||||||
|
var data;
|
||||||
|
} iterator_t;
|
||||||
|
|
||||||
|
typedef int (*iter_make_fn_t)(iterator_t*, var);
|
||||||
|
typedef int (*iter_next_fn_t)(iterator_t*, void**);
|
||||||
|
typedef int (*iter_reset_fn_t)(iterator_t*);
|
||||||
|
typedef void (*iter_destroy_fn_t)(iterator_t*);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
iter_make_fn_t make;
|
||||||
|
iter_next_fn_t next;
|
||||||
|
iter_reset_fn_t reset;
|
||||||
|
iter_destroy_fn_t destroy;
|
||||||
|
} intf_iterator_t;
|
||||||
|
|
||||||
|
/* reference and deref */
|
||||||
|
typedef int32_t (*reference_fn_t)(var);
|
||||||
|
typedef void (*dereference_fn_t)(var);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
reference_fn_t reference;
|
||||||
|
dereference_fn_t dereference;
|
||||||
|
} intf_reference_t;
|
||||||
|
|
||||||
|
/* hash */
|
||||||
|
|
||||||
|
typedef int32_t (*hash_fn_t)(var);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
hash_fn_t hash;
|
||||||
|
} intf_hash_t;
|
||||||
|
|
||||||
|
/* length */
|
||||||
|
typedef int64_t (*length_fn_t)(var);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
length_fn_t length;
|
||||||
|
} intf_length_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
intf_lock_t* lock;
|
||||||
|
intf_tostring_t* toString;
|
||||||
|
intf_iterator_t* iter;
|
||||||
|
intf_reference_t* reference;
|
||||||
|
intf_hash_t* hash;
|
||||||
|
intf_length_t* length;
|
||||||
|
} interface_table_t;
|
||||||
|
|
||||||
|
struct typeinfo_ {
|
||||||
|
char* name;
|
||||||
|
size_t privateSize;
|
||||||
|
datasize_fn_t dataSize;
|
||||||
|
obj_init_fn_t init;
|
||||||
|
obj_destroy_fn_t destroy;
|
||||||
|
interface_table_t interfaces;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct meta_obj_ {
|
||||||
|
typeinfo_t* type;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern var makeInstance(typeinfo_t*, ...);
|
||||||
|
extern void destroy(var);
|
||||||
|
extern int lock(var, uint64_t);
|
||||||
|
extern void unlock(var);
|
||||||
|
extern char* toString(var, ...);
|
||||||
|
extern int iter_make(iterator_t*, var);
|
||||||
|
extern int iter_next(iterator_t*, void**);
|
||||||
|
extern int iter_reset(iterator_t*);
|
||||||
|
extern void iter_destroy(iterator_t*);
|
||||||
|
extern int32_t hash(var);
|
||||||
|
extern int64_t length(var);
|
||||||
|
extern int32_t reference(var);
|
||||||
|
extern void dereference(var);
|
||||||
|
|
||||||
|
#endif
|
||||||
30
include/rtti/utils.h
Normal file
30
include/rtti/utils.h
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#if !defined(_RTTI_UTILS_H_)
|
||||||
|
|
||||||
|
#define _RTTI_UTILS_H_ 1
|
||||||
|
|
||||||
|
#define RTTI_GET_METHOD(result, obj, intf, method) \
|
||||||
|
do { \
|
||||||
|
typeinfo_t* type_ = NULL; \
|
||||||
|
meta_obj_t* obj_ = NULL; \
|
||||||
|
\
|
||||||
|
(result) = NULL; \
|
||||||
|
\
|
||||||
|
if ((obj) == NULL) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
obj_ = DATA_TO_OBJ(obj); \
|
||||||
|
\
|
||||||
|
type_ = obj_->type; \
|
||||||
|
if (type_ == NULL) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (type_->interfaces.intf == NULL) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
(result) = type_->interfaces.intf->method; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif
|
||||||
18
meson.build
Normal file
18
meson.build
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
project('librtti',
|
||||||
|
['c'],
|
||||||
|
version: '0.0.1',
|
||||||
|
meson_version: '>=1.5',
|
||||||
|
default_options: [
|
||||||
|
'c_std=gnu17'])
|
||||||
|
|
||||||
|
add_project_arguments(['-ggdb',
|
||||||
|
'-g3',
|
||||||
|
'-Wno-cpp'],
|
||||||
|
language: ['c'])
|
||||||
|
|
||||||
|
subdir('src')
|
||||||
|
if get_option('with_debug') == true
|
||||||
|
subdir('testsuite')
|
||||||
|
endif
|
||||||
|
# subdir('examples')
|
||||||
|
|
||||||
1
meson.options
Normal file
1
meson.options
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
option('with_debug', type: 'boolean', value: false, yield: true)
|
||||||
20
nixSupport/default.nix
Normal file
20
nixSupport/default.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
librtti = pkgs.callPackage ./librtti.nix {
|
||||||
|
inherit pkgs;
|
||||||
|
withDebug = false;
|
||||||
|
withAsan = false;
|
||||||
|
};
|
||||||
|
librtti_debug = pkgs.callPackage ./librtti.nix {
|
||||||
|
inherit pkgs;
|
||||||
|
withDebug = true;
|
||||||
|
withAsan = true;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
librtti = librtti;
|
||||||
|
librtti_debug = librtti_debug;
|
||||||
|
}
|
||||||
35
nixSupport/librtti.nix
Normal file
35
nixSupport/librtti.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
pkgs,
|
||||||
|
withDebug ? false,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
|
||||||
|
pname = "rtti";
|
||||||
|
version = "0.0.1";
|
||||||
|
|
||||||
|
src = ./..;
|
||||||
|
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
meson
|
||||||
|
ninja
|
||||||
|
pkg-config
|
||||||
|
which
|
||||||
|
unity_test_with_color
|
||||||
|
];
|
||||||
|
|
||||||
|
build-system = [ pkgs.meson ];
|
||||||
|
|
||||||
|
dontStrip = withDebug;
|
||||||
|
separateDebugInfo = withDebug;
|
||||||
|
|
||||||
|
impureEnvVars = [ "HOME" ];
|
||||||
|
|
||||||
|
mesonFlags = [
|
||||||
|
(lib.optional withDebug "--buildtype=debug -Db_sanitize=address -Dwith_debug=true ")
|
||||||
|
# (lib.optional (!with_debug) "-Dbuildtype=release")
|
||||||
|
];
|
||||||
|
}
|
||||||
81
src/create.c
Normal file
81
src/create.c
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "rtti.h"
|
||||||
|
|
||||||
|
static void* objAlloc(typeinfo_t* type, size_t sz)
|
||||||
|
{
|
||||||
|
size_t privateSize = SIZE_ROUNDUP(type->privateSize);
|
||||||
|
size_t headerSize = OBJ_HEADER_SIZE;
|
||||||
|
char* p = NULL;
|
||||||
|
meta_obj_t* obj = NULL;
|
||||||
|
size_t total = privateSize + headerSize + sz;
|
||||||
|
|
||||||
|
p = (char*)calloc(1, total);
|
||||||
|
if (p == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = (meta_obj_t*)(p + privateSize);
|
||||||
|
obj->type = type;
|
||||||
|
|
||||||
|
return (void*)(p + privateSize + headerSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
var makeInstance(typeinfo_t* type, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_list ap1;
|
||||||
|
var v = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if ((type == NULL) || (type->init == NULL) || (type->dataSize == NULL)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start(ap, type);
|
||||||
|
va_copy(ap1, ap);
|
||||||
|
v = objAlloc(type, type->dataSize(ap1));
|
||||||
|
va_end(ap1);
|
||||||
|
|
||||||
|
if (v != NULL) {
|
||||||
|
rc = type->init(v, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (rc < 0) {
|
||||||
|
destroy(v);
|
||||||
|
v = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy(var v)
|
||||||
|
{
|
||||||
|
typeinfo_t* type = NULL;
|
||||||
|
meta_obj_t* obj = NULL;
|
||||||
|
void* p = NULL;
|
||||||
|
|
||||||
|
if (v == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = DATA_TO_OBJ(v);
|
||||||
|
|
||||||
|
type = obj->type;
|
||||||
|
if (type == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type->destroy != NULL) {
|
||||||
|
type->destroy(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
p = OBJ_TO_PRIV(obj);
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
74
src/iter.c
Normal file
74
src/iter.c
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "rtti.h"
|
||||||
|
|
||||||
|
int iter_make(iterator_t* it, var v)
|
||||||
|
{
|
||||||
|
iter_make_fn_t method = NULL;
|
||||||
|
|
||||||
|
if (it == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, v, iter, make);
|
||||||
|
if (method == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(it, 0x0, sizeof(*it));
|
||||||
|
it->v = v;
|
||||||
|
|
||||||
|
return method(it, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iter_next(iterator_t* it, void** data)
|
||||||
|
{
|
||||||
|
iter_next_fn_t method = NULL;
|
||||||
|
|
||||||
|
if ((it == NULL) || (data == NULL) || (it->v == NULL)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, it->v, iter, next);
|
||||||
|
if (method == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return method(it, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iter_reset(iterator_t* it)
|
||||||
|
{
|
||||||
|
iter_reset_fn_t method = NULL;
|
||||||
|
|
||||||
|
if ((it == NULL) || (it->v == NULL)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, it->v, iter, reset);
|
||||||
|
if (method == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return method(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void iter_destroy(iterator_t* it)
|
||||||
|
{
|
||||||
|
iter_destroy_fn_t method = NULL;
|
||||||
|
|
||||||
|
if ((it == NULL) || (it->v == NULL)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, it->v, iter, destroy);
|
||||||
|
if (method == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
method(it);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
30
src/lock.c
Normal file
30
src/lock.c
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "rtti.h"
|
||||||
|
|
||||||
|
int lock(var v, uint64_t option)
|
||||||
|
{
|
||||||
|
lock_fn_t method = NULL;
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, v, lock, lock);
|
||||||
|
if (method == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return method(v, option);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock(var v)
|
||||||
|
{
|
||||||
|
unlock_fn_t method = NULL;
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, v, lock, unlock);
|
||||||
|
if (method == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
method(v);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
42
src/meson.build
Normal file
42
src/meson.build
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
pkg = import('pkgconfig')
|
||||||
|
|
||||||
|
librtti_c_srcs=[
|
||||||
|
'create.c',
|
||||||
|
'lock.c',
|
||||||
|
'iter.c',
|
||||||
|
'ref.c',
|
||||||
|
'str.c',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
librtti_srcs= librtti_c_srcs
|
||||||
|
|
||||||
|
incdir = include_directories('../include', '.')
|
||||||
|
|
||||||
|
rtti_top_headers = [
|
||||||
|
'../include/rtti.h',
|
||||||
|
]
|
||||||
|
|
||||||
|
rtti_headers = [
|
||||||
|
'../include/rtti/typeinfo.h',
|
||||||
|
'../include/rtti/utils.h',
|
||||||
|
]
|
||||||
|
|
||||||
|
librtti_deps = [
|
||||||
|
]
|
||||||
|
|
||||||
|
librtti = static_library('librtti',
|
||||||
|
librtti_srcs,
|
||||||
|
include_directories: incdir,
|
||||||
|
dependencies: librtti_deps,
|
||||||
|
install: true)
|
||||||
|
|
||||||
|
install_headers(rtti_top_headers, install_dir: 'include')
|
||||||
|
install_headers(rtti_headers, install_dir: 'include/rtti')
|
||||||
|
|
||||||
|
dep_librtti = declare_dependency(link_with: librtti)
|
||||||
|
|
||||||
|
pkg.generate(librtti,
|
||||||
|
name: 'librtti',
|
||||||
|
description: 'runtime type information library for c',
|
||||||
|
version: '0.0.1')
|
||||||
29
src/ref.c
Normal file
29
src/ref.c
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "rtti.h"
|
||||||
|
|
||||||
|
int32_t reference(var v)
|
||||||
|
{
|
||||||
|
reference_fn_t method = NULL;
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, v, reference, reference);
|
||||||
|
if (method == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return method(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dereference(var v)
|
||||||
|
{
|
||||||
|
dereference_fn_t method = NULL;
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method,v, reference, dereference);
|
||||||
|
if (method != NULL) {
|
||||||
|
method(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
23
src/str.c
Normal file
23
src/str.c
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "rtti.h"
|
||||||
|
|
||||||
|
char* toString(var v, ...)
|
||||||
|
{
|
||||||
|
to_string_fn_t method = NULL;
|
||||||
|
va_list ap;
|
||||||
|
char* s = NULL;
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, v, toString, toString);
|
||||||
|
if (method == NULL) {
|
||||||
|
errno = -EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start(ap, v);
|
||||||
|
s = method(v, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
13
testsuite/meson.build
Normal file
13
testsuite/meson.build
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
librtti_test_srcs = [
|
||||||
|
'test.c',
|
||||||
|
'test_iter.c',
|
||||||
|
]
|
||||||
|
|
||||||
|
unity_dep = dependency('unity')
|
||||||
|
librtti_test_deps = [dep_librtti, unity_dep]
|
||||||
|
|
||||||
|
librtti_test = executable('rtti_test',
|
||||||
|
librtti_test_srcs,
|
||||||
|
include_directories: [incdir],
|
||||||
|
dependencies: librtti_test_deps,
|
||||||
|
install: true)
|
||||||
29
testsuite/test.c
Normal file
29
testsuite/test.c
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <unity/unity.h>
|
||||||
|
|
||||||
|
void setUp(void)
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void)
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void test_iter(void);
|
||||||
|
|
||||||
|
#define TEST(x) x()
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
TEST(test_iter);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
153
testsuite/test_iter.c
Normal file
153
testsuite/test_iter.c
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <unity/unity.h>
|
||||||
|
|
||||||
|
#include "rtti.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int count;
|
||||||
|
int* data;
|
||||||
|
} myArray_t;
|
||||||
|
|
||||||
|
static size_t my_array_datasize(va_list ap) { return sizeof(myArray_t); }
|
||||||
|
|
||||||
|
static int my_array_init(myArray_t* a, va_list ap)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
count = va_arg(ap, int);
|
||||||
|
if (count <= 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
a->data = (int*)calloc(count, sizeof(int));
|
||||||
|
if (a->data == NULL) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
a->count = count;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
a->data[i] = va_arg(ap, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_array_destroy(myArray_t* a)
|
||||||
|
{
|
||||||
|
if (a->data != NULL) {
|
||||||
|
free(a->data);
|
||||||
|
a->data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int my_array_make_iter(iterator_t* iter, var obj)
|
||||||
|
{
|
||||||
|
iter->data = (void*)(long)0;
|
||||||
|
|
||||||
|
return ITER_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int my_array_iter_next(iterator_t* iter, void** data)
|
||||||
|
{
|
||||||
|
myArray_t* a = iter->v;
|
||||||
|
int idx = (int)(long)iter->data;
|
||||||
|
|
||||||
|
if (idx >= a->count) {
|
||||||
|
/* no data */
|
||||||
|
return ITER_NO_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
*data = (void*)(long)a->data[idx];
|
||||||
|
iter->data = (void*)(long)(idx + 1);
|
||||||
|
|
||||||
|
return ITER_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int my_array_iter_reset(iterator_t* iter)
|
||||||
|
{
|
||||||
|
iter->data = (void*)(long)0;
|
||||||
|
|
||||||
|
return ITER_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_array_iter_destroy(iterator_t* iter) { return; }
|
||||||
|
|
||||||
|
static typeinfo_t myintArray
|
||||||
|
= { .name = "myintArray",
|
||||||
|
.privateSize = 0,
|
||||||
|
.dataSize = (datasize_fn_t)my_array_datasize,
|
||||||
|
.init = (obj_init_fn_t)my_array_init,
|
||||||
|
.destroy = (obj_destroy_fn_t)my_array_destroy,
|
||||||
|
.interfaces
|
||||||
|
= { .iter = &(intf_iterator_t) {
|
||||||
|
.make = (iter_make_fn_t)my_array_make_iter,
|
||||||
|
.next = (iter_next_fn_t)my_array_iter_next,
|
||||||
|
.reset = (iter_reset_fn_t)my_array_iter_reset,
|
||||||
|
.destroy = (iter_destroy_fn_t)my_array_iter_destroy } } };
|
||||||
|
|
||||||
|
static void test_array_iter(void)
|
||||||
|
{
|
||||||
|
var array = makeInstance(&myintArray, 5, 0, 1, 2, 3, 4);
|
||||||
|
iterator_t it;
|
||||||
|
int rc, sum;
|
||||||
|
void* data;
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(array != NULL);
|
||||||
|
|
||||||
|
rc = iter_make(&it, array);
|
||||||
|
TEST_ASSERT_TRUE(rc == 1);
|
||||||
|
|
||||||
|
rc = iter_next(&it, (void**)&data);
|
||||||
|
TEST_ASSERT_TRUE(rc >= 0);
|
||||||
|
TEST_ASSERT_TRUE((int)(long)data == 0);
|
||||||
|
|
||||||
|
rc = iter_next(&it, (void**)&data);
|
||||||
|
TEST_ASSERT_TRUE(rc >= 0);
|
||||||
|
TEST_ASSERT_TRUE((int)(long)data == 1);
|
||||||
|
|
||||||
|
rc = iter_next(&it, (void**)&data);
|
||||||
|
TEST_ASSERT_TRUE(rc >= 0);
|
||||||
|
TEST_ASSERT_TRUE((int)(long)data == 2);
|
||||||
|
|
||||||
|
rc = iter_next(&it, (void**)&data);
|
||||||
|
TEST_ASSERT_TRUE(rc >= 0);
|
||||||
|
TEST_ASSERT_TRUE((int)(long)data == 3);
|
||||||
|
|
||||||
|
rc = iter_next(&it, (void**)&data);
|
||||||
|
TEST_ASSERT_TRUE(rc >= 0);
|
||||||
|
TEST_ASSERT_TRUE((int)(long)data == 4);
|
||||||
|
|
||||||
|
rc = iter_next(&it, (void**)&data);
|
||||||
|
TEST_ASSERT_TRUE(rc == ITER_NO_DATA);
|
||||||
|
|
||||||
|
sum = 0;
|
||||||
|
rc = iter_reset(&it);
|
||||||
|
TEST_ASSERT_TRUE(rc >= 0);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
rc = iter_next(&it, &data);
|
||||||
|
TEST_ASSERT_TRUE(rc >= 0);
|
||||||
|
if (rc == ITER_NO_DATA) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sum += (int)(long)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(sum == 10);
|
||||||
|
|
||||||
|
iter_destroy(&it);
|
||||||
|
|
||||||
|
destroy(array);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_iter(void)
|
||||||
|
{
|
||||||
|
printf("\n iterator test\n\n");
|
||||||
|
|
||||||
|
RUN_TEST(test_array_iter);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue