Initial generator: functions, structs, enums (#2)

* migrated code from dart_ffi_bindings_generator repository

Commits till now:

Prerak Mann (6):
      init stagehand dart package template, minor changes
      Updated Project Structure, Readme
      Reading pubspec configuration via yaml package
      setup tool - libclang_binding_generator
      restructure code
      setup basic classes for code_generator

* update readme: building steps

* code_generation: added function generation for primitives

* code_generator: added test for function

* code_generation: added struct generation for primitives, added tests

* code_generation: added pointer support for function and structure, added test

* tool: added script for basic clang_binding generator

* code_generator: added constant, global, C string support (ptr to utf8), added tests

* code_generator: added typedefc, added test

* tool: completed basic clang binding generation

* update readme

* simplify setup

* added basic parser logic, fixed visitChildren_wrap function

* copied clang_constants from libclang

* header_parser: revamped api and code_structure

* wrapper.c: added pointer conversion utility, updated bindings

* header_parser: basic parser completed

- updated code_generator's Func, Struct, Typedef to not use const, as it makes list unmodifiable
- added example from previous prototype

* header_parser: updated exception handling

- print stack trace of dart functions called via C

* cleanup

* Handled Disposing of pointers

- Updated dartdocs on clang_binding functions
- Added dispose methods in cx.. ..cursor,..type, ..string
- Updated parser code to handle disposing

* Added input_checker, passing compilerOpts to clang

* fix nullpointer error on compilerOpts list

* config_provider: added filtering for functions

- added new libclang example
- moved old example to example/simple

* updated lib-clang example to work with clang not in include path, restructured filters

* Multiple Changes

- Added sort method in code_generator library
- Sorted generated clang_bindings
- Added typedef declaration visitor for extracting typestring of typedef parameters
- Added new methods to wrapper.c for getting type declarations

* created a temporary logging solution

* added typedef struct parser

* cleanup

* restructured parsing

* restructured code

* header_parser: added struct parser, minor changes

- added type_extracter, moved typedeclaration_visitor into it
- cleanup imports

* parser: fixed type extraction

* updated libclang-example, minor fix for record_type spelling

* code_generator: added EnumClass, added test

* header_parser: added enum parsing

* header_parser: added typedef enums

* header_parser: extracted doxygen comment

- added clang_Cursor_getBriefCommentText_wrap in libclang bindings
- added comment extraction for functions, enums, structs

* Added args parsing and logging

- option for alternate yaml config
- added verbosity levels:[ all, fine, info, warning, severe ]

* config_provider: added output file option

* tests: added native_function_test

* code_generator: breaking change

- updated internal handling of type
- added support for NativeFunction type needed for creating typedefC
- updated tests, tool
- updated header_parser/type_extractor

* Added support for function pointers in bindings

- example/libclang-example: added clang_visitChildren_wrap method
- clang_bindings: added new methods getNumArgType, getArgType

* header_parser: changes, complete libclang_example

- completed libclang_example, all structs starting with CX
all functions starting with clang_ except those passing/returning structs b value
- added automatic typenaming to unnamed typedefs, unnamed function paramters

* minor changes

- code_generator: added factory Type constructor
- updated tests and code to prefer using factory type constructors
- added location methods to bindings

* header_parser: added support for multiple headers, header-filters

* header_parser: add structs used by functions

- updated example/libclang to auto add IndexerCallback struct
as its used in a function
- structs are now added automatically if they are returned or
passed in to a function (if struct type is parsed by extractor
it automatically adds it)

* config_provider: added sizemap for char, ints

* tests: added simple tests for functions

- test with supported types
- added automatic argument naming for functions in code_gen if they are null or only whitspaces
- code_gen_tests: only create debug file on test failure

* config_provider: added sort option to config

- updated libclang-example to use this
- renamed generated file names
- renamed package name for example

* example: added new cJSON example, bug fix

- new cJSON example, parsing a json and comparing it to json parsed by dart:convert
- bug fix: shouldInclude.* functions not adding to seen Set in includer

* linter bug fix, updated code for warnings

* minor changes

- documentation updates
- code_gen: wrong binding string type in metadata fix

* logging: improved log comments

* code_generator: removed global constants file

- lib prefixes are passed via writer now

* improved tests, minor changes

- improved header_parser_test
- updated named constructors of code_generator: Type

* header_parser: struct fields parsed

- all structs fields are excluded, if any field is struct by value or array
- added 2 functions using tool to clang bindings for parsing array element name, number
- updated libclang example
- added Broadtype.Array for code_gen (only used as indicator of type rn to exclude from parsing)

* parser: extract type from supported typdef

- Added config 'use-supported-typedefs'
- support for intptr_t
- updated test: native_function_bindings, added intptr_t

* header_parser: added workaround for array in struct

- updated libclang example

* fix: exclude array of struct in struct

* config_provider: revamped internal API

Reason: Multiple seperate things were added whenever a config spec was added to the tool
regarding-
1. validate yaml, detect unknown keys
2. tracking default value
3. extracting from map
4. Warning user if config is required and isnt provided

All this is now being managed at one place, A map of Spec is provided using
the getSpecs function, Spec has everything listed above
Adding a configuration is simply adding a Spec to the map returned by getSpecs
in config.dart

* Removed generated binding's dependency on package:ffi

- updated examples, tests
- changed Char_S type to Int8 (previously Utf8)

* temp: adding cmake

* WIP: cmakefile

* fix: loading dylib for other platforms

- updated validator, extractor
- updated examples
- config: changed libclang-dylib to libclang-dylib-folder

* Added build script for windows: tool/wrapped_libclang/build_dylib_windows

* Windows Testing

- Added build scripts(.bat files) for building dll for examples/tests
- Updated exmaple's input header globs to work on Windows (Globs on windows dont work if they start with "." or".."
- Used path package instead

* added warn about removing functions, minor changes

* config_provider: minor changes - sizemap, enum, comments

- Added enum to sizemap
- warn unknown subkeys in sizemap
- config option to disable dartdoc comment extraction

* fixed tests, minor changes

* Added warning for TU diagnostic errors

* header_parser: handling unimplemented types

- Added a BroadType.unimplemented, which can be used to determine and remove types
- Removing functions and struct members if unimplemented types are used (and show warning) (earlier exception was thrown)
- Added a flag to remove function with constant array passed as parameter

* update readme, comments

* update readme(s), linked todos to github issues

* added copyright notice to code files, update readme(s)

* Self hosting the tool: added libclang_config.yaml

- Removed clang_constants.dart file, all bindings are now in clang_bindings.dart

- Added build_dylib_macos script

* Replace platform based build scripts with build.dart

* Improved comments in accordance with styleguide

* config_provider: refactoring

* Added 3 lint rules

- prefer_final_fields
- prefer_final_locals
- prefer_final_in_for_each

* config_provider: made libclang_dylib_folder optional

User now has an option to provide a seperate folder containing the dynamic library
The default is to use the dynamic libraries in the tool/wrapped_libclang folder

* header_parser: removed file extension checks

User can provide any file path or glob matcher.
If clang can't parse a header, we print a severe log
and skip that header

* minor changes

* Updated warnings/error logs

* Minor changes

- Added test/native_function_test/build_test_dylib.dart
- Updated comments
- Added top level third_party folder
- Updated examples, test with fixed comments

* minor comment fix

* Updated preamble message

Preamble on generated files is now
/// AUTO GENERATED FILE, DO NOT EDIT.
///
/// Generated by `package:ffigen`.

* Updated build.dart, build_test_dylib.dart, Minor changes

- Added map of <String, Options> for storing default values for all platforms
- Using Options instead of global variables

* Minor changes

* minor refactoring

Co-authored-by: Daco Harkes <dacoharkes@google.com>
diff --git a/.gitignore b/.gitignore
index 3d4ae48..57990d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,32 @@
 # See https://dart.dev/guides/libraries/private-files
 
-# Files and directories created by pub
+# Files and directories created by pub.
 .dart_tool/
 .packages
 pubspec.lock
+
+# Directory created by dartdoc.
+# If you don't generate documentation locally you can remove this line.
+doc/api/
+
+# Avoid committing generated Javascript files:
+*.dart.js
+*.info.json      # Produced by the --dump-info flag.
+*.js             # When generated by dart2js. Don't specify *.js if your
+                 # project includes source files written in JavaScript.
+*.js_
+*.js.deps
+*.js.map
+
+# Generated shared libraries.
+*.so
+*.so.*
+*.dylib
+*.dll
+
+# Directory for quick experiments.
+experiments/
+
+# Files generated by tests for debugging purposes.
+test/debug_generated/*
+!test/debug_generated/readme.md
diff --git a/AUTHORS b/AUTHORS
index 846e4a1..4f334e8 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -4,3 +4,5 @@
 #   Name/Organization <email address>
 
 Google LLC
+
+Prerak Mann <mannprerak2@gmail.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..8fcd296
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# 0.1.0
+- Initial release supporing binding generation for Functions, Structs, Enums.
+- Glob support for specifying headers.
+- HeaderFilter - Include/Exclude declarations from specific header files.
+- Filters - Include/Exclude function, structs and enum declarations using Regexp or Name matching.
diff --git a/README.md b/README.md
index 41a9d58..d85769b 100644
--- a/README.md
+++ b/README.md
@@ -2,3 +2,69 @@
 
 Experimental binding generator for [FFI](https://dart.dev/guides/libraries/c-interop)
 bindings.
+
+## Example
+
+For some header file _example.h_:
+```C
+int sum(int a, int b);
+```
+Add configurations to Pubspec File:
+```yaml
+ffigen:
+  output: 'generated_bindings.dart'
+  headers:
+    - 'example.h'
+```
+Output (_generated_bindings.dart_).
+```dart
+DynamicLibrary _dylib;
+
+/// Initialises dynamic library
+void init(DynamicLibrary dylib) {
+  _dylib = dylib;
+}
+
+int sum(int a,int b) {
+  return _sum(a,b);
+}
+
+final _dart_sum _sum = _dylib.lookupFunction<_c_sum, _dart_sum>('sum');
+
+typedef _c_sum = Int32 Function(Int32 a,Int32 b);
+
+typedef _dart_sum = int Function(int a,int b);
+```
+## Using this package
+- clone/download this repository.
+- Build it (see [building](#building)).
+- Add this package as dev_dependency in your `pubspec.yaml`.
+- Configurations must be provided in the pubspec.yaml file under the key `ffigen` (or directly under a seperate yaml file which when u specify it passing `--config filename` when running the tool)
+- Run the tool- `pub run ffigen:generate`.
+
+## Building
+A dynamic library for a wrapper to libclang needs to be generated as it is used by the parser submodule.
+
+#### ubuntu/linux
+1. Install libclangdev - `sudo apt-get install libclang-dev`.
+2. `cd tool/wrapped_libclang`, then run `dart build.dart`.
+
+#### Windows
+1. Install Visual Studio with C++ development support.
+2. Install LLVM.
+3. `cd tool\wrapped_libclang`, then run `dart build.dart`.
+
+#### MacOS
+1. Install LLVM.
+2. `cd tool/wrapped_libclang`, then run `dart build.dart`.
+
+## Trying out examples
+1. `cd examples/<example_u_want_to_run>`, Run `pub get`.
+2. Run `pub run ffigen:generate`.
+
+## Running Tests
+Dynamic library for some tests need to be built before running the examples.
+1. `cd test/native_functions_test`.
+2. Run `dart build_test_dylib.dart`.
+
+Run tests from the root of the package with `pub run test`.
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 108d105..fb0e867 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1 +1,19 @@
+# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
 include: package:pedantic/analysis_options.yaml
+
+analyzer:
+  strong-mode:
+    implicit-casts: false
+    implicit-dynamic: false
+  errors:
+    omit_local_variable_types: ignore
+
+linter:
+  rules:
+    - directives_ordering
+    - prefer_final_fields
+    - prefer_final_locals
+    - prefer_final_in_for_each
diff --git a/bin/generate.dart b/bin/generate.dart
new file mode 100644
index 0000000..7f29f2a
--- /dev/null
+++ b/bin/generate.dart
@@ -0,0 +1,176 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Executable script to generate bindings for some C library.
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:ffigen/src/config_provider.dart';
+import 'package:ffigen/src/header_parser.dart' as parser;
+import 'package:logging/logging.dart';
+import 'package:yaml/yaml.dart' as yaml;
+
+var _logger = Logger('generate.dart');
+
+void main(List<String> args) {
+  // Parses the cmd args.
+  final result = getArgResults(args);
+
+  // Setup logging level and printing.
+  setupLogger(result);
+
+  // Create a config object.
+  final config = getConfig(result);
+
+  // Parse the bindings according to config object provided.
+  final library = parser.parse(config);
+
+  if (config.sort) {
+    library.sort();
+  }
+
+  // Generate file for the parsed bindings.
+  final gen = File(config.output);
+  library.generateFile(gen);
+  _logger.info('Finished, Bindings generated in ${gen?.absolute?.path}');
+}
+
+Config getConfig(ArgResults result) {
+  _logger.info('Running in ${Directory.current}');
+
+  if (result.wasParsed('config')) {
+    return getConfigFromCustomYaml(result['config'] as String);
+  } else {
+    return getConfigFromPubspec();
+  }
+}
+
+/// Extracts configuration from pubspec file.
+Config getConfigFromPubspec() {
+  final pubspecName = 'pubspec.yaml';
+  final configKey = 'ffigen';
+
+  final pubspecFile = File(pubspecName);
+
+  if (!pubspecFile.existsSync()) {
+    _logger.severe(
+        'Error: $pubspecName not found, please run this tool from the root of your package.');
+    exit(1);
+  }
+
+  // Casting this because pubspec is expected to be a YamlMap.
+
+  // Throws a [YamlException] if it's unable to parse the Yaml.
+  final bindingsConfigMap =
+      yaml.loadYaml(pubspecFile.readAsStringSync())[configKey] as yaml.YamlMap;
+
+  if (bindingsConfigMap == null) {
+    _logger.severe("Couldn't find an entry for '$configKey' in $pubspecName.");
+    exit(1);
+  }
+  return Config.fromYaml(bindingsConfigMap);
+}
+
+/// Extracts configuration from a custom yaml file.
+Config getConfigFromCustomYaml(String yamlPath) {
+  final yamlFile = File(yamlPath);
+
+  if (!yamlFile.existsSync()) {
+    _logger.severe('Error: $yamlPath not found.');
+    exit(1);
+  }
+
+  // Throws a [YamlException] if it's unable to parse the Yaml.
+  final bindingsConfigMap =
+      yaml.loadYaml(yamlFile.readAsStringSync()) as yaml.YamlMap;
+
+  return Config.fromYaml(bindingsConfigMap);
+}
+
+/// Parses the cmd line arguments.
+ArgResults getArgResults(List<String> args) {
+  final parser = ArgParser(allowTrailingOptions: true);
+
+  parser.addSeparator(
+      'FFIGEN: Generate dart bindings from C header files\nUsage:');
+  parser.addOption(
+    'config',
+    help: 'path to Yaml file containing configurations if not in pubspec.yaml',
+  );
+  parser.addOption(
+    'verbose',
+    abbr: 'v',
+    defaultsTo: 'info',
+    allowed: [
+      'all',
+      'fine',
+      'info',
+      'warning',
+      'severe',
+    ],
+  );
+  parser.addFlag(
+    'help',
+    abbr: 'h',
+    help: 'prints this usage',
+    negatable: false,
+  );
+
+  ArgResults results;
+  try {
+    results = parser.parse(args);
+
+    if (results.wasParsed('help')) {
+      print(parser.usage);
+      exit(0);
+    }
+  } catch (e) {
+    print(e);
+    print(parser.usage);
+    exit(1);
+  }
+
+  return results;
+}
+
+/// Sets up the logging level and printing.
+void setupLogger(ArgResults result) {
+  if (result.wasParsed('verbose')) {
+    switch (result['verbose'] as String) {
+      case 'all':
+        // Logs everything, the entire AST touched by our parser.
+        Logger.root.level = Level.ALL;
+        break;
+      case 'fine':
+        // Logs AST parts relevant to user (i.e those included in filters).
+        Logger.root.level = Level.FINE;
+        break;
+      case 'info':
+        // Logs relevant info for general user (default).
+        Logger.root.level = Level.INFO;
+        break;
+      case 'warning':
+        // Logs warnings for relevant stuff.
+        Logger.root.level = Level.WARNING;
+        break;
+      case 'severe':
+        // Logs severe warnings and errors.
+        Logger.root.level = Level.SEVERE;
+        break;
+    }
+    // Setup logger for printing (if verbosity was set by user).
+    Logger.root.onRecord.listen((record) {
+      print('${record.level.name.padRight(8)}: ${record.message}');
+    });
+  } else {
+    // Setup logger for printing (if verbosity was not set by user).
+    Logger.root.onRecord.listen((record) {
+      if (record.level.value > Level.INFO.value) {
+        print('  ${record.level.name.padRight(8)}: ${record.message}');
+      } else {
+        print(record.message);
+      }
+    });
+  }
+}
diff --git a/example/c_json/.gitignore b/example/c_json/.gitignore
new file mode 100644
index 0000000..1b05164
--- /dev/null
+++ b/example/c_json/.gitignore
@@ -0,0 +1,11 @@
+# Files and directories created by pub.
+.dart_tool/
+.packages
+# Remove the following pattern if you wish to check in your lock file.
+pubspec.lock
+
+# Conventional directory for build outputs.
+build/
+
+# Directory created by dartdoc.
+doc/api/
diff --git a/example/c_json/README.md b/example/c_json/README.md
new file mode 100644
index 0000000..9ba9d43
--- /dev/null
+++ b/example/c_json/README.md
@@ -0,0 +1,25 @@
+# cJson example
+
+Demonstrates generation of bindings for a C library called
+[cJson](https://github.com/DaveGamble/cJSON) and then using these bindings
+to parse some json.
+
+## Building the cJson dynamic library
+From the root of this repository -
+```
+cd third_party/cjson_library
+cmake .
+make
+```
+
+## Generating bindings
+At the root of this example (`example/c_json`), run -
+```
+pub run ffigen:generate
+```
+This will generate bindings in a file: [cjson_generated_bindings.dart](./cjson_generated_bindings.dart)
+
+## Running the example
+```
+dart main.dart
+```
diff --git a/example/c_json/cjson_generated_bindings.dart b/example/c_json/cjson_generated_bindings.dart
new file mode 100644
index 0000000..1cf00a3
--- /dev/null
+++ b/example/c_json/cjson_generated_bindings.dart
@@ -0,0 +1,1691 @@
+/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib) {
+  _dylib = dylib;
+}
+
+class cJSON extends ffi.Struct {
+  ffi.Pointer<cJSON> next;
+
+  ffi.Pointer<cJSON> prev;
+
+  ffi.Pointer<cJSON> child;
+
+  @ffi.Int32()
+  int type;
+
+  ffi.Pointer<ffi.Int8> valuestring;
+
+  @ffi.Int32()
+  int valueint;
+
+  @ffi.Double()
+  double valuedouble;
+
+  ffi.Pointer<ffi.Int8> string;
+}
+
+typedef _typedefC_noname_1 = ffi.Pointer<ffi.Void> Function(
+  ffi.Uint64,
+);
+
+typedef _typedefC_noname_2 = ffi.Void Function(
+  ffi.Pointer<ffi.Void>,
+);
+
+class cJSON_Hooks extends ffi.Struct {
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_1>> malloc_fn;
+
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_2>> free_fn;
+}
+
+ffi.Pointer<ffi.Int8> cJSON_Version() {
+  return _cJSON_Version();
+}
+
+final _dart_cJSON_Version _cJSON_Version = _dylib
+    .lookupFunction<_c_cJSON_Version, _dart_cJSON_Version>('cJSON_Version');
+
+typedef _c_cJSON_Version = ffi.Pointer<ffi.Int8> Function();
+
+typedef _dart_cJSON_Version = ffi.Pointer<ffi.Int8> Function();
+
+void cJSON_InitHooks(
+  ffi.Pointer<cJSON_Hooks> hooks,
+) {
+  return _cJSON_InitHooks(
+    hooks,
+  );
+}
+
+final _dart_cJSON_InitHooks _cJSON_InitHooks =
+    _dylib.lookupFunction<_c_cJSON_InitHooks, _dart_cJSON_InitHooks>(
+        'cJSON_InitHooks');
+
+typedef _c_cJSON_InitHooks = ffi.Void Function(
+  ffi.Pointer<cJSON_Hooks> hooks,
+);
+
+typedef _dart_cJSON_InitHooks = void Function(
+  ffi.Pointer<cJSON_Hooks> hooks,
+);
+
+ffi.Pointer<cJSON> cJSON_Parse(
+  ffi.Pointer<ffi.Int8> value,
+) {
+  return _cJSON_Parse(
+    value,
+  );
+}
+
+final _dart_cJSON_Parse _cJSON_Parse =
+    _dylib.lookupFunction<_c_cJSON_Parse, _dart_cJSON_Parse>('cJSON_Parse');
+
+typedef _c_cJSON_Parse = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int8> value,
+);
+
+typedef _dart_cJSON_Parse = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int8> value,
+);
+
+ffi.Pointer<cJSON> cJSON_ParseWithOpts(
+  ffi.Pointer<ffi.Int8> value,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> return_parse_end,
+  int require_null_terminated,
+) {
+  return _cJSON_ParseWithOpts(
+    value,
+    return_parse_end,
+    require_null_terminated,
+  );
+}
+
+final _dart_cJSON_ParseWithOpts _cJSON_ParseWithOpts =
+    _dylib.lookupFunction<_c_cJSON_ParseWithOpts, _dart_cJSON_ParseWithOpts>(
+        'cJSON_ParseWithOpts');
+
+typedef _c_cJSON_ParseWithOpts = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int8> value,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> return_parse_end,
+  ffi.Int32 require_null_terminated,
+);
+
+typedef _dart_cJSON_ParseWithOpts = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int8> value,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> return_parse_end,
+  int require_null_terminated,
+);
+
+ffi.Pointer<ffi.Int8> cJSON_Print(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_Print(
+    item,
+  );
+}
+
+final _dart_cJSON_Print _cJSON_Print =
+    _dylib.lookupFunction<_c_cJSON_Print, _dart_cJSON_Print>('cJSON_Print');
+
+typedef _c_cJSON_Print = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_Print = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<cJSON> item,
+);
+
+ffi.Pointer<ffi.Int8> cJSON_PrintUnformatted(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_PrintUnformatted(
+    item,
+  );
+}
+
+final _dart_cJSON_PrintUnformatted _cJSON_PrintUnformatted = _dylib
+    .lookupFunction<_c_cJSON_PrintUnformatted, _dart_cJSON_PrintUnformatted>(
+        'cJSON_PrintUnformatted');
+
+typedef _c_cJSON_PrintUnformatted = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_PrintUnformatted = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<cJSON> item,
+);
+
+ffi.Pointer<ffi.Int8> cJSON_PrintBuffered(
+  ffi.Pointer<cJSON> item,
+  int prebuffer,
+  int fmt,
+) {
+  return _cJSON_PrintBuffered(
+    item,
+    prebuffer,
+    fmt,
+  );
+}
+
+final _dart_cJSON_PrintBuffered _cJSON_PrintBuffered =
+    _dylib.lookupFunction<_c_cJSON_PrintBuffered, _dart_cJSON_PrintBuffered>(
+        'cJSON_PrintBuffered');
+
+typedef _c_cJSON_PrintBuffered = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<cJSON> item,
+  ffi.Int32 prebuffer,
+  ffi.Int32 fmt,
+);
+
+typedef _dart_cJSON_PrintBuffered = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<cJSON> item,
+  int prebuffer,
+  int fmt,
+);
+
+int cJSON_PrintPreallocated(
+  ffi.Pointer<cJSON> item,
+  ffi.Pointer<ffi.Int8> buffer,
+  int length,
+  int format,
+) {
+  return _cJSON_PrintPreallocated(
+    item,
+    buffer,
+    length,
+    format,
+  );
+}
+
+final _dart_cJSON_PrintPreallocated _cJSON_PrintPreallocated = _dylib
+    .lookupFunction<_c_cJSON_PrintPreallocated, _dart_cJSON_PrintPreallocated>(
+        'cJSON_PrintPreallocated');
+
+typedef _c_cJSON_PrintPreallocated = ffi.Int32 Function(
+  ffi.Pointer<cJSON> item,
+  ffi.Pointer<ffi.Int8> buffer,
+  ffi.Int32 length,
+  ffi.Int32 format,
+);
+
+typedef _dart_cJSON_PrintPreallocated = int Function(
+  ffi.Pointer<cJSON> item,
+  ffi.Pointer<ffi.Int8> buffer,
+  int length,
+  int format,
+);
+
+void cJSON_Delete(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_Delete(
+    item,
+  );
+}
+
+final _dart_cJSON_Delete _cJSON_Delete =
+    _dylib.lookupFunction<_c_cJSON_Delete, _dart_cJSON_Delete>('cJSON_Delete');
+
+typedef _c_cJSON_Delete = ffi.Void Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_Delete = void Function(
+  ffi.Pointer<cJSON> item,
+);
+
+int cJSON_GetArraySize(
+  ffi.Pointer<cJSON> array,
+) {
+  return _cJSON_GetArraySize(
+    array,
+  );
+}
+
+final _dart_cJSON_GetArraySize _cJSON_GetArraySize =
+    _dylib.lookupFunction<_c_cJSON_GetArraySize, _dart_cJSON_GetArraySize>(
+        'cJSON_GetArraySize');
+
+typedef _c_cJSON_GetArraySize = ffi.Int32 Function(
+  ffi.Pointer<cJSON> array,
+);
+
+typedef _dart_cJSON_GetArraySize = int Function(
+  ffi.Pointer<cJSON> array,
+);
+
+ffi.Pointer<cJSON> cJSON_GetArrayItem(
+  ffi.Pointer<cJSON> array,
+  int index,
+) {
+  return _cJSON_GetArrayItem(
+    array,
+    index,
+  );
+}
+
+final _dart_cJSON_GetArrayItem _cJSON_GetArrayItem =
+    _dylib.lookupFunction<_c_cJSON_GetArrayItem, _dart_cJSON_GetArrayItem>(
+        'cJSON_GetArrayItem');
+
+typedef _c_cJSON_GetArrayItem = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> array,
+  ffi.Int32 index,
+);
+
+typedef _dart_cJSON_GetArrayItem = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> array,
+  int index,
+);
+
+ffi.Pointer<cJSON> cJSON_GetObjectItem(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+) {
+  return _cJSON_GetObjectItem(
+    object,
+    string,
+  );
+}
+
+final _dart_cJSON_GetObjectItem _cJSON_GetObjectItem =
+    _dylib.lookupFunction<_c_cJSON_GetObjectItem, _dart_cJSON_GetObjectItem>(
+        'cJSON_GetObjectItem');
+
+typedef _c_cJSON_GetObjectItem = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+typedef _dart_cJSON_GetObjectItem = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+ffi.Pointer<cJSON> cJSON_GetObjectItemCaseSensitive(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+) {
+  return _cJSON_GetObjectItemCaseSensitive(
+    object,
+    string,
+  );
+}
+
+final _dart_cJSON_GetObjectItemCaseSensitive _cJSON_GetObjectItemCaseSensitive =
+    _dylib.lookupFunction<_c_cJSON_GetObjectItemCaseSensitive,
+            _dart_cJSON_GetObjectItemCaseSensitive>(
+        'cJSON_GetObjectItemCaseSensitive');
+
+typedef _c_cJSON_GetObjectItemCaseSensitive = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+typedef _dart_cJSON_GetObjectItemCaseSensitive = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+int cJSON_HasObjectItem(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+) {
+  return _cJSON_HasObjectItem(
+    object,
+    string,
+  );
+}
+
+final _dart_cJSON_HasObjectItem _cJSON_HasObjectItem =
+    _dylib.lookupFunction<_c_cJSON_HasObjectItem, _dart_cJSON_HasObjectItem>(
+        'cJSON_HasObjectItem');
+
+typedef _c_cJSON_HasObjectItem = ffi.Int32 Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+typedef _dart_cJSON_HasObjectItem = int Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+ffi.Pointer<ffi.Int8> cJSON_GetErrorPtr() {
+  return _cJSON_GetErrorPtr();
+}
+
+final _dart_cJSON_GetErrorPtr _cJSON_GetErrorPtr =
+    _dylib.lookupFunction<_c_cJSON_GetErrorPtr, _dart_cJSON_GetErrorPtr>(
+        'cJSON_GetErrorPtr');
+
+typedef _c_cJSON_GetErrorPtr = ffi.Pointer<ffi.Int8> Function();
+
+typedef _dart_cJSON_GetErrorPtr = ffi.Pointer<ffi.Int8> Function();
+
+ffi.Pointer<ffi.Int8> cJSON_GetStringValue(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_GetStringValue(
+    item,
+  );
+}
+
+final _dart_cJSON_GetStringValue _cJSON_GetStringValue =
+    _dylib.lookupFunction<_c_cJSON_GetStringValue, _dart_cJSON_GetStringValue>(
+        'cJSON_GetStringValue');
+
+typedef _c_cJSON_GetStringValue = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_GetStringValue = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<cJSON> item,
+);
+
+int cJSON_IsInvalid(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_IsInvalid(
+    item,
+  );
+}
+
+final _dart_cJSON_IsInvalid _cJSON_IsInvalid =
+    _dylib.lookupFunction<_c_cJSON_IsInvalid, _dart_cJSON_IsInvalid>(
+        'cJSON_IsInvalid');
+
+typedef _c_cJSON_IsInvalid = ffi.Int32 Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_IsInvalid = int Function(
+  ffi.Pointer<cJSON> item,
+);
+
+int cJSON_IsFalse(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_IsFalse(
+    item,
+  );
+}
+
+final _dart_cJSON_IsFalse _cJSON_IsFalse = _dylib
+    .lookupFunction<_c_cJSON_IsFalse, _dart_cJSON_IsFalse>('cJSON_IsFalse');
+
+typedef _c_cJSON_IsFalse = ffi.Int32 Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_IsFalse = int Function(
+  ffi.Pointer<cJSON> item,
+);
+
+int cJSON_IsTrue(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_IsTrue(
+    item,
+  );
+}
+
+final _dart_cJSON_IsTrue _cJSON_IsTrue =
+    _dylib.lookupFunction<_c_cJSON_IsTrue, _dart_cJSON_IsTrue>('cJSON_IsTrue');
+
+typedef _c_cJSON_IsTrue = ffi.Int32 Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_IsTrue = int Function(
+  ffi.Pointer<cJSON> item,
+);
+
+int cJSON_IsBool(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_IsBool(
+    item,
+  );
+}
+
+final _dart_cJSON_IsBool _cJSON_IsBool =
+    _dylib.lookupFunction<_c_cJSON_IsBool, _dart_cJSON_IsBool>('cJSON_IsBool');
+
+typedef _c_cJSON_IsBool = ffi.Int32 Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_IsBool = int Function(
+  ffi.Pointer<cJSON> item,
+);
+
+int cJSON_IsNull(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_IsNull(
+    item,
+  );
+}
+
+final _dart_cJSON_IsNull _cJSON_IsNull =
+    _dylib.lookupFunction<_c_cJSON_IsNull, _dart_cJSON_IsNull>('cJSON_IsNull');
+
+typedef _c_cJSON_IsNull = ffi.Int32 Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_IsNull = int Function(
+  ffi.Pointer<cJSON> item,
+);
+
+int cJSON_IsNumber(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_IsNumber(
+    item,
+  );
+}
+
+final _dart_cJSON_IsNumber _cJSON_IsNumber = _dylib
+    .lookupFunction<_c_cJSON_IsNumber, _dart_cJSON_IsNumber>('cJSON_IsNumber');
+
+typedef _c_cJSON_IsNumber = ffi.Int32 Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_IsNumber = int Function(
+  ffi.Pointer<cJSON> item,
+);
+
+int cJSON_IsString(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_IsString(
+    item,
+  );
+}
+
+final _dart_cJSON_IsString _cJSON_IsString = _dylib
+    .lookupFunction<_c_cJSON_IsString, _dart_cJSON_IsString>('cJSON_IsString');
+
+typedef _c_cJSON_IsString = ffi.Int32 Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_IsString = int Function(
+  ffi.Pointer<cJSON> item,
+);
+
+int cJSON_IsArray(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_IsArray(
+    item,
+  );
+}
+
+final _dart_cJSON_IsArray _cJSON_IsArray = _dylib
+    .lookupFunction<_c_cJSON_IsArray, _dart_cJSON_IsArray>('cJSON_IsArray');
+
+typedef _c_cJSON_IsArray = ffi.Int32 Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_IsArray = int Function(
+  ffi.Pointer<cJSON> item,
+);
+
+int cJSON_IsObject(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_IsObject(
+    item,
+  );
+}
+
+final _dart_cJSON_IsObject _cJSON_IsObject = _dylib
+    .lookupFunction<_c_cJSON_IsObject, _dart_cJSON_IsObject>('cJSON_IsObject');
+
+typedef _c_cJSON_IsObject = ffi.Int32 Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_IsObject = int Function(
+  ffi.Pointer<cJSON> item,
+);
+
+int cJSON_IsRaw(
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_IsRaw(
+    item,
+  );
+}
+
+final _dart_cJSON_IsRaw _cJSON_IsRaw =
+    _dylib.lookupFunction<_c_cJSON_IsRaw, _dart_cJSON_IsRaw>('cJSON_IsRaw');
+
+typedef _c_cJSON_IsRaw = ffi.Int32 Function(
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_IsRaw = int Function(
+  ffi.Pointer<cJSON> item,
+);
+
+ffi.Pointer<cJSON> cJSON_CreateNull() {
+  return _cJSON_CreateNull();
+}
+
+final _dart_cJSON_CreateNull _cJSON_CreateNull =
+    _dylib.lookupFunction<_c_cJSON_CreateNull, _dart_cJSON_CreateNull>(
+        'cJSON_CreateNull');
+
+typedef _c_cJSON_CreateNull = ffi.Pointer<cJSON> Function();
+
+typedef _dart_cJSON_CreateNull = ffi.Pointer<cJSON> Function();
+
+ffi.Pointer<cJSON> cJSON_CreateTrue() {
+  return _cJSON_CreateTrue();
+}
+
+final _dart_cJSON_CreateTrue _cJSON_CreateTrue =
+    _dylib.lookupFunction<_c_cJSON_CreateTrue, _dart_cJSON_CreateTrue>(
+        'cJSON_CreateTrue');
+
+typedef _c_cJSON_CreateTrue = ffi.Pointer<cJSON> Function();
+
+typedef _dart_cJSON_CreateTrue = ffi.Pointer<cJSON> Function();
+
+ffi.Pointer<cJSON> cJSON_CreateFalse() {
+  return _cJSON_CreateFalse();
+}
+
+final _dart_cJSON_CreateFalse _cJSON_CreateFalse =
+    _dylib.lookupFunction<_c_cJSON_CreateFalse, _dart_cJSON_CreateFalse>(
+        'cJSON_CreateFalse');
+
+typedef _c_cJSON_CreateFalse = ffi.Pointer<cJSON> Function();
+
+typedef _dart_cJSON_CreateFalse = ffi.Pointer<cJSON> Function();
+
+ffi.Pointer<cJSON> cJSON_CreateBool(
+  int boolean,
+) {
+  return _cJSON_CreateBool(
+    boolean,
+  );
+}
+
+final _dart_cJSON_CreateBool _cJSON_CreateBool =
+    _dylib.lookupFunction<_c_cJSON_CreateBool, _dart_cJSON_CreateBool>(
+        'cJSON_CreateBool');
+
+typedef _c_cJSON_CreateBool = ffi.Pointer<cJSON> Function(
+  ffi.Int32 boolean,
+);
+
+typedef _dart_cJSON_CreateBool = ffi.Pointer<cJSON> Function(
+  int boolean,
+);
+
+ffi.Pointer<cJSON> cJSON_CreateNumber(
+  double num,
+) {
+  return _cJSON_CreateNumber(
+    num,
+  );
+}
+
+final _dart_cJSON_CreateNumber _cJSON_CreateNumber =
+    _dylib.lookupFunction<_c_cJSON_CreateNumber, _dart_cJSON_CreateNumber>(
+        'cJSON_CreateNumber');
+
+typedef _c_cJSON_CreateNumber = ffi.Pointer<cJSON> Function(
+  ffi.Double num,
+);
+
+typedef _dart_cJSON_CreateNumber = ffi.Pointer<cJSON> Function(
+  double num,
+);
+
+ffi.Pointer<cJSON> cJSON_CreateString(
+  ffi.Pointer<ffi.Int8> string,
+) {
+  return _cJSON_CreateString(
+    string,
+  );
+}
+
+final _dart_cJSON_CreateString _cJSON_CreateString =
+    _dylib.lookupFunction<_c_cJSON_CreateString, _dart_cJSON_CreateString>(
+        'cJSON_CreateString');
+
+typedef _c_cJSON_CreateString = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int8> string,
+);
+
+typedef _dart_cJSON_CreateString = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int8> string,
+);
+
+ffi.Pointer<cJSON> cJSON_CreateRaw(
+  ffi.Pointer<ffi.Int8> raw,
+) {
+  return _cJSON_CreateRaw(
+    raw,
+  );
+}
+
+final _dart_cJSON_CreateRaw _cJSON_CreateRaw =
+    _dylib.lookupFunction<_c_cJSON_CreateRaw, _dart_cJSON_CreateRaw>(
+        'cJSON_CreateRaw');
+
+typedef _c_cJSON_CreateRaw = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int8> raw,
+);
+
+typedef _dart_cJSON_CreateRaw = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int8> raw,
+);
+
+ffi.Pointer<cJSON> cJSON_CreateArray() {
+  return _cJSON_CreateArray();
+}
+
+final _dart_cJSON_CreateArray _cJSON_CreateArray =
+    _dylib.lookupFunction<_c_cJSON_CreateArray, _dart_cJSON_CreateArray>(
+        'cJSON_CreateArray');
+
+typedef _c_cJSON_CreateArray = ffi.Pointer<cJSON> Function();
+
+typedef _dart_cJSON_CreateArray = ffi.Pointer<cJSON> Function();
+
+ffi.Pointer<cJSON> cJSON_CreateObject() {
+  return _cJSON_CreateObject();
+}
+
+final _dart_cJSON_CreateObject _cJSON_CreateObject =
+    _dylib.lookupFunction<_c_cJSON_CreateObject, _dart_cJSON_CreateObject>(
+        'cJSON_CreateObject');
+
+typedef _c_cJSON_CreateObject = ffi.Pointer<cJSON> Function();
+
+typedef _dart_cJSON_CreateObject = ffi.Pointer<cJSON> Function();
+
+ffi.Pointer<cJSON> cJSON_CreateStringReference(
+  ffi.Pointer<ffi.Int8> string,
+) {
+  return _cJSON_CreateStringReference(
+    string,
+  );
+}
+
+final _dart_cJSON_CreateStringReference _cJSON_CreateStringReference =
+    _dylib.lookupFunction<_c_cJSON_CreateStringReference,
+        _dart_cJSON_CreateStringReference>('cJSON_CreateStringReference');
+
+typedef _c_cJSON_CreateStringReference = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int8> string,
+);
+
+typedef _dart_cJSON_CreateStringReference = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int8> string,
+);
+
+ffi.Pointer<cJSON> cJSON_CreateObjectReference(
+  ffi.Pointer<cJSON> child,
+) {
+  return _cJSON_CreateObjectReference(
+    child,
+  );
+}
+
+final _dart_cJSON_CreateObjectReference _cJSON_CreateObjectReference =
+    _dylib.lookupFunction<_c_cJSON_CreateObjectReference,
+        _dart_cJSON_CreateObjectReference>('cJSON_CreateObjectReference');
+
+typedef _c_cJSON_CreateObjectReference = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> child,
+);
+
+typedef _dart_cJSON_CreateObjectReference = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> child,
+);
+
+ffi.Pointer<cJSON> cJSON_CreateArrayReference(
+  ffi.Pointer<cJSON> child,
+) {
+  return _cJSON_CreateArrayReference(
+    child,
+  );
+}
+
+final _dart_cJSON_CreateArrayReference _cJSON_CreateArrayReference =
+    _dylib.lookupFunction<_c_cJSON_CreateArrayReference,
+        _dart_cJSON_CreateArrayReference>('cJSON_CreateArrayReference');
+
+typedef _c_cJSON_CreateArrayReference = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> child,
+);
+
+typedef _dart_cJSON_CreateArrayReference = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> child,
+);
+
+ffi.Pointer<cJSON> cJSON_CreateIntArray(
+  ffi.Pointer<ffi.Int32> numbers,
+  int count,
+) {
+  return _cJSON_CreateIntArray(
+    numbers,
+    count,
+  );
+}
+
+final _dart_cJSON_CreateIntArray _cJSON_CreateIntArray =
+    _dylib.lookupFunction<_c_cJSON_CreateIntArray, _dart_cJSON_CreateIntArray>(
+        'cJSON_CreateIntArray');
+
+typedef _c_cJSON_CreateIntArray = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int32> numbers,
+  ffi.Int32 count,
+);
+
+typedef _dart_cJSON_CreateIntArray = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Int32> numbers,
+  int count,
+);
+
+ffi.Pointer<cJSON> cJSON_CreateFloatArray(
+  ffi.Pointer<ffi.Float> numbers,
+  int count,
+) {
+  return _cJSON_CreateFloatArray(
+    numbers,
+    count,
+  );
+}
+
+final _dart_cJSON_CreateFloatArray _cJSON_CreateFloatArray = _dylib
+    .lookupFunction<_c_cJSON_CreateFloatArray, _dart_cJSON_CreateFloatArray>(
+        'cJSON_CreateFloatArray');
+
+typedef _c_cJSON_CreateFloatArray = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Float> numbers,
+  ffi.Int32 count,
+);
+
+typedef _dart_cJSON_CreateFloatArray = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Float> numbers,
+  int count,
+);
+
+ffi.Pointer<cJSON> cJSON_CreateDoubleArray(
+  ffi.Pointer<ffi.Double> numbers,
+  int count,
+) {
+  return _cJSON_CreateDoubleArray(
+    numbers,
+    count,
+  );
+}
+
+final _dart_cJSON_CreateDoubleArray _cJSON_CreateDoubleArray = _dylib
+    .lookupFunction<_c_cJSON_CreateDoubleArray, _dart_cJSON_CreateDoubleArray>(
+        'cJSON_CreateDoubleArray');
+
+typedef _c_cJSON_CreateDoubleArray = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Double> numbers,
+  ffi.Int32 count,
+);
+
+typedef _dart_cJSON_CreateDoubleArray = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Double> numbers,
+  int count,
+);
+
+ffi.Pointer<cJSON> cJSON_CreateStringArray(
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> strings,
+  int count,
+) {
+  return _cJSON_CreateStringArray(
+    strings,
+    count,
+  );
+}
+
+final _dart_cJSON_CreateStringArray _cJSON_CreateStringArray = _dylib
+    .lookupFunction<_c_cJSON_CreateStringArray, _dart_cJSON_CreateStringArray>(
+        'cJSON_CreateStringArray');
+
+typedef _c_cJSON_CreateStringArray = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> strings,
+  ffi.Int32 count,
+);
+
+typedef _dart_cJSON_CreateStringArray = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> strings,
+  int count,
+);
+
+void cJSON_AddItemToArray(
+  ffi.Pointer<cJSON> array,
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_AddItemToArray(
+    array,
+    item,
+  );
+}
+
+final _dart_cJSON_AddItemToArray _cJSON_AddItemToArray =
+    _dylib.lookupFunction<_c_cJSON_AddItemToArray, _dart_cJSON_AddItemToArray>(
+        'cJSON_AddItemToArray');
+
+typedef _c_cJSON_AddItemToArray = ffi.Void Function(
+  ffi.Pointer<cJSON> array,
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_AddItemToArray = void Function(
+  ffi.Pointer<cJSON> array,
+  ffi.Pointer<cJSON> item,
+);
+
+void cJSON_AddItemToObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_AddItemToObject(
+    object,
+    string,
+    item,
+  );
+}
+
+final _dart_cJSON_AddItemToObject _cJSON_AddItemToObject = _dylib
+    .lookupFunction<_c_cJSON_AddItemToObject, _dart_cJSON_AddItemToObject>(
+        'cJSON_AddItemToObject');
+
+typedef _c_cJSON_AddItemToObject = ffi.Void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_AddItemToObject = void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> item,
+);
+
+void cJSON_AddItemToObjectCS(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_AddItemToObjectCS(
+    object,
+    string,
+    item,
+  );
+}
+
+final _dart_cJSON_AddItemToObjectCS _cJSON_AddItemToObjectCS = _dylib
+    .lookupFunction<_c_cJSON_AddItemToObjectCS, _dart_cJSON_AddItemToObjectCS>(
+        'cJSON_AddItemToObjectCS');
+
+typedef _c_cJSON_AddItemToObjectCS = ffi.Void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_AddItemToObjectCS = void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> item,
+);
+
+void cJSON_AddItemReferenceToArray(
+  ffi.Pointer<cJSON> array,
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_AddItemReferenceToArray(
+    array,
+    item,
+  );
+}
+
+final _dart_cJSON_AddItemReferenceToArray _cJSON_AddItemReferenceToArray =
+    _dylib.lookupFunction<_c_cJSON_AddItemReferenceToArray,
+        _dart_cJSON_AddItemReferenceToArray>('cJSON_AddItemReferenceToArray');
+
+typedef _c_cJSON_AddItemReferenceToArray = ffi.Void Function(
+  ffi.Pointer<cJSON> array,
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_AddItemReferenceToArray = void Function(
+  ffi.Pointer<cJSON> array,
+  ffi.Pointer<cJSON> item,
+);
+
+void cJSON_AddItemReferenceToObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_AddItemReferenceToObject(
+    object,
+    string,
+    item,
+  );
+}
+
+final _dart_cJSON_AddItemReferenceToObject _cJSON_AddItemReferenceToObject =
+    _dylib.lookupFunction<_c_cJSON_AddItemReferenceToObject,
+        _dart_cJSON_AddItemReferenceToObject>('cJSON_AddItemReferenceToObject');
+
+typedef _c_cJSON_AddItemReferenceToObject = ffi.Void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_AddItemReferenceToObject = void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> item,
+);
+
+ffi.Pointer<cJSON> cJSON_DetachItemViaPointer(
+  ffi.Pointer<cJSON> parent,
+  ffi.Pointer<cJSON> item,
+) {
+  return _cJSON_DetachItemViaPointer(
+    parent,
+    item,
+  );
+}
+
+final _dart_cJSON_DetachItemViaPointer _cJSON_DetachItemViaPointer =
+    _dylib.lookupFunction<_c_cJSON_DetachItemViaPointer,
+        _dart_cJSON_DetachItemViaPointer>('cJSON_DetachItemViaPointer');
+
+typedef _c_cJSON_DetachItemViaPointer = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> parent,
+  ffi.Pointer<cJSON> item,
+);
+
+typedef _dart_cJSON_DetachItemViaPointer = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> parent,
+  ffi.Pointer<cJSON> item,
+);
+
+ffi.Pointer<cJSON> cJSON_DetachItemFromArray(
+  ffi.Pointer<cJSON> array,
+  int which,
+) {
+  return _cJSON_DetachItemFromArray(
+    array,
+    which,
+  );
+}
+
+final _dart_cJSON_DetachItemFromArray _cJSON_DetachItemFromArray =
+    _dylib.lookupFunction<_c_cJSON_DetachItemFromArray,
+        _dart_cJSON_DetachItemFromArray>('cJSON_DetachItemFromArray');
+
+typedef _c_cJSON_DetachItemFromArray = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> array,
+  ffi.Int32 which,
+);
+
+typedef _dart_cJSON_DetachItemFromArray = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> array,
+  int which,
+);
+
+void cJSON_DeleteItemFromArray(
+  ffi.Pointer<cJSON> array,
+  int which,
+) {
+  return _cJSON_DeleteItemFromArray(
+    array,
+    which,
+  );
+}
+
+final _dart_cJSON_DeleteItemFromArray _cJSON_DeleteItemFromArray =
+    _dylib.lookupFunction<_c_cJSON_DeleteItemFromArray,
+        _dart_cJSON_DeleteItemFromArray>('cJSON_DeleteItemFromArray');
+
+typedef _c_cJSON_DeleteItemFromArray = ffi.Void Function(
+  ffi.Pointer<cJSON> array,
+  ffi.Int32 which,
+);
+
+typedef _dart_cJSON_DeleteItemFromArray = void Function(
+  ffi.Pointer<cJSON> array,
+  int which,
+);
+
+ffi.Pointer<cJSON> cJSON_DetachItemFromObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+) {
+  return _cJSON_DetachItemFromObject(
+    object,
+    string,
+  );
+}
+
+final _dart_cJSON_DetachItemFromObject _cJSON_DetachItemFromObject =
+    _dylib.lookupFunction<_c_cJSON_DetachItemFromObject,
+        _dart_cJSON_DetachItemFromObject>('cJSON_DetachItemFromObject');
+
+typedef _c_cJSON_DetachItemFromObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+typedef _dart_cJSON_DetachItemFromObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+ffi.Pointer<cJSON> cJSON_DetachItemFromObjectCaseSensitive(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+) {
+  return _cJSON_DetachItemFromObjectCaseSensitive(
+    object,
+    string,
+  );
+}
+
+final _dart_cJSON_DetachItemFromObjectCaseSensitive
+    _cJSON_DetachItemFromObjectCaseSensitive = _dylib.lookupFunction<
+            _c_cJSON_DetachItemFromObjectCaseSensitive,
+            _dart_cJSON_DetachItemFromObjectCaseSensitive>(
+        'cJSON_DetachItemFromObjectCaseSensitive');
+
+typedef _c_cJSON_DetachItemFromObjectCaseSensitive = ffi.Pointer<cJSON>
+    Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+typedef _dart_cJSON_DetachItemFromObjectCaseSensitive = ffi.Pointer<cJSON>
+    Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+void cJSON_DeleteItemFromObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+) {
+  return _cJSON_DeleteItemFromObject(
+    object,
+    string,
+  );
+}
+
+final _dart_cJSON_DeleteItemFromObject _cJSON_DeleteItemFromObject =
+    _dylib.lookupFunction<_c_cJSON_DeleteItemFromObject,
+        _dart_cJSON_DeleteItemFromObject>('cJSON_DeleteItemFromObject');
+
+typedef _c_cJSON_DeleteItemFromObject = ffi.Void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+typedef _dart_cJSON_DeleteItemFromObject = void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+void cJSON_DeleteItemFromObjectCaseSensitive(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+) {
+  return _cJSON_DeleteItemFromObjectCaseSensitive(
+    object,
+    string,
+  );
+}
+
+final _dart_cJSON_DeleteItemFromObjectCaseSensitive
+    _cJSON_DeleteItemFromObjectCaseSensitive = _dylib.lookupFunction<
+            _c_cJSON_DeleteItemFromObjectCaseSensitive,
+            _dart_cJSON_DeleteItemFromObjectCaseSensitive>(
+        'cJSON_DeleteItemFromObjectCaseSensitive');
+
+typedef _c_cJSON_DeleteItemFromObjectCaseSensitive = ffi.Void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+typedef _dart_cJSON_DeleteItemFromObjectCaseSensitive = void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+void cJSON_InsertItemInArray(
+  ffi.Pointer<cJSON> array,
+  int which,
+  ffi.Pointer<cJSON> newitem,
+) {
+  return _cJSON_InsertItemInArray(
+    array,
+    which,
+    newitem,
+  );
+}
+
+final _dart_cJSON_InsertItemInArray _cJSON_InsertItemInArray = _dylib
+    .lookupFunction<_c_cJSON_InsertItemInArray, _dart_cJSON_InsertItemInArray>(
+        'cJSON_InsertItemInArray');
+
+typedef _c_cJSON_InsertItemInArray = ffi.Void Function(
+  ffi.Pointer<cJSON> array,
+  ffi.Int32 which,
+  ffi.Pointer<cJSON> newitem,
+);
+
+typedef _dart_cJSON_InsertItemInArray = void Function(
+  ffi.Pointer<cJSON> array,
+  int which,
+  ffi.Pointer<cJSON> newitem,
+);
+
+int cJSON_ReplaceItemViaPointer(
+  ffi.Pointer<cJSON> parent,
+  ffi.Pointer<cJSON> item,
+  ffi.Pointer<cJSON> replacement,
+) {
+  return _cJSON_ReplaceItemViaPointer(
+    parent,
+    item,
+    replacement,
+  );
+}
+
+final _dart_cJSON_ReplaceItemViaPointer _cJSON_ReplaceItemViaPointer =
+    _dylib.lookupFunction<_c_cJSON_ReplaceItemViaPointer,
+        _dart_cJSON_ReplaceItemViaPointer>('cJSON_ReplaceItemViaPointer');
+
+typedef _c_cJSON_ReplaceItemViaPointer = ffi.Int32 Function(
+  ffi.Pointer<cJSON> parent,
+  ffi.Pointer<cJSON> item,
+  ffi.Pointer<cJSON> replacement,
+);
+
+typedef _dart_cJSON_ReplaceItemViaPointer = int Function(
+  ffi.Pointer<cJSON> parent,
+  ffi.Pointer<cJSON> item,
+  ffi.Pointer<cJSON> replacement,
+);
+
+void cJSON_ReplaceItemInArray(
+  ffi.Pointer<cJSON> array,
+  int which,
+  ffi.Pointer<cJSON> newitem,
+) {
+  return _cJSON_ReplaceItemInArray(
+    array,
+    which,
+    newitem,
+  );
+}
+
+final _dart_cJSON_ReplaceItemInArray _cJSON_ReplaceItemInArray =
+    _dylib.lookupFunction<_c_cJSON_ReplaceItemInArray,
+        _dart_cJSON_ReplaceItemInArray>('cJSON_ReplaceItemInArray');
+
+typedef _c_cJSON_ReplaceItemInArray = ffi.Void Function(
+  ffi.Pointer<cJSON> array,
+  ffi.Int32 which,
+  ffi.Pointer<cJSON> newitem,
+);
+
+typedef _dart_cJSON_ReplaceItemInArray = void Function(
+  ffi.Pointer<cJSON> array,
+  int which,
+  ffi.Pointer<cJSON> newitem,
+);
+
+void cJSON_ReplaceItemInObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> newitem,
+) {
+  return _cJSON_ReplaceItemInObject(
+    object,
+    string,
+    newitem,
+  );
+}
+
+final _dart_cJSON_ReplaceItemInObject _cJSON_ReplaceItemInObject =
+    _dylib.lookupFunction<_c_cJSON_ReplaceItemInObject,
+        _dart_cJSON_ReplaceItemInObject>('cJSON_ReplaceItemInObject');
+
+typedef _c_cJSON_ReplaceItemInObject = ffi.Void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> newitem,
+);
+
+typedef _dart_cJSON_ReplaceItemInObject = void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> newitem,
+);
+
+void cJSON_ReplaceItemInObjectCaseSensitive(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> newitem,
+) {
+  return _cJSON_ReplaceItemInObjectCaseSensitive(
+    object,
+    string,
+    newitem,
+  );
+}
+
+final _dart_cJSON_ReplaceItemInObjectCaseSensitive
+    _cJSON_ReplaceItemInObjectCaseSensitive = _dylib.lookupFunction<
+            _c_cJSON_ReplaceItemInObjectCaseSensitive,
+            _dart_cJSON_ReplaceItemInObjectCaseSensitive>(
+        'cJSON_ReplaceItemInObjectCaseSensitive');
+
+typedef _c_cJSON_ReplaceItemInObjectCaseSensitive = ffi.Void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> newitem,
+);
+
+typedef _dart_cJSON_ReplaceItemInObjectCaseSensitive = void Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> string,
+  ffi.Pointer<cJSON> newitem,
+);
+
+ffi.Pointer<cJSON> cJSON_Duplicate(
+  ffi.Pointer<cJSON> item,
+  int recurse,
+) {
+  return _cJSON_Duplicate(
+    item,
+    recurse,
+  );
+}
+
+final _dart_cJSON_Duplicate _cJSON_Duplicate =
+    _dylib.lookupFunction<_c_cJSON_Duplicate, _dart_cJSON_Duplicate>(
+        'cJSON_Duplicate');
+
+typedef _c_cJSON_Duplicate = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> item,
+  ffi.Int32 recurse,
+);
+
+typedef _dart_cJSON_Duplicate = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> item,
+  int recurse,
+);
+
+int cJSON_Compare(
+  ffi.Pointer<cJSON> a,
+  ffi.Pointer<cJSON> b,
+  int case_sensitive,
+) {
+  return _cJSON_Compare(
+    a,
+    b,
+    case_sensitive,
+  );
+}
+
+final _dart_cJSON_Compare _cJSON_Compare = _dylib
+    .lookupFunction<_c_cJSON_Compare, _dart_cJSON_Compare>('cJSON_Compare');
+
+typedef _c_cJSON_Compare = ffi.Int32 Function(
+  ffi.Pointer<cJSON> a,
+  ffi.Pointer<cJSON> b,
+  ffi.Int32 case_sensitive,
+);
+
+typedef _dart_cJSON_Compare = int Function(
+  ffi.Pointer<cJSON> a,
+  ffi.Pointer<cJSON> b,
+  int case_sensitive,
+);
+
+void cJSON_Minify(
+  ffi.Pointer<ffi.Int8> json,
+) {
+  return _cJSON_Minify(
+    json,
+  );
+}
+
+final _dart_cJSON_Minify _cJSON_Minify =
+    _dylib.lookupFunction<_c_cJSON_Minify, _dart_cJSON_Minify>('cJSON_Minify');
+
+typedef _c_cJSON_Minify = ffi.Void Function(
+  ffi.Pointer<ffi.Int8> json,
+);
+
+typedef _dart_cJSON_Minify = void Function(
+  ffi.Pointer<ffi.Int8> json,
+);
+
+ffi.Pointer<cJSON> cJSON_AddNullToObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+) {
+  return _cJSON_AddNullToObject(
+    object,
+    name,
+  );
+}
+
+final _dart_cJSON_AddNullToObject _cJSON_AddNullToObject = _dylib
+    .lookupFunction<_c_cJSON_AddNullToObject, _dart_cJSON_AddNullToObject>(
+        'cJSON_AddNullToObject');
+
+typedef _c_cJSON_AddNullToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+);
+
+typedef _dart_cJSON_AddNullToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+);
+
+ffi.Pointer<cJSON> cJSON_AddTrueToObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+) {
+  return _cJSON_AddTrueToObject(
+    object,
+    name,
+  );
+}
+
+final _dart_cJSON_AddTrueToObject _cJSON_AddTrueToObject = _dylib
+    .lookupFunction<_c_cJSON_AddTrueToObject, _dart_cJSON_AddTrueToObject>(
+        'cJSON_AddTrueToObject');
+
+typedef _c_cJSON_AddTrueToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+);
+
+typedef _dart_cJSON_AddTrueToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+);
+
+ffi.Pointer<cJSON> cJSON_AddFalseToObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+) {
+  return _cJSON_AddFalseToObject(
+    object,
+    name,
+  );
+}
+
+final _dart_cJSON_AddFalseToObject _cJSON_AddFalseToObject = _dylib
+    .lookupFunction<_c_cJSON_AddFalseToObject, _dart_cJSON_AddFalseToObject>(
+        'cJSON_AddFalseToObject');
+
+typedef _c_cJSON_AddFalseToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+);
+
+typedef _dart_cJSON_AddFalseToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+);
+
+ffi.Pointer<cJSON> cJSON_AddBoolToObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  int boolean,
+) {
+  return _cJSON_AddBoolToObject(
+    object,
+    name,
+    boolean,
+  );
+}
+
+final _dart_cJSON_AddBoolToObject _cJSON_AddBoolToObject = _dylib
+    .lookupFunction<_c_cJSON_AddBoolToObject, _dart_cJSON_AddBoolToObject>(
+        'cJSON_AddBoolToObject');
+
+typedef _c_cJSON_AddBoolToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  ffi.Int32 boolean,
+);
+
+typedef _dart_cJSON_AddBoolToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  int boolean,
+);
+
+ffi.Pointer<cJSON> cJSON_AddNumberToObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  double number,
+) {
+  return _cJSON_AddNumberToObject(
+    object,
+    name,
+    number,
+  );
+}
+
+final _dart_cJSON_AddNumberToObject _cJSON_AddNumberToObject = _dylib
+    .lookupFunction<_c_cJSON_AddNumberToObject, _dart_cJSON_AddNumberToObject>(
+        'cJSON_AddNumberToObject');
+
+typedef _c_cJSON_AddNumberToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  ffi.Double number,
+);
+
+typedef _dart_cJSON_AddNumberToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  double number,
+);
+
+ffi.Pointer<cJSON> cJSON_AddStringToObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  ffi.Pointer<ffi.Int8> string,
+) {
+  return _cJSON_AddStringToObject(
+    object,
+    name,
+    string,
+  );
+}
+
+final _dart_cJSON_AddStringToObject _cJSON_AddStringToObject = _dylib
+    .lookupFunction<_c_cJSON_AddStringToObject, _dart_cJSON_AddStringToObject>(
+        'cJSON_AddStringToObject');
+
+typedef _c_cJSON_AddStringToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+typedef _dart_cJSON_AddStringToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  ffi.Pointer<ffi.Int8> string,
+);
+
+ffi.Pointer<cJSON> cJSON_AddRawToObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  ffi.Pointer<ffi.Int8> raw,
+) {
+  return _cJSON_AddRawToObject(
+    object,
+    name,
+    raw,
+  );
+}
+
+final _dart_cJSON_AddRawToObject _cJSON_AddRawToObject =
+    _dylib.lookupFunction<_c_cJSON_AddRawToObject, _dart_cJSON_AddRawToObject>(
+        'cJSON_AddRawToObject');
+
+typedef _c_cJSON_AddRawToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  ffi.Pointer<ffi.Int8> raw,
+);
+
+typedef _dart_cJSON_AddRawToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+  ffi.Pointer<ffi.Int8> raw,
+);
+
+ffi.Pointer<cJSON> cJSON_AddObjectToObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+) {
+  return _cJSON_AddObjectToObject(
+    object,
+    name,
+  );
+}
+
+final _dart_cJSON_AddObjectToObject _cJSON_AddObjectToObject = _dylib
+    .lookupFunction<_c_cJSON_AddObjectToObject, _dart_cJSON_AddObjectToObject>(
+        'cJSON_AddObjectToObject');
+
+typedef _c_cJSON_AddObjectToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+);
+
+typedef _dart_cJSON_AddObjectToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+);
+
+ffi.Pointer<cJSON> cJSON_AddArrayToObject(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+) {
+  return _cJSON_AddArrayToObject(
+    object,
+    name,
+  );
+}
+
+final _dart_cJSON_AddArrayToObject _cJSON_AddArrayToObject = _dylib
+    .lookupFunction<_c_cJSON_AddArrayToObject, _dart_cJSON_AddArrayToObject>(
+        'cJSON_AddArrayToObject');
+
+typedef _c_cJSON_AddArrayToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+);
+
+typedef _dart_cJSON_AddArrayToObject = ffi.Pointer<cJSON> Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Pointer<ffi.Int8> name,
+);
+
+double cJSON_SetNumberHelper(
+  ffi.Pointer<cJSON> object,
+  double number,
+) {
+  return _cJSON_SetNumberHelper(
+    object,
+    number,
+  );
+}
+
+final _dart_cJSON_SetNumberHelper _cJSON_SetNumberHelper = _dylib
+    .lookupFunction<_c_cJSON_SetNumberHelper, _dart_cJSON_SetNumberHelper>(
+        'cJSON_SetNumberHelper');
+
+typedef _c_cJSON_SetNumberHelper = ffi.Double Function(
+  ffi.Pointer<cJSON> object,
+  ffi.Double number,
+);
+
+typedef _dart_cJSON_SetNumberHelper = double Function(
+  ffi.Pointer<cJSON> object,
+  double number,
+);
+
+ffi.Pointer<ffi.Void> cJSON_malloc(
+  int size,
+) {
+  return _cJSON_malloc(
+    size,
+  );
+}
+
+final _dart_cJSON_malloc _cJSON_malloc =
+    _dylib.lookupFunction<_c_cJSON_malloc, _dart_cJSON_malloc>('cJSON_malloc');
+
+typedef _c_cJSON_malloc = ffi.Pointer<ffi.Void> Function(
+  ffi.Uint64 size,
+);
+
+typedef _dart_cJSON_malloc = ffi.Pointer<ffi.Void> Function(
+  int size,
+);
+
+void cJSON_free(
+  ffi.Pointer<ffi.Void> object,
+) {
+  return _cJSON_free(
+    object,
+  );
+}
+
+final _dart_cJSON_free _cJSON_free =
+    _dylib.lookupFunction<_c_cJSON_free, _dart_cJSON_free>('cJSON_free');
+
+typedef _c_cJSON_free = ffi.Void Function(
+  ffi.Pointer<ffi.Void> object,
+);
+
+typedef _dart_cJSON_free = void Function(
+  ffi.Pointer<ffi.Void> object,
+);
diff --git a/example/c_json/example.json b/example/c_json/example.json
new file mode 100644
index 0000000..073b05c
--- /dev/null
+++ b/example/c_json/example.json
@@ -0,0 +1,14 @@
+{
+    "name": "CoolGuy",
+    "age": 21,
+    "nicknames": [
+        {
+            "name": "Mr. Cool",
+            "length": 8
+        },
+        {
+            "name": "Ice Cold",
+            "length": 8
+        }
+    ]
+}
diff --git a/example/c_json/main.dart b/example/c_json/main.dart
new file mode 100644
index 0000000..22db183
--- /dev/null
+++ b/example/c_json/main.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'dart:ffi';
+import 'dart:io';
+
+import 'package:ffi/ffi.dart';
+
+import 'cjson_generated_bindings.dart' as cjson;
+
+/// Using the generated C_JSON bindings.
+void main() {
+  // Initialise cjson bindings.
+  cjson.init(DynamicLibrary.open(_getPath()));
+
+  // Load json from [example.json] file.
+  final jsonString = File('./example.json').readAsStringSync();
+
+  // Parse this json string using our cJSON library.
+  final cjsonParsedJson = cjson.cJSON_Parse(Utf8.toUtf8(jsonString).cast());
+  if (cjsonParsedJson == nullptr) {
+    print('Error parsing cjson.');
+    exit(1);
+  }
+  // The json is now stored in some C data structure which we need
+  // to iterate and convert to a dart object (map/list).
+
+  // Converting cjson object to a dart object.
+  final dynamic dartJson = convertCJsonToDartObj(cjsonParsedJson.cast());
+
+  // Delete the cjsonParsedJson object.
+  cjson.cJSON_Delete(cjsonParsedJson);
+
+  // Check if the converted json is correct
+  // by comparing the result with json converted by `dart:convert`.
+  if (dartJson.toString() == json.decode(jsonString).toString()) {
+    print('Parsed Json: $dartJson');
+    print('Json converted successfully');
+  } else {
+    print("Converted json doesn't match\n");
+    print('Actual:\n' + dartJson.toString() + '\n');
+    print('Expected:\n' + json.decode(jsonString).toString());
+  }
+}
+
+String _getPath() {
+  var path = '../../third_party/cjson_library/libcjson.so';
+  if (Platform.isMacOS) {
+    path = '../../third_party/cjson_library/libstructs.dylib';
+  }
+  if (Platform.isWindows) {
+    path = r'..\..\third_party\cjson_library\Debug\structs.dll';
+  }
+  return path;
+}
+
+dynamic convertCJsonToDartObj(Pointer<cjson.cJSON> parsedcjson) {
+  dynamic obj;
+  if (cjson.cJSON_IsObject(parsedcjson.cast()) == 1) {
+    obj = <String, dynamic>{};
+
+    Pointer<cjson.cJSON> ptr;
+    ptr = parsedcjson.ref.child;
+    while (ptr != nullptr) {
+      final dynamic o = convertCJsonToDartObj(ptr);
+      _addToObj(obj, o, ptr.ref.string.cast());
+      ptr = ptr.ref.next;
+    }
+  } else if (cjson.cJSON_IsArray(parsedcjson.cast()) == 1) {
+    obj = <dynamic>[];
+
+    Pointer<cjson.cJSON> ptr;
+    ptr = parsedcjson.ref.child;
+    while (ptr != nullptr) {
+      final dynamic o = convertCJsonToDartObj(ptr);
+      _addToObj(obj, o);
+      ptr = ptr.ref.next;
+    }
+  } else if (cjson.cJSON_IsString(parsedcjson.cast()) == 1) {
+    obj = Utf8.fromUtf8(parsedcjson.ref.valuestring.cast());
+  } else if (cjson.cJSON_IsNumber(parsedcjson.cast()) == 1) {
+    obj = parsedcjson.ref.valueint == parsedcjson.ref.valuedouble
+        ? parsedcjson.ref.valueint
+        : parsedcjson.ref.valuedouble;
+  }
+
+  return obj;
+}
+
+void _addToObj(dynamic obj, dynamic o, [Pointer<Utf8> name]) {
+  if (obj is Map<String, dynamic>) {
+    obj[Utf8.fromUtf8(name)] = o;
+  } else if (obj is List<dynamic>) {
+    obj.add(o);
+  }
+}
diff --git a/example/c_json/pubspec.yaml b/example/c_json/pubspec.yaml
new file mode 100644
index 0000000..7e913b6
--- /dev/null
+++ b/example/c_json/pubspec.yaml
@@ -0,0 +1,23 @@
+# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+name: c_json_example
+
+environment:
+  sdk: '>=2.8.1 <3.0.0'
+
+dependencies:
+  ffi: ^0.1.3
+
+dev_dependencies:
+  ffigen:
+    path: '../../'
+
+ffigen:
+  output: 'cjson_generated_bindings.dart'
+  headers:
+    - '../../third_party/cjson_library/cJSON.h'
+  header-filter:
+    include:
+      - 'cJSON.h'
diff --git a/example/libclang-example/.gitignore b/example/libclang-example/.gitignore
new file mode 100644
index 0000000..1b05164
--- /dev/null
+++ b/example/libclang-example/.gitignore
@@ -0,0 +1,11 @@
+# Files and directories created by pub.
+.dart_tool/
+.packages
+# Remove the following pattern if you wish to check in your lock file.
+pubspec.lock
+
+# Conventional directory for build outputs.
+build/
+
+# Directory created by dartdoc.
+doc/api/
diff --git a/example/libclang-example/generated_bindings.dart b/example/libclang-example/generated_bindings.dart
new file mode 100644
index 0000000..f68f632
--- /dev/null
+++ b/example/libclang-example/generated_bindings.dart
@@ -0,0 +1,4405 @@
+/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib) {
+  _dylib = dylib;
+}
+
+/// Contains the results of code-completion.
+class CXCodeCompleteResults extends ffi.Struct {
+  ffi.Pointer<CXCompletionResult> Results;
+
+  @ffi.Uint32()
+  int NumResults;
+}
+
+/// A single result of code completion.
+class CXCompletionResult extends ffi.Struct {
+  @ffi.Int32()
+  int CursorKind;
+
+  ffi.Pointer<ffi.Void> CompletionString;
+}
+
+/// A cursor representing some element in the abstract syntax tree for a translation unit.
+class CXCursor extends ffi.Struct {
+  @ffi.Int32()
+  int kind;
+
+  @ffi.Int32()
+  int xdata;
+
+  ffi.Pointer<ffi.Void> _data_item_0;
+  ffi.Pointer<ffi.Void> _data_item_1;
+  ffi.Pointer<ffi.Void> _data_item_2;
+
+  /// helper for array, supports `[]` operator
+  _ArrayHelper_CXCursor_data get data => _ArrayHelper_CXCursor_data(this, 3);
+}
+
+/// Helper for array data in struct CXCursor
+class _ArrayHelper_CXCursor_data {
+  final CXCursor _struct;
+  final int length;
+  _ArrayHelper_CXCursor_data(this._struct, this.length);
+  void operator []=(int index, ffi.Pointer<ffi.Void> value) {
+    switch (index) {
+      case 0:
+        _struct._data_item_0 = value;
+        break;
+      case 1:
+        _struct._data_item_1 = value;
+        break;
+      case 2:
+        _struct._data_item_2 = value;
+        break;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    switch (index) {
+      case 0:
+        return _struct._data_item_0;
+      case 1:
+        return _struct._data_item_1;
+      case 2:
+        return _struct._data_item_2;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  @override
+  String toString() {
+    if (length == 0) return '[]';
+    final sb = StringBuffer('[');
+    sb.write(this[0]);
+    for (var i = 1; i < length; i++) {
+      sb.write(',');
+      sb.write(this[i]);
+    }
+    sb.write(']');
+    return sb.toString();
+  }
+}
+
+class CXCursorAndRangeVisitor extends ffi.Struct {
+  ffi.Pointer<ffi.Void> context;
+
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_2>> visit;
+}
+
+class CXCursorSetImpl extends ffi.Struct {}
+
+typedef CXCursorVisitor = ffi.Int32 Function(
+  CXCursor,
+  CXCursor,
+  ffi.Pointer<ffi.Void>,
+);
+
+typedef CXFieldVisitor = ffi.Int32 Function(
+  CXCursor,
+  ffi.Pointer<ffi.Void>,
+);
+
+/// Uniquely identifies a CXFile, that refers to the same underlying file, across an indexing session.
+class CXFileUniqueID extends ffi.Struct {
+  @ffi.Uint64()
+  int _data_item_0;
+  @ffi.Uint64()
+  int _data_item_1;
+  @ffi.Uint64()
+  int _data_item_2;
+
+  /// helper for array, supports `[]` operator
+  _ArrayHelper_CXFileUniqueID_data get data =>
+      _ArrayHelper_CXFileUniqueID_data(this, 3);
+}
+
+/// Helper for array data in struct CXFileUniqueID
+class _ArrayHelper_CXFileUniqueID_data {
+  final CXFileUniqueID _struct;
+  final int length;
+  _ArrayHelper_CXFileUniqueID_data(this._struct, this.length);
+  void operator []=(int index, int value) {
+    switch (index) {
+      case 0:
+        _struct._data_item_0 = value;
+        break;
+      case 1:
+        _struct._data_item_1 = value;
+        break;
+      case 2:
+        _struct._data_item_2 = value;
+        break;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  int operator [](int index) {
+    switch (index) {
+      case 0:
+        return _struct._data_item_0;
+      case 1:
+        return _struct._data_item_1;
+      case 2:
+        return _struct._data_item_2;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  @override
+  String toString() {
+    if (length == 0) return '[]';
+    final sb = StringBuffer('[');
+    sb.write(this[0]);
+    for (var i = 1; i < length; i++) {
+      sb.write(',');
+      sb.write(this[i]);
+    }
+    sb.write(']');
+    return sb.toString();
+  }
+}
+
+class CXGlobalOptFlags {
+  static const int CXGlobalOpt_None = 0;
+  static const int CXGlobalOpt_ThreadBackgroundPriorityForIndexing = 1;
+  static const int CXGlobalOpt_ThreadBackgroundPriorityForEditing = 2;
+  static const int CXGlobalOpt_ThreadBackgroundPriorityForAll = 3;
+}
+
+class CXIdxAttrInfo extends ffi.Struct {}
+
+class CXIdxBaseClassInfo extends ffi.Struct {}
+
+class CXIdxCXXClassDeclInfo extends ffi.Struct {
+  ffi.Pointer<CXIdxDeclInfo> declInfo;
+
+  ffi.Pointer<ffi.Pointer<CXIdxBaseClassInfo>> bases;
+
+  @ffi.Uint32()
+  int numBases;
+}
+
+class CXIdxContainerInfo extends ffi.Struct {}
+
+class CXIdxDeclInfo extends ffi.Struct {}
+
+class CXIdxEntityInfo extends ffi.Struct {}
+
+/// Data for IndexerCallbacks#indexEntityReference.
+class CXIdxEntityRefInfo extends ffi.Struct {}
+
+class CXIdxIBOutletCollectionAttrInfo extends ffi.Struct {}
+
+/// Data for IndexerCallbacks#importedASTFile.
+class CXIdxImportedASTFileInfo extends ffi.Struct {}
+
+/// Data for ppIncludedFile callback.
+class CXIdxIncludedFileInfo extends ffi.Struct {}
+
+/// Source location passed to index callbacks.
+class CXIdxLoc extends ffi.Struct {
+  ffi.Pointer<ffi.Void> _ptr_data_item_0;
+  ffi.Pointer<ffi.Void> _ptr_data_item_1;
+  ffi.Pointer<ffi.Void> _ptr_data_item_2;
+
+  /// helper for array, supports `[]` operator
+  _ArrayHelper_CXIdxLoc_ptr_data get ptr_data =>
+      _ArrayHelper_CXIdxLoc_ptr_data(this, 3);
+  @ffi.Uint32()
+  int int_data;
+}
+
+/// Helper for array ptr_data in struct CXIdxLoc
+class _ArrayHelper_CXIdxLoc_ptr_data {
+  final CXIdxLoc _struct;
+  final int length;
+  _ArrayHelper_CXIdxLoc_ptr_data(this._struct, this.length);
+  void operator []=(int index, ffi.Pointer<ffi.Void> value) {
+    switch (index) {
+      case 0:
+        _struct._ptr_data_item_0 = value;
+        break;
+      case 1:
+        _struct._ptr_data_item_1 = value;
+        break;
+      case 2:
+        _struct._ptr_data_item_2 = value;
+        break;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    switch (index) {
+      case 0:
+        return _struct._ptr_data_item_0;
+      case 1:
+        return _struct._ptr_data_item_1;
+      case 2:
+        return _struct._ptr_data_item_2;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  @override
+  String toString() {
+    if (length == 0) return '[]';
+    final sb = StringBuffer('[');
+    sb.write(this[0]);
+    for (var i = 1; i < length; i++) {
+      sb.write(',');
+      sb.write(this[i]);
+    }
+    sb.write(']');
+    return sb.toString();
+  }
+}
+
+class CXIdxObjCCategoryDeclInfo extends ffi.Struct {}
+
+class CXIdxObjCContainerDeclInfo extends ffi.Struct {
+  ffi.Pointer<CXIdxDeclInfo> declInfo;
+
+  @ffi.Int32()
+  int kind;
+}
+
+class CXIdxObjCInterfaceDeclInfo extends ffi.Struct {
+  ffi.Pointer<CXIdxObjCContainerDeclInfo> containerInfo;
+
+  ffi.Pointer<CXIdxBaseClassInfo> superInfo;
+
+  ffi.Pointer<CXIdxObjCProtocolRefListInfo> protocols;
+}
+
+class CXIdxObjCPropertyDeclInfo extends ffi.Struct {
+  ffi.Pointer<CXIdxDeclInfo> declInfo;
+
+  ffi.Pointer<CXIdxEntityInfo> getter;
+
+  ffi.Pointer<CXIdxEntityInfo> setter;
+}
+
+class CXIdxObjCProtocolRefInfo extends ffi.Struct {}
+
+class CXIdxObjCProtocolRefListInfo extends ffi.Struct {
+  ffi.Pointer<ffi.Pointer<CXIdxObjCProtocolRefInfo>> protocols;
+
+  @ffi.Uint32()
+  int numProtocols;
+}
+
+typedef CXInclusionVisitor = ffi.Void Function(
+  ffi.Pointer<ffi.Void>,
+  ffi.Pointer<CXSourceLocation>,
+  ffi.Uint32,
+  ffi.Pointer<ffi.Void>,
+);
+
+/// Describes the availability of a given entity on a particular platform, e.g., a particular class might only be available on Mac OS 10.7 or newer.
+class CXPlatformAvailability extends ffi.Struct {}
+
+/// Identifies a specific source location within a translation unit.
+class CXSourceLocation extends ffi.Struct {
+  ffi.Pointer<ffi.Void> _ptr_data_item_0;
+  ffi.Pointer<ffi.Void> _ptr_data_item_1;
+  ffi.Pointer<ffi.Void> _ptr_data_item_2;
+
+  /// helper for array, supports `[]` operator
+  _ArrayHelper_CXSourceLocation_ptr_data get ptr_data =>
+      _ArrayHelper_CXSourceLocation_ptr_data(this, 3);
+  @ffi.Uint32()
+  int int_data;
+}
+
+/// Helper for array ptr_data in struct CXSourceLocation
+class _ArrayHelper_CXSourceLocation_ptr_data {
+  final CXSourceLocation _struct;
+  final int length;
+  _ArrayHelper_CXSourceLocation_ptr_data(this._struct, this.length);
+  void operator []=(int index, ffi.Pointer<ffi.Void> value) {
+    switch (index) {
+      case 0:
+        _struct._ptr_data_item_0 = value;
+        break;
+      case 1:
+        _struct._ptr_data_item_1 = value;
+        break;
+      case 2:
+        _struct._ptr_data_item_2 = value;
+        break;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    switch (index) {
+      case 0:
+        return _struct._ptr_data_item_0;
+      case 1:
+        return _struct._ptr_data_item_1;
+      case 2:
+        return _struct._ptr_data_item_2;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  @override
+  String toString() {
+    if (length == 0) return '[]';
+    final sb = StringBuffer('[');
+    sb.write(this[0]);
+    for (var i = 1; i < length; i++) {
+      sb.write(',');
+      sb.write(this[i]);
+    }
+    sb.write(']');
+    return sb.toString();
+  }
+}
+
+/// Identifies a half-open character range in the source code.
+class CXSourceRange extends ffi.Struct {
+  ffi.Pointer<ffi.Void> _ptr_data_item_0;
+  ffi.Pointer<ffi.Void> _ptr_data_item_1;
+  ffi.Pointer<ffi.Void> _ptr_data_item_2;
+
+  /// helper for array, supports `[]` operator
+  _ArrayHelper_CXSourceRange_ptr_data get ptr_data =>
+      _ArrayHelper_CXSourceRange_ptr_data(this, 3);
+  @ffi.Uint32()
+  int begin_int_data;
+
+  @ffi.Uint32()
+  int end_int_data;
+}
+
+/// Helper for array ptr_data in struct CXSourceRange
+class _ArrayHelper_CXSourceRange_ptr_data {
+  final CXSourceRange _struct;
+  final int length;
+  _ArrayHelper_CXSourceRange_ptr_data(this._struct, this.length);
+  void operator []=(int index, ffi.Pointer<ffi.Void> value) {
+    switch (index) {
+      case 0:
+        _struct._ptr_data_item_0 = value;
+        break;
+      case 1:
+        _struct._ptr_data_item_1 = value;
+        break;
+      case 2:
+        _struct._ptr_data_item_2 = value;
+        break;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    switch (index) {
+      case 0:
+        return _struct._ptr_data_item_0;
+      case 1:
+        return _struct._ptr_data_item_1;
+      case 2:
+        return _struct._ptr_data_item_2;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  @override
+  String toString() {
+    if (length == 0) return '[]';
+    final sb = StringBuffer('[');
+    sb.write(this[0]);
+    for (var i = 1; i < length; i++) {
+      sb.write(',');
+      sb.write(this[i]);
+    }
+    sb.write(']');
+    return sb.toString();
+  }
+}
+
+/// Identifies an array of ranges.
+class CXSourceRangeList extends ffi.Struct {
+  @ffi.Uint32()
+  int count;
+
+  ffi.Pointer<CXSourceRange> ranges;
+}
+
+/// A character string.
+class CXString extends ffi.Struct {
+  ffi.Pointer<ffi.Void> data;
+
+  @ffi.Uint32()
+  int private_flags;
+}
+
+class CXStringSet extends ffi.Struct {
+  ffi.Pointer<CXString> Strings;
+
+  @ffi.Uint32()
+  int Count;
+}
+
+/// The memory usage of a CXTranslationUnit, broken into categories.
+class CXTUResourceUsage extends ffi.Struct {
+  ffi.Pointer<ffi.Void> data;
+
+  @ffi.Uint32()
+  int numEntries;
+
+  ffi.Pointer<CXTUResourceUsageEntry> entries;
+}
+
+class CXTUResourceUsageEntry extends ffi.Struct {
+  @ffi.Int32()
+  int kind;
+
+  @ffi.Uint64()
+  int amount;
+}
+
+class CXTargetInfoImpl extends ffi.Struct {}
+
+/// Describes a single preprocessing token.
+class CXToken extends ffi.Struct {
+  @ffi.Uint32()
+  int _int_data_item_0;
+  @ffi.Uint32()
+  int _int_data_item_1;
+  @ffi.Uint32()
+  int _int_data_item_2;
+
+  /// helper for array, supports `[]` operator
+  _ArrayHelper_CXToken_int_data get int_data =>
+      _ArrayHelper_CXToken_int_data(this, 3);
+  ffi.Pointer<ffi.Void> ptr_data;
+}
+
+/// Helper for array int_data in struct CXToken
+class _ArrayHelper_CXToken_int_data {
+  final CXToken _struct;
+  final int length;
+  _ArrayHelper_CXToken_int_data(this._struct, this.length);
+  void operator []=(int index, int value) {
+    switch (index) {
+      case 0:
+        _struct._int_data_item_0 = value;
+        break;
+      case 1:
+        _struct._int_data_item_1 = value;
+        break;
+      case 2:
+        _struct._int_data_item_2 = value;
+        break;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  int operator [](int index) {
+    switch (index) {
+      case 0:
+        return _struct._int_data_item_0;
+      case 1:
+        return _struct._int_data_item_1;
+      case 2:
+        return _struct._int_data_item_2;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  @override
+  String toString() {
+    if (length == 0) return '[]';
+    final sb = StringBuffer('[');
+    sb.write(this[0]);
+    for (var i = 1; i < length; i++) {
+      sb.write(',');
+      sb.write(this[i]);
+    }
+    sb.write(']');
+    return sb.toString();
+  }
+}
+
+class CXTranslationUnitImpl extends ffi.Struct {}
+
+/// The type of an element in the abstract syntax tree.
+class CXType extends ffi.Struct {
+  @ffi.Int32()
+  int kind;
+
+  ffi.Pointer<ffi.Void> _data_item_0;
+  ffi.Pointer<ffi.Void> _data_item_1;
+  ffi.Pointer<ffi.Void> _data_item_2;
+
+  /// helper for array, supports `[]` operator
+  _ArrayHelper_CXType_data get data => _ArrayHelper_CXType_data(this, 3);
+}
+
+/// Helper for array data in struct CXType
+class _ArrayHelper_CXType_data {
+  final CXType _struct;
+  final int length;
+  _ArrayHelper_CXType_data(this._struct, this.length);
+  void operator []=(int index, ffi.Pointer<ffi.Void> value) {
+    switch (index) {
+      case 0:
+        _struct._data_item_0 = value;
+        break;
+      case 1:
+        _struct._data_item_1 = value;
+        break;
+      case 2:
+        _struct._data_item_2 = value;
+        break;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    switch (index) {
+      case 0:
+        return _struct._data_item_0;
+      case 1:
+        return _struct._data_item_1;
+      case 2:
+        return _struct._data_item_2;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  @override
+  String toString() {
+    if (length == 0) return '[]';
+    final sb = StringBuffer('[');
+    sb.write(this[0]);
+    for (var i = 1; i < length; i++) {
+      sb.write(',');
+      sb.write(this[i]);
+    }
+    sb.write(']');
+    return sb.toString();
+  }
+}
+
+/// Describes the kind of type
+class CXTypeKind {
+  static const int CXType_Invalid = 0;
+  static const int CXType_Unexposed = 1;
+  static const int CXType_Void = 2;
+  static const int CXType_Bool = 3;
+  static const int CXType_Char_U = 4;
+  static const int CXType_UChar = 5;
+  static const int CXType_Char16 = 6;
+  static const int CXType_Char32 = 7;
+  static const int CXType_UShort = 8;
+  static const int CXType_UInt = 9;
+  static const int CXType_ULong = 10;
+  static const int CXType_ULongLong = 11;
+  static const int CXType_UInt128 = 12;
+  static const int CXType_Char_S = 13;
+  static const int CXType_SChar = 14;
+  static const int CXType_WChar = 15;
+  static const int CXType_Short = 16;
+  static const int CXType_Int = 17;
+  static const int CXType_Long = 18;
+  static const int CXType_LongLong = 19;
+  static const int CXType_Int128 = 20;
+  static const int CXType_Float = 21;
+  static const int CXType_Double = 22;
+  static const int CXType_LongDouble = 23;
+  static const int CXType_NullPtr = 24;
+  static const int CXType_Overload = 25;
+  static const int CXType_Dependent = 26;
+  static const int CXType_ObjCId = 27;
+  static const int CXType_ObjCClass = 28;
+  static const int CXType_ObjCSel = 29;
+  static const int CXType_Float128 = 30;
+  static const int CXType_Half = 31;
+  static const int CXType_Float16 = 32;
+  static const int CXType_ShortAccum = 33;
+  static const int CXType_Accum = 34;
+  static const int CXType_LongAccum = 35;
+  static const int CXType_UShortAccum = 36;
+  static const int CXType_UAccum = 37;
+  static const int CXType_ULongAccum = 38;
+  static const int CXType_FirstBuiltin = 2;
+  static const int CXType_LastBuiltin = 38;
+  static const int CXType_Complex = 100;
+  static const int CXType_Pointer = 101;
+  static const int CXType_BlockPointer = 102;
+  static const int CXType_LValueReference = 103;
+  static const int CXType_RValueReference = 104;
+  static const int CXType_Record = 105;
+  static const int CXType_Enum = 106;
+  static const int CXType_Typedef = 107;
+  static const int CXType_ObjCInterface = 108;
+  static const int CXType_ObjCObjectPointer = 109;
+  static const int CXType_FunctionNoProto = 110;
+  static const int CXType_FunctionProto = 111;
+  static const int CXType_ConstantArray = 112;
+  static const int CXType_Vector = 113;
+  static const int CXType_IncompleteArray = 114;
+  static const int CXType_VariableArray = 115;
+  static const int CXType_DependentSizedArray = 116;
+  static const int CXType_MemberPointer = 117;
+  static const int CXType_Auto = 118;
+  static const int CXType_Elaborated = 119;
+  static const int CXType_Pipe = 120;
+  static const int CXType_OCLImage1dRO = 121;
+  static const int CXType_OCLImage1dArrayRO = 122;
+  static const int CXType_OCLImage1dBufferRO = 123;
+  static const int CXType_OCLImage2dRO = 124;
+  static const int CXType_OCLImage2dArrayRO = 125;
+  static const int CXType_OCLImage2dDepthRO = 126;
+  static const int CXType_OCLImage2dArrayDepthRO = 127;
+  static const int CXType_OCLImage2dMSAARO = 128;
+  static const int CXType_OCLImage2dArrayMSAARO = 129;
+  static const int CXType_OCLImage2dMSAADepthRO = 130;
+  static const int CXType_OCLImage2dArrayMSAADepthRO = 131;
+  static const int CXType_OCLImage3dRO = 132;
+  static const int CXType_OCLImage1dWO = 133;
+  static const int CXType_OCLImage1dArrayWO = 134;
+  static const int CXType_OCLImage1dBufferWO = 135;
+  static const int CXType_OCLImage2dWO = 136;
+  static const int CXType_OCLImage2dArrayWO = 137;
+  static const int CXType_OCLImage2dDepthWO = 138;
+  static const int CXType_OCLImage2dArrayDepthWO = 139;
+  static const int CXType_OCLImage2dMSAAWO = 140;
+  static const int CXType_OCLImage2dArrayMSAAWO = 141;
+  static const int CXType_OCLImage2dMSAADepthWO = 142;
+  static const int CXType_OCLImage2dArrayMSAADepthWO = 143;
+  static const int CXType_OCLImage3dWO = 144;
+  static const int CXType_OCLImage1dRW = 145;
+  static const int CXType_OCLImage1dArrayRW = 146;
+  static const int CXType_OCLImage1dBufferRW = 147;
+  static const int CXType_OCLImage2dRW = 148;
+  static const int CXType_OCLImage2dArrayRW = 149;
+  static const int CXType_OCLImage2dDepthRW = 150;
+  static const int CXType_OCLImage2dArrayDepthRW = 151;
+  static const int CXType_OCLImage2dMSAARW = 152;
+  static const int CXType_OCLImage2dArrayMSAARW = 153;
+  static const int CXType_OCLImage2dMSAADepthRW = 154;
+  static const int CXType_OCLImage2dArrayMSAADepthRW = 155;
+  static const int CXType_OCLImage3dRW = 156;
+  static const int CXType_OCLSampler = 157;
+  static const int CXType_OCLEvent = 158;
+  static const int CXType_OCLQueue = 159;
+  static const int CXType_OCLReserveID = 160;
+  static const int CXType_ObjCObject = 161;
+  static const int CXType_ObjCTypeParam = 162;
+  static const int CXType_Attributed = 163;
+  static const int CXType_OCLIntelSubgroupAVCMcePayload = 164;
+  static const int CXType_OCLIntelSubgroupAVCImePayload = 165;
+  static const int CXType_OCLIntelSubgroupAVCRefPayload = 166;
+  static const int CXType_OCLIntelSubgroupAVCSicPayload = 167;
+  static const int CXType_OCLIntelSubgroupAVCMceResult = 168;
+  static const int CXType_OCLIntelSubgroupAVCImeResult = 169;
+  static const int CXType_OCLIntelSubgroupAVCRefResult = 170;
+  static const int CXType_OCLIntelSubgroupAVCSicResult = 171;
+  static const int CXType_OCLIntelSubgroupAVCImeResultSingleRefStreamout = 172;
+  static const int CXType_OCLIntelSubgroupAVCImeResultDualRefStreamout = 173;
+  static const int CXType_OCLIntelSubgroupAVCImeSingleRefStreamin = 174;
+  static const int CXType_OCLIntelSubgroupAVCImeDualRefStreamin = 175;
+  static const int CXType_ExtVector = 176;
+}
+
+/// Provides the contents of a file that has not yet been saved to disk.
+class CXUnsavedFile extends ffi.Struct {
+  ffi.Pointer<ffi.Int8> Filename;
+
+  ffi.Pointer<ffi.Int8> Contents;
+
+  @ffi.Uint64()
+  int Length;
+}
+
+/// Describes a version number of the form major.minor.subminor.
+class CXVersion extends ffi.Struct {
+  @ffi.Int32()
+  int Major;
+
+  @ffi.Int32()
+  int Minor;
+
+  @ffi.Int32()
+  int Subminor;
+}
+
+/// A group of callbacks used by #clang_indexSourceFile and #clang_indexTranslationUnit.
+class IndexerCallbacks extends ffi.Struct {
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_3>> abortQuery;
+
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_4>> diagnostic;
+
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_5>> enteredMainFile;
+
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_6>> ppIncludedFile;
+
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_7>> importedASTFile;
+
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_8>> startedTranslationUnit;
+
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_9>> indexDeclaration;
+
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_10>> indexEntityReference;
+}
+
+typedef ModifiedCXCursorVisitor = ffi.Int32 Function(
+  ffi.Pointer<CXCursor>,
+  ffi.Pointer<CXCursor>,
+  ffi.Pointer<ffi.Void>,
+);
+
+typedef _typedefC_noname_1 = ffi.Void Function(
+  ffi.Pointer<ffi.Void>,
+);
+
+typedef _typedefC_noname_10 = ffi.Void Function(
+  ffi.Pointer<ffi.Void>,
+  ffi.Pointer<CXIdxEntityRefInfo>,
+);
+
+typedef _typedefC_noname_2 = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void>,
+  CXCursor,
+  CXSourceRange,
+);
+
+typedef _typedefC_noname_3 = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void>,
+  ffi.Pointer<ffi.Void>,
+);
+
+typedef _typedefC_noname_4 = ffi.Void Function(
+  ffi.Pointer<ffi.Void>,
+  ffi.Pointer<ffi.Void>,
+  ffi.Pointer<ffi.Void>,
+);
+
+typedef _typedefC_noname_5 = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void>,
+  ffi.Pointer<ffi.Void>,
+  ffi.Pointer<ffi.Void>,
+);
+
+typedef _typedefC_noname_6 = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void>,
+  ffi.Pointer<CXIdxIncludedFileInfo>,
+);
+
+typedef _typedefC_noname_7 = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void>,
+  ffi.Pointer<CXIdxImportedASTFileInfo>,
+);
+
+typedef _typedefC_noname_8 = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void>,
+  ffi.Pointer<ffi.Void>,
+);
+
+typedef _typedefC_noname_9 = ffi.Void Function(
+  ffi.Pointer<ffi.Void>,
+  ffi.Pointer<CXIdxDeclInfo>,
+);
+
+/// Gets the general options associated with a CXIndex.
+int clang_CXIndex_getGlobalOptions(
+  ffi.Pointer<ffi.Void> arg0,
+) {
+  return _clang_CXIndex_getGlobalOptions(
+    arg0,
+  );
+}
+
+final _dart_clang_CXIndex_getGlobalOptions _clang_CXIndex_getGlobalOptions =
+    _dylib.lookupFunction<_c_clang_CXIndex_getGlobalOptions,
+        _dart_clang_CXIndex_getGlobalOptions>('clang_CXIndex_getGlobalOptions');
+
+typedef _c_clang_CXIndex_getGlobalOptions = ffi.Uint32 Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+typedef _dart_clang_CXIndex_getGlobalOptions = int Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+/// Sets general options associated with a CXIndex.
+void clang_CXIndex_setGlobalOptions(
+  ffi.Pointer<ffi.Void> arg0,
+  int options,
+) {
+  return _clang_CXIndex_setGlobalOptions(
+    arg0,
+    options,
+  );
+}
+
+final _dart_clang_CXIndex_setGlobalOptions _clang_CXIndex_setGlobalOptions =
+    _dylib.lookupFunction<_c_clang_CXIndex_setGlobalOptions,
+        _dart_clang_CXIndex_setGlobalOptions>('clang_CXIndex_setGlobalOptions');
+
+typedef _c_clang_CXIndex_setGlobalOptions = ffi.Void Function(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Uint32 options,
+);
+
+typedef _dart_clang_CXIndex_setGlobalOptions = void Function(
+  ffi.Pointer<ffi.Void> arg0,
+  int options,
+);
+
+/// Sets the invocation emission path option in a CXIndex.
+void clang_CXIndex_setInvocationEmissionPathOption(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Int8> Path,
+) {
+  return _clang_CXIndex_setInvocationEmissionPathOption(
+    arg0,
+    Path,
+  );
+}
+
+final _dart_clang_CXIndex_setInvocationEmissionPathOption
+    _clang_CXIndex_setInvocationEmissionPathOption = _dylib.lookupFunction<
+            _c_clang_CXIndex_setInvocationEmissionPathOption,
+            _dart_clang_CXIndex_setInvocationEmissionPathOption>(
+        'clang_CXIndex_setInvocationEmissionPathOption');
+
+typedef _c_clang_CXIndex_setInvocationEmissionPathOption = ffi.Void Function(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Int8> Path,
+);
+
+typedef _dart_clang_CXIndex_setInvocationEmissionPathOption = void Function(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Int8> Path,
+);
+
+ffi.Pointer<CXCursor> clang_Cursor_getArgument_wrap(
+  ffi.Pointer<CXCursor> cursor,
+  int i,
+) {
+  return _clang_Cursor_getArgument_wrap(
+    cursor,
+    i,
+  );
+}
+
+final _dart_clang_Cursor_getArgument_wrap _clang_Cursor_getArgument_wrap =
+    _dylib.lookupFunction<_c_clang_Cursor_getArgument_wrap,
+        _dart_clang_Cursor_getArgument_wrap>('clang_Cursor_getArgument_wrap');
+
+typedef _c_clang_Cursor_getArgument_wrap = ffi.Pointer<CXCursor> Function(
+  ffi.Pointer<CXCursor> cursor,
+  ffi.Uint32 i,
+);
+
+typedef _dart_clang_Cursor_getArgument_wrap = ffi.Pointer<CXCursor> Function(
+  ffi.Pointer<CXCursor> cursor,
+  int i,
+);
+
+/// Returns the first paragraph of doxygen doc comment.
+ffi.Pointer<CXString> clang_Cursor_getBriefCommentText_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_Cursor_getBriefCommentText_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_Cursor_getBriefCommentText_wrap
+    _clang_Cursor_getBriefCommentText_wrap = _dylib.lookupFunction<
+            _c_clang_Cursor_getBriefCommentText_wrap,
+            _dart_clang_Cursor_getBriefCommentText_wrap>(
+        'clang_Cursor_getBriefCommentText_wrap');
+
+typedef _c_clang_Cursor_getBriefCommentText_wrap = ffi.Pointer<CXString>
+    Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_Cursor_getBriefCommentText_wrap = ffi.Pointer<CXString>
+    Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+int clang_Cursor_getNumArguments_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_Cursor_getNumArguments_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_Cursor_getNumArguments_wrap
+    _clang_Cursor_getNumArguments_wrap = _dylib.lookupFunction<
+            _c_clang_Cursor_getNumArguments_wrap,
+            _dart_clang_Cursor_getNumArguments_wrap>(
+        'clang_Cursor_getNumArguments_wrap');
+
+typedef _c_clang_Cursor_getNumArguments_wrap = ffi.Int32 Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_Cursor_getNumArguments_wrap = int Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+/// Disposes the created Eval memory.
+void clang_EvalResult_dispose(
+  ffi.Pointer<ffi.Void> E,
+) {
+  return _clang_EvalResult_dispose(
+    E,
+  );
+}
+
+final _dart_clang_EvalResult_dispose _clang_EvalResult_dispose =
+    _dylib.lookupFunction<_c_clang_EvalResult_dispose,
+        _dart_clang_EvalResult_dispose>('clang_EvalResult_dispose');
+
+typedef _c_clang_EvalResult_dispose = ffi.Void Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_dispose = void Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+/// Returns the evaluation result as double if the kind is double.
+double clang_EvalResult_getAsDouble(
+  ffi.Pointer<ffi.Void> E,
+) {
+  return _clang_EvalResult_getAsDouble(
+    E,
+  );
+}
+
+final _dart_clang_EvalResult_getAsDouble _clang_EvalResult_getAsDouble =
+    _dylib.lookupFunction<_c_clang_EvalResult_getAsDouble,
+        _dart_clang_EvalResult_getAsDouble>('clang_EvalResult_getAsDouble');
+
+typedef _c_clang_EvalResult_getAsDouble = ffi.Double Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_getAsDouble = double Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+/// Returns the evaluation result as integer if the kind is Int.
+int clang_EvalResult_getAsInt(
+  ffi.Pointer<ffi.Void> E,
+) {
+  return _clang_EvalResult_getAsInt(
+    E,
+  );
+}
+
+final _dart_clang_EvalResult_getAsInt _clang_EvalResult_getAsInt =
+    _dylib.lookupFunction<_c_clang_EvalResult_getAsInt,
+        _dart_clang_EvalResult_getAsInt>('clang_EvalResult_getAsInt');
+
+typedef _c_clang_EvalResult_getAsInt = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_getAsInt = int Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+/// Returns the evaluation result as a long long integer if the kind is Int. This prevents overflows that may happen if the result is returned with clang_EvalResult_getAsInt.
+int clang_EvalResult_getAsLongLong(
+  ffi.Pointer<ffi.Void> E,
+) {
+  return _clang_EvalResult_getAsLongLong(
+    E,
+  );
+}
+
+final _dart_clang_EvalResult_getAsLongLong _clang_EvalResult_getAsLongLong =
+    _dylib.lookupFunction<_c_clang_EvalResult_getAsLongLong,
+        _dart_clang_EvalResult_getAsLongLong>('clang_EvalResult_getAsLongLong');
+
+typedef _c_clang_EvalResult_getAsLongLong = ffi.Int64 Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_getAsLongLong = int Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+/// Returns the evaluation result as a constant string if the kind is other than Int or float. User must not free this pointer, instead call clang_EvalResult_dispose on the CXEvalResult returned by clang_Cursor_Evaluate.
+ffi.Pointer<ffi.Int8> clang_EvalResult_getAsStr(
+  ffi.Pointer<ffi.Void> E,
+) {
+  return _clang_EvalResult_getAsStr(
+    E,
+  );
+}
+
+final _dart_clang_EvalResult_getAsStr _clang_EvalResult_getAsStr =
+    _dylib.lookupFunction<_c_clang_EvalResult_getAsStr,
+        _dart_clang_EvalResult_getAsStr>('clang_EvalResult_getAsStr');
+
+typedef _c_clang_EvalResult_getAsStr = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_getAsStr = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+/// Returns the evaluation result as an unsigned integer if the kind is Int and clang_EvalResult_isUnsignedInt is non-zero.
+int clang_EvalResult_getAsUnsigned(
+  ffi.Pointer<ffi.Void> E,
+) {
+  return _clang_EvalResult_getAsUnsigned(
+    E,
+  );
+}
+
+final _dart_clang_EvalResult_getAsUnsigned _clang_EvalResult_getAsUnsigned =
+    _dylib.lookupFunction<_c_clang_EvalResult_getAsUnsigned,
+        _dart_clang_EvalResult_getAsUnsigned>('clang_EvalResult_getAsUnsigned');
+
+typedef _c_clang_EvalResult_getAsUnsigned = ffi.Uint64 Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_getAsUnsigned = int Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+/// Returns the kind of the evaluated result.
+int clang_EvalResult_getKind(
+  ffi.Pointer<ffi.Void> E,
+) {
+  return _clang_EvalResult_getKind(
+    E,
+  );
+}
+
+final _dart_clang_EvalResult_getKind _clang_EvalResult_getKind =
+    _dylib.lookupFunction<_c_clang_EvalResult_getKind,
+        _dart_clang_EvalResult_getKind>('clang_EvalResult_getKind');
+
+typedef _c_clang_EvalResult_getKind = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_getKind = int Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+/// Returns a non-zero value if the kind is Int and the evaluation result resulted in an unsigned integer.
+int clang_EvalResult_isUnsignedInt(
+  ffi.Pointer<ffi.Void> E,
+) {
+  return _clang_EvalResult_isUnsignedInt(
+    E,
+  );
+}
+
+final _dart_clang_EvalResult_isUnsignedInt _clang_EvalResult_isUnsignedInt =
+    _dylib.lookupFunction<_c_clang_EvalResult_isUnsignedInt,
+        _dart_clang_EvalResult_isUnsignedInt>('clang_EvalResult_isUnsignedInt');
+
+typedef _c_clang_EvalResult_isUnsignedInt = ffi.Uint32 Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_isUnsignedInt = int Function(
+  ffi.Pointer<ffi.Void> E,
+);
+
+/// Returns non-zero if the file1 and file2 point to the same file, or they are both NULL.
+int clang_File_isEqual(
+  ffi.Pointer<ffi.Void> file1,
+  ffi.Pointer<ffi.Void> file2,
+) {
+  return _clang_File_isEqual(
+    file1,
+    file2,
+  );
+}
+
+final _dart_clang_File_isEqual _clang_File_isEqual =
+    _dylib.lookupFunction<_c_clang_File_isEqual, _dart_clang_File_isEqual>(
+        'clang_File_isEqual');
+
+typedef _c_clang_File_isEqual = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> file1,
+  ffi.Pointer<ffi.Void> file2,
+);
+
+typedef _dart_clang_File_isEqual = int Function(
+  ffi.Pointer<ffi.Void> file1,
+  ffi.Pointer<ffi.Void> file2,
+);
+
+/// An indexing action/session, to be applied to one or multiple translation units.
+ffi.Pointer<ffi.Void> clang_IndexAction_create(
+  ffi.Pointer<ffi.Void> CIdx,
+) {
+  return _clang_IndexAction_create(
+    CIdx,
+  );
+}
+
+final _dart_clang_IndexAction_create _clang_IndexAction_create =
+    _dylib.lookupFunction<_c_clang_IndexAction_create,
+        _dart_clang_IndexAction_create>('clang_IndexAction_create');
+
+typedef _c_clang_IndexAction_create = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void> CIdx,
+);
+
+typedef _dart_clang_IndexAction_create = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void> CIdx,
+);
+
+/// Destroy the given index action.
+void clang_IndexAction_dispose(
+  ffi.Pointer<ffi.Void> arg0,
+) {
+  return _clang_IndexAction_dispose(
+    arg0,
+  );
+}
+
+final _dart_clang_IndexAction_dispose _clang_IndexAction_dispose =
+    _dylib.lookupFunction<_c_clang_IndexAction_dispose,
+        _dart_clang_IndexAction_dispose>('clang_IndexAction_dispose');
+
+typedef _c_clang_IndexAction_dispose = ffi.Void Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+typedef _dart_clang_IndexAction_dispose = void Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+/// Returns the module file where the provided module object came from.
+ffi.Pointer<ffi.Void> clang_Module_getASTFile(
+  ffi.Pointer<ffi.Void> Module,
+) {
+  return _clang_Module_getASTFile(
+    Module,
+  );
+}
+
+final _dart_clang_Module_getASTFile _clang_Module_getASTFile = _dylib
+    .lookupFunction<_c_clang_Module_getASTFile, _dart_clang_Module_getASTFile>(
+        'clang_Module_getASTFile');
+
+typedef _c_clang_Module_getASTFile = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void> Module,
+);
+
+typedef _dart_clang_Module_getASTFile = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void> Module,
+);
+
+/// Returns the number of top level headers associated with this module.
+int clang_Module_getNumTopLevelHeaders(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+  ffi.Pointer<ffi.Void> Module,
+) {
+  return _clang_Module_getNumTopLevelHeaders(
+    arg0,
+    Module,
+  );
+}
+
+final _dart_clang_Module_getNumTopLevelHeaders
+    _clang_Module_getNumTopLevelHeaders = _dylib.lookupFunction<
+            _c_clang_Module_getNumTopLevelHeaders,
+            _dart_clang_Module_getNumTopLevelHeaders>(
+        'clang_Module_getNumTopLevelHeaders');
+
+typedef _c_clang_Module_getNumTopLevelHeaders = ffi.Uint32 Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+  ffi.Pointer<ffi.Void> Module,
+);
+
+typedef _dart_clang_Module_getNumTopLevelHeaders = int Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+  ffi.Pointer<ffi.Void> Module,
+);
+
+/// Returns the parent of a sub-module or NULL if the given module is top-level, e.g. for 'std.vector' it will return the 'std' module.
+ffi.Pointer<ffi.Void> clang_Module_getParent(
+  ffi.Pointer<ffi.Void> Module,
+) {
+  return _clang_Module_getParent(
+    Module,
+  );
+}
+
+final _dart_clang_Module_getParent _clang_Module_getParent = _dylib
+    .lookupFunction<_c_clang_Module_getParent, _dart_clang_Module_getParent>(
+        'clang_Module_getParent');
+
+typedef _c_clang_Module_getParent = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void> Module,
+);
+
+typedef _dart_clang_Module_getParent = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void> Module,
+);
+
+/// Returns the specified top level header associated with the module.
+ffi.Pointer<ffi.Void> clang_Module_getTopLevelHeader(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+  ffi.Pointer<ffi.Void> Module,
+  int Index,
+) {
+  return _clang_Module_getTopLevelHeader(
+    arg0,
+    Module,
+    Index,
+  );
+}
+
+final _dart_clang_Module_getTopLevelHeader _clang_Module_getTopLevelHeader =
+    _dylib.lookupFunction<_c_clang_Module_getTopLevelHeader,
+        _dart_clang_Module_getTopLevelHeader>('clang_Module_getTopLevelHeader');
+
+typedef _c_clang_Module_getTopLevelHeader = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+  ffi.Pointer<ffi.Void> Module,
+  ffi.Uint32 Index,
+);
+
+typedef _dart_clang_Module_getTopLevelHeader = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+  ffi.Pointer<ffi.Void> Module,
+  int Index,
+);
+
+/// Returns non-zero if the module is a system one.
+int clang_Module_isSystem(
+  ffi.Pointer<ffi.Void> Module,
+) {
+  return _clang_Module_isSystem(
+    Module,
+  );
+}
+
+final _dart_clang_Module_isSystem _clang_Module_isSystem = _dylib
+    .lookupFunction<_c_clang_Module_isSystem, _dart_clang_Module_isSystem>(
+        'clang_Module_isSystem');
+
+typedef _c_clang_Module_isSystem = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> Module,
+);
+
+typedef _dart_clang_Module_isSystem = int Function(
+  ffi.Pointer<ffi.Void> Module,
+);
+
+/// Release a printing policy.
+void clang_PrintingPolicy_dispose(
+  ffi.Pointer<ffi.Void> Policy,
+) {
+  return _clang_PrintingPolicy_dispose(
+    Policy,
+  );
+}
+
+final _dart_clang_PrintingPolicy_dispose _clang_PrintingPolicy_dispose =
+    _dylib.lookupFunction<_c_clang_PrintingPolicy_dispose,
+        _dart_clang_PrintingPolicy_dispose>('clang_PrintingPolicy_dispose');
+
+typedef _c_clang_PrintingPolicy_dispose = ffi.Void Function(
+  ffi.Pointer<ffi.Void> Policy,
+);
+
+typedef _dart_clang_PrintingPolicy_dispose = void Function(
+  ffi.Pointer<ffi.Void> Policy,
+);
+
+/// Get a property value for the given printing policy.
+int clang_PrintingPolicy_getProperty(
+  ffi.Pointer<ffi.Void> Policy,
+  int Property,
+) {
+  return _clang_PrintingPolicy_getProperty(
+    Policy,
+    Property,
+  );
+}
+
+final _dart_clang_PrintingPolicy_getProperty _clang_PrintingPolicy_getProperty =
+    _dylib.lookupFunction<_c_clang_PrintingPolicy_getProperty,
+            _dart_clang_PrintingPolicy_getProperty>(
+        'clang_PrintingPolicy_getProperty');
+
+typedef _c_clang_PrintingPolicy_getProperty = ffi.Uint32 Function(
+  ffi.Pointer<ffi.Void> Policy,
+  ffi.Int32 Property,
+);
+
+typedef _dart_clang_PrintingPolicy_getProperty = int Function(
+  ffi.Pointer<ffi.Void> Policy,
+  int Property,
+);
+
+/// Set a property value for the given printing policy.
+void clang_PrintingPolicy_setProperty(
+  ffi.Pointer<ffi.Void> Policy,
+  int Property,
+  int Value,
+) {
+  return _clang_PrintingPolicy_setProperty(
+    Policy,
+    Property,
+    Value,
+  );
+}
+
+final _dart_clang_PrintingPolicy_setProperty _clang_PrintingPolicy_setProperty =
+    _dylib.lookupFunction<_c_clang_PrintingPolicy_setProperty,
+            _dart_clang_PrintingPolicy_setProperty>(
+        'clang_PrintingPolicy_setProperty');
+
+typedef _c_clang_PrintingPolicy_setProperty = ffi.Void Function(
+  ffi.Pointer<ffi.Void> Policy,
+  ffi.Int32 Property,
+  ffi.Uint32 Value,
+);
+
+typedef _dart_clang_PrintingPolicy_setProperty = void Function(
+  ffi.Pointer<ffi.Void> Policy,
+  int Property,
+  int Value,
+);
+
+/// Destroy the CXTargetInfo object.
+void clang_TargetInfo_dispose(
+  ffi.Pointer<CXTargetInfoImpl> Info,
+) {
+  return _clang_TargetInfo_dispose(
+    Info,
+  );
+}
+
+final _dart_clang_TargetInfo_dispose _clang_TargetInfo_dispose =
+    _dylib.lookupFunction<_c_clang_TargetInfo_dispose,
+        _dart_clang_TargetInfo_dispose>('clang_TargetInfo_dispose');
+
+typedef _c_clang_TargetInfo_dispose = ffi.Void Function(
+  ffi.Pointer<CXTargetInfoImpl> Info,
+);
+
+typedef _dart_clang_TargetInfo_dispose = void Function(
+  ffi.Pointer<CXTargetInfoImpl> Info,
+);
+
+/// Get the pointer width of the target in bits.
+int clang_TargetInfo_getPointerWidth(
+  ffi.Pointer<CXTargetInfoImpl> Info,
+) {
+  return _clang_TargetInfo_getPointerWidth(
+    Info,
+  );
+}
+
+final _dart_clang_TargetInfo_getPointerWidth _clang_TargetInfo_getPointerWidth =
+    _dylib.lookupFunction<_c_clang_TargetInfo_getPointerWidth,
+            _dart_clang_TargetInfo_getPointerWidth>(
+        'clang_TargetInfo_getPointerWidth');
+
+typedef _c_clang_TargetInfo_getPointerWidth = ffi.Int32 Function(
+  ffi.Pointer<CXTargetInfoImpl> Info,
+);
+
+typedef _dart_clang_TargetInfo_getPointerWidth = int Function(
+  ffi.Pointer<CXTargetInfoImpl> Info,
+);
+
+ffi.Pointer<CXType> clang_Type_getNamedType_wrap(
+  ffi.Pointer<CXType> elaboratedType,
+) {
+  return _clang_Type_getNamedType_wrap(
+    elaboratedType,
+  );
+}
+
+final _dart_clang_Type_getNamedType_wrap _clang_Type_getNamedType_wrap =
+    _dylib.lookupFunction<_c_clang_Type_getNamedType_wrap,
+        _dart_clang_Type_getNamedType_wrap>('clang_Type_getNamedType_wrap');
+
+typedef _c_clang_Type_getNamedType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> elaboratedType,
+);
+
+typedef _dart_clang_Type_getNamedType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> elaboratedType,
+);
+
+/// Annotate the given set of tokens by providing cursors for each token that can be mapped to a specific entity within the abstract syntax tree.
+void clang_annotateTokens(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<CXToken> Tokens,
+  int NumTokens,
+  ffi.Pointer<CXCursor> Cursors,
+) {
+  return _clang_annotateTokens(
+    TU,
+    Tokens,
+    NumTokens,
+    Cursors,
+  );
+}
+
+final _dart_clang_annotateTokens _clang_annotateTokens =
+    _dylib.lookupFunction<_c_clang_annotateTokens, _dart_clang_annotateTokens>(
+        'clang_annotateTokens');
+
+typedef _c_clang_annotateTokens = ffi.Void Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<CXToken> Tokens,
+  ffi.Uint32 NumTokens,
+  ffi.Pointer<CXCursor> Cursors,
+);
+
+typedef _dart_clang_annotateTokens = void Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<CXToken> Tokens,
+  int NumTokens,
+  ffi.Pointer<CXCursor> Cursors,
+);
+
+/// Perform code completion at a given location in a translation unit.
+ffi.Pointer<CXCodeCompleteResults> clang_codeCompleteAt(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<ffi.Int8> complete_filename,
+  int complete_line,
+  int complete_column,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  int options,
+) {
+  return _clang_codeCompleteAt(
+    TU,
+    complete_filename,
+    complete_line,
+    complete_column,
+    unsaved_files,
+    num_unsaved_files,
+    options,
+  );
+}
+
+final _dart_clang_codeCompleteAt _clang_codeCompleteAt =
+    _dylib.lookupFunction<_c_clang_codeCompleteAt, _dart_clang_codeCompleteAt>(
+        'clang_codeCompleteAt');
+
+typedef _c_clang_codeCompleteAt = ffi.Pointer<CXCodeCompleteResults> Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<ffi.Int8> complete_filename,
+  ffi.Uint32 complete_line,
+  ffi.Uint32 complete_column,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  ffi.Uint32 num_unsaved_files,
+  ffi.Uint32 options,
+);
+
+typedef _dart_clang_codeCompleteAt = ffi.Pointer<CXCodeCompleteResults>
+    Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<ffi.Int8> complete_filename,
+  int complete_line,
+  int complete_column,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  int options,
+);
+
+/// Returns the cursor kind for the container for the current code completion context. The container is only guaranteed to be set for contexts where a container exists (i.e. member accesses or Objective-C message sends); if there is not a container, this function will return CXCursor_InvalidCode.
+int clang_codeCompleteGetContainerKind(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+  ffi.Pointer<ffi.Uint32> IsIncomplete,
+) {
+  return _clang_codeCompleteGetContainerKind(
+    Results,
+    IsIncomplete,
+  );
+}
+
+final _dart_clang_codeCompleteGetContainerKind
+    _clang_codeCompleteGetContainerKind = _dylib.lookupFunction<
+            _c_clang_codeCompleteGetContainerKind,
+            _dart_clang_codeCompleteGetContainerKind>(
+        'clang_codeCompleteGetContainerKind');
+
+typedef _c_clang_codeCompleteGetContainerKind = ffi.Int32 Function(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+  ffi.Pointer<ffi.Uint32> IsIncomplete,
+);
+
+typedef _dart_clang_codeCompleteGetContainerKind = int Function(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+  ffi.Pointer<ffi.Uint32> IsIncomplete,
+);
+
+/// Determines what completions are appropriate for the context the given code completion.
+int clang_codeCompleteGetContexts(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+) {
+  return _clang_codeCompleteGetContexts(
+    Results,
+  );
+}
+
+final _dart_clang_codeCompleteGetContexts _clang_codeCompleteGetContexts =
+    _dylib.lookupFunction<_c_clang_codeCompleteGetContexts,
+        _dart_clang_codeCompleteGetContexts>('clang_codeCompleteGetContexts');
+
+typedef _c_clang_codeCompleteGetContexts = ffi.Uint64 Function(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+);
+
+typedef _dart_clang_codeCompleteGetContexts = int Function(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+);
+
+/// Retrieve a diagnostic associated with the given code completion.
+ffi.Pointer<ffi.Void> clang_codeCompleteGetDiagnostic(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+  int Index,
+) {
+  return _clang_codeCompleteGetDiagnostic(
+    Results,
+    Index,
+  );
+}
+
+final _dart_clang_codeCompleteGetDiagnostic _clang_codeCompleteGetDiagnostic =
+    _dylib.lookupFunction<_c_clang_codeCompleteGetDiagnostic,
+            _dart_clang_codeCompleteGetDiagnostic>(
+        'clang_codeCompleteGetDiagnostic');
+
+typedef _c_clang_codeCompleteGetDiagnostic = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+  ffi.Uint32 Index,
+);
+
+typedef _dart_clang_codeCompleteGetDiagnostic = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+  int Index,
+);
+
+/// Determine the number of diagnostics produced prior to the location where code completion was performed.
+int clang_codeCompleteGetNumDiagnostics(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+) {
+  return _clang_codeCompleteGetNumDiagnostics(
+    Results,
+  );
+}
+
+final _dart_clang_codeCompleteGetNumDiagnostics
+    _clang_codeCompleteGetNumDiagnostics = _dylib.lookupFunction<
+            _c_clang_codeCompleteGetNumDiagnostics,
+            _dart_clang_codeCompleteGetNumDiagnostics>(
+        'clang_codeCompleteGetNumDiagnostics');
+
+typedef _c_clang_codeCompleteGetNumDiagnostics = ffi.Uint32 Function(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+);
+
+typedef _dart_clang_codeCompleteGetNumDiagnostics = int Function(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+);
+
+/// Creates an empty CXCursorSet.
+ffi.Pointer<CXCursorSetImpl> clang_createCXCursorSet() {
+  return _clang_createCXCursorSet();
+}
+
+final _dart_clang_createCXCursorSet _clang_createCXCursorSet = _dylib
+    .lookupFunction<_c_clang_createCXCursorSet, _dart_clang_createCXCursorSet>(
+        'clang_createCXCursorSet');
+
+typedef _c_clang_createCXCursorSet = ffi.Pointer<CXCursorSetImpl> Function();
+
+typedef _dart_clang_createCXCursorSet = ffi.Pointer<CXCursorSetImpl> Function();
+
+/// Provides a shared context for creating translation units.
+ffi.Pointer<ffi.Void> clang_createIndex(
+  int excludeDeclarationsFromPCH,
+  int displayDiagnostics,
+) {
+  return _clang_createIndex(
+    excludeDeclarationsFromPCH,
+    displayDiagnostics,
+  );
+}
+
+final _dart_clang_createIndex _clang_createIndex =
+    _dylib.lookupFunction<_c_clang_createIndex, _dart_clang_createIndex>(
+        'clang_createIndex');
+
+typedef _c_clang_createIndex = ffi.Pointer<ffi.Void> Function(
+  ffi.Int32 excludeDeclarationsFromPCH,
+  ffi.Int32 displayDiagnostics,
+);
+
+typedef _dart_clang_createIndex = ffi.Pointer<ffi.Void> Function(
+  int excludeDeclarationsFromPCH,
+  int displayDiagnostics,
+);
+
+/// Same as clang_createTranslationUnit2, but returns the CXTranslationUnit instead of an error code. In case of an error this routine returns a NULL CXTranslationUnit, without further detailed error codes.
+ffi.Pointer<CXTranslationUnitImpl> clang_createTranslationUnit(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> ast_filename,
+) {
+  return _clang_createTranslationUnit(
+    CIdx,
+    ast_filename,
+  );
+}
+
+final _dart_clang_createTranslationUnit _clang_createTranslationUnit =
+    _dylib.lookupFunction<_c_clang_createTranslationUnit,
+        _dart_clang_createTranslationUnit>('clang_createTranslationUnit');
+
+typedef _c_clang_createTranslationUnit = ffi.Pointer<CXTranslationUnitImpl>
+    Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> ast_filename,
+);
+
+typedef _dart_clang_createTranslationUnit = ffi.Pointer<CXTranslationUnitImpl>
+    Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> ast_filename,
+);
+
+/// Create a translation unit from an AST file ( -emit-ast).
+int clang_createTranslationUnit2(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> ast_filename,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+) {
+  return _clang_createTranslationUnit2(
+    CIdx,
+    ast_filename,
+    out_TU,
+  );
+}
+
+final _dart_clang_createTranslationUnit2 _clang_createTranslationUnit2 =
+    _dylib.lookupFunction<_c_clang_createTranslationUnit2,
+        _dart_clang_createTranslationUnit2>('clang_createTranslationUnit2');
+
+typedef _c_clang_createTranslationUnit2 = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> ast_filename,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+);
+
+typedef _dart_clang_createTranslationUnit2 = int Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> ast_filename,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+);
+
+/// Return the CXTranslationUnit for a given source file and the provided command line arguments one would pass to the compiler.
+ffi.Pointer<CXTranslationUnitImpl> clang_createTranslationUnitFromSourceFile(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  int num_clang_command_line_args,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> clang_command_line_args,
+  int num_unsaved_files,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+) {
+  return _clang_createTranslationUnitFromSourceFile(
+    CIdx,
+    source_filename,
+    num_clang_command_line_args,
+    clang_command_line_args,
+    num_unsaved_files,
+    unsaved_files,
+  );
+}
+
+final _dart_clang_createTranslationUnitFromSourceFile
+    _clang_createTranslationUnitFromSourceFile = _dylib.lookupFunction<
+            _c_clang_createTranslationUnitFromSourceFile,
+            _dart_clang_createTranslationUnitFromSourceFile>(
+        'clang_createTranslationUnitFromSourceFile');
+
+typedef _c_clang_createTranslationUnitFromSourceFile
+    = ffi.Pointer<CXTranslationUnitImpl> Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Int32 num_clang_command_line_args,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> clang_command_line_args,
+  ffi.Uint32 num_unsaved_files,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+);
+
+typedef _dart_clang_createTranslationUnitFromSourceFile
+    = ffi.Pointer<CXTranslationUnitImpl> Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  int num_clang_command_line_args,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> clang_command_line_args,
+  int num_unsaved_files,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+);
+
+/// Returns a default set of code-completion options that can be passed to clang_codeCompleteAt().
+int clang_defaultCodeCompleteOptions() {
+  return _clang_defaultCodeCompleteOptions();
+}
+
+final _dart_clang_defaultCodeCompleteOptions _clang_defaultCodeCompleteOptions =
+    _dylib.lookupFunction<_c_clang_defaultCodeCompleteOptions,
+            _dart_clang_defaultCodeCompleteOptions>(
+        'clang_defaultCodeCompleteOptions');
+
+typedef _c_clang_defaultCodeCompleteOptions = ffi.Uint32 Function();
+
+typedef _dart_clang_defaultCodeCompleteOptions = int Function();
+
+/// Retrieve the set of display options most similar to the default behavior of the clang compiler.
+int clang_defaultDiagnosticDisplayOptions() {
+  return _clang_defaultDiagnosticDisplayOptions();
+}
+
+final _dart_clang_defaultDiagnosticDisplayOptions
+    _clang_defaultDiagnosticDisplayOptions = _dylib.lookupFunction<
+            _c_clang_defaultDiagnosticDisplayOptions,
+            _dart_clang_defaultDiagnosticDisplayOptions>(
+        'clang_defaultDiagnosticDisplayOptions');
+
+typedef _c_clang_defaultDiagnosticDisplayOptions = ffi.Uint32 Function();
+
+typedef _dart_clang_defaultDiagnosticDisplayOptions = int Function();
+
+/// Returns the set of flags that is suitable for parsing a translation unit that is being edited.
+int clang_defaultEditingTranslationUnitOptions() {
+  return _clang_defaultEditingTranslationUnitOptions();
+}
+
+final _dart_clang_defaultEditingTranslationUnitOptions
+    _clang_defaultEditingTranslationUnitOptions = _dylib.lookupFunction<
+            _c_clang_defaultEditingTranslationUnitOptions,
+            _dart_clang_defaultEditingTranslationUnitOptions>(
+        'clang_defaultEditingTranslationUnitOptions');
+
+typedef _c_clang_defaultEditingTranslationUnitOptions = ffi.Uint32 Function();
+
+typedef _dart_clang_defaultEditingTranslationUnitOptions = int Function();
+
+/// Returns the set of flags that is suitable for reparsing a translation unit.
+int clang_defaultReparseOptions(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+) {
+  return _clang_defaultReparseOptions(
+    TU,
+  );
+}
+
+final _dart_clang_defaultReparseOptions _clang_defaultReparseOptions =
+    _dylib.lookupFunction<_c_clang_defaultReparseOptions,
+        _dart_clang_defaultReparseOptions>('clang_defaultReparseOptions');
+
+typedef _c_clang_defaultReparseOptions = ffi.Uint32 Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+);
+
+typedef _dart_clang_defaultReparseOptions = int Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+);
+
+/// Returns the set of flags that is suitable for saving a translation unit.
+int clang_defaultSaveOptions(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+) {
+  return _clang_defaultSaveOptions(
+    TU,
+  );
+}
+
+final _dart_clang_defaultSaveOptions _clang_defaultSaveOptions =
+    _dylib.lookupFunction<_c_clang_defaultSaveOptions,
+        _dart_clang_defaultSaveOptions>('clang_defaultSaveOptions');
+
+typedef _c_clang_defaultSaveOptions = ffi.Uint32 Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+);
+
+typedef _dart_clang_defaultSaveOptions = int Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+);
+
+/// Disposes a CXCursorSet and releases its associated memory.
+void clang_disposeCXCursorSet(
+  ffi.Pointer<CXCursorSetImpl> cset,
+) {
+  return _clang_disposeCXCursorSet(
+    cset,
+  );
+}
+
+final _dart_clang_disposeCXCursorSet _clang_disposeCXCursorSet =
+    _dylib.lookupFunction<_c_clang_disposeCXCursorSet,
+        _dart_clang_disposeCXCursorSet>('clang_disposeCXCursorSet');
+
+typedef _c_clang_disposeCXCursorSet = ffi.Void Function(
+  ffi.Pointer<CXCursorSetImpl> cset,
+);
+
+typedef _dart_clang_disposeCXCursorSet = void Function(
+  ffi.Pointer<CXCursorSetImpl> cset,
+);
+
+/// Free the memory associated with a CXPlatformAvailability structure.
+void clang_disposeCXPlatformAvailability(
+  ffi.Pointer<CXPlatformAvailability> availability,
+) {
+  return _clang_disposeCXPlatformAvailability(
+    availability,
+  );
+}
+
+final _dart_clang_disposeCXPlatformAvailability
+    _clang_disposeCXPlatformAvailability = _dylib.lookupFunction<
+            _c_clang_disposeCXPlatformAvailability,
+            _dart_clang_disposeCXPlatformAvailability>(
+        'clang_disposeCXPlatformAvailability');
+
+typedef _c_clang_disposeCXPlatformAvailability = ffi.Void Function(
+  ffi.Pointer<CXPlatformAvailability> availability,
+);
+
+typedef _dart_clang_disposeCXPlatformAvailability = void Function(
+  ffi.Pointer<CXPlatformAvailability> availability,
+);
+
+/// Free the given set of code-completion results.
+void clang_disposeCodeCompleteResults(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+) {
+  return _clang_disposeCodeCompleteResults(
+    Results,
+  );
+}
+
+final _dart_clang_disposeCodeCompleteResults _clang_disposeCodeCompleteResults =
+    _dylib.lookupFunction<_c_clang_disposeCodeCompleteResults,
+            _dart_clang_disposeCodeCompleteResults>(
+        'clang_disposeCodeCompleteResults');
+
+typedef _c_clang_disposeCodeCompleteResults = ffi.Void Function(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+);
+
+typedef _dart_clang_disposeCodeCompleteResults = void Function(
+  ffi.Pointer<CXCodeCompleteResults> Results,
+);
+
+/// Destroy a diagnostic.
+void clang_disposeDiagnostic(
+  ffi.Pointer<ffi.Void> Diagnostic,
+) {
+  return _clang_disposeDiagnostic(
+    Diagnostic,
+  );
+}
+
+final _dart_clang_disposeDiagnostic _clang_disposeDiagnostic = _dylib
+    .lookupFunction<_c_clang_disposeDiagnostic, _dart_clang_disposeDiagnostic>(
+        'clang_disposeDiagnostic');
+
+typedef _c_clang_disposeDiagnostic = ffi.Void Function(
+  ffi.Pointer<ffi.Void> Diagnostic,
+);
+
+typedef _dart_clang_disposeDiagnostic = void Function(
+  ffi.Pointer<ffi.Void> Diagnostic,
+);
+
+/// Release a CXDiagnosticSet and all of its contained diagnostics.
+void clang_disposeDiagnosticSet(
+  ffi.Pointer<ffi.Void> Diags,
+) {
+  return _clang_disposeDiagnosticSet(
+    Diags,
+  );
+}
+
+final _dart_clang_disposeDiagnosticSet _clang_disposeDiagnosticSet =
+    _dylib.lookupFunction<_c_clang_disposeDiagnosticSet,
+        _dart_clang_disposeDiagnosticSet>('clang_disposeDiagnosticSet');
+
+typedef _c_clang_disposeDiagnosticSet = ffi.Void Function(
+  ffi.Pointer<ffi.Void> Diags,
+);
+
+typedef _dart_clang_disposeDiagnosticSet = void Function(
+  ffi.Pointer<ffi.Void> Diags,
+);
+
+/// Destroy the given index.
+void clang_disposeIndex(
+  ffi.Pointer<ffi.Void> index,
+) {
+  return _clang_disposeIndex(
+    index,
+  );
+}
+
+final _dart_clang_disposeIndex _clang_disposeIndex =
+    _dylib.lookupFunction<_c_clang_disposeIndex, _dart_clang_disposeIndex>(
+        'clang_disposeIndex');
+
+typedef _c_clang_disposeIndex = ffi.Void Function(
+  ffi.Pointer<ffi.Void> index,
+);
+
+typedef _dart_clang_disposeIndex = void Function(
+  ffi.Pointer<ffi.Void> index,
+);
+
+/// Free the set of overridden cursors returned by clang_getOverriddenCursors().
+void clang_disposeOverriddenCursors(
+  ffi.Pointer<CXCursor> overridden,
+) {
+  return _clang_disposeOverriddenCursors(
+    overridden,
+  );
+}
+
+final _dart_clang_disposeOverriddenCursors _clang_disposeOverriddenCursors =
+    _dylib.lookupFunction<_c_clang_disposeOverriddenCursors,
+        _dart_clang_disposeOverriddenCursors>('clang_disposeOverriddenCursors');
+
+typedef _c_clang_disposeOverriddenCursors = ffi.Void Function(
+  ffi.Pointer<CXCursor> overridden,
+);
+
+typedef _dart_clang_disposeOverriddenCursors = void Function(
+  ffi.Pointer<CXCursor> overridden,
+);
+
+/// Destroy the given CXSourceRangeList.
+void clang_disposeSourceRangeList(
+  ffi.Pointer<CXSourceRangeList> ranges,
+) {
+  return _clang_disposeSourceRangeList(
+    ranges,
+  );
+}
+
+final _dart_clang_disposeSourceRangeList _clang_disposeSourceRangeList =
+    _dylib.lookupFunction<_c_clang_disposeSourceRangeList,
+        _dart_clang_disposeSourceRangeList>('clang_disposeSourceRangeList');
+
+typedef _c_clang_disposeSourceRangeList = ffi.Void Function(
+  ffi.Pointer<CXSourceRangeList> ranges,
+);
+
+typedef _dart_clang_disposeSourceRangeList = void Function(
+  ffi.Pointer<CXSourceRangeList> ranges,
+);
+
+/// Free the given string set.
+void clang_disposeStringSet(
+  ffi.Pointer<CXStringSet> set,
+) {
+  return _clang_disposeStringSet(
+    set,
+  );
+}
+
+final _dart_clang_disposeStringSet _clang_disposeStringSet = _dylib
+    .lookupFunction<_c_clang_disposeStringSet, _dart_clang_disposeStringSet>(
+        'clang_disposeStringSet');
+
+typedef _c_clang_disposeStringSet = ffi.Void Function(
+  ffi.Pointer<CXStringSet> set,
+);
+
+typedef _dart_clang_disposeStringSet = void Function(
+  ffi.Pointer<CXStringSet> set,
+);
+
+void clang_disposeString_wrap(
+  ffi.Pointer<CXString> string,
+) {
+  return _clang_disposeString_wrap(
+    string,
+  );
+}
+
+final _dart_clang_disposeString_wrap _clang_disposeString_wrap =
+    _dylib.lookupFunction<_c_clang_disposeString_wrap,
+        _dart_clang_disposeString_wrap>('clang_disposeString_wrap');
+
+typedef _c_clang_disposeString_wrap = ffi.Void Function(
+  ffi.Pointer<CXString> string,
+);
+
+typedef _dart_clang_disposeString_wrap = void Function(
+  ffi.Pointer<CXString> string,
+);
+
+/// Free the given set of tokens.
+void clang_disposeTokens(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<CXToken> Tokens,
+  int NumTokens,
+) {
+  return _clang_disposeTokens(
+    TU,
+    Tokens,
+    NumTokens,
+  );
+}
+
+final _dart_clang_disposeTokens _clang_disposeTokens =
+    _dylib.lookupFunction<_c_clang_disposeTokens, _dart_clang_disposeTokens>(
+        'clang_disposeTokens');
+
+typedef _c_clang_disposeTokens = ffi.Void Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<CXToken> Tokens,
+  ffi.Uint32 NumTokens,
+);
+
+typedef _dart_clang_disposeTokens = void Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<CXToken> Tokens,
+  int NumTokens,
+);
+
+/// Destroy the specified CXTranslationUnit object.
+void clang_disposeTranslationUnit(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+) {
+  return _clang_disposeTranslationUnit(
+    arg0,
+  );
+}
+
+final _dart_clang_disposeTranslationUnit _clang_disposeTranslationUnit =
+    _dylib.lookupFunction<_c_clang_disposeTranslationUnit,
+        _dart_clang_disposeTranslationUnit>('clang_disposeTranslationUnit');
+
+typedef _c_clang_disposeTranslationUnit = ffi.Void Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+);
+
+typedef _dart_clang_disposeTranslationUnit = void Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+);
+
+void clang_enableStackTraces() {
+  return _clang_enableStackTraces();
+}
+
+final _dart_clang_enableStackTraces _clang_enableStackTraces = _dylib
+    .lookupFunction<_c_clang_enableStackTraces, _dart_clang_enableStackTraces>(
+        'clang_enableStackTraces');
+
+typedef _c_clang_enableStackTraces = ffi.Void Function();
+
+typedef _dart_clang_enableStackTraces = void Function();
+
+void clang_executeOnThread(
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_1>> fn,
+  ffi.Pointer<ffi.Void> user_data,
+  int stack_size,
+) {
+  return _clang_executeOnThread(
+    fn,
+    user_data,
+    stack_size,
+  );
+}
+
+final _dart_clang_executeOnThread _clang_executeOnThread = _dylib
+    .lookupFunction<_c_clang_executeOnThread, _dart_clang_executeOnThread>(
+        'clang_executeOnThread');
+
+typedef _c_clang_executeOnThread = ffi.Void Function(
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_1>> fn,
+  ffi.Pointer<ffi.Void> user_data,
+  ffi.Uint32 stack_size,
+);
+
+typedef _dart_clang_executeOnThread = void Function(
+  ffi.Pointer<ffi.NativeFunction<_typedefC_noname_1>> fn,
+  ffi.Pointer<ffi.Void> user_data,
+  int stack_size,
+);
+
+ffi.Pointer<CXString> clang_formatDiagnostic_wrap(
+  ffi.Pointer<ffi.Void> diag,
+  int opts,
+) {
+  return _clang_formatDiagnostic_wrap(
+    diag,
+    opts,
+  );
+}
+
+final _dart_clang_formatDiagnostic_wrap _clang_formatDiagnostic_wrap =
+    _dylib.lookupFunction<_c_clang_formatDiagnostic_wrap,
+        _dart_clang_formatDiagnostic_wrap>('clang_formatDiagnostic_wrap');
+
+typedef _c_clang_formatDiagnostic_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<ffi.Void> diag,
+  ffi.Int32 opts,
+);
+
+typedef _dart_clang_formatDiagnostic_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<ffi.Void> diag,
+  int opts,
+);
+
+/// Retrieve all ranges from all files that were skipped by the preprocessor.
+ffi.Pointer<CXSourceRangeList> clang_getAllSkippedRanges(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+) {
+  return _clang_getAllSkippedRanges(
+    tu,
+  );
+}
+
+final _dart_clang_getAllSkippedRanges _clang_getAllSkippedRanges =
+    _dylib.lookupFunction<_c_clang_getAllSkippedRanges,
+        _dart_clang_getAllSkippedRanges>('clang_getAllSkippedRanges');
+
+typedef _c_clang_getAllSkippedRanges = ffi.Pointer<CXSourceRangeList> Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+);
+
+typedef _dart_clang_getAllSkippedRanges = ffi.Pointer<CXSourceRangeList>
+    Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+);
+
+ffi.Pointer<CXType> clang_getArgType_wrap(
+  ffi.Pointer<CXType> cxtype,
+  int i,
+) {
+  return _clang_getArgType_wrap(
+    cxtype,
+    i,
+  );
+}
+
+final _dart_clang_getArgType_wrap _clang_getArgType_wrap = _dylib
+    .lookupFunction<_c_clang_getArgType_wrap, _dart_clang_getArgType_wrap>(
+        'clang_getArgType_wrap');
+
+typedef _c_clang_getArgType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> cxtype,
+  ffi.Uint32 i,
+);
+
+typedef _dart_clang_getArgType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> cxtype,
+  int i,
+);
+
+ffi.Pointer<CXType> clang_getArrayElementType_wrap(
+  ffi.Pointer<CXType> cxtype,
+) {
+  return _clang_getArrayElementType_wrap(
+    cxtype,
+  );
+}
+
+final _dart_clang_getArrayElementType_wrap _clang_getArrayElementType_wrap =
+    _dylib.lookupFunction<_c_clang_getArrayElementType_wrap,
+        _dart_clang_getArrayElementType_wrap>('clang_getArrayElementType_wrap');
+
+typedef _c_clang_getArrayElementType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+typedef _dart_clang_getArrayElementType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+ffi.Pointer<ffi.Int8> clang_getCString_wrap(
+  ffi.Pointer<CXString> string,
+) {
+  return _clang_getCString_wrap(
+    string,
+  );
+}
+
+final _dart_clang_getCString_wrap _clang_getCString_wrap = _dylib
+    .lookupFunction<_c_clang_getCString_wrap, _dart_clang_getCString_wrap>(
+        'clang_getCString_wrap');
+
+typedef _c_clang_getCString_wrap = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<CXString> string,
+);
+
+typedef _dart_clang_getCString_wrap = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<CXString> string,
+);
+
+ffi.Pointer<CXType> clang_getCanonicalType_wrap(
+  ffi.Pointer<CXType> typerefType,
+) {
+  return _clang_getCanonicalType_wrap(
+    typerefType,
+  );
+}
+
+final _dart_clang_getCanonicalType_wrap _clang_getCanonicalType_wrap =
+    _dylib.lookupFunction<_c_clang_getCanonicalType_wrap,
+        _dart_clang_getCanonicalType_wrap>('clang_getCanonicalType_wrap');
+
+typedef _c_clang_getCanonicalType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> typerefType,
+);
+
+typedef _dart_clang_getCanonicalType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> typerefType,
+);
+
+/// Retrieve the child diagnostics of a CXDiagnostic.
+ffi.Pointer<ffi.Void> clang_getChildDiagnostics(
+  ffi.Pointer<ffi.Void> D,
+) {
+  return _clang_getChildDiagnostics(
+    D,
+  );
+}
+
+final _dart_clang_getChildDiagnostics _clang_getChildDiagnostics =
+    _dylib.lookupFunction<_c_clang_getChildDiagnostics,
+        _dart_clang_getChildDiagnostics>('clang_getChildDiagnostics');
+
+typedef _c_clang_getChildDiagnostics = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void> D,
+);
+
+typedef _dart_clang_getChildDiagnostics = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void> D,
+);
+
+/// Determine the availability of the entity that this code-completion string refers to.
+int clang_getCompletionAvailability(
+  ffi.Pointer<ffi.Void> completion_string,
+) {
+  return _clang_getCompletionAvailability(
+    completion_string,
+  );
+}
+
+final _dart_clang_getCompletionAvailability _clang_getCompletionAvailability =
+    _dylib.lookupFunction<_c_clang_getCompletionAvailability,
+            _dart_clang_getCompletionAvailability>(
+        'clang_getCompletionAvailability');
+
+typedef _c_clang_getCompletionAvailability = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> completion_string,
+);
+
+typedef _dart_clang_getCompletionAvailability = int Function(
+  ffi.Pointer<ffi.Void> completion_string,
+);
+
+/// Retrieve the completion string associated with a particular chunk within a completion string.
+ffi.Pointer<ffi.Void> clang_getCompletionChunkCompletionString(
+  ffi.Pointer<ffi.Void> completion_string,
+  int chunk_number,
+) {
+  return _clang_getCompletionChunkCompletionString(
+    completion_string,
+    chunk_number,
+  );
+}
+
+final _dart_clang_getCompletionChunkCompletionString
+    _clang_getCompletionChunkCompletionString = _dylib.lookupFunction<
+            _c_clang_getCompletionChunkCompletionString,
+            _dart_clang_getCompletionChunkCompletionString>(
+        'clang_getCompletionChunkCompletionString');
+
+typedef _c_clang_getCompletionChunkCompletionString = ffi.Pointer<ffi.Void>
+    Function(
+  ffi.Pointer<ffi.Void> completion_string,
+  ffi.Uint32 chunk_number,
+);
+
+typedef _dart_clang_getCompletionChunkCompletionString = ffi.Pointer<ffi.Void>
+    Function(
+  ffi.Pointer<ffi.Void> completion_string,
+  int chunk_number,
+);
+
+/// Determine the kind of a particular chunk within a completion string.
+int clang_getCompletionChunkKind(
+  ffi.Pointer<ffi.Void> completion_string,
+  int chunk_number,
+) {
+  return _clang_getCompletionChunkKind(
+    completion_string,
+    chunk_number,
+  );
+}
+
+final _dart_clang_getCompletionChunkKind _clang_getCompletionChunkKind =
+    _dylib.lookupFunction<_c_clang_getCompletionChunkKind,
+        _dart_clang_getCompletionChunkKind>('clang_getCompletionChunkKind');
+
+typedef _c_clang_getCompletionChunkKind = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> completion_string,
+  ffi.Uint32 chunk_number,
+);
+
+typedef _dart_clang_getCompletionChunkKind = int Function(
+  ffi.Pointer<ffi.Void> completion_string,
+  int chunk_number,
+);
+
+/// Retrieve the number of annotations associated with the given completion string.
+int clang_getCompletionNumAnnotations(
+  ffi.Pointer<ffi.Void> completion_string,
+) {
+  return _clang_getCompletionNumAnnotations(
+    completion_string,
+  );
+}
+
+final _dart_clang_getCompletionNumAnnotations
+    _clang_getCompletionNumAnnotations = _dylib.lookupFunction<
+            _c_clang_getCompletionNumAnnotations,
+            _dart_clang_getCompletionNumAnnotations>(
+        'clang_getCompletionNumAnnotations');
+
+typedef _c_clang_getCompletionNumAnnotations = ffi.Uint32 Function(
+  ffi.Pointer<ffi.Void> completion_string,
+);
+
+typedef _dart_clang_getCompletionNumAnnotations = int Function(
+  ffi.Pointer<ffi.Void> completion_string,
+);
+
+/// Retrieve the number of fix-its for the given completion index.
+int clang_getCompletionNumFixIts(
+  ffi.Pointer<CXCodeCompleteResults> results,
+  int completion_index,
+) {
+  return _clang_getCompletionNumFixIts(
+    results,
+    completion_index,
+  );
+}
+
+final _dart_clang_getCompletionNumFixIts _clang_getCompletionNumFixIts =
+    _dylib.lookupFunction<_c_clang_getCompletionNumFixIts,
+        _dart_clang_getCompletionNumFixIts>('clang_getCompletionNumFixIts');
+
+typedef _c_clang_getCompletionNumFixIts = ffi.Uint32 Function(
+  ffi.Pointer<CXCodeCompleteResults> results,
+  ffi.Uint32 completion_index,
+);
+
+typedef _dart_clang_getCompletionNumFixIts = int Function(
+  ffi.Pointer<CXCodeCompleteResults> results,
+  int completion_index,
+);
+
+/// Determine the priority of this code completion.
+int clang_getCompletionPriority(
+  ffi.Pointer<ffi.Void> completion_string,
+) {
+  return _clang_getCompletionPriority(
+    completion_string,
+  );
+}
+
+final _dart_clang_getCompletionPriority _clang_getCompletionPriority =
+    _dylib.lookupFunction<_c_clang_getCompletionPriority,
+        _dart_clang_getCompletionPriority>('clang_getCompletionPriority');
+
+typedef _c_clang_getCompletionPriority = ffi.Uint32 Function(
+  ffi.Pointer<ffi.Void> completion_string,
+);
+
+typedef _dart_clang_getCompletionPriority = int Function(
+  ffi.Pointer<ffi.Void> completion_string,
+);
+
+ffi.Pointer<CXString> clang_getCursorKindSpelling_wrap(
+  int kind,
+) {
+  return _clang_getCursorKindSpelling_wrap(
+    kind,
+  );
+}
+
+final _dart_clang_getCursorKindSpelling_wrap _clang_getCursorKindSpelling_wrap =
+    _dylib.lookupFunction<_c_clang_getCursorKindSpelling_wrap,
+            _dart_clang_getCursorKindSpelling_wrap>(
+        'clang_getCursorKindSpelling_wrap');
+
+typedef _c_clang_getCursorKindSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Int32 kind,
+);
+
+typedef _dart_clang_getCursorKindSpelling_wrap = ffi.Pointer<CXString> Function(
+  int kind,
+);
+
+int clang_getCursorKind_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_getCursorKind_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_getCursorKind_wrap _clang_getCursorKind_wrap =
+    _dylib.lookupFunction<_c_clang_getCursorKind_wrap,
+        _dart_clang_getCursorKind_wrap>('clang_getCursorKind_wrap');
+
+typedef _c_clang_getCursorKind_wrap = ffi.Int32 Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_getCursorKind_wrap = int Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+ffi.Pointer<CXSourceLocation> clang_getCursorLocation_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_getCursorLocation_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_getCursorLocation_wrap _clang_getCursorLocation_wrap =
+    _dylib.lookupFunction<_c_clang_getCursorLocation_wrap,
+        _dart_clang_getCursorLocation_wrap>('clang_getCursorLocation_wrap');
+
+typedef _c_clang_getCursorLocation_wrap = ffi.Pointer<CXSourceLocation>
+    Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_getCursorLocation_wrap = ffi.Pointer<CXSourceLocation>
+    Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+/// The name of parameter, struct, typedef.
+ffi.Pointer<CXString> clang_getCursorSpelling_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_getCursorSpelling_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_getCursorSpelling_wrap _clang_getCursorSpelling_wrap =
+    _dylib.lookupFunction<_c_clang_getCursorSpelling_wrap,
+        _dart_clang_getCursorSpelling_wrap>('clang_getCursorSpelling_wrap');
+
+typedef _c_clang_getCursorSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_getCursorSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+ffi.Pointer<CXType> clang_getCursorType_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_getCursorType_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_getCursorType_wrap _clang_getCursorType_wrap =
+    _dylib.lookupFunction<_c_clang_getCursorType_wrap,
+        _dart_clang_getCursorType_wrap>('clang_getCursorType_wrap');
+
+typedef _c_clang_getCursorType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_getCursorType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+/// Retrieve a diagnostic associated with the given translation unit.
+ffi.Pointer<ffi.Void> clang_getDiagnostic(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+  int Index,
+) {
+  return _clang_getDiagnostic(
+    Unit,
+    Index,
+  );
+}
+
+final _dart_clang_getDiagnostic _clang_getDiagnostic =
+    _dylib.lookupFunction<_c_clang_getDiagnostic, _dart_clang_getDiagnostic>(
+        'clang_getDiagnostic');
+
+typedef _c_clang_getDiagnostic = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+  ffi.Uint32 Index,
+);
+
+typedef _dart_clang_getDiagnostic = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+  int Index,
+);
+
+/// Retrieve the category number for this diagnostic.
+int clang_getDiagnosticCategory(
+  ffi.Pointer<ffi.Void> arg0,
+) {
+  return _clang_getDiagnosticCategory(
+    arg0,
+  );
+}
+
+final _dart_clang_getDiagnosticCategory _clang_getDiagnosticCategory =
+    _dylib.lookupFunction<_c_clang_getDiagnosticCategory,
+        _dart_clang_getDiagnosticCategory>('clang_getDiagnosticCategory');
+
+typedef _c_clang_getDiagnosticCategory = ffi.Uint32 Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+typedef _dart_clang_getDiagnosticCategory = int Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+/// Retrieve a diagnostic associated with the given CXDiagnosticSet.
+ffi.Pointer<ffi.Void> clang_getDiagnosticInSet(
+  ffi.Pointer<ffi.Void> Diags,
+  int Index,
+) {
+  return _clang_getDiagnosticInSet(
+    Diags,
+    Index,
+  );
+}
+
+final _dart_clang_getDiagnosticInSet _clang_getDiagnosticInSet =
+    _dylib.lookupFunction<_c_clang_getDiagnosticInSet,
+        _dart_clang_getDiagnosticInSet>('clang_getDiagnosticInSet');
+
+typedef _c_clang_getDiagnosticInSet = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void> Diags,
+  ffi.Uint32 Index,
+);
+
+typedef _dart_clang_getDiagnosticInSet = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Void> Diags,
+  int Index,
+);
+
+/// Determine the number of fix-it hints associated with the given diagnostic.
+int clang_getDiagnosticNumFixIts(
+  ffi.Pointer<ffi.Void> Diagnostic,
+) {
+  return _clang_getDiagnosticNumFixIts(
+    Diagnostic,
+  );
+}
+
+final _dart_clang_getDiagnosticNumFixIts _clang_getDiagnosticNumFixIts =
+    _dylib.lookupFunction<_c_clang_getDiagnosticNumFixIts,
+        _dart_clang_getDiagnosticNumFixIts>('clang_getDiagnosticNumFixIts');
+
+typedef _c_clang_getDiagnosticNumFixIts = ffi.Uint32 Function(
+  ffi.Pointer<ffi.Void> Diagnostic,
+);
+
+typedef _dart_clang_getDiagnosticNumFixIts = int Function(
+  ffi.Pointer<ffi.Void> Diagnostic,
+);
+
+/// Determine the number of source ranges associated with the given diagnostic.
+int clang_getDiagnosticNumRanges(
+  ffi.Pointer<ffi.Void> arg0,
+) {
+  return _clang_getDiagnosticNumRanges(
+    arg0,
+  );
+}
+
+final _dart_clang_getDiagnosticNumRanges _clang_getDiagnosticNumRanges =
+    _dylib.lookupFunction<_c_clang_getDiagnosticNumRanges,
+        _dart_clang_getDiagnosticNumRanges>('clang_getDiagnosticNumRanges');
+
+typedef _c_clang_getDiagnosticNumRanges = ffi.Uint32 Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+typedef _dart_clang_getDiagnosticNumRanges = int Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+/// Retrieve the complete set of diagnostics associated with a translation unit.
+ffi.Pointer<ffi.Void> clang_getDiagnosticSetFromTU(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+) {
+  return _clang_getDiagnosticSetFromTU(
+    Unit,
+  );
+}
+
+final _dart_clang_getDiagnosticSetFromTU _clang_getDiagnosticSetFromTU =
+    _dylib.lookupFunction<_c_clang_getDiagnosticSetFromTU,
+        _dart_clang_getDiagnosticSetFromTU>('clang_getDiagnosticSetFromTU');
+
+typedef _c_clang_getDiagnosticSetFromTU = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+);
+
+typedef _dart_clang_getDiagnosticSetFromTU = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+);
+
+/// Determine the severity of the given diagnostic.
+int clang_getDiagnosticSeverity(
+  ffi.Pointer<ffi.Void> arg0,
+) {
+  return _clang_getDiagnosticSeverity(
+    arg0,
+  );
+}
+
+final _dart_clang_getDiagnosticSeverity _clang_getDiagnosticSeverity =
+    _dylib.lookupFunction<_c_clang_getDiagnosticSeverity,
+        _dart_clang_getDiagnosticSeverity>('clang_getDiagnosticSeverity');
+
+typedef _c_clang_getDiagnosticSeverity = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+typedef _dart_clang_getDiagnosticSeverity = int Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+int clang_getEnumConstantDeclValue_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_getEnumConstantDeclValue_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_getEnumConstantDeclValue_wrap
+    _clang_getEnumConstantDeclValue_wrap = _dylib.lookupFunction<
+            _c_clang_getEnumConstantDeclValue_wrap,
+            _dart_clang_getEnumConstantDeclValue_wrap>(
+        'clang_getEnumConstantDeclValue_wrap');
+
+typedef _c_clang_getEnumConstantDeclValue_wrap = ffi.Int64 Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_getEnumConstantDeclValue_wrap = int Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+/// Retrieve a file handle within the given translation unit.
+ffi.Pointer<ffi.Void> clang_getFile(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Int8> file_name,
+) {
+  return _clang_getFile(
+    tu,
+    file_name,
+  );
+}
+
+final _dart_clang_getFile _clang_getFile = _dylib
+    .lookupFunction<_c_clang_getFile, _dart_clang_getFile>('clang_getFile');
+
+typedef _c_clang_getFile = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Int8> file_name,
+);
+
+typedef _dart_clang_getFile = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Int8> file_name,
+);
+
+/// Retrieve the buffer associated with the given file.
+ffi.Pointer<ffi.Int8> clang_getFileContents(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Void> file,
+  ffi.Pointer<ffi.Uint64> size,
+) {
+  return _clang_getFileContents(
+    tu,
+    file,
+    size,
+  );
+}
+
+final _dart_clang_getFileContents _clang_getFileContents = _dylib
+    .lookupFunction<_c_clang_getFileContents, _dart_clang_getFileContents>(
+        'clang_getFileContents');
+
+typedef _c_clang_getFileContents = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Void> file,
+  ffi.Pointer<ffi.Uint64> size,
+);
+
+typedef _dart_clang_getFileContents = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Void> file,
+  ffi.Pointer<ffi.Uint64> size,
+);
+
+void clang_getFileLocation_wrap(
+  ffi.Pointer<CXSourceLocation> location,
+  ffi.Pointer<ffi.Pointer<ffi.Void>> file,
+  ffi.Pointer<ffi.Uint32> line,
+  ffi.Pointer<ffi.Uint32> column,
+  ffi.Pointer<ffi.Uint32> offset,
+) {
+  return _clang_getFileLocation_wrap(
+    location,
+    file,
+    line,
+    column,
+    offset,
+  );
+}
+
+final _dart_clang_getFileLocation_wrap _clang_getFileLocation_wrap =
+    _dylib.lookupFunction<_c_clang_getFileLocation_wrap,
+        _dart_clang_getFileLocation_wrap>('clang_getFileLocation_wrap');
+
+typedef _c_clang_getFileLocation_wrap = ffi.Void Function(
+  ffi.Pointer<CXSourceLocation> location,
+  ffi.Pointer<ffi.Pointer<ffi.Void>> file,
+  ffi.Pointer<ffi.Uint32> line,
+  ffi.Pointer<ffi.Uint32> column,
+  ffi.Pointer<ffi.Uint32> offset,
+);
+
+typedef _dart_clang_getFileLocation_wrap = void Function(
+  ffi.Pointer<CXSourceLocation> location,
+  ffi.Pointer<ffi.Pointer<ffi.Void>> file,
+  ffi.Pointer<ffi.Uint32> line,
+  ffi.Pointer<ffi.Uint32> column,
+  ffi.Pointer<ffi.Uint32> offset,
+);
+
+ffi.Pointer<CXString> clang_getFileName_wrap(
+  ffi.Pointer<ffi.Void> SFile,
+) {
+  return _clang_getFileName_wrap(
+    SFile,
+  );
+}
+
+final _dart_clang_getFileName_wrap _clang_getFileName_wrap = _dylib
+    .lookupFunction<_c_clang_getFileName_wrap, _dart_clang_getFileName_wrap>(
+        'clang_getFileName_wrap');
+
+typedef _c_clang_getFileName_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<ffi.Void> SFile,
+);
+
+typedef _dart_clang_getFileName_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<ffi.Void> SFile,
+);
+
+/// Retrieve the last modification time of the given file.
+int clang_getFileTime(
+  ffi.Pointer<ffi.Void> SFile,
+) {
+  return _clang_getFileTime(
+    SFile,
+  );
+}
+
+final _dart_clang_getFileTime _clang_getFileTime =
+    _dylib.lookupFunction<_c_clang_getFileTime, _dart_clang_getFileTime>(
+        'clang_getFileTime');
+
+typedef _c_clang_getFileTime = ffi.Int64 Function(
+  ffi.Pointer<ffi.Void> SFile,
+);
+
+typedef _dart_clang_getFileTime = int Function(
+  ffi.Pointer<ffi.Void> SFile,
+);
+
+/// Retrieve the unique ID for the given file.
+int clang_getFileUniqueID(
+  ffi.Pointer<ffi.Void> file,
+  ffi.Pointer<CXFileUniqueID> outID,
+) {
+  return _clang_getFileUniqueID(
+    file,
+    outID,
+  );
+}
+
+final _dart_clang_getFileUniqueID _clang_getFileUniqueID = _dylib
+    .lookupFunction<_c_clang_getFileUniqueID, _dart_clang_getFileUniqueID>(
+        'clang_getFileUniqueID');
+
+typedef _c_clang_getFileUniqueID = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> file,
+  ffi.Pointer<CXFileUniqueID> outID,
+);
+
+typedef _dart_clang_getFileUniqueID = int Function(
+  ffi.Pointer<ffi.Void> file,
+  ffi.Pointer<CXFileUniqueID> outID,
+);
+
+/// Visit the set of preprocessor inclusions in a translation unit. The visitor function is called with the provided data for every included file. This does not include headers included by the PCH file (unless one is inspecting the inclusions in the PCH file itself).
+void clang_getInclusions(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.NativeFunction<CXInclusionVisitor>> visitor,
+  ffi.Pointer<ffi.Void> client_data,
+) {
+  return _clang_getInclusions(
+    tu,
+    visitor,
+    client_data,
+  );
+}
+
+final _dart_clang_getInclusions _clang_getInclusions =
+    _dylib.lookupFunction<_c_clang_getInclusions, _dart_clang_getInclusions>(
+        'clang_getInclusions');
+
+typedef _c_clang_getInclusions = ffi.Void Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.NativeFunction<CXInclusionVisitor>> visitor,
+  ffi.Pointer<ffi.Void> client_data,
+);
+
+typedef _dart_clang_getInclusions = void Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.NativeFunction<CXInclusionVisitor>> visitor,
+  ffi.Pointer<ffi.Void> client_data,
+);
+
+/// Given a CXFile header file, return the module that contains it, if one exists.
+ffi.Pointer<ffi.Void> clang_getModuleForFile(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+  ffi.Pointer<ffi.Void> arg1,
+) {
+  return _clang_getModuleForFile(
+    arg0,
+    arg1,
+  );
+}
+
+final _dart_clang_getModuleForFile _clang_getModuleForFile = _dylib
+    .lookupFunction<_c_clang_getModuleForFile, _dart_clang_getModuleForFile>(
+        'clang_getModuleForFile');
+
+typedef _c_clang_getModuleForFile = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+  ffi.Pointer<ffi.Void> arg1,
+);
+
+typedef _dart_clang_getModuleForFile = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+  ffi.Pointer<ffi.Void> arg1,
+);
+
+int clang_getNumArgTypes_wrap(
+  ffi.Pointer<CXType> cxtype,
+) {
+  return _clang_getNumArgTypes_wrap(
+    cxtype,
+  );
+}
+
+final _dart_clang_getNumArgTypes_wrap _clang_getNumArgTypes_wrap =
+    _dylib.lookupFunction<_c_clang_getNumArgTypes_wrap,
+        _dart_clang_getNumArgTypes_wrap>('clang_getNumArgTypes_wrap');
+
+typedef _c_clang_getNumArgTypes_wrap = ffi.Int32 Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+typedef _dart_clang_getNumArgTypes_wrap = int Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+/// Retrieve the number of chunks in the given code-completion string.
+int clang_getNumCompletionChunks(
+  ffi.Pointer<ffi.Void> completion_string,
+) {
+  return _clang_getNumCompletionChunks(
+    completion_string,
+  );
+}
+
+final _dart_clang_getNumCompletionChunks _clang_getNumCompletionChunks =
+    _dylib.lookupFunction<_c_clang_getNumCompletionChunks,
+        _dart_clang_getNumCompletionChunks>('clang_getNumCompletionChunks');
+
+typedef _c_clang_getNumCompletionChunks = ffi.Uint32 Function(
+  ffi.Pointer<ffi.Void> completion_string,
+);
+
+typedef _dart_clang_getNumCompletionChunks = int Function(
+  ffi.Pointer<ffi.Void> completion_string,
+);
+
+/// Determine the number of diagnostics produced for the given translation unit.
+int clang_getNumDiagnostics(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+) {
+  return _clang_getNumDiagnostics(
+    Unit,
+  );
+}
+
+final _dart_clang_getNumDiagnostics _clang_getNumDiagnostics = _dylib
+    .lookupFunction<_c_clang_getNumDiagnostics, _dart_clang_getNumDiagnostics>(
+        'clang_getNumDiagnostics');
+
+typedef _c_clang_getNumDiagnostics = ffi.Uint32 Function(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+);
+
+typedef _dart_clang_getNumDiagnostics = int Function(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+);
+
+/// Determine the number of diagnostics in a CXDiagnosticSet.
+int clang_getNumDiagnosticsInSet(
+  ffi.Pointer<ffi.Void> Diags,
+) {
+  return _clang_getNumDiagnosticsInSet(
+    Diags,
+  );
+}
+
+final _dart_clang_getNumDiagnosticsInSet _clang_getNumDiagnosticsInSet =
+    _dylib.lookupFunction<_c_clang_getNumDiagnosticsInSet,
+        _dart_clang_getNumDiagnosticsInSet>('clang_getNumDiagnosticsInSet');
+
+typedef _c_clang_getNumDiagnosticsInSet = ffi.Uint32 Function(
+  ffi.Pointer<ffi.Void> Diags,
+);
+
+typedef _dart_clang_getNumDiagnosticsInSet = int Function(
+  ffi.Pointer<ffi.Void> Diags,
+);
+
+int clang_getNumElements_wrap(
+  ffi.Pointer<CXType> cxtype,
+) {
+  return _clang_getNumElements_wrap(
+    cxtype,
+  );
+}
+
+final _dart_clang_getNumElements_wrap _clang_getNumElements_wrap =
+    _dylib.lookupFunction<_c_clang_getNumElements_wrap,
+        _dart_clang_getNumElements_wrap>('clang_getNumElements_wrap');
+
+typedef _c_clang_getNumElements_wrap = ffi.Uint64 Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+typedef _dart_clang_getNumElements_wrap = int Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+ffi.Pointer<CXType> clang_getPointeeType_wrap(
+  ffi.Pointer<CXType> pointerType,
+) {
+  return _clang_getPointeeType_wrap(
+    pointerType,
+  );
+}
+
+final _dart_clang_getPointeeType_wrap _clang_getPointeeType_wrap =
+    _dylib.lookupFunction<_c_clang_getPointeeType_wrap,
+        _dart_clang_getPointeeType_wrap>('clang_getPointeeType_wrap');
+
+typedef _c_clang_getPointeeType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> pointerType,
+);
+
+typedef _dart_clang_getPointeeType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> pointerType,
+);
+
+/// Retrieve a remapping.
+ffi.Pointer<ffi.Void> clang_getRemappings(
+  ffi.Pointer<ffi.Int8> path,
+) {
+  return _clang_getRemappings(
+    path,
+  );
+}
+
+final _dart_clang_getRemappings _clang_getRemappings =
+    _dylib.lookupFunction<_c_clang_getRemappings, _dart_clang_getRemappings>(
+        'clang_getRemappings');
+
+typedef _c_clang_getRemappings = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Int8> path,
+);
+
+typedef _dart_clang_getRemappings = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Int8> path,
+);
+
+/// Retrieve a remapping.
+ffi.Pointer<ffi.Void> clang_getRemappingsFromFileList(
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> filePaths,
+  int numFiles,
+) {
+  return _clang_getRemappingsFromFileList(
+    filePaths,
+    numFiles,
+  );
+}
+
+final _dart_clang_getRemappingsFromFileList _clang_getRemappingsFromFileList =
+    _dylib.lookupFunction<_c_clang_getRemappingsFromFileList,
+            _dart_clang_getRemappingsFromFileList>(
+        'clang_getRemappingsFromFileList');
+
+typedef _c_clang_getRemappingsFromFileList = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> filePaths,
+  ffi.Uint32 numFiles,
+);
+
+typedef _dart_clang_getRemappingsFromFileList = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> filePaths,
+  int numFiles,
+);
+
+ffi.Pointer<CXType> clang_getResultType_wrap(
+  ffi.Pointer<CXType> functionType,
+) {
+  return _clang_getResultType_wrap(
+    functionType,
+  );
+}
+
+final _dart_clang_getResultType_wrap _clang_getResultType_wrap =
+    _dylib.lookupFunction<_c_clang_getResultType_wrap,
+        _dart_clang_getResultType_wrap>('clang_getResultType_wrap');
+
+typedef _c_clang_getResultType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> functionType,
+);
+
+typedef _dart_clang_getResultType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> functionType,
+);
+
+/// Retrieve all ranges that were skipped by the preprocessor.
+ffi.Pointer<CXSourceRangeList> clang_getSkippedRanges(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Void> file,
+) {
+  return _clang_getSkippedRanges(
+    tu,
+    file,
+  );
+}
+
+final _dart_clang_getSkippedRanges _clang_getSkippedRanges = _dylib
+    .lookupFunction<_c_clang_getSkippedRanges, _dart_clang_getSkippedRanges>(
+        'clang_getSkippedRanges');
+
+typedef _c_clang_getSkippedRanges = ffi.Pointer<CXSourceRangeList> Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Void> file,
+);
+
+typedef _dart_clang_getSkippedRanges = ffi.Pointer<CXSourceRangeList> Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Void> file,
+);
+
+/// Returns the human-readable null-terminated C string that represents the name of the memory category. This string should never be freed.
+ffi.Pointer<ffi.Int8> clang_getTUResourceUsageName(
+  int kind,
+) {
+  return _clang_getTUResourceUsageName(
+    kind,
+  );
+}
+
+final _dart_clang_getTUResourceUsageName _clang_getTUResourceUsageName =
+    _dylib.lookupFunction<_c_clang_getTUResourceUsageName,
+        _dart_clang_getTUResourceUsageName>('clang_getTUResourceUsageName');
+
+typedef _c_clang_getTUResourceUsageName = ffi.Pointer<ffi.Int8> Function(
+  ffi.Int32 kind,
+);
+
+typedef _dart_clang_getTUResourceUsageName = ffi.Pointer<ffi.Int8> Function(
+  int kind,
+);
+
+ffi.Pointer<CXCursor> clang_getTranslationUnitCursor_wrap(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+) {
+  return _clang_getTranslationUnitCursor_wrap(
+    tu,
+  );
+}
+
+final _dart_clang_getTranslationUnitCursor_wrap
+    _clang_getTranslationUnitCursor_wrap = _dylib.lookupFunction<
+            _c_clang_getTranslationUnitCursor_wrap,
+            _dart_clang_getTranslationUnitCursor_wrap>(
+        'clang_getTranslationUnitCursor_wrap');
+
+typedef _c_clang_getTranslationUnitCursor_wrap = ffi.Pointer<CXCursor> Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+);
+
+typedef _dart_clang_getTranslationUnitCursor_wrap = ffi.Pointer<CXCursor>
+    Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+);
+
+/// Get target information for this translation unit.
+ffi.Pointer<CXTargetInfoImpl> clang_getTranslationUnitTargetInfo(
+  ffi.Pointer<CXTranslationUnitImpl> CTUnit,
+) {
+  return _clang_getTranslationUnitTargetInfo(
+    CTUnit,
+  );
+}
+
+final _dart_clang_getTranslationUnitTargetInfo
+    _clang_getTranslationUnitTargetInfo = _dylib.lookupFunction<
+            _c_clang_getTranslationUnitTargetInfo,
+            _dart_clang_getTranslationUnitTargetInfo>(
+        'clang_getTranslationUnitTargetInfo');
+
+typedef _c_clang_getTranslationUnitTargetInfo = ffi.Pointer<CXTargetInfoImpl>
+    Function(
+  ffi.Pointer<CXTranslationUnitImpl> CTUnit,
+);
+
+typedef _dart_clang_getTranslationUnitTargetInfo = ffi.Pointer<CXTargetInfoImpl>
+    Function(
+  ffi.Pointer<CXTranslationUnitImpl> CTUnit,
+);
+
+ffi.Pointer<CXCursor> clang_getTypeDeclaration_wrap(
+  ffi.Pointer<CXType> cxtype,
+) {
+  return _clang_getTypeDeclaration_wrap(
+    cxtype,
+  );
+}
+
+final _dart_clang_getTypeDeclaration_wrap _clang_getTypeDeclaration_wrap =
+    _dylib.lookupFunction<_c_clang_getTypeDeclaration_wrap,
+        _dart_clang_getTypeDeclaration_wrap>('clang_getTypeDeclaration_wrap');
+
+typedef _c_clang_getTypeDeclaration_wrap = ffi.Pointer<CXCursor> Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+typedef _dart_clang_getTypeDeclaration_wrap = ffi.Pointer<CXCursor> Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+ffi.Pointer<CXString> clang_getTypeKindSpelling_wrap(
+  int typeKind,
+) {
+  return _clang_getTypeKindSpelling_wrap(
+    typeKind,
+  );
+}
+
+final _dart_clang_getTypeKindSpelling_wrap _clang_getTypeKindSpelling_wrap =
+    _dylib.lookupFunction<_c_clang_getTypeKindSpelling_wrap,
+        _dart_clang_getTypeKindSpelling_wrap>('clang_getTypeKindSpelling_wrap');
+
+typedef _c_clang_getTypeKindSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Int32 typeKind,
+);
+
+typedef _dart_clang_getTypeKindSpelling_wrap = ffi.Pointer<CXString> Function(
+  int typeKind,
+);
+
+ffi.Pointer<CXString> clang_getTypeSpelling_wrap(
+  ffi.Pointer<CXType> type,
+) {
+  return _clang_getTypeSpelling_wrap(
+    type,
+  );
+}
+
+final _dart_clang_getTypeSpelling_wrap _clang_getTypeSpelling_wrap =
+    _dylib.lookupFunction<_c_clang_getTypeSpelling_wrap,
+        _dart_clang_getTypeSpelling_wrap>('clang_getTypeSpelling_wrap');
+
+typedef _c_clang_getTypeSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<CXType> type,
+);
+
+typedef _dart_clang_getTypeSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<CXType> type,
+);
+
+ffi.Pointer<CXType> clang_getTypedefDeclUnderlyingType_wrap(
+  ffi.Pointer<CXCursor> cxcursor,
+) {
+  return _clang_getTypedefDeclUnderlyingType_wrap(
+    cxcursor,
+  );
+}
+
+final _dart_clang_getTypedefDeclUnderlyingType_wrap
+    _clang_getTypedefDeclUnderlyingType_wrap = _dylib.lookupFunction<
+            _c_clang_getTypedefDeclUnderlyingType_wrap,
+            _dart_clang_getTypedefDeclUnderlyingType_wrap>(
+        'clang_getTypedefDeclUnderlyingType_wrap');
+
+typedef _c_clang_getTypedefDeclUnderlyingType_wrap = ffi.Pointer<CXType>
+    Function(
+  ffi.Pointer<CXCursor> cxcursor,
+);
+
+typedef _dart_clang_getTypedefDeclUnderlyingType_wrap = ffi.Pointer<CXType>
+    Function(
+  ffi.Pointer<CXCursor> cxcursor,
+);
+
+/// Index the given source file and the translation unit corresponding to that file via callbacks implemented through #IndexerCallbacks.
+int clang_indexSourceFile(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Void> client_data,
+  ffi.Pointer<IndexerCallbacks> index_callbacks,
+  int index_callbacks_size,
+  int index_options,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+  int TU_options,
+) {
+  return _clang_indexSourceFile(
+    arg0,
+    client_data,
+    index_callbacks,
+    index_callbacks_size,
+    index_options,
+    source_filename,
+    command_line_args,
+    num_command_line_args,
+    unsaved_files,
+    num_unsaved_files,
+    out_TU,
+    TU_options,
+  );
+}
+
+final _dart_clang_indexSourceFile _clang_indexSourceFile = _dylib
+    .lookupFunction<_c_clang_indexSourceFile, _dart_clang_indexSourceFile>(
+        'clang_indexSourceFile');
+
+typedef _c_clang_indexSourceFile = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Void> client_data,
+  ffi.Pointer<IndexerCallbacks> index_callbacks,
+  ffi.Uint32 index_callbacks_size,
+  ffi.Uint32 index_options,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  ffi.Int32 num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  ffi.Uint32 num_unsaved_files,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+  ffi.Uint32 TU_options,
+);
+
+typedef _dart_clang_indexSourceFile = int Function(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Void> client_data,
+  ffi.Pointer<IndexerCallbacks> index_callbacks,
+  int index_callbacks_size,
+  int index_options,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+  int TU_options,
+);
+
+/// Same as clang_indexSourceFile but requires a full command line for command_line_args including argv[0]. This is useful if the standard library paths are relative to the binary.
+int clang_indexSourceFileFullArgv(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Void> client_data,
+  ffi.Pointer<IndexerCallbacks> index_callbacks,
+  int index_callbacks_size,
+  int index_options,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+  int TU_options,
+) {
+  return _clang_indexSourceFileFullArgv(
+    arg0,
+    client_data,
+    index_callbacks,
+    index_callbacks_size,
+    index_options,
+    source_filename,
+    command_line_args,
+    num_command_line_args,
+    unsaved_files,
+    num_unsaved_files,
+    out_TU,
+    TU_options,
+  );
+}
+
+final _dart_clang_indexSourceFileFullArgv _clang_indexSourceFileFullArgv =
+    _dylib.lookupFunction<_c_clang_indexSourceFileFullArgv,
+        _dart_clang_indexSourceFileFullArgv>('clang_indexSourceFileFullArgv');
+
+typedef _c_clang_indexSourceFileFullArgv = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Void> client_data,
+  ffi.Pointer<IndexerCallbacks> index_callbacks,
+  ffi.Uint32 index_callbacks_size,
+  ffi.Uint32 index_options,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  ffi.Int32 num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  ffi.Uint32 num_unsaved_files,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+  ffi.Uint32 TU_options,
+);
+
+typedef _dart_clang_indexSourceFileFullArgv = int Function(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Void> client_data,
+  ffi.Pointer<IndexerCallbacks> index_callbacks,
+  int index_callbacks_size,
+  int index_options,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+  int TU_options,
+);
+
+/// Index the given translation unit via callbacks implemented through #IndexerCallbacks.
+int clang_indexTranslationUnit(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Void> client_data,
+  ffi.Pointer<IndexerCallbacks> index_callbacks,
+  int index_callbacks_size,
+  int index_options,
+  ffi.Pointer<CXTranslationUnitImpl> arg5,
+) {
+  return _clang_indexTranslationUnit(
+    arg0,
+    client_data,
+    index_callbacks,
+    index_callbacks_size,
+    index_options,
+    arg5,
+  );
+}
+
+final _dart_clang_indexTranslationUnit _clang_indexTranslationUnit =
+    _dylib.lookupFunction<_c_clang_indexTranslationUnit,
+        _dart_clang_indexTranslationUnit>('clang_indexTranslationUnit');
+
+typedef _c_clang_indexTranslationUnit = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Void> client_data,
+  ffi.Pointer<IndexerCallbacks> index_callbacks,
+  ffi.Uint32 index_callbacks_size,
+  ffi.Uint32 index_options,
+  ffi.Pointer<CXTranslationUnitImpl> arg5,
+);
+
+typedef _dart_clang_indexTranslationUnit = int Function(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Pointer<ffi.Void> client_data,
+  ffi.Pointer<IndexerCallbacks> index_callbacks,
+  int index_callbacks_size,
+  int index_options,
+  ffi.Pointer<CXTranslationUnitImpl> arg5,
+);
+
+ffi.Pointer<CXIdxCXXClassDeclInfo> clang_index_getCXXClassDeclInfo(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+) {
+  return _clang_index_getCXXClassDeclInfo(
+    arg0,
+  );
+}
+
+final _dart_clang_index_getCXXClassDeclInfo _clang_index_getCXXClassDeclInfo =
+    _dylib.lookupFunction<_c_clang_index_getCXXClassDeclInfo,
+            _dart_clang_index_getCXXClassDeclInfo>(
+        'clang_index_getCXXClassDeclInfo');
+
+typedef _c_clang_index_getCXXClassDeclInfo = ffi.Pointer<CXIdxCXXClassDeclInfo>
+    Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+typedef _dart_clang_index_getCXXClassDeclInfo
+    = ffi.Pointer<CXIdxCXXClassDeclInfo> Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+/// For retrieving a custom CXIdxClientContainer attached to a container.
+ffi.Pointer<ffi.Void> clang_index_getClientContainer(
+  ffi.Pointer<CXIdxContainerInfo> arg0,
+) {
+  return _clang_index_getClientContainer(
+    arg0,
+  );
+}
+
+final _dart_clang_index_getClientContainer _clang_index_getClientContainer =
+    _dylib.lookupFunction<_c_clang_index_getClientContainer,
+        _dart_clang_index_getClientContainer>('clang_index_getClientContainer');
+
+typedef _c_clang_index_getClientContainer = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXIdxContainerInfo> arg0,
+);
+
+typedef _dart_clang_index_getClientContainer = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXIdxContainerInfo> arg0,
+);
+
+/// For retrieving a custom CXIdxClientEntity attached to an entity.
+ffi.Pointer<ffi.Void> clang_index_getClientEntity(
+  ffi.Pointer<CXIdxEntityInfo> arg0,
+) {
+  return _clang_index_getClientEntity(
+    arg0,
+  );
+}
+
+final _dart_clang_index_getClientEntity _clang_index_getClientEntity =
+    _dylib.lookupFunction<_c_clang_index_getClientEntity,
+        _dart_clang_index_getClientEntity>('clang_index_getClientEntity');
+
+typedef _c_clang_index_getClientEntity = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXIdxEntityInfo> arg0,
+);
+
+typedef _dart_clang_index_getClientEntity = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXIdxEntityInfo> arg0,
+);
+
+ffi.Pointer<CXIdxIBOutletCollectionAttrInfo>
+    clang_index_getIBOutletCollectionAttrInfo(
+  ffi.Pointer<CXIdxAttrInfo> arg0,
+) {
+  return _clang_index_getIBOutletCollectionAttrInfo(
+    arg0,
+  );
+}
+
+final _dart_clang_index_getIBOutletCollectionAttrInfo
+    _clang_index_getIBOutletCollectionAttrInfo = _dylib.lookupFunction<
+            _c_clang_index_getIBOutletCollectionAttrInfo,
+            _dart_clang_index_getIBOutletCollectionAttrInfo>(
+        'clang_index_getIBOutletCollectionAttrInfo');
+
+typedef _c_clang_index_getIBOutletCollectionAttrInfo
+    = ffi.Pointer<CXIdxIBOutletCollectionAttrInfo> Function(
+  ffi.Pointer<CXIdxAttrInfo> arg0,
+);
+
+typedef _dart_clang_index_getIBOutletCollectionAttrInfo
+    = ffi.Pointer<CXIdxIBOutletCollectionAttrInfo> Function(
+  ffi.Pointer<CXIdxAttrInfo> arg0,
+);
+
+ffi.Pointer<CXIdxObjCCategoryDeclInfo> clang_index_getObjCCategoryDeclInfo(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+) {
+  return _clang_index_getObjCCategoryDeclInfo(
+    arg0,
+  );
+}
+
+final _dart_clang_index_getObjCCategoryDeclInfo
+    _clang_index_getObjCCategoryDeclInfo = _dylib.lookupFunction<
+            _c_clang_index_getObjCCategoryDeclInfo,
+            _dart_clang_index_getObjCCategoryDeclInfo>(
+        'clang_index_getObjCCategoryDeclInfo');
+
+typedef _c_clang_index_getObjCCategoryDeclInfo
+    = ffi.Pointer<CXIdxObjCCategoryDeclInfo> Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+typedef _dart_clang_index_getObjCCategoryDeclInfo
+    = ffi.Pointer<CXIdxObjCCategoryDeclInfo> Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+ffi.Pointer<CXIdxObjCContainerDeclInfo> clang_index_getObjCContainerDeclInfo(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+) {
+  return _clang_index_getObjCContainerDeclInfo(
+    arg0,
+  );
+}
+
+final _dart_clang_index_getObjCContainerDeclInfo
+    _clang_index_getObjCContainerDeclInfo = _dylib.lookupFunction<
+            _c_clang_index_getObjCContainerDeclInfo,
+            _dart_clang_index_getObjCContainerDeclInfo>(
+        'clang_index_getObjCContainerDeclInfo');
+
+typedef _c_clang_index_getObjCContainerDeclInfo
+    = ffi.Pointer<CXIdxObjCContainerDeclInfo> Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+typedef _dart_clang_index_getObjCContainerDeclInfo
+    = ffi.Pointer<CXIdxObjCContainerDeclInfo> Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+ffi.Pointer<CXIdxObjCInterfaceDeclInfo> clang_index_getObjCInterfaceDeclInfo(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+) {
+  return _clang_index_getObjCInterfaceDeclInfo(
+    arg0,
+  );
+}
+
+final _dart_clang_index_getObjCInterfaceDeclInfo
+    _clang_index_getObjCInterfaceDeclInfo = _dylib.lookupFunction<
+            _c_clang_index_getObjCInterfaceDeclInfo,
+            _dart_clang_index_getObjCInterfaceDeclInfo>(
+        'clang_index_getObjCInterfaceDeclInfo');
+
+typedef _c_clang_index_getObjCInterfaceDeclInfo
+    = ffi.Pointer<CXIdxObjCInterfaceDeclInfo> Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+typedef _dart_clang_index_getObjCInterfaceDeclInfo
+    = ffi.Pointer<CXIdxObjCInterfaceDeclInfo> Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+ffi.Pointer<CXIdxObjCPropertyDeclInfo> clang_index_getObjCPropertyDeclInfo(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+) {
+  return _clang_index_getObjCPropertyDeclInfo(
+    arg0,
+  );
+}
+
+final _dart_clang_index_getObjCPropertyDeclInfo
+    _clang_index_getObjCPropertyDeclInfo = _dylib.lookupFunction<
+            _c_clang_index_getObjCPropertyDeclInfo,
+            _dart_clang_index_getObjCPropertyDeclInfo>(
+        'clang_index_getObjCPropertyDeclInfo');
+
+typedef _c_clang_index_getObjCPropertyDeclInfo
+    = ffi.Pointer<CXIdxObjCPropertyDeclInfo> Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+typedef _dart_clang_index_getObjCPropertyDeclInfo
+    = ffi.Pointer<CXIdxObjCPropertyDeclInfo> Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+ffi.Pointer<CXIdxObjCProtocolRefListInfo>
+    clang_index_getObjCProtocolRefListInfo(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+) {
+  return _clang_index_getObjCProtocolRefListInfo(
+    arg0,
+  );
+}
+
+final _dart_clang_index_getObjCProtocolRefListInfo
+    _clang_index_getObjCProtocolRefListInfo = _dylib.lookupFunction<
+            _c_clang_index_getObjCProtocolRefListInfo,
+            _dart_clang_index_getObjCProtocolRefListInfo>(
+        'clang_index_getObjCProtocolRefListInfo');
+
+typedef _c_clang_index_getObjCProtocolRefListInfo
+    = ffi.Pointer<CXIdxObjCProtocolRefListInfo> Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+typedef _dart_clang_index_getObjCProtocolRefListInfo
+    = ffi.Pointer<CXIdxObjCProtocolRefListInfo> Function(
+  ffi.Pointer<CXIdxDeclInfo> arg0,
+);
+
+int clang_index_isEntityObjCContainerKind(
+  int arg0,
+) {
+  return _clang_index_isEntityObjCContainerKind(
+    arg0,
+  );
+}
+
+final _dart_clang_index_isEntityObjCContainerKind
+    _clang_index_isEntityObjCContainerKind = _dylib.lookupFunction<
+            _c_clang_index_isEntityObjCContainerKind,
+            _dart_clang_index_isEntityObjCContainerKind>(
+        'clang_index_isEntityObjCContainerKind');
+
+typedef _c_clang_index_isEntityObjCContainerKind = ffi.Int32 Function(
+  ffi.Int32 arg0,
+);
+
+typedef _dart_clang_index_isEntityObjCContainerKind = int Function(
+  int arg0,
+);
+
+/// For setting a custom CXIdxClientContainer attached to a container.
+void clang_index_setClientContainer(
+  ffi.Pointer<CXIdxContainerInfo> arg0,
+  ffi.Pointer<ffi.Void> arg1,
+) {
+  return _clang_index_setClientContainer(
+    arg0,
+    arg1,
+  );
+}
+
+final _dart_clang_index_setClientContainer _clang_index_setClientContainer =
+    _dylib.lookupFunction<_c_clang_index_setClientContainer,
+        _dart_clang_index_setClientContainer>('clang_index_setClientContainer');
+
+typedef _c_clang_index_setClientContainer = ffi.Void Function(
+  ffi.Pointer<CXIdxContainerInfo> arg0,
+  ffi.Pointer<ffi.Void> arg1,
+);
+
+typedef _dart_clang_index_setClientContainer = void Function(
+  ffi.Pointer<CXIdxContainerInfo> arg0,
+  ffi.Pointer<ffi.Void> arg1,
+);
+
+/// For setting a custom CXIdxClientEntity attached to an entity.
+void clang_index_setClientEntity(
+  ffi.Pointer<CXIdxEntityInfo> arg0,
+  ffi.Pointer<ffi.Void> arg1,
+) {
+  return _clang_index_setClientEntity(
+    arg0,
+    arg1,
+  );
+}
+
+final _dart_clang_index_setClientEntity _clang_index_setClientEntity =
+    _dylib.lookupFunction<_c_clang_index_setClientEntity,
+        _dart_clang_index_setClientEntity>('clang_index_setClientEntity');
+
+typedef _c_clang_index_setClientEntity = ffi.Void Function(
+  ffi.Pointer<CXIdxEntityInfo> arg0,
+  ffi.Pointer<ffi.Void> arg1,
+);
+
+typedef _dart_clang_index_setClientEntity = void Function(
+  ffi.Pointer<CXIdxEntityInfo> arg0,
+  ffi.Pointer<ffi.Void> arg1,
+);
+
+/// Determine whether the given cursor kind represents an attribute.
+int clang_isAttribute(
+  int arg0,
+) {
+  return _clang_isAttribute(
+    arg0,
+  );
+}
+
+final _dart_clang_isAttribute _clang_isAttribute =
+    _dylib.lookupFunction<_c_clang_isAttribute, _dart_clang_isAttribute>(
+        'clang_isAttribute');
+
+typedef _c_clang_isAttribute = ffi.Uint32 Function(
+  ffi.Int32 arg0,
+);
+
+typedef _dart_clang_isAttribute = int Function(
+  int arg0,
+);
+
+/// Determine whether the given cursor kind represents a declaration.
+int clang_isDeclaration(
+  int arg0,
+) {
+  return _clang_isDeclaration(
+    arg0,
+  );
+}
+
+final _dart_clang_isDeclaration _clang_isDeclaration =
+    _dylib.lookupFunction<_c_clang_isDeclaration, _dart_clang_isDeclaration>(
+        'clang_isDeclaration');
+
+typedef _c_clang_isDeclaration = ffi.Uint32 Function(
+  ffi.Int32 arg0,
+);
+
+typedef _dart_clang_isDeclaration = int Function(
+  int arg0,
+);
+
+/// Determine whether the given cursor kind represents an expression.
+int clang_isExpression(
+  int arg0,
+) {
+  return _clang_isExpression(
+    arg0,
+  );
+}
+
+final _dart_clang_isExpression _clang_isExpression =
+    _dylib.lookupFunction<_c_clang_isExpression, _dart_clang_isExpression>(
+        'clang_isExpression');
+
+typedef _c_clang_isExpression = ffi.Uint32 Function(
+  ffi.Int32 arg0,
+);
+
+typedef _dart_clang_isExpression = int Function(
+  int arg0,
+);
+
+/// Determine whether the given header is guarded against multiple inclusions, either with the conventional #ifndef/#define/#endif macro guards or with #pragma once.
+int clang_isFileMultipleIncludeGuarded(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Void> file,
+) {
+  return _clang_isFileMultipleIncludeGuarded(
+    tu,
+    file,
+  );
+}
+
+final _dart_clang_isFileMultipleIncludeGuarded
+    _clang_isFileMultipleIncludeGuarded = _dylib.lookupFunction<
+            _c_clang_isFileMultipleIncludeGuarded,
+            _dart_clang_isFileMultipleIncludeGuarded>(
+        'clang_isFileMultipleIncludeGuarded');
+
+typedef _c_clang_isFileMultipleIncludeGuarded = ffi.Uint32 Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Void> file,
+);
+
+typedef _dart_clang_isFileMultipleIncludeGuarded = int Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+  ffi.Pointer<ffi.Void> file,
+);
+
+/// Determine whether the given cursor kind represents an invalid cursor.
+int clang_isInvalid(
+  int arg0,
+) {
+  return _clang_isInvalid(
+    arg0,
+  );
+}
+
+final _dart_clang_isInvalid _clang_isInvalid =
+    _dylib.lookupFunction<_c_clang_isInvalid, _dart_clang_isInvalid>(
+        'clang_isInvalid');
+
+typedef _c_clang_isInvalid = ffi.Uint32 Function(
+  ffi.Int32 arg0,
+);
+
+typedef _dart_clang_isInvalid = int Function(
+  int arg0,
+);
+
+/// * Determine whether the given cursor represents a preprocessing element, such as a preprocessor directive or macro instantiation.
+int clang_isPreprocessing(
+  int arg0,
+) {
+  return _clang_isPreprocessing(
+    arg0,
+  );
+}
+
+final _dart_clang_isPreprocessing _clang_isPreprocessing = _dylib
+    .lookupFunction<_c_clang_isPreprocessing, _dart_clang_isPreprocessing>(
+        'clang_isPreprocessing');
+
+typedef _c_clang_isPreprocessing = ffi.Uint32 Function(
+  ffi.Int32 arg0,
+);
+
+typedef _dart_clang_isPreprocessing = int Function(
+  int arg0,
+);
+
+/// Determine whether the given cursor kind represents a simple reference.
+int clang_isReference(
+  int arg0,
+) {
+  return _clang_isReference(
+    arg0,
+  );
+}
+
+final _dart_clang_isReference _clang_isReference =
+    _dylib.lookupFunction<_c_clang_isReference, _dart_clang_isReference>(
+        'clang_isReference');
+
+typedef _c_clang_isReference = ffi.Uint32 Function(
+  ffi.Int32 arg0,
+);
+
+typedef _dart_clang_isReference = int Function(
+  int arg0,
+);
+
+/// Determine whether the given cursor kind represents a statement.
+int clang_isStatement(
+  int arg0,
+) {
+  return _clang_isStatement(
+    arg0,
+  );
+}
+
+final _dart_clang_isStatement _clang_isStatement =
+    _dylib.lookupFunction<_c_clang_isStatement, _dart_clang_isStatement>(
+        'clang_isStatement');
+
+typedef _c_clang_isStatement = ffi.Uint32 Function(
+  ffi.Int32 arg0,
+);
+
+typedef _dart_clang_isStatement = int Function(
+  int arg0,
+);
+
+/// Determine whether the given cursor kind represents a translation unit.
+int clang_isTranslationUnit(
+  int arg0,
+) {
+  return _clang_isTranslationUnit(
+    arg0,
+  );
+}
+
+final _dart_clang_isTranslationUnit _clang_isTranslationUnit = _dylib
+    .lookupFunction<_c_clang_isTranslationUnit, _dart_clang_isTranslationUnit>(
+        'clang_isTranslationUnit');
+
+typedef _c_clang_isTranslationUnit = ffi.Uint32 Function(
+  ffi.Int32 arg0,
+);
+
+typedef _dart_clang_isTranslationUnit = int Function(
+  int arg0,
+);
+
+/// * Determine whether the given cursor represents a currently unexposed piece of the AST (e.g., CXCursor_UnexposedStmt).
+int clang_isUnexposed(
+  int arg0,
+) {
+  return _clang_isUnexposed(
+    arg0,
+  );
+}
+
+final _dart_clang_isUnexposed _clang_isUnexposed =
+    _dylib.lookupFunction<_c_clang_isUnexposed, _dart_clang_isUnexposed>(
+        'clang_isUnexposed');
+
+typedef _c_clang_isUnexposed = ffi.Uint32 Function(
+  ffi.Int32 arg0,
+);
+
+typedef _dart_clang_isUnexposed = int Function(
+  int arg0,
+);
+
+/// Deserialize a set of diagnostics from a Clang diagnostics bitcode file.
+ffi.Pointer<ffi.Void> clang_loadDiagnostics(
+  ffi.Pointer<ffi.Int8> file,
+  ffi.Pointer<ffi.Int32> error,
+  ffi.Pointer<CXString> errorString,
+) {
+  return _clang_loadDiagnostics(
+    file,
+    error,
+    errorString,
+  );
+}
+
+final _dart_clang_loadDiagnostics _clang_loadDiagnostics = _dylib
+    .lookupFunction<_c_clang_loadDiagnostics, _dart_clang_loadDiagnostics>(
+        'clang_loadDiagnostics');
+
+typedef _c_clang_loadDiagnostics = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Int8> file,
+  ffi.Pointer<ffi.Int32> error,
+  ffi.Pointer<CXString> errorString,
+);
+
+typedef _dart_clang_loadDiagnostics = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<ffi.Int8> file,
+  ffi.Pointer<ffi.Int32> error,
+  ffi.Pointer<CXString> errorString,
+);
+
+/// Same as clang_parseTranslationUnit2, but returns the CXTranslationUnit instead of an error code. In case of an error this routine returns a NULL CXTranslationUnit, without further detailed error codes.
+ffi.Pointer<CXTranslationUnitImpl> clang_parseTranslationUnit(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  int options,
+) {
+  return _clang_parseTranslationUnit(
+    CIdx,
+    source_filename,
+    command_line_args,
+    num_command_line_args,
+    unsaved_files,
+    num_unsaved_files,
+    options,
+  );
+}
+
+final _dart_clang_parseTranslationUnit _clang_parseTranslationUnit =
+    _dylib.lookupFunction<_c_clang_parseTranslationUnit,
+        _dart_clang_parseTranslationUnit>('clang_parseTranslationUnit');
+
+typedef _c_clang_parseTranslationUnit = ffi.Pointer<CXTranslationUnitImpl>
+    Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  ffi.Int32 num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  ffi.Uint32 num_unsaved_files,
+  ffi.Uint32 options,
+);
+
+typedef _dart_clang_parseTranslationUnit = ffi.Pointer<CXTranslationUnitImpl>
+    Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  int options,
+);
+
+/// Parse the given source file and the translation unit corresponding to that file.
+int clang_parseTranslationUnit2(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  int options,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+) {
+  return _clang_parseTranslationUnit2(
+    CIdx,
+    source_filename,
+    command_line_args,
+    num_command_line_args,
+    unsaved_files,
+    num_unsaved_files,
+    options,
+    out_TU,
+  );
+}
+
+final _dart_clang_parseTranslationUnit2 _clang_parseTranslationUnit2 =
+    _dylib.lookupFunction<_c_clang_parseTranslationUnit2,
+        _dart_clang_parseTranslationUnit2>('clang_parseTranslationUnit2');
+
+typedef _c_clang_parseTranslationUnit2 = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  ffi.Int32 num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  ffi.Uint32 num_unsaved_files,
+  ffi.Uint32 options,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+);
+
+typedef _dart_clang_parseTranslationUnit2 = int Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  int options,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+);
+
+/// Same as clang_parseTranslationUnit2 but requires a full command line for command_line_args including argv[0]. This is useful if the standard library paths are relative to the binary.
+int clang_parseTranslationUnit2FullArgv(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  int options,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+) {
+  return _clang_parseTranslationUnit2FullArgv(
+    CIdx,
+    source_filename,
+    command_line_args,
+    num_command_line_args,
+    unsaved_files,
+    num_unsaved_files,
+    options,
+    out_TU,
+  );
+}
+
+final _dart_clang_parseTranslationUnit2FullArgv
+    _clang_parseTranslationUnit2FullArgv = _dylib.lookupFunction<
+            _c_clang_parseTranslationUnit2FullArgv,
+            _dart_clang_parseTranslationUnit2FullArgv>(
+        'clang_parseTranslationUnit2FullArgv');
+
+typedef _c_clang_parseTranslationUnit2FullArgv = ffi.Int32 Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  ffi.Int32 num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  ffi.Uint32 num_unsaved_files,
+  ffi.Uint32 options,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+);
+
+typedef _dart_clang_parseTranslationUnit2FullArgv = int Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  int options,
+  ffi.Pointer<ffi.Pointer<CXTranslationUnitImpl>> out_TU,
+);
+
+/// Dispose the remapping.
+void clang_remap_dispose(
+  ffi.Pointer<ffi.Void> arg0,
+) {
+  return _clang_remap_dispose(
+    arg0,
+  );
+}
+
+final _dart_clang_remap_dispose _clang_remap_dispose =
+    _dylib.lookupFunction<_c_clang_remap_dispose, _dart_clang_remap_dispose>(
+        'clang_remap_dispose');
+
+typedef _c_clang_remap_dispose = ffi.Void Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+typedef _dart_clang_remap_dispose = void Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+/// Get the original and the associated filename from the remapping.
+void clang_remap_getFilenames(
+  ffi.Pointer<ffi.Void> arg0,
+  int index,
+  ffi.Pointer<CXString> original,
+  ffi.Pointer<CXString> transformed,
+) {
+  return _clang_remap_getFilenames(
+    arg0,
+    index,
+    original,
+    transformed,
+  );
+}
+
+final _dart_clang_remap_getFilenames _clang_remap_getFilenames =
+    _dylib.lookupFunction<_c_clang_remap_getFilenames,
+        _dart_clang_remap_getFilenames>('clang_remap_getFilenames');
+
+typedef _c_clang_remap_getFilenames = ffi.Void Function(
+  ffi.Pointer<ffi.Void> arg0,
+  ffi.Uint32 index,
+  ffi.Pointer<CXString> original,
+  ffi.Pointer<CXString> transformed,
+);
+
+typedef _dart_clang_remap_getFilenames = void Function(
+  ffi.Pointer<ffi.Void> arg0,
+  int index,
+  ffi.Pointer<CXString> original,
+  ffi.Pointer<CXString> transformed,
+);
+
+/// Determine the number of remappings.
+int clang_remap_getNumFiles(
+  ffi.Pointer<ffi.Void> arg0,
+) {
+  return _clang_remap_getNumFiles(
+    arg0,
+  );
+}
+
+final _dart_clang_remap_getNumFiles _clang_remap_getNumFiles = _dylib
+    .lookupFunction<_c_clang_remap_getNumFiles, _dart_clang_remap_getNumFiles>(
+        'clang_remap_getNumFiles');
+
+typedef _c_clang_remap_getNumFiles = ffi.Uint32 Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+typedef _dart_clang_remap_getNumFiles = int Function(
+  ffi.Pointer<ffi.Void> arg0,
+);
+
+/// Reparse the source files that produced this translation unit.
+int clang_reparseTranslationUnit(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  int num_unsaved_files,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int options,
+) {
+  return _clang_reparseTranslationUnit(
+    TU,
+    num_unsaved_files,
+    unsaved_files,
+    options,
+  );
+}
+
+final _dart_clang_reparseTranslationUnit _clang_reparseTranslationUnit =
+    _dylib.lookupFunction<_c_clang_reparseTranslationUnit,
+        _dart_clang_reparseTranslationUnit>('clang_reparseTranslationUnit');
+
+typedef _c_clang_reparseTranslationUnit = ffi.Int32 Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Uint32 num_unsaved_files,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  ffi.Uint32 options,
+);
+
+typedef _dart_clang_reparseTranslationUnit = int Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  int num_unsaved_files,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int options,
+);
+
+/// Saves a translation unit into a serialized representation of that translation unit on disk.
+int clang_saveTranslationUnit(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<ffi.Int8> FileName,
+  int options,
+) {
+  return _clang_saveTranslationUnit(
+    TU,
+    FileName,
+    options,
+  );
+}
+
+final _dart_clang_saveTranslationUnit _clang_saveTranslationUnit =
+    _dylib.lookupFunction<_c_clang_saveTranslationUnit,
+        _dart_clang_saveTranslationUnit>('clang_saveTranslationUnit');
+
+typedef _c_clang_saveTranslationUnit = ffi.Int32 Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<ffi.Int8> FileName,
+  ffi.Uint32 options,
+);
+
+typedef _dart_clang_saveTranslationUnit = int Function(
+  ffi.Pointer<CXTranslationUnitImpl> TU,
+  ffi.Pointer<ffi.Int8> FileName,
+  int options,
+);
+
+/// Sort the code-completion results in case-insensitive alphabetical order.
+void clang_sortCodeCompletionResults(
+  ffi.Pointer<CXCompletionResult> Results,
+  int NumResults,
+) {
+  return _clang_sortCodeCompletionResults(
+    Results,
+    NumResults,
+  );
+}
+
+final _dart_clang_sortCodeCompletionResults _clang_sortCodeCompletionResults =
+    _dylib.lookupFunction<_c_clang_sortCodeCompletionResults,
+            _dart_clang_sortCodeCompletionResults>(
+        'clang_sortCodeCompletionResults');
+
+typedef _c_clang_sortCodeCompletionResults = ffi.Void Function(
+  ffi.Pointer<CXCompletionResult> Results,
+  ffi.Uint32 NumResults,
+);
+
+typedef _dart_clang_sortCodeCompletionResults = void Function(
+  ffi.Pointer<CXCompletionResult> Results,
+  int NumResults,
+);
+
+/// Suspend a translation unit in order to free memory associated with it.
+int clang_suspendTranslationUnit(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+) {
+  return _clang_suspendTranslationUnit(
+    arg0,
+  );
+}
+
+final _dart_clang_suspendTranslationUnit _clang_suspendTranslationUnit =
+    _dylib.lookupFunction<_c_clang_suspendTranslationUnit,
+        _dart_clang_suspendTranslationUnit>('clang_suspendTranslationUnit');
+
+typedef _c_clang_suspendTranslationUnit = ffi.Uint32 Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+);
+
+typedef _dart_clang_suspendTranslationUnit = int Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+);
+
+/// Enable/disable crash recovery.
+void clang_toggleCrashRecovery(
+  int isEnabled,
+) {
+  return _clang_toggleCrashRecovery(
+    isEnabled,
+  );
+}
+
+final _dart_clang_toggleCrashRecovery _clang_toggleCrashRecovery =
+    _dylib.lookupFunction<_c_clang_toggleCrashRecovery,
+        _dart_clang_toggleCrashRecovery>('clang_toggleCrashRecovery');
+
+typedef _c_clang_toggleCrashRecovery = ffi.Void Function(
+  ffi.Uint32 isEnabled,
+);
+
+typedef _dart_clang_toggleCrashRecovery = void Function(
+  int isEnabled,
+);
+
+/// Visitor is a function pointer with parameters having pointers to cxcursor instead of cxcursor by default.
+int clang_visitChildren_wrap(
+  ffi.Pointer<CXCursor> parent,
+  ffi.Pointer<ffi.NativeFunction<ModifiedCXCursorVisitor>> _modifiedVisitor,
+  ffi.Pointer<ffi.Void> clientData,
+) {
+  return _clang_visitChildren_wrap(
+    parent,
+    _modifiedVisitor,
+    clientData,
+  );
+}
+
+final _dart_clang_visitChildren_wrap _clang_visitChildren_wrap =
+    _dylib.lookupFunction<_c_clang_visitChildren_wrap,
+        _dart_clang_visitChildren_wrap>('clang_visitChildren_wrap');
+
+typedef _c_clang_visitChildren_wrap = ffi.Uint32 Function(
+  ffi.Pointer<CXCursor> parent,
+  ffi.Pointer<ffi.NativeFunction<ModifiedCXCursorVisitor>> _modifiedVisitor,
+  ffi.Pointer<ffi.Void> clientData,
+);
+
+typedef _dart_clang_visitChildren_wrap = int Function(
+  ffi.Pointer<CXCursor> parent,
+  ffi.Pointer<ffi.NativeFunction<ModifiedCXCursorVisitor>> _modifiedVisitor,
+  ffi.Pointer<ffi.Void> clientData,
+);
diff --git a/example/libclang-example/pubspec.yaml b/example/libclang-example/pubspec.yaml
new file mode 100644
index 0000000..bd000c6
--- /dev/null
+++ b/example/libclang-example/pubspec.yaml
@@ -0,0 +1,63 @@
+# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+name: libclang_example
+
+environment:
+  sdk: '>=2.8.1 <3.0.0'
+
+dev_dependencies:
+  ffigen:
+    path: '../../'
+
+ffigen:
+  output: 'generated_bindings.dart'
+  sort: true
+
+  # Bash style Glob matching is also supported.
+  # TODO(11): Globs dont work on windows if they begin with '.' or '..'.
+  headers:
+    - '../../tool/wrapped_libclang/wrapper.c'
+
+  # Excludes included headers based on their names (not fullpath name).
+  header-filter:
+    include:
+      - 'wrapper.c'
+      - 'CXString.h'
+      - 'Index.h'
+
+  compiler-opts: '-I/usr/lib/llvm-9/include/ -I/usr/lib/llvm-10/include/ -IC:\Progra~1\LLVM\include -I/usr/local/opt/llvm/include/ -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/'
+  functions:
+    include:
+      matches:
+      # Should be valid regexp.
+        - 'clang_.*'
+  structs:
+    include:
+        matches:
+          - 'CX.*'
+  enums:
+    include:
+      # Compares the exact name.
+      names:
+        - 'CXTypeKind'
+        - 'CXGlobalOptFlags'
+
+  # These are optional and also default,
+  # Omitting any and the default will be used.
+  size-map:
+    char: 1
+    unsigned char: 1
+    short: 2
+    unsigned short: 2
+    int: 4
+    unsigned int: 4
+    long: 8
+    unsigned long: 8
+    long long: 8
+    unsigned long long: 8
+    enum: 4
+
+  # True by default
+  extract-comments: true
diff --git a/example/libclang-example/readme.md b/example/libclang-example/readme.md
new file mode 100644
index 0000000..4918a37
--- /dev/null
+++ b/example/libclang-example/readme.md
@@ -0,0 +1,11 @@
+# Libclang example
+
+Demonstrates generating bindings for [Libclang](https://clang.llvm.org/doxygen/group__CINDEX.html).
+This example actually uses a C file used in this package itself, ([wrapper.c](../../tool/wrapped_libclang/wrapper.c)), which adds a few more wrapper functions atop Libclang.
+
+## Generating bindings
+At the root of this example (`example/libclang-example`), run -
+```
+pub run ffigen:generate
+```
+This will generate bindings in a file: [generated_bindings.dart](./generated_bindings.dart).
diff --git a/example/simple/.gitignore b/example/simple/.gitignore
new file mode 100644
index 0000000..1b05164
--- /dev/null
+++ b/example/simple/.gitignore
@@ -0,0 +1,11 @@
+# Files and directories created by pub.
+.dart_tool/
+.packages
+# Remove the following pattern if you wish to check in your lock file.
+pubspec.lock
+
+# Conventional directory for build outputs.
+build/
+
+# Directory created by dartdoc.
+doc/api/
diff --git a/example/simple/README.md b/example/simple/README.md
new file mode 100644
index 0000000..6fc5243
--- /dev/null
+++ b/example/simple/README.md
@@ -0,0 +1,10 @@
+# Simple header example
+
+A very simple example, generates bindings for a very small header file (`headers/example.h`).
+
+## Generating bindings
+At the root of this example (`example/simple`), run -
+```
+pub run ffigen:generate
+```
+This will generate bindings in a file: [generated_bindings.dart](./generated_bindings.dart).
diff --git a/example/simple/generated_bindings.dart b/example/simple/generated_bindings.dart
new file mode 100644
index 0000000..6e3a97b
--- /dev/null
+++ b/example/simple/generated_bindings.dart
@@ -0,0 +1,132 @@
+/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib) {
+  _dylib = dylib;
+}
+
+/// Adds 2 integers.
+int sum(
+  int a,
+  int b,
+) {
+  return _sum(
+    a,
+    b,
+  );
+}
+
+final _dart_sum _sum = _dylib.lookupFunction<_c_sum, _dart_sum>('sum');
+
+typedef _c_sum = ffi.Int32 Function(
+  ffi.Int32 a,
+  ffi.Int32 b,
+);
+
+typedef _dart_sum = int Function(
+  int a,
+  int b,
+);
+
+/// Subtracts 2 integers.
+int subtract(
+  ffi.Pointer<ffi.Int32> a,
+  int b,
+) {
+  return _subtract(
+    a,
+    b,
+  );
+}
+
+final _dart_subtract _subtract =
+    _dylib.lookupFunction<_c_subtract, _dart_subtract>('subtract');
+
+typedef _c_subtract = ffi.Int32 Function(
+  ffi.Pointer<ffi.Int32> a,
+  ffi.Int32 b,
+);
+
+typedef _dart_subtract = int Function(
+  ffi.Pointer<ffi.Int32> a,
+  int b,
+);
+
+/// Multiplies 2 integers, returns pointer to an integer,.
+ffi.Pointer<ffi.Int32> multiply(
+  int a,
+  int b,
+) {
+  return _multiply(
+    a,
+    b,
+  );
+}
+
+final _dart_multiply _multiply =
+    _dylib.lookupFunction<_c_multiply, _dart_multiply>('multiply');
+
+typedef _c_multiply = ffi.Pointer<ffi.Int32> Function(
+  ffi.Int32 a,
+  ffi.Int32 b,
+);
+
+typedef _dart_multiply = ffi.Pointer<ffi.Int32> Function(
+  int a,
+  int b,
+);
+
+/// Divides 2 integers, returns pointer to a float.
+ffi.Pointer<ffi.Float> divide(
+  int a,
+  int b,
+) {
+  return _divide(
+    a,
+    b,
+  );
+}
+
+final _dart_divide _divide =
+    _dylib.lookupFunction<_c_divide, _dart_divide>('divide');
+
+typedef _c_divide = ffi.Pointer<ffi.Float> Function(
+  ffi.Int32 a,
+  ffi.Int32 b,
+);
+
+typedef _dart_divide = ffi.Pointer<ffi.Float> Function(
+  int a,
+  int b,
+);
+
+/// Divides 2 floats, returns a pointer to double.
+ffi.Pointer<ffi.Double> dividePercision(
+  ffi.Pointer<ffi.Float> a,
+  ffi.Pointer<ffi.Float> b,
+) {
+  return _dividePercision(
+    a,
+    b,
+  );
+}
+
+final _dart_dividePercision _dividePercision =
+    _dylib.lookupFunction<_c_dividePercision, _dart_dividePercision>(
+        'dividePercision');
+
+typedef _c_dividePercision = ffi.Pointer<ffi.Double> Function(
+  ffi.Pointer<ffi.Float> a,
+  ffi.Pointer<ffi.Float> b,
+);
+
+typedef _dart_dividePercision = ffi.Pointer<ffi.Double> Function(
+  ffi.Pointer<ffi.Float> a,
+  ffi.Pointer<ffi.Float> b,
+);
diff --git a/example/simple/headers/example.h b/example/simple/headers/example.h
new file mode 100644
index 0000000..0f936ee
--- /dev/null
+++ b/example/simple/headers/example.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/** Adds 2 integers. */
+int sum(int a, int b);
+
+/** Subtracts 2 integers. */
+int subtract(int *a, int b);
+
+/** Multiplies 2 integers, returns pointer to an integer,. */
+int *multiply(int a, int b);
+
+/** Divides 2 integers, returns pointer to a float. */
+float *divide(int a, int b);
+
+/** Divides 2 floats, returns a pointer to double. */
+double *dividePercision(float *a, float *b);
diff --git a/example/simple/pubspec.yaml b/example/simple/pubspec.yaml
new file mode 100644
index 0000000..454c138
--- /dev/null
+++ b/example/simple/pubspec.yaml
@@ -0,0 +1,17 @@
+# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+name: simple_example
+
+environment:
+  sdk: '>=2.8.1 <3.0.0'
+
+dev_dependencies:
+  ffigen:
+    path: '../../'
+
+ffigen:
+  output: 'generated_bindings.dart'
+  headers:
+    - 'headers/example.h'
diff --git a/lib/src/README.md b/lib/src/README.md
new file mode 100644
index 0000000..2832400
--- /dev/null
+++ b/lib/src/README.md
@@ -0,0 +1,41 @@
+## Project Structure
+
+- `bin` - Contains generate.dart script which end user will execute.
+- `tool` - Contains script to generate LibClang bindings using Code_Generator submodule (dev use only).
+- `example` - Example projects which demonstrate generation of bindings for given C header files.
+- `lib/src/code_generator` - Generates binding files.
+- `lib/src/config_provider` - Holds configurations to be passed to other modules.
+- `lib/src/header_parser` - Parses header files, utilises clang_bindings.
+
+## Basic Workflow
+1. The User provides the location all the header files (as a list of globs or filepaths),
+For each header file, we create a translation unit and parse the `declarations` in it
+to the bindings.
+2. User can provide `header filters` to select which declaration from a particular header file should be added to the generated bindings. The can provide a list of header 'names' to include/exclude.
+We compare the header file name (not the exact path) to decide.
+The default behaviour is to include everything that's included when parsing a header.
+3. Use can provide Compiler options, which are passed to clang compiler as it is.
+4. All bindings are generated in a single file.
+
+# Code Details
+## Modules
+We are using libclang to parse header files.
+This project is roughly divided in 3 major modules -
+### code_generator
+Converts a library(all bindings) to an actual string representation.
+- Library (output of the header parser).
+- Writer (provides configurations for generating bindings).
+- Binding (base class for all bindings - Func, Struc, Global, EnumClass, etc).
+### config_provider
+This takes care of validating user config files, printing config warnings and errors,
+converting config.yaml to a format the header_parser can use.
+- Spec (represents a single config, which a user can provide in the config file).
+- Config (holds all the config which will be required by header parser).
+### header_parser
+Uses libclang to convert the header to a Library which is then used by code_generator.
+- clang_bindings (bindings to libclang which are used for parsing).
+- sub_parsers (each sub-parser parses a particular kind of declaration - struct, function, typedef, enum).
+- type_extractor (extracts types from variables, function parameters, return types).
+- includer (tells what should/shouldn't be included depending of config).
+- parser (Main Entrypoint) (creates translation units for all header files, and sets up parsing them).
+- translation_unit_parser (parses header files, splits declarations and feeds them to their respective sub_parsers).
\ No newline at end of file
diff --git a/lib/src/code_generator.dart b/lib/src/code_generator.dart
new file mode 100644
index 0000000..9eb01b6
--- /dev/null
+++ b/lib/src/code_generator.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Generates FFI bindings for a given [Library].
+library code_generator;
+
+export 'code_generator/binding.dart';
+export 'code_generator/constant.dart';
+export 'code_generator/enum_class.dart';
+export 'code_generator/func.dart';
+export 'code_generator/global.dart';
+export 'code_generator/library.dart';
+export 'code_generator/struc.dart';
+export 'code_generator/type.dart';
+export 'code_generator/typedef.dart';
+
diff --git a/lib/src/code_generator/binding.dart b/lib/src/code_generator/binding.dart
new file mode 100644
index 0000000..127c0d2
--- /dev/null
+++ b/lib/src/code_generator/binding.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+import 'binding_string.dart';
+import 'writer.dart';
+
+/// Base class for all Bindings.
+abstract class Binding {
+  final String name;
+
+  final String dartDoc;
+
+  const Binding({@required this.name, this.dartDoc});
+
+  /// Converts a Binding to its actual string representation.
+  BindingString toBindingString(Writer w);
+}
diff --git a/lib/src/code_generator/binding_string.dart b/lib/src/code_generator/binding_string.dart
new file mode 100644
index 0000000..c0d4325
--- /dev/null
+++ b/lib/src/code_generator/binding_string.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+/// A Binding's String representation.
+class BindingString {
+  // Meta data, (not used for generation).
+  final BindingStringType type;
+  final String string;
+
+  const BindingString({@required this.type, @required this.string});
+
+  @override
+  String toString() => string;
+}
+
+/// A [BindingString]'s type.
+enum BindingStringType {
+  func,
+  struc,
+  constant,
+  global,
+  enumClass,
+  typeDef,
+}
diff --git a/lib/src/code_generator/constant.dart b/lib/src/code_generator/constant.dart
new file mode 100644
index 0000000..bef22d8
--- /dev/null
+++ b/lib/src/code_generator/constant.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+import 'binding.dart';
+import 'binding_string.dart';
+import 'type.dart';
+import 'writer.dart';
+
+/// A simple Constant.
+///
+/// Expands to -
+/// ```dart
+/// const <type> <name> = <rawValue>;
+/// ```
+///
+/// Example -
+/// ```dart
+/// const int name = 10;
+/// ```
+class Constant extends Binding {
+  final Type type;
+
+  /// The rawValue is pasted as it is.
+  ///
+  /// Put quotes if type is a string.
+  final String rawValue;
+
+  const Constant({
+    @required String name,
+    String dartDoc,
+    @required this.type,
+    @required this.rawValue,
+  }) : super(name: name, dartDoc: dartDoc);
+
+  @override
+  BindingString toBindingString(Writer w) {
+    final s = StringBuffer();
+
+    if (dartDoc != null) {
+      s.write('/// ');
+      s.writeAll(dartDoc.split('\n'), '\n/// ');
+      s.write('\n');
+    }
+
+    s.write('const ${type.getDartType(w)} $name = $rawValue;\n\n');
+
+    return BindingString(
+        type: BindingStringType.constant, string: s.toString());
+  }
+}
diff --git a/lib/src/code_generator/enum_class.dart b/lib/src/code_generator/enum_class.dart
new file mode 100644
index 0000000..90faf5b
--- /dev/null
+++ b/lib/src/code_generator/enum_class.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+import 'binding.dart';
+import 'binding_string.dart';
+import 'writer.dart';
+
+/// A binding for enums in C.
+///
+/// For a C enum -
+/// ```c
+/// enum Fruits {apple, banana = 10};
+/// ```
+/// The generated dart code is
+///
+/// ```dart
+/// class Fruits {
+///   static const apple = 0;
+///   static const banana = 10;
+/// }
+/// ```
+class EnumClass extends Binding {
+  final List<EnumConstant> enumConstants;
+
+  EnumClass({
+    @required String name,
+    String dartDoc,
+    List<EnumConstant> enumConstants,
+  })  : enumConstants = enumConstants ?? [],
+        super(name: name, dartDoc: dartDoc);
+
+  @override
+  BindingString toBindingString(Writer w) {
+    final s = StringBuffer();
+
+    if (dartDoc != null) {
+      s.write('/// ');
+      s.writeAll(dartDoc.split('\n'), '\n/// ');
+      s.write('\n');
+    }
+
+    // Print enclosing class.
+    s.write('class $name {\n');
+    const depth = '  ';
+    for (final ec in enumConstants) {
+      if (ec.dartDoc != null) {
+        s.write(depth + '/// ');
+        s.writeAll(ec.dartDoc.split('\n'), '\n' + depth + '/// ');
+        s.write('\n');
+      }
+      s.write(depth + 'static const int ${ec.name} = ${ec.value};\n');
+    }
+    s.write('}\n\n');
+
+    return BindingString(
+        type: BindingStringType.enumClass, string: s.toString());
+  }
+}
+
+/// Represents a single value in an enum.
+class EnumConstant {
+  final String dartDoc;
+  final String name;
+  final int value;
+  const EnumConstant({@required this.name, @required this.value, this.dartDoc});
+}
diff --git a/lib/src/code_generator/func.dart b/lib/src/code_generator/func.dart
new file mode 100644
index 0000000..688c573
--- /dev/null
+++ b/lib/src/code_generator/func.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+import 'binding.dart';
+import 'binding_string.dart';
+import 'type.dart';
+import 'writer.dart';
+
+/// A binding for C function.
+///
+/// For a C function -
+/// ```c
+/// int sum(int a, int b);
+/// ```
+/// The Generated dart code is -
+/// ```dart
+/// int sum(int a, int b) {
+///   return _sum(a, b);
+/// }
+///
+/// final _dart_sum _sum = _dylib.lookupFunction<_c_sum, _dart_sum>('sum');
+///
+/// typedef _c_sum = ffi.Int32 Function(ffi.Int32 a, ffi.Int32 b);
+///
+/// typedef _dart_sum = int Function(int a, int b);
+/// ```
+class Func extends Binding {
+  final Type returnType;
+  final List<Parameter> parameters;
+
+  Func({
+    @required String name,
+    String dartDoc,
+    @required this.returnType,
+    List<Parameter> parameters,
+  })  : parameters = parameters ?? [],
+        super(name: name, dartDoc: dartDoc) {
+    for (var i = 0; i < this.parameters.length; i++) {
+      if (this.parameters[i].name == null ||
+          this.parameters[i].name.trim() == '') {
+        this.parameters[i].name = 'arg$i';
+      }
+    }
+  }
+
+  @override
+  BindingString toBindingString(Writer w) {
+    final s = StringBuffer();
+
+    final funcVarName = '_$name';
+    final typedefC = '_c_$name';
+    final typedefDart = '_dart_$name';
+
+    if (dartDoc != null) {
+      s.write('/// ');
+      s.writeAll(dartDoc.split('\n'), '\n/// ');
+      s.write('\n');
+    }
+
+    // Write enclosing function.
+    s.write('${returnType.getDartType(w)} $name(\n');
+    for (final p in parameters) {
+      s.write('  ${p.type.getDartType(w)} ${p.name},\n');
+    }
+    s.write(') {\n');
+    s.write('  return $funcVarName(\n');
+    for (final p in parameters) {
+      s.write('    ${p.name},\n');
+    }
+    s.write('  );\n');
+    s.write('}\n\n');
+
+    // Write function with dylib lookup.
+    s.write(
+        "final $typedefDart $funcVarName = ${w.dylibIdentifier}.lookupFunction<$typedefC,$typedefDart>('$name');\n\n");
+
+    // Write typdef for C.
+    s.write('typedef $typedefC = ${returnType.getCType(w)} Function(\n');
+    for (final p in parameters) {
+      s.write('  ${p.type.getCType(w)} ${p.name},\n');
+    }
+    s.write(');\n\n');
+
+    // Write typdef for dart.
+    s.write('typedef $typedefDart = ${returnType.getDartType(w)} Function(\n');
+    for (final p in parameters) {
+      s.write('  ${p.type.getDartType(w)} ${p.name},\n');
+    }
+    s.write(');\n\n');
+
+    return BindingString(type: BindingStringType.func, string: s.toString());
+  }
+}
+
+/// Represents a Function's parameter.
+class Parameter {
+  String name;
+  final Type type;
+
+  Parameter({this.name, @required this.type});
+}
diff --git a/lib/src/code_generator/global.dart b/lib/src/code_generator/global.dart
new file mode 100644
index 0000000..8729785
--- /dev/null
+++ b/lib/src/code_generator/global.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+import 'binding.dart';
+import 'binding_string.dart';
+import 'type.dart';
+import 'writer.dart';
+
+/// A binding to a global variable
+///
+/// For a C global variable -
+/// ```c
+/// int a;
+/// ```
+/// The generated dart code is -
+/// ```dart
+/// final int a = _dylib.lookup<ffi.Int32>('a').value;
+/// ```
+class Global extends Binding {
+  final Type type;
+
+  const Global({
+    @required String name,
+    @required this.type,
+    String dartDoc,
+  }) : super(name: name, dartDoc: dartDoc);
+
+  @override
+  BindingString toBindingString(Writer w) {
+    final s = StringBuffer();
+
+    if (dartDoc != null) {
+      s.write('/// ');
+      s.writeAll(dartDoc.split('\n'), '\n/// ');
+      s.write('\n');
+    }
+
+    s.write(
+        "final ${type.getDartType(w)} $name = ${w.dylibIdentifier}.lookup<${type.getCType(w)}>('$name').value;\n\n");
+
+    return BindingString(type: BindingStringType.global, string: s.toString());
+  }
+}
diff --git a/lib/src/code_generator/library.dart b/lib/src/code_generator/library.dart
new file mode 100644
index 0000000..8ae4a06
--- /dev/null
+++ b/lib/src/code_generator/library.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:logging/logging.dart';
+import 'package:meta/meta.dart';
+
+import 'binding.dart';
+import 'writer.dart';
+
+var _logger = Logger('code_generator');
+
+/// Container for all Bindings.
+class Library {
+  /// Variable identifier used for dynamicLibrary. Defaults to `_dylib`,
+  final String dylibIdentifier;
+
+  /// Init function for providing dynamic library. Defaults to `init`,
+  ///
+  /// Can be renamed in case of name conflicts with something else.
+  final String initFunctionIdentifier;
+
+  /// Header of file.
+  final String header;
+
+  /// List of bindings in this library.
+  final List<Binding> bindings;
+
+  Library({
+    @required this.bindings,
+    this.dylibIdentifier = '_dylib',
+    this.initFunctionIdentifier = 'init',
+    this.header,
+  })  : assert(dylibIdentifier != null),
+        assert(initFunctionIdentifier != null);
+
+  /// Sort all bindings in alphabetical order.
+  void sort() {
+    bindings.sort((b1, b2) => b1.name.compareTo(b2.name));
+  }
+
+  /// Generates [file] by generating C bindings.
+  ///
+  /// If format is true(default), 'dartfmt -w $PATH' will be called to format the generated file.
+  void generateFile(File file, {bool format = true}) {
+    file.writeAsStringSync(generate());
+    if (format) {
+      _dartFmt(file.path);
+    }
+  }
+
+  /// Generates bindings and stores it in given [Writer].
+  void _generate(Writer w) {
+    w.header = header;
+    for (final b in bindings) {
+      w.addBindingString(b.toBindingString(w));
+    }
+  }
+
+  /// Formats a file using `dartfmt`.
+  void _dartFmt(String path) {
+    final result = Process.runSync('dartfmt', ['-w', path],
+        runInShell: Platform.isWindows);
+    if (result.stderr.toString().isNotEmpty) {
+      _logger.severe(result.stderr);
+    }
+  }
+
+  /// Generates the bindings.
+  String generate() {
+    final w = Writer(
+      dylibIdentifier: dylibIdentifier,
+      initFunctionIdentifier: initFunctionIdentifier,
+    );
+    _generate(w);
+    return w.generate();
+  }
+
+  @override
+  bool operator ==(Object o) => o is Library && o.generate() == generate();
+}
diff --git a/lib/src/code_generator/struc.dart b/lib/src/code_generator/struc.dart
new file mode 100644
index 0000000..391dc2e
--- /dev/null
+++ b/lib/src/code_generator/struc.dart
@@ -0,0 +1,194 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+import 'binding.dart';
+import 'binding_string.dart';
+import 'type.dart';
+import 'writer.dart';
+
+/// A binding for C Struct.
+///
+/// For a C structure -
+/// ```c
+/// struct C {
+///   int a;
+///   double b;
+///   int c;
+/// };
+/// ```
+/// The generated dart code is -
+/// ```dart
+/// class Struct extends ffi.Struct{
+///  @ffi.Int32()
+///  int a;
+///
+///  @ffi.Double()
+///  double b;
+///
+///  @ffi.Uint8()
+///  int c;
+///
+/// }
+/// ```
+class Struc extends Binding {
+  final List<Member> members;
+
+  Struc({
+    @required String name,
+    String dartDoc,
+    List<Member> members,
+  })  : members = members ?? [],
+        super(name: name, dartDoc: dartDoc);
+
+  @override
+  BindingString toBindingString(Writer w) {
+    final s = StringBuffer();
+
+    if (dartDoc != null) {
+      s.write('/// ');
+      s.writeAll(dartDoc.split('\n'), '\n/// ');
+      s.write('\n');
+    }
+
+    final helpers = <ArrayHelper>[];
+
+    // Write class declaration.
+    s.write('class $name extends ${w.ffiLibraryPrefix}.Struct{\n');
+    for (final m in members) {
+      if (m.type.broadType == BroadType.ConstantArray) {
+        // TODO(5): Remove array helpers when inline array support arives.
+        final arrayHelper = ArrayHelper(
+          helperClassName: '_ArrayHelper_${name}_${m.name}',
+          elementType: m.type.elementType,
+          length: 3,
+          name: m.name,
+          structName: name,
+          elementNamePrefix: '_${m.name}_item_',
+        );
+        s.write(arrayHelper.declarationString(w));
+        helpers.add(arrayHelper);
+      } else {
+        if (m.type.isPrimitive) {
+          s.write('  @${m.type.getCType(w)}()\n');
+        }
+        s.write('  ${m.type.getDartType(w)} ${m.name};\n\n');
+      }
+    }
+    s.write('}\n\n');
+
+    for (final helper in helpers) {
+      s.write(helper.helperClassString(w));
+    }
+
+    return BindingString(type: BindingStringType.struc, string: s.toString());
+  }
+}
+
+class Member {
+  final String name;
+  final Type type;
+
+  const Member({this.name, this.type});
+}
+
+// Helper bindings for struct array.
+class ArrayHelper {
+  final Type elementType;
+  final int length;
+  final String structName;
+
+  final String name;
+  final String helperClassName;
+  final String elementNamePrefix;
+
+  ArrayHelper({
+    @required this.elementType,
+    @required this.length,
+    @required this.structName,
+    @required this.name,
+    @required this.helperClassName,
+    @required this.elementNamePrefix,
+  });
+
+  /// Create declaration binding, added inside the struct binding.
+  String declarationString(Writer w) {
+    final s = StringBuffer();
+    final arrayDartType = elementType.getDartType(w);
+    final arrayCType = elementType.getCType(w);
+
+    for (var i = 0; i < length; i++) {
+      if (elementType.isPrimitive) {
+        s.write('  @${arrayCType}()\n');
+      }
+      s.write('  ${arrayDartType} ${elementNamePrefix}$i;\n');
+    }
+
+    s.write('/// helper for array, supports `[]` operator\n');
+    s.write(
+        '$helperClassName get $name => ${helperClassName}(this, $length);\n');
+
+    return s.toString();
+  }
+
+  /// Creates an array helper binding for struct array.
+  String helperClassString(Writer w) {
+    final s = StringBuffer();
+
+    final arrayType = elementType.getDartType(w);
+
+    s.write('/// Helper for array $name in struct $structName\n');
+
+    // Write class declaration.
+    s.write('class $helperClassName{\n');
+    s.write('final $structName _struct;\n');
+    s.write('final int length;\n');
+    s.write('$helperClassName(this._struct, this.length);\n');
+
+    // Override []= operator.
+    s.write('void operator []=(int index, $arrayType value) {\n');
+    s.write('switch(index) {\n');
+    for (var i = 0; i < length; i++) {
+      s.write('case $i:\n');
+      s.write('  _struct.${elementNamePrefix}$i = value;\n');
+      s.write('  break;\n');
+    }
+    s.write('default:\n');
+    s.write(
+        "  throw RangeError('Index \$index must be in the range [0..${length - 1}].');");
+    s.write('}\n');
+    s.write('}\n');
+
+    // Override [] operator.
+    s.write('$arrayType operator [](int index) {\n');
+    s.write('switch(index) {\n');
+    for (var i = 0; i < length; i++) {
+      s.write('case $i:\n');
+      s.write('  return _struct.${elementNamePrefix}$i;\n');
+    }
+    s.write('default:\n');
+    s.write(
+        "  throw RangeError('Index \$index must be in the range [0..${length - 1}].');");
+    s.write('}\n');
+    s.write('}\n');
+
+    // Override toString().
+    s.write('@override\n');
+    s.write('String toString() {\n');
+    s.write("if (length == 0) return '[]';\n");
+    s.write("final sb = StringBuffer('[');\n");
+    s.write('sb.write(this[0]);\n');
+    s.write('for (var i = 1; i < length; i++) {\n');
+    s.write("  sb.write(',');\n");
+    s.write('  sb.write(this[i]);');
+    s.write('}\n');
+    s.write("sb.write(']');");
+    s.write('return sb.toString();\n');
+    s.write('}\n');
+
+    s.write('}\n\n');
+    return s.toString();
+  }
+}
diff --git a/lib/src/code_generator/type.dart b/lib/src/code_generator/type.dart
new file mode 100644
index 0000000..b393d34
--- /dev/null
+++ b/lib/src/code_generator/type.dart
@@ -0,0 +1,165 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+import 'writer.dart';
+
+class _SubType {
+  final String c;
+  final String dart;
+
+  const _SubType({this.c, this.dart});
+}
+
+enum SupportedNativeType {
+  Void,
+  Char,
+  Int8,
+  Int16,
+  Int32,
+  Int64,
+  Uint8,
+  Uint16,
+  Uint32,
+  Uint64,
+  Float,
+  Double,
+  IntPtr,
+}
+
+/// The basic types in which all types can be broadly classified into.
+enum BroadType {
+  NativeType,
+  Pointer,
+  Struct,
+  NativeFunction,
+
+  /// Stores its element type in NativeType as only those are supported.
+  ConstantArray,
+
+  /// Used as a marker, so that functions/structs having these can exclude them.
+  Unimplemented,
+}
+
+/// Type class for return types, variable types, etc.
+class Type {
+  static const _primitives = <SupportedNativeType, _SubType>{
+    SupportedNativeType.Void: _SubType(c: 'Void', dart: 'void'),
+    SupportedNativeType.Char: _SubType(c: 'Uint8', dart: 'int'),
+    SupportedNativeType.Int8: _SubType(c: 'Int8', dart: 'int'),
+    SupportedNativeType.Int16: _SubType(c: 'Int16', dart: 'int'),
+    SupportedNativeType.Int32: _SubType(c: 'Int32', dart: 'int'),
+    SupportedNativeType.Int64: _SubType(c: 'Int64', dart: 'int'),
+    SupportedNativeType.Uint8: _SubType(c: 'Uint8', dart: 'int'),
+    SupportedNativeType.Uint16: _SubType(c: 'Uint16', dart: 'int'),
+    SupportedNativeType.Uint32: _SubType(c: 'Uint32', dart: 'int'),
+    SupportedNativeType.Uint64: _SubType(c: 'Uint64', dart: 'int'),
+    SupportedNativeType.Float: _SubType(c: 'Float', dart: 'double'),
+    SupportedNativeType.Double: _SubType(c: 'Double', dart: 'double'),
+    SupportedNativeType.IntPtr: _SubType(c: 'IntPtr', dart: 'int'),
+  };
+
+  /// For providing name of Struct.
+  String structName;
+
+  /// For providing name of nativeFunc.
+  String nativeFuncName;
+
+  /// For providing [SupportedNativeType] only.
+  final SupportedNativeType nativeType;
+
+  /// The BroadType of this Type.
+  final BroadType broadType;
+
+  /// Child Type, e.g Pointer(Parent) to Int(Child).
+  final Type child;
+
+  /// For ConstantArray type.
+  final int arrayLength;
+  final Type elementType;
+
+  /// For storing cursor type info for an unimplemented type.
+  String unimplementedReason;
+
+  Type._({
+    @required this.broadType,
+    this.child,
+    this.structName,
+    this.nativeType,
+    this.nativeFuncName,
+    this.arrayLength,
+    this.elementType,
+    this.unimplementedReason,
+  });
+
+  factory Type.pointer(Type child) {
+    return Type._(broadType: BroadType.Pointer, child: child);
+  }
+  factory Type.struct(String structName) {
+    return Type._(broadType: BroadType.Struct, structName: structName);
+  }
+  factory Type.nativeFunc(String nativeFuncName) {
+    return Type._(
+        broadType: BroadType.NativeFunction, nativeFuncName: nativeFuncName);
+  }
+  factory Type.nativeType(SupportedNativeType nativeType) {
+    return Type._(broadType: BroadType.NativeType, nativeType: nativeType);
+  }
+  factory Type.constantArray(int arrayLength, Type elementType) {
+    return Type._(broadType: BroadType.ConstantArray, elementType: elementType);
+  }
+  factory Type.unimplemented(String reason) {
+    return Type._(
+        broadType: BroadType.Unimplemented, unimplementedReason: reason);
+  }
+
+  /// Get base broad type for any type.
+  ///
+  /// E.g int** has base Broadtype as NativeType.
+  BroadType getBaseBroadType() {
+    if (broadType == BroadType.Pointer) {
+      return child.getBaseBroadType();
+    } else {
+      return broadType;
+    }
+  }
+
+  bool get isPrimitive => broadType == BroadType.NativeType;
+
+  String getCType(Writer w) {
+    switch (broadType) {
+      case BroadType.NativeType:
+        return '${w.ffiLibraryPrefix}.${_primitives[nativeType].c}';
+      case BroadType.Pointer:
+        return '${w.ffiLibraryPrefix}.Pointer<${child.getCType(w)}>';
+      case BroadType.Struct:
+        return structName;
+      case BroadType.NativeFunction:
+        return '${w.ffiLibraryPrefix}.NativeFunction<${nativeFuncName}>';
+      default:
+        throw Exception('cType unknown');
+    }
+  }
+
+  String getDartType(Writer w) {
+    switch (broadType) {
+      case BroadType.NativeType:
+        return _primitives[nativeType].dart;
+      case BroadType.Pointer:
+        return '${w.ffiLibraryPrefix}.Pointer<${child.getCType(w)}>';
+      case BroadType.Struct:
+        return structName;
+      case BroadType.NativeFunction:
+        return '${w.ffiLibraryPrefix}.NativeFunction<${nativeFuncName}>';
+      default:
+        throw Exception('dart type unknown for ${broadType.toString()}');
+    }
+  }
+
+  @override
+  String toString() {
+    return 'Type: ${broadType}';
+  }
+}
diff --git a/lib/src/code_generator/typedef.dart b/lib/src/code_generator/typedef.dart
new file mode 100644
index 0000000..ea9568f
--- /dev/null
+++ b/lib/src/code_generator/typedef.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+import 'binding.dart';
+import 'binding_string.dart';
+import 'func.dart' show Parameter;
+import 'type.dart';
+import 'writer.dart';
+
+/// A simple typedef function for C functions, Expands to -
+///
+/// ```dart
+/// typedef $name = $returnType Function(
+///   $parameter1...,
+///   $parameter2...,
+///   .
+///   .
+/// );`
+/// ```
+/// Note: This doesn't bind with anything.
+class TypedefC extends Binding {
+  final Type returnType;
+  final List<Parameter> parameters;
+
+  TypedefC({
+    @required String name,
+    String dartDoc,
+    @required this.returnType,
+    List<Parameter> parameters,
+  })  : parameters = parameters ?? [],
+        super(name: name, dartDoc: dartDoc);
+
+  @override
+  BindingString toBindingString(Writer w) {
+    final s = StringBuffer();
+
+    if (dartDoc != null) {
+      s.write('/// ');
+      s.writeAll(dartDoc.split('\n'), '\n/// ');
+      s.write('\n');
+    }
+
+    s.write('typedef $name = ${returnType.getCType(w)} Function(\n');
+    for (final p in parameters) {
+      s.write('  ${p.type.getCType(w)} ${p.name},\n');
+    }
+    s.write(');\n\n');
+
+    return BindingString(type: BindingStringType.typeDef, string: s.toString());
+  }
+}
diff --git a/lib/src/code_generator/writer.dart b/lib/src/code_generator/writer.dart
new file mode 100644
index 0000000..cc4496f
--- /dev/null
+++ b/lib/src/code_generator/writer.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'binding_string.dart';
+
+/// To store generated String bindings.
+class Writer {
+  String header;
+  String dylibIdentifier;
+  String initFunctionIdentifier;
+
+  /// dart:ffi library import prefix.
+  String ffiLibraryPrefix;
+
+  final List<BindingString> _bindings = [];
+
+  Writer({
+    this.dylibIdentifier = '_dylib',
+    this.initFunctionIdentifier = 'init',
+    this.ffiLibraryPrefix = 'ffi',
+  });
+
+  String generate() {
+    final s = StringBuffer();
+
+    // Write header (if any)
+    if (header != null) {
+      s.write(header);
+      s.write('\n');
+    } else {
+      // Write default header, in case none was provided.
+      s.write('''/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+''');
+    }
+
+    // Write neccesary imports.
+    s.write("import 'dart:ffi' as $ffiLibraryPrefix;\n");
+    s.write('\n');
+
+    // Write dylib.
+    s.write('/// Holds the Dynamic library.\n');
+    s.write('$ffiLibraryPrefix.DynamicLibrary ${dylibIdentifier};\n');
+    s.write('\n');
+    s.write('/// Initialises the Dynamic library.\n');
+    s.write(
+        'void $initFunctionIdentifier($ffiLibraryPrefix.DynamicLibrary dylib){\n');
+    s.write('  ${dylibIdentifier} = dylib;\n');
+    s.write('}\n');
+
+    // Write bindings.
+    for (final bs in _bindings) {
+      s.write(bs.string);
+    }
+
+    return s.toString();
+  }
+
+  void addBindingString(BindingString b) {
+    _bindings.add(b);
+  }
+}
diff --git a/lib/src/config_provider.dart b/lib/src/config_provider.dart
new file mode 100644
index 0000000..990e137
--- /dev/null
+++ b/lib/src/config_provider.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Creates config object used by other sub_modules.
+library config_provider;
+
+export 'config_provider/config.dart';
diff --git a/lib/src/config_provider/config.dart b/lib/src/config_provider/config.dart
new file mode 100644
index 0000000..89f55c2
--- /dev/null
+++ b/lib/src/config_provider/config.dart
@@ -0,0 +1,287 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+/// Validates the yaml input by the user, prints useful info for the user
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:ffigen/src/header_parser/type_extractor/cxtypekindmap.dart';
+
+import 'package:logging/logging.dart';
+import 'package:meta/meta.dart';
+import 'package:path/path.dart' as path;
+import 'package:yaml/yaml.dart';
+
+import '../strings.dart' as strings;
+import 'filter.dart';
+import 'spec_utils.dart';
+
+var _logger = Logger('config_provider/config');
+
+/// Provides configurations to other modules.
+///
+/// Handles validation, extraction of confiurations from yaml file.
+class Config {
+  /// output file name.
+  String output;
+
+  /// libclang path (in accordance with the platform).
+  ///
+  /// File may have the following extensions - `.so` / `.dll` / `.dylib`
+  /// as extracted by configspec.
+  String libclang_dylib_path;
+
+  /// Path to headers.
+  ///
+  /// This contains all the headers, after extraction from Globs.
+  List<String> headers;
+
+  /// Filter for headers.
+  HeaderFilter headerFilter;
+
+  /// CommandLine Arguments to pass to clang_compiler.
+  List<String> compilerOpts;
+
+  /// Filter for functions.
+  Filter functionFilters;
+
+  /// Filter for structs.
+  Filter structFilters;
+
+  /// Filter for enumClass.
+  Filter enumClassFilters;
+
+  /// If generated bindings should be sorted alphabetically.
+  bool sort;
+
+  /// If typedef of supported types(int8_t) should be directly used.
+  bool useSupportedTypedefs;
+
+  /// If tool should extract doc comment from bindings.
+  bool extractComments;
+
+  /// Manually creating configurations.
+  ///
+  /// Use [Config.fromYaml] if extracting info from a yaml file.
+  /// Ensure that log printing is setup before using this.
+  Config.raw({
+    this.output,
+    @required this.libclang_dylib_path,
+    @required this.headers,
+    this.headerFilter,
+    this.compilerOpts,
+    this.functionFilters,
+    this.structFilters,
+    this.enumClassFilters,
+    this.sort = false,
+    this.useSupportedTypedefs = true,
+    this.extractComments = true,
+  });
+
+  Config._();
+
+  /// Create config from Yaml map.
+  ///
+  /// Ensure that log printing is setup before using this.
+  factory Config.fromYaml(YamlMap map) {
+    final configspecs = Config._();
+    _logger.finest('Config Map: ' + map.toString());
+
+    final specs = configspecs._getSpecs();
+
+    final result = configspecs._checkConfigs(map, specs);
+    if (!result) {
+      _logger.info('Please fix errors in Configurations and re-run the tool');
+      exit(1);
+    }
+
+    configspecs._extract(map, specs);
+    return configspecs;
+  }
+
+  /// Validates Yaml according to given specs.
+  bool _checkConfigs(YamlMap map, Map<String, Specification> specs) {
+    var _result = true;
+    for (final key in specs.keys) {
+      final spec = specs[key];
+      if (spec.isRequired && !map.containsKey(key)) {
+        _logger.severe("Key '${key}' is required.");
+        _result = false;
+      } else if (map.containsKey(key)) {
+        _result = _result && spec.validator(key, map[key]);
+      }
+    }
+    // Warn about unknown keys.
+    for (final key in map.keys) {
+      if (!specs.containsKey(key)) {
+        _logger.warning("Unknown key '$key' found.");
+      }
+    }
+
+    return _result;
+  }
+
+  /// Extracts variables from Yaml according to given specs.
+  ///
+  /// Validation must be done beforehand, using [_checkConfigs].
+  void _extract(YamlMap map, Map<String, Specification> specs) {
+    for (final key in specs.keys) {
+      final spec = specs[key];
+      if (map.containsKey(key)) {
+        spec.extractedResult(spec.extractor(map[key]));
+      } else {
+        spec.extractedResult(spec.defaultValue);
+      }
+    }
+  }
+
+  /// Returns map of various specifications avaialble for our tool.
+  ///
+  /// Key: Name, Value: [Specification]
+  Map<String, Specification> _getSpecs() {
+    return <String, Specification>{
+      strings.output: Specification<String>(
+        description: 'Output file name',
+        isRequired: true,
+        validator: outputValidator,
+        extractor: outputExtractor,
+        defaultValue: null,
+        extractedResult: (dynamic result) => output = result as String,
+      ),
+      strings.libclang_dylib_folder: Specification<String>(
+        description:
+            'Path to folder containing libclang dynamic library, used to parse C headers',
+        isRequired: false,
+        defaultValue: getDylibPath(Platform.script
+            .resolve(path.join('..', 'tool', 'wrapped_libclang'))
+            .toFilePath()),
+        validator: libclangDylibValidator,
+        extractor: libclangDylibExtractor,
+        extractedResult: (dynamic result) =>
+            libclang_dylib_path = result as String,
+      ),
+      strings.headers: Specification<List<String>>(
+        description: 'List of C headers to generate bindings of',
+        isRequired: true,
+        validator: headersValidator,
+        extractor: headersExtractor,
+        extractedResult: (dynamic result) => headers = result as List<String>,
+      ),
+      strings.headerFilter: Specification<HeaderFilter>(
+        description: 'Include/Exclude inclusion headers',
+        validator: headerFilterValidator,
+        extractor: headerFilterExtractor,
+        defaultValue: HeaderFilter(),
+        extractedResult: (dynamic result) {
+          return headerFilter = result as HeaderFilter;
+        },
+      ),
+      strings.compilerOpts: Specification<List<String>>(
+        description: 'Raw compiler options to pass to clang compiler',
+        isRequired: false,
+        validator: compilerOptsValidator,
+        extractor: compilerOptsExtractor,
+        defaultValue: null,
+        extractedResult: (dynamic result) =>
+            compilerOpts = result as List<String>,
+      ),
+      strings.functions: Specification<Filter>(
+        description: 'Filter for functions',
+        isRequired: false,
+        validator: filterValidator,
+        extractor: filterExtractor,
+        defaultValue: null,
+        extractedResult: (dynamic result) => functionFilters = result as Filter,
+      ),
+      strings.structs: Specification<Filter>(
+        description: 'Filter for Structs',
+        isRequired: false,
+        validator: filterValidator,
+        extractor: filterExtractor,
+        defaultValue: null,
+        extractedResult: (dynamic result) => structFilters = result as Filter,
+      ),
+      strings.enums: Specification<Filter>(
+        description: 'Filter for enums',
+        isRequired: false,
+        validator: filterValidator,
+        extractor: filterExtractor,
+        defaultValue: null,
+        extractedResult: (dynamic result) =>
+            enumClassFilters = result as Filter,
+      ),
+      strings.sizemap: Specification<Map<int, SupportedNativeType>>(
+        description: 'map of types: byte size in int',
+        validator: sizemapValidator,
+        extractor: sizemapExtractor,
+        defaultValue: <int, SupportedNativeType>{},
+        extractedResult: (dynamic result) {
+          final map = result as Map<int, SupportedNativeType>;
+          for (final key in map.keys) {
+            if (cxTypeKindToSupportedNativeTypes.containsKey(key)) {
+              cxTypeKindToSupportedNativeTypes[key] = map[key];
+            }
+          }
+        },
+      ),
+      strings.sort: Specification<bool>(
+        description: 'whether or not to sort the bindings alphabetically',
+        isRequired: false,
+        validator: booleanValidator,
+        extractor: booleanExtractor,
+        defaultValue: false,
+        extractedResult: (dynamic result) => sort = result as bool,
+      ),
+      strings.useSupportedTypedefs: Specification<bool>(
+        description: 'whether or not to directly map supported typedef by name',
+        isRequired: false,
+        validator: booleanValidator,
+        extractor: booleanExtractor,
+        defaultValue: true,
+        extractedResult: (dynamic result) =>
+            useSupportedTypedefs = result as bool,
+      ),
+      strings.extractComments: Specification<bool>(
+        description: 'whether or not to extract comments from bindings',
+        isRequired: false,
+        validator: booleanValidator,
+        extractor: booleanExtractor,
+        defaultValue: true,
+        extractedResult: (dynamic result) => extractComments = result as bool,
+      ),
+    };
+  }
+}
+
+/// Represents a single specification in configurations.
+///
+/// [E] is the return type of the extractedResult.
+class Specification<E> {
+  final String description;
+  final bool Function(String name, dynamic value) validator;
+  final E Function(dynamic map) extractor;
+  final E defaultValue;
+  final bool isRequired;
+  final void Function(dynamic result) extractedResult;
+
+  Specification({
+    @required this.extractedResult,
+    @required this.description,
+    @required this.validator,
+    @required this.extractor,
+    this.defaultValue,
+    this.isRequired = false,
+  });
+}
+
+class HeaderFilter {
+  Set<String> includedInclusionHeaders;
+  Set<String> excludedInclusionHeaders;
+
+  HeaderFilter({
+    this.includedInclusionHeaders = const {},
+    this.excludedInclusionHeaders = const {},
+  });
+}
diff --git a/lib/src/config_provider/filter.dart b/lib/src/config_provider/filter.dart
new file mode 100644
index 0000000..b35dc0b
--- /dev/null
+++ b/lib/src/config_provider/filter.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// A generic filter for filtering strings based on regexes and prefixes.
+///
+/// Excludes override includes.
+///
+/// User can provide fiters for functions, structs, enums and include/exclude
+/// them using regexp and full name matching.
+class Filter {
+  // matchers
+  List<RegExp> _includeMatchers = [];
+  Set<String> _includeFull = {};
+  List<RegExp> _excludeMatchers = [];
+  Set<String> _excludeFull = {};
+
+  Filter({
+    List<String> includeMatchers,
+    List<String> includeFull,
+    List<String> excludeMatchers,
+    List<String> excludeFull,
+  }) {
+    if (includeMatchers != null) {
+      _includeMatchers =
+          includeMatchers.map((e) => RegExp(e, dotAll: true)).toList();
+    }
+    if (includeFull != null) {
+      _includeFull = includeFull.map((e) => e).toSet();
+    }
+    if (excludeMatchers != null) {
+      _excludeMatchers =
+          excludeMatchers.map((e) => RegExp(e, dotAll: true)).toList();
+    }
+    if (excludeFull != null) {
+      _excludeFull = excludeFull.map((e) => e).toSet();
+    }
+  }
+
+  /// Checks if a name is allowed by a filter.
+  bool shouldInclude(String name) {
+    if (_excludeFull.contains(name)) {
+      return false;
+    }
+
+    for (final em in _excludeMatchers) {
+      if (em.firstMatch(name)?.end == name.length) {
+        return false;
+      }
+    }
+
+    if (_includeFull.contains(name)) {
+      return true;
+    }
+
+    for (final im in _includeMatchers) {
+      if (im.firstMatch(name)?.end == name.length) {
+        return true;
+      }
+    }
+
+    // If user has provided 'include' field in the filter, then default
+    // matching is false.
+    if (_includeMatchers.isNotEmpty || _includeFull.isNotEmpty) {
+      return false;
+    } else {
+      return true;
+    }
+  }
+
+  @override
+  String toString() {
+    return ''' (includeFull, includeMatchers, excludeFull, excludeMatchers)
+$_includeFull
+$_includeMatchers
+$_excludeFull
+$_excludeMatchers
+    ''';
+  }
+}
diff --git a/lib/src/config_provider/spec_utils.dart b/lib/src/config_provider/spec_utils.dart
new file mode 100644
index 0000000..683d53d
--- /dev/null
+++ b/lib/src/config_provider/spec_utils.dart
@@ -0,0 +1,241 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:glob/glob.dart';
+import 'package:logging/logging.dart';
+import 'package:path/path.dart' as p;
+import 'package:yaml/yaml.dart';
+
+import '../strings.dart' as strings;
+import './config.dart';
+import 'filter.dart';
+
+var _logger = Logger('config_provider/utils');
+
+bool booleanExtractor(dynamic value) => value as bool;
+
+bool booleanValidator(String name, dynamic value) {
+  if (value is! bool) {
+    _logger.severe("Expected value of key '$name' to be a bool.");
+    return false;
+  } else {
+    return true;
+  }
+}
+
+Map<int, SupportedNativeType> sizemapExtractor(dynamic yamlConfig) {
+  final resultMap = <int, SupportedNativeType>{};
+  final sizemap = yamlConfig as YamlMap;
+  if (sizemap != null) {
+    for (final typeName in strings.sizemap_native_mapping.keys) {
+      if (sizemap.containsKey(typeName)) {
+        final cxTypeInt = strings.sizemap_native_mapping[typeName];
+        final byteSize = sizemap[typeName] as int;
+        resultMap[cxTypeInt] = nativeSupportedType(byteSize,
+            signed: typeName.contains('unsigned') ? false : true);
+      }
+    }
+  }
+  return resultMap;
+}
+
+bool sizemapValidator(String name, dynamic yamlConfig) {
+  if (yamlConfig is! YamlMap) {
+    _logger.severe("Expected value of key '$name' to be a Map.");
+    return false;
+  }
+  for (final key in (yamlConfig as YamlMap).keys) {
+    if (!strings.sizemap_native_mapping.containsKey(key)) {
+      _logger.warning("Unknown subkey '$key' in '$name'.");
+    }
+  }
+
+  return true;
+}
+
+List<String> compilerOptsExtractor(dynamic value) =>
+    (value as String)?.split(' ');
+
+bool compilerOptsValidator(String name, dynamic value) {
+  if (value is! String) {
+    _logger.severe("Expected value of key '$name' to be a string.");
+    return false;
+  } else {
+    return true;
+  }
+}
+
+HeaderFilter headerFilterExtractor(dynamic yamlConfig) {
+  final includedInclusionHeaders = <String>{};
+  final excludedInclusionHeaders = <String>{};
+
+  final headerFilter = yamlConfig as YamlMap;
+  if (headerFilter != null) {
+    // Add include/excluded header-filter from Yaml.
+    final include = headerFilter[strings.include] as YamlList;
+    include?.cast<String>()?.forEach(includedInclusionHeaders.add);
+
+    final exclude = headerFilter[strings.exclude] as YamlList;
+    exclude?.cast<String>()?.forEach(excludedInclusionHeaders.add);
+  }
+
+  return HeaderFilter(
+    includedInclusionHeaders: includedInclusionHeaders,
+    excludedInclusionHeaders: excludedInclusionHeaders,
+  );
+}
+
+bool headerFilterValidator(String name, dynamic value) {
+  if (value is! YamlMap) {
+    _logger.severe("Expected value of key '$name' to be a Map.");
+    return false;
+  } else {
+    return true;
+  }
+}
+
+List<String> headersExtractor(dynamic yamlConfig) {
+  final headers = <String>[];
+  for (final h in (yamlConfig as YamlList)) {
+    final headerGlob = h as String;
+    // Add file directly to header if it's not a Glob but a File.
+    if (File(headerGlob).existsSync()) {
+      headers.add(headerGlob);
+      _logger.fine('Adding header/file: $headerGlob');
+    } else {
+      final glob = Glob(headerGlob);
+      for (final file in glob.listSync(followLinks: true)) {
+        headers.add(file.path);
+        _logger.fine('Adding header/file: ${file.path}');
+      }
+    }
+  }
+  return headers;
+}
+
+bool headersValidator(String name, dynamic value) {
+  if (value is! YamlList) {
+    _logger.severe(
+        "Expected value of key '${strings.headers}' to be a List of String.");
+    return false;
+  } else {
+    return true;
+  }
+}
+
+String libclangDylibExtractor(dynamic value) => getDylibPath(value as String);
+
+bool libclangDylibValidator(String name, dynamic value) {
+  if (value is! String) {
+    _logger.severe("Expected value of key '$name' to be a string.");
+    return false;
+  } else {
+    final dylibPath = getDylibPath(value as String);
+    if (!File(dylibPath).existsSync()) {
+      _logger.severe(
+          'Dynamic library: $dylibPath does not exist or is corrupt, input folder: $value.');
+      return false;
+    } else {
+      return true;
+    }
+  }
+}
+
+String getDylibPath(String dylibParentFoler) {
+  String dylibPath;
+  if (Platform.isMacOS) {
+    dylibPath = p.join(dylibParentFoler, strings.libclang_dylib_macos);
+  } else if (Platform.isWindows) {
+    // Fix path for windows if '/' is used as seperator instead of '\'
+    // because our examples input path like this.
+    final newValue = dylibParentFoler.replaceAll('/', r'\');
+    dylibPath = p.join(newValue, strings.libclang_dylib_windows);
+  } else {
+    dylibPath = p.join(dylibParentFoler, strings.libclang_dylib_linux);
+  }
+  return dylibPath;
+}
+
+String outputExtractor(dynamic value) => value as String;
+
+bool outputValidator(String name, dynamic value) {
+  if (value is String) {
+    return true;
+  } else {
+    _logger.severe("Expected value of key '${strings.output}' to be a String.");
+    return false;
+  }
+}
+
+Filter filterExtractor(dynamic yamlMap) {
+  List<String> includeMatchers, includeFull, excludeMatchers, excludeFull;
+
+  final include = yamlMap[strings.include] as YamlMap;
+  if (include != null) {
+    includeMatchers = (include[strings.matches] as YamlList)?.cast<String>();
+    includeFull = (include[strings.names] as YamlList)?.cast<String>();
+  }
+
+  final exclude = yamlMap[strings.exclude] as YamlMap;
+  if (exclude != null) {
+    excludeMatchers = (exclude[strings.matches] as YamlList)?.cast<String>();
+    excludeFull = (exclude[strings.names] as YamlList)?.cast<String>();
+  }
+
+  return Filter(
+    includeMatchers: includeMatchers,
+    includeFull: includeFull,
+    excludeMatchers: excludeMatchers,
+    excludeFull: excludeFull,
+  );
+}
+
+bool filterValidator(String name, dynamic value) {
+  var _result = true;
+  if (value is YamlMap) {
+    for (final key in value.keys) {
+      if (key == strings.include || key == strings.exclude) {
+        if (value[key] is! YamlMap) {
+          _logger.severe("Expected '$name -> $key' to be a Map.");
+        }
+        for (final subkey in value[key].keys) {
+          if (subkey == strings.matches || subkey == strings.names) {
+            if (value[key][subkey] is! YamlList) {
+              _logger.severe("Expected '$name -> $key -> $subkey' to be a List.");
+              _result = false;
+            }
+          } else {
+            _logger.severe("Unknown key '$subkey' in '$name -> $key'.");
+          }
+        }
+      } else {
+        _logger.severe("Unknown key '$key' in '$name'.");
+        _result = false;
+      }
+    }
+  } else {
+    _logger.severe("Expected value '$name' to be a Map.");
+    _result = false;
+  }
+  return _result;
+}
+
+SupportedNativeType nativeSupportedType(int value, {bool signed = true}) {
+  switch (value) {
+    case 1:
+      return signed ? SupportedNativeType.Int8 : SupportedNativeType.Uint8;
+    case 2:
+      return signed ? SupportedNativeType.Int16 : SupportedNativeType.Uint16;
+    case 4:
+      return signed ? SupportedNativeType.Int32 : SupportedNativeType.Uint32;
+    case 8:
+      return signed ? SupportedNativeType.Int64 : SupportedNativeType.Uint64;
+    default:
+      throw Exception(
+          'Unsupported value given to sizemap, Allowed values for sizes are: 1, 2, 4, 8');
+  }
+}
diff --git a/lib/src/header_parser.dart b/lib/src/header_parser.dart
new file mode 100644
index 0000000..e4dc2c9
--- /dev/null
+++ b/lib/src/header_parser.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Generates a [Library] (code_generator)
+///
+/// Parses the header files AST using clang_bindings.
+library header_parser;
+
+export 'header_parser/parser.dart' show parse;
diff --git a/lib/src/header_parser/clang_bindings/clang_bindings.dart b/lib/src/header_parser/clang_bindings/clang_bindings.dart
new file mode 100644
index 0000000..f701971
--- /dev/null
+++ b/lib/src/header_parser/clang_bindings/clang_bindings.dart
@@ -0,0 +1,1447 @@
+/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib) {
+  _dylib = dylib;
+}
+
+/// Describes how the traversal of the children of a particular cursor should proceed after visiting a particular child cursor.
+class CXChildVisitResult {
+  static const int CXChildVisit_Break = 0;
+  static const int CXChildVisit_Continue = 1;
+  static const int CXChildVisit_Recurse = 2;
+}
+
+/// A cursor representing some element in the abstract syntax tree for a translation unit.
+class CXCursor extends ffi.Struct {
+  @ffi.Int32()
+  int kind;
+
+  @ffi.Int32()
+  int xdata;
+
+  ffi.Pointer<ffi.Void> _data_item_0;
+  ffi.Pointer<ffi.Void> _data_item_1;
+  ffi.Pointer<ffi.Void> _data_item_2;
+
+  /// helper for array, supports `[]` operator
+  _ArrayHelper_CXCursor_data get data => _ArrayHelper_CXCursor_data(this, 3);
+}
+
+/// Helper for array data in struct CXCursor
+class _ArrayHelper_CXCursor_data {
+  final CXCursor _struct;
+  final int length;
+  _ArrayHelper_CXCursor_data(this._struct, this.length);
+  void operator []=(int index, ffi.Pointer<ffi.Void> value) {
+    switch (index) {
+      case 0:
+        _struct._data_item_0 = value;
+        break;
+      case 1:
+        _struct._data_item_1 = value;
+        break;
+      case 2:
+        _struct._data_item_2 = value;
+        break;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    switch (index) {
+      case 0:
+        return _struct._data_item_0;
+      case 1:
+        return _struct._data_item_1;
+      case 2:
+        return _struct._data_item_2;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  @override
+  String toString() {
+    if (length == 0) return '[]';
+    final sb = StringBuffer('[');
+    sb.write(this[0]);
+    for (var i = 1; i < length; i++) {
+      sb.write(',');
+      sb.write(this[i]);
+    }
+    sb.write(']');
+    return sb.toString();
+  }
+}
+
+/// Describes the kind of entity that a cursor refers to.
+class CXCursorKind {
+  static const int CXCursor_UnexposedDecl = 1;
+  static const int CXCursor_StructDecl = 2;
+  static const int CXCursor_UnionDecl = 3;
+  static const int CXCursor_ClassDecl = 4;
+  static const int CXCursor_EnumDecl = 5;
+  static const int CXCursor_FieldDecl = 6;
+  static const int CXCursor_EnumConstantDecl = 7;
+  static const int CXCursor_FunctionDecl = 8;
+  static const int CXCursor_VarDecl = 9;
+  static const int CXCursor_ParmDecl = 10;
+  static const int CXCursor_ObjCInterfaceDecl = 11;
+  static const int CXCursor_ObjCCategoryDecl = 12;
+  static const int CXCursor_ObjCProtocolDecl = 13;
+  static const int CXCursor_ObjCPropertyDecl = 14;
+  static const int CXCursor_ObjCIvarDecl = 15;
+  static const int CXCursor_ObjCInstanceMethodDecl = 16;
+  static const int CXCursor_ObjCClassMethodDecl = 17;
+  static const int CXCursor_ObjCImplementationDecl = 18;
+  static const int CXCursor_ObjCCategoryImplDecl = 19;
+  static const int CXCursor_TypedefDecl = 20;
+  static const int CXCursor_CXXMethod = 21;
+  static const int CXCursor_Namespace = 22;
+  static const int CXCursor_LinkageSpec = 23;
+  static const int CXCursor_Constructor = 24;
+  static const int CXCursor_Destructor = 25;
+  static const int CXCursor_ConversionFunction = 26;
+  static const int CXCursor_TemplateTypeParameter = 27;
+  static const int CXCursor_NonTypeTemplateParameter = 28;
+  static const int CXCursor_TemplateTemplateParameter = 29;
+  static const int CXCursor_FunctionTemplate = 30;
+  static const int CXCursor_ClassTemplate = 31;
+  static const int CXCursor_ClassTemplatePartialSpecialization = 32;
+  static const int CXCursor_NamespaceAlias = 33;
+  static const int CXCursor_UsingDirective = 34;
+  static const int CXCursor_UsingDeclaration = 35;
+  static const int CXCursor_TypeAliasDecl = 36;
+  static const int CXCursor_ObjCSynthesizeDecl = 37;
+  static const int CXCursor_ObjCDynamicDecl = 38;
+  static const int CXCursor_CXXAccessSpecifier = 39;
+  static const int CXCursor_FirstDecl = 1;
+  static const int CXCursor_LastDecl = 39;
+  static const int CXCursor_FirstRef = 40;
+  static const int CXCursor_ObjCSuperClassRef = 40;
+  static const int CXCursor_ObjCProtocolRef = 41;
+  static const int CXCursor_ObjCClassRef = 42;
+  static const int CXCursor_TypeRef = 43;
+  static const int CXCursor_CXXBaseSpecifier = 44;
+  static const int CXCursor_TemplateRef = 45;
+  static const int CXCursor_NamespaceRef = 46;
+  static const int CXCursor_MemberRef = 47;
+  static const int CXCursor_LabelRef = 48;
+  static const int CXCursor_OverloadedDeclRef = 49;
+  static const int CXCursor_VariableRef = 50;
+  static const int CXCursor_LastRef = 50;
+  static const int CXCursor_FirstInvalid = 70;
+  static const int CXCursor_InvalidFile = 70;
+  static const int CXCursor_NoDeclFound = 71;
+  static const int CXCursor_NotImplemented = 72;
+  static const int CXCursor_InvalidCode = 73;
+  static const int CXCursor_LastInvalid = 73;
+  static const int CXCursor_FirstExpr = 100;
+  static const int CXCursor_UnexposedExpr = 100;
+  static const int CXCursor_DeclRefExpr = 101;
+  static const int CXCursor_MemberRefExpr = 102;
+  static const int CXCursor_CallExpr = 103;
+  static const int CXCursor_ObjCMessageExpr = 104;
+  static const int CXCursor_BlockExpr = 105;
+  static const int CXCursor_IntegerLiteral = 106;
+  static const int CXCursor_FloatingLiteral = 107;
+  static const int CXCursor_ImaginaryLiteral = 108;
+  static const int CXCursor_StringLiteral = 109;
+  static const int CXCursor_CharacterLiteral = 110;
+  static const int CXCursor_ParenExpr = 111;
+  static const int CXCursor_UnaryOperator = 112;
+  static const int CXCursor_ArraySubscriptExpr = 113;
+  static const int CXCursor_BinaryOperator = 114;
+  static const int CXCursor_CompoundAssignOperator = 115;
+  static const int CXCursor_ConditionalOperator = 116;
+  static const int CXCursor_CStyleCastExpr = 117;
+  static const int CXCursor_CompoundLiteralExpr = 118;
+  static const int CXCursor_InitListExpr = 119;
+  static const int CXCursor_AddrLabelExpr = 120;
+  static const int CXCursor_StmtExpr = 121;
+  static const int CXCursor_GenericSelectionExpr = 122;
+  static const int CXCursor_GNUNullExpr = 123;
+  static const int CXCursor_CXXStaticCastExpr = 124;
+  static const int CXCursor_CXXDynamicCastExpr = 125;
+  static const int CXCursor_CXXReinterpretCastExpr = 126;
+  static const int CXCursor_CXXConstCastExpr = 127;
+  static const int CXCursor_CXXFunctionalCastExpr = 128;
+  static const int CXCursor_CXXTypeidExpr = 129;
+  static const int CXCursor_CXXBoolLiteralExpr = 130;
+  static const int CXCursor_CXXNullPtrLiteralExpr = 131;
+  static const int CXCursor_CXXThisExpr = 132;
+  static const int CXCursor_CXXThrowExpr = 133;
+  static const int CXCursor_CXXNewExpr = 134;
+  static const int CXCursor_CXXDeleteExpr = 135;
+  static const int CXCursor_UnaryExpr = 136;
+  static const int CXCursor_ObjCStringLiteral = 137;
+  static const int CXCursor_ObjCEncodeExpr = 138;
+  static const int CXCursor_ObjCSelectorExpr = 139;
+  static const int CXCursor_ObjCProtocolExpr = 140;
+  static const int CXCursor_ObjCBridgedCastExpr = 141;
+  static const int CXCursor_PackExpansionExpr = 142;
+  static const int CXCursor_SizeOfPackExpr = 143;
+  static const int CXCursor_LambdaExpr = 144;
+  static const int CXCursor_ObjCBoolLiteralExpr = 145;
+  static const int CXCursor_ObjCSelfExpr = 146;
+  static const int CXCursor_OMPArraySectionExpr = 147;
+  static const int CXCursor_ObjCAvailabilityCheckExpr = 148;
+  static const int CXCursor_FixedPointLiteral = 149;
+  static const int CXCursor_LastExpr = 149;
+  static const int CXCursor_FirstStmt = 200;
+  static const int CXCursor_UnexposedStmt = 200;
+  static const int CXCursor_LabelStmt = 201;
+  static const int CXCursor_CompoundStmt = 202;
+  static const int CXCursor_CaseStmt = 203;
+  static const int CXCursor_DefaultStmt = 204;
+  static const int CXCursor_IfStmt = 205;
+  static const int CXCursor_SwitchStmt = 206;
+  static const int CXCursor_WhileStmt = 207;
+  static const int CXCursor_DoStmt = 208;
+  static const int CXCursor_ForStmt = 209;
+  static const int CXCursor_GotoStmt = 210;
+  static const int CXCursor_IndirectGotoStmt = 211;
+  static const int CXCursor_ContinueStmt = 212;
+  static const int CXCursor_BreakStmt = 213;
+  static const int CXCursor_ReturnStmt = 214;
+  static const int CXCursor_GCCAsmStmt = 215;
+  static const int CXCursor_AsmStmt = 215;
+  static const int CXCursor_ObjCAtTryStmt = 216;
+  static const int CXCursor_ObjCAtCatchStmt = 217;
+  static const int CXCursor_ObjCAtFinallyStmt = 218;
+  static const int CXCursor_ObjCAtThrowStmt = 219;
+  static const int CXCursor_ObjCAtSynchronizedStmt = 220;
+  static const int CXCursor_ObjCAutoreleasePoolStmt = 221;
+  static const int CXCursor_ObjCForCollectionStmt = 222;
+  static const int CXCursor_CXXCatchStmt = 223;
+  static const int CXCursor_CXXTryStmt = 224;
+  static const int CXCursor_CXXForRangeStmt = 225;
+  static const int CXCursor_SEHTryStmt = 226;
+  static const int CXCursor_SEHExceptStmt = 227;
+  static const int CXCursor_SEHFinallyStmt = 228;
+  static const int CXCursor_MSAsmStmt = 229;
+  static const int CXCursor_NullStmt = 230;
+  static const int CXCursor_DeclStmt = 231;
+  static const int CXCursor_OMPParallelDirective = 232;
+  static const int CXCursor_OMPSimdDirective = 233;
+  static const int CXCursor_OMPForDirective = 234;
+  static const int CXCursor_OMPSectionsDirective = 235;
+  static const int CXCursor_OMPSectionDirective = 236;
+  static const int CXCursor_OMPSingleDirective = 237;
+  static const int CXCursor_OMPParallelForDirective = 238;
+  static const int CXCursor_OMPParallelSectionsDirective = 239;
+  static const int CXCursor_OMPTaskDirective = 240;
+  static const int CXCursor_OMPMasterDirective = 241;
+  static const int CXCursor_OMPCriticalDirective = 242;
+  static const int CXCursor_OMPTaskyieldDirective = 243;
+  static const int CXCursor_OMPBarrierDirective = 244;
+  static const int CXCursor_OMPTaskwaitDirective = 245;
+  static const int CXCursor_OMPFlushDirective = 246;
+  static const int CXCursor_SEHLeaveStmt = 247;
+  static const int CXCursor_OMPOrderedDirective = 248;
+  static const int CXCursor_OMPAtomicDirective = 249;
+  static const int CXCursor_OMPForSimdDirective = 250;
+  static const int CXCursor_OMPParallelForSimdDirective = 251;
+  static const int CXCursor_OMPTargetDirective = 252;
+  static const int CXCursor_OMPTeamsDirective = 253;
+  static const int CXCursor_OMPTaskgroupDirective = 254;
+  static const int CXCursor_OMPCancellationPointDirective = 255;
+  static const int CXCursor_OMPCancelDirective = 256;
+  static const int CXCursor_OMPTargetDataDirective = 257;
+  static const int CXCursor_OMPTaskLoopDirective = 258;
+  static const int CXCursor_OMPTaskLoopSimdDirective = 259;
+  static const int CXCursor_OMPDistributeDirective = 260;
+  static const int CXCursor_OMPTargetEnterDataDirective = 261;
+  static const int CXCursor_OMPTargetExitDataDirective = 262;
+  static const int CXCursor_OMPTargetParallelDirective = 263;
+  static const int CXCursor_OMPTargetParallelForDirective = 264;
+  static const int CXCursor_OMPTargetUpdateDirective = 265;
+  static const int CXCursor_OMPDistributeParallelForDirective = 266;
+  static const int CXCursor_OMPDistributeParallelForSimdDirective = 267;
+  static const int CXCursor_OMPDistributeSimdDirective = 268;
+  static const int CXCursor_OMPTargetParallelForSimdDirective = 269;
+  static const int CXCursor_OMPTargetSimdDirective = 270;
+  static const int CXCursor_OMPTeamsDistributeDirective = 271;
+  static const int CXCursor_OMPTeamsDistributeSimdDirective = 272;
+  static const int CXCursor_OMPTeamsDistributeParallelForSimdDirective = 273;
+  static const int CXCursor_OMPTeamsDistributeParallelForDirective = 274;
+  static const int CXCursor_OMPTargetTeamsDirective = 275;
+  static const int CXCursor_OMPTargetTeamsDistributeDirective = 276;
+  static const int CXCursor_OMPTargetTeamsDistributeParallelForDirective = 277;
+  static const int CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective =
+      278;
+  static const int CXCursor_OMPTargetTeamsDistributeSimdDirective = 279;
+  static const int CXCursor_BuiltinBitCastExpr = 280;
+  static const int CXCursor_OMPMasterTaskLoopDirective = 281;
+  static const int CXCursor_OMPParallelMasterTaskLoopDirective = 282;
+  static const int CXCursor_OMPMasterTaskLoopSimdDirective = 283;
+  static const int CXCursor_OMPParallelMasterTaskLoopSimdDirective = 284;
+  static const int CXCursor_OMPParallelMasterDirective = 285;
+  static const int CXCursor_LastStmt = 285;
+  static const int CXCursor_TranslationUnit = 300;
+  static const int CXCursor_FirstAttr = 400;
+  static const int CXCursor_UnexposedAttr = 400;
+  static const int CXCursor_IBActionAttr = 401;
+  static const int CXCursor_IBOutletAttr = 402;
+  static const int CXCursor_IBOutletCollectionAttr = 403;
+  static const int CXCursor_CXXFinalAttr = 404;
+  static const int CXCursor_CXXOverrideAttr = 405;
+  static const int CXCursor_AnnotateAttr = 406;
+  static const int CXCursor_AsmLabelAttr = 407;
+  static const int CXCursor_PackedAttr = 408;
+  static const int CXCursor_PureAttr = 409;
+  static const int CXCursor_ConstAttr = 410;
+  static const int CXCursor_NoDuplicateAttr = 411;
+  static const int CXCursor_CUDAConstantAttr = 412;
+  static const int CXCursor_CUDADeviceAttr = 413;
+  static const int CXCursor_CUDAGlobalAttr = 414;
+  static const int CXCursor_CUDAHostAttr = 415;
+  static const int CXCursor_CUDASharedAttr = 416;
+  static const int CXCursor_VisibilityAttr = 417;
+  static const int CXCursor_DLLExport = 418;
+  static const int CXCursor_DLLImport = 419;
+  static const int CXCursor_NSReturnsRetained = 420;
+  static const int CXCursor_NSReturnsNotRetained = 421;
+  static const int CXCursor_NSReturnsAutoreleased = 422;
+  static const int CXCursor_NSConsumesSelf = 423;
+  static const int CXCursor_NSConsumed = 424;
+  static const int CXCursor_ObjCException = 425;
+  static const int CXCursor_ObjCNSObject = 426;
+  static const int CXCursor_ObjCIndependentClass = 427;
+  static const int CXCursor_ObjCPreciseLifetime = 428;
+  static const int CXCursor_ObjCReturnsInnerPointer = 429;
+  static const int CXCursor_ObjCRequiresSuper = 430;
+  static const int CXCursor_ObjCRootClass = 431;
+  static const int CXCursor_ObjCSubclassingRestricted = 432;
+  static const int CXCursor_ObjCExplicitProtocolImpl = 433;
+  static const int CXCursor_ObjCDesignatedInitializer = 434;
+  static const int CXCursor_ObjCRuntimeVisible = 435;
+  static const int CXCursor_ObjCBoxable = 436;
+  static const int CXCursor_FlagEnum = 437;
+  static const int CXCursor_ConvergentAttr = 438;
+  static const int CXCursor_WarnUnusedAttr = 439;
+  static const int CXCursor_WarnUnusedResultAttr = 440;
+  static const int CXCursor_AlignedAttr = 441;
+  static const int CXCursor_LastAttr = 441;
+  static const int CXCursor_PreprocessingDirective = 500;
+  static const int CXCursor_MacroDefinition = 501;
+  static const int CXCursor_MacroExpansion = 502;
+  static const int CXCursor_MacroInstantiation = 502;
+  static const int CXCursor_InclusionDirective = 503;
+  static const int CXCursor_FirstPreprocessing = 500;
+  static const int CXCursor_LastPreprocessing = 503;
+  static const int CXCursor_ModuleImportDecl = 600;
+  static const int CXCursor_TypeAliasTemplateDecl = 601;
+  static const int CXCursor_StaticAssert = 602;
+  static const int CXCursor_FriendDecl = 603;
+  static const int CXCursor_FirstExtraDecl = 600;
+  static const int CXCursor_LastExtraDecl = 603;
+  static const int CXCursor_OverloadCandidate = 700;
+}
+
+/// Options to control the display of diagnostics.
+class CXDiagnosticDisplayOptions {
+  static const int CXDiagnostic_DisplaySourceLocation = 1;
+  static const int CXDiagnostic_DisplayColumn = 2;
+  static const int CXDiagnostic_DisplaySourceRanges = 4;
+  static const int CXDiagnostic_DisplayOption = 8;
+  static const int CXDiagnostic_DisplayCategoryId = 16;
+  static const int CXDiagnostic_DisplayCategoryName = 32;
+}
+
+/// Identifies a specific source location within a translation unit.
+class CXSourceLocation extends ffi.Struct {
+  ffi.Pointer<ffi.Void> _ptr_data_item_0;
+  ffi.Pointer<ffi.Void> _ptr_data_item_1;
+  ffi.Pointer<ffi.Void> _ptr_data_item_2;
+
+  /// helper for array, supports `[]` operator
+  _ArrayHelper_CXSourceLocation_ptr_data get ptr_data =>
+      _ArrayHelper_CXSourceLocation_ptr_data(this, 3);
+  @ffi.Uint32()
+  int int_data;
+}
+
+/// Helper for array ptr_data in struct CXSourceLocation
+class _ArrayHelper_CXSourceLocation_ptr_data {
+  final CXSourceLocation _struct;
+  final int length;
+  _ArrayHelper_CXSourceLocation_ptr_data(this._struct, this.length);
+  void operator []=(int index, ffi.Pointer<ffi.Void> value) {
+    switch (index) {
+      case 0:
+        _struct._ptr_data_item_0 = value;
+        break;
+      case 1:
+        _struct._ptr_data_item_1 = value;
+        break;
+      case 2:
+        _struct._ptr_data_item_2 = value;
+        break;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    switch (index) {
+      case 0:
+        return _struct._ptr_data_item_0;
+      case 1:
+        return _struct._ptr_data_item_1;
+      case 2:
+        return _struct._ptr_data_item_2;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  @override
+  String toString() {
+    if (length == 0) return '[]';
+    final sb = StringBuffer('[');
+    sb.write(this[0]);
+    for (var i = 1; i < length; i++) {
+      sb.write(',');
+      sb.write(this[i]);
+    }
+    sb.write(']');
+    return sb.toString();
+  }
+}
+
+/// A character string.
+class CXString extends ffi.Struct {
+  ffi.Pointer<ffi.Void> data;
+
+  @ffi.Uint32()
+  int private_flags;
+}
+
+class CXTranslationUnitImpl extends ffi.Struct {}
+
+/// Flags that control the creation of translation units.
+class CXTranslationUnit_Flags {
+  static const int CXTranslationUnit_None = 0;
+  static const int CXTranslationUnit_DetailedPreprocessingRecord = 1;
+  static const int CXTranslationUnit_Incomplete = 2;
+  static const int CXTranslationUnit_PrecompiledPreamble = 4;
+  static const int CXTranslationUnit_CacheCompletionResults = 8;
+  static const int CXTranslationUnit_ForSerialization = 16;
+  static const int CXTranslationUnit_CXXChainedPCH = 32;
+  static const int CXTranslationUnit_SkipFunctionBodies = 64;
+  static const int CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 128;
+  static const int CXTranslationUnit_CreatePreambleOnFirstParse = 256;
+  static const int CXTranslationUnit_KeepGoing = 512;
+  static const int CXTranslationUnit_SingleFileParse = 1024;
+  static const int CXTranslationUnit_LimitSkipFunctionBodiesToPreamble = 2048;
+  static const int CXTranslationUnit_IncludeAttributedTypes = 4096;
+  static const int CXTranslationUnit_VisitImplicitAttributes = 8192;
+  static const int CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles = 16384;
+  static const int CXTranslationUnit_RetainExcludedConditionalBlocks = 32768;
+}
+
+/// The type of an element in the abstract syntax tree.
+class CXType extends ffi.Struct {
+  @ffi.Int32()
+  int kind;
+
+  ffi.Pointer<ffi.Void> _data_item_0;
+  ffi.Pointer<ffi.Void> _data_item_1;
+  ffi.Pointer<ffi.Void> _data_item_2;
+
+  /// helper for array, supports `[]` operator
+  _ArrayHelper_CXType_data get data => _ArrayHelper_CXType_data(this, 3);
+}
+
+/// Helper for array data in struct CXType
+class _ArrayHelper_CXType_data {
+  final CXType _struct;
+  final int length;
+  _ArrayHelper_CXType_data(this._struct, this.length);
+  void operator []=(int index, ffi.Pointer<ffi.Void> value) {
+    switch (index) {
+      case 0:
+        _struct._data_item_0 = value;
+        break;
+      case 1:
+        _struct._data_item_1 = value;
+        break;
+      case 2:
+        _struct._data_item_2 = value;
+        break;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    switch (index) {
+      case 0:
+        return _struct._data_item_0;
+      case 1:
+        return _struct._data_item_1;
+      case 2:
+        return _struct._data_item_2;
+      default:
+        throw RangeError('Index $index must be in the range [0..2].');
+    }
+  }
+
+  @override
+  String toString() {
+    if (length == 0) return '[]';
+    final sb = StringBuffer('[');
+    sb.write(this[0]);
+    for (var i = 1; i < length; i++) {
+      sb.write(',');
+      sb.write(this[i]);
+    }
+    sb.write(']');
+    return sb.toString();
+  }
+}
+
+/// Describes the kind of type
+class CXTypeKind {
+  static const int CXType_Invalid = 0;
+  static const int CXType_Unexposed = 1;
+  static const int CXType_Void = 2;
+  static const int CXType_Bool = 3;
+  static const int CXType_Char_U = 4;
+  static const int CXType_UChar = 5;
+  static const int CXType_Char16 = 6;
+  static const int CXType_Char32 = 7;
+  static const int CXType_UShort = 8;
+  static const int CXType_UInt = 9;
+  static const int CXType_ULong = 10;
+  static const int CXType_ULongLong = 11;
+  static const int CXType_UInt128 = 12;
+  static const int CXType_Char_S = 13;
+  static const int CXType_SChar = 14;
+  static const int CXType_WChar = 15;
+  static const int CXType_Short = 16;
+  static const int CXType_Int = 17;
+  static const int CXType_Long = 18;
+  static const int CXType_LongLong = 19;
+  static const int CXType_Int128 = 20;
+  static const int CXType_Float = 21;
+  static const int CXType_Double = 22;
+  static const int CXType_LongDouble = 23;
+  static const int CXType_NullPtr = 24;
+  static const int CXType_Overload = 25;
+  static const int CXType_Dependent = 26;
+  static const int CXType_ObjCId = 27;
+  static const int CXType_ObjCClass = 28;
+  static const int CXType_ObjCSel = 29;
+  static const int CXType_Float128 = 30;
+  static const int CXType_Half = 31;
+  static const int CXType_Float16 = 32;
+  static const int CXType_ShortAccum = 33;
+  static const int CXType_Accum = 34;
+  static const int CXType_LongAccum = 35;
+  static const int CXType_UShortAccum = 36;
+  static const int CXType_UAccum = 37;
+  static const int CXType_ULongAccum = 38;
+  static const int CXType_FirstBuiltin = 2;
+  static const int CXType_LastBuiltin = 38;
+  static const int CXType_Complex = 100;
+  static const int CXType_Pointer = 101;
+  static const int CXType_BlockPointer = 102;
+  static const int CXType_LValueReference = 103;
+  static const int CXType_RValueReference = 104;
+  static const int CXType_Record = 105;
+  static const int CXType_Enum = 106;
+  static const int CXType_Typedef = 107;
+  static const int CXType_ObjCInterface = 108;
+  static const int CXType_ObjCObjectPointer = 109;
+  static const int CXType_FunctionNoProto = 110;
+  static const int CXType_FunctionProto = 111;
+  static const int CXType_ConstantArray = 112;
+  static const int CXType_Vector = 113;
+  static const int CXType_IncompleteArray = 114;
+  static const int CXType_VariableArray = 115;
+  static const int CXType_DependentSizedArray = 116;
+  static const int CXType_MemberPointer = 117;
+  static const int CXType_Auto = 118;
+  static const int CXType_Elaborated = 119;
+  static const int CXType_Pipe = 120;
+  static const int CXType_OCLImage1dRO = 121;
+  static const int CXType_OCLImage1dArrayRO = 122;
+  static const int CXType_OCLImage1dBufferRO = 123;
+  static const int CXType_OCLImage2dRO = 124;
+  static const int CXType_OCLImage2dArrayRO = 125;
+  static const int CXType_OCLImage2dDepthRO = 126;
+  static const int CXType_OCLImage2dArrayDepthRO = 127;
+  static const int CXType_OCLImage2dMSAARO = 128;
+  static const int CXType_OCLImage2dArrayMSAARO = 129;
+  static const int CXType_OCLImage2dMSAADepthRO = 130;
+  static const int CXType_OCLImage2dArrayMSAADepthRO = 131;
+  static const int CXType_OCLImage3dRO = 132;
+  static const int CXType_OCLImage1dWO = 133;
+  static const int CXType_OCLImage1dArrayWO = 134;
+  static const int CXType_OCLImage1dBufferWO = 135;
+  static const int CXType_OCLImage2dWO = 136;
+  static const int CXType_OCLImage2dArrayWO = 137;
+  static const int CXType_OCLImage2dDepthWO = 138;
+  static const int CXType_OCLImage2dArrayDepthWO = 139;
+  static const int CXType_OCLImage2dMSAAWO = 140;
+  static const int CXType_OCLImage2dArrayMSAAWO = 141;
+  static const int CXType_OCLImage2dMSAADepthWO = 142;
+  static const int CXType_OCLImage2dArrayMSAADepthWO = 143;
+  static const int CXType_OCLImage3dWO = 144;
+  static const int CXType_OCLImage1dRW = 145;
+  static const int CXType_OCLImage1dArrayRW = 146;
+  static const int CXType_OCLImage1dBufferRW = 147;
+  static const int CXType_OCLImage2dRW = 148;
+  static const int CXType_OCLImage2dArrayRW = 149;
+  static const int CXType_OCLImage2dDepthRW = 150;
+  static const int CXType_OCLImage2dArrayDepthRW = 151;
+  static const int CXType_OCLImage2dMSAARW = 152;
+  static const int CXType_OCLImage2dArrayMSAARW = 153;
+  static const int CXType_OCLImage2dMSAADepthRW = 154;
+  static const int CXType_OCLImage2dArrayMSAADepthRW = 155;
+  static const int CXType_OCLImage3dRW = 156;
+  static const int CXType_OCLSampler = 157;
+  static const int CXType_OCLEvent = 158;
+  static const int CXType_OCLQueue = 159;
+  static const int CXType_OCLReserveID = 160;
+  static const int CXType_ObjCObject = 161;
+  static const int CXType_ObjCTypeParam = 162;
+  static const int CXType_Attributed = 163;
+  static const int CXType_OCLIntelSubgroupAVCMcePayload = 164;
+  static const int CXType_OCLIntelSubgroupAVCImePayload = 165;
+  static const int CXType_OCLIntelSubgroupAVCRefPayload = 166;
+  static const int CXType_OCLIntelSubgroupAVCSicPayload = 167;
+  static const int CXType_OCLIntelSubgroupAVCMceResult = 168;
+  static const int CXType_OCLIntelSubgroupAVCImeResult = 169;
+  static const int CXType_OCLIntelSubgroupAVCRefResult = 170;
+  static const int CXType_OCLIntelSubgroupAVCSicResult = 171;
+  static const int CXType_OCLIntelSubgroupAVCImeResultSingleRefStreamout = 172;
+  static const int CXType_OCLIntelSubgroupAVCImeResultDualRefStreamout = 173;
+  static const int CXType_OCLIntelSubgroupAVCImeSingleRefStreamin = 174;
+  static const int CXType_OCLIntelSubgroupAVCImeDualRefStreamin = 175;
+  static const int CXType_ExtVector = 176;
+}
+
+/// Provides the contents of a file that has not yet been saved to disk.
+class CXUnsavedFile extends ffi.Struct {
+  ffi.Pointer<ffi.Int8> Filename;
+
+  ffi.Pointer<ffi.Int8> Contents;
+
+  @ffi.Uint64()
+  int Length;
+}
+
+typedef ModifiedCXCursorVisitor = ffi.Int32 Function(
+  ffi.Pointer<CXCursor>,
+  ffi.Pointer<CXCursor>,
+  ffi.Pointer<ffi.Void>,
+);
+
+ffi.Pointer<CXCursor> clang_Cursor_getArgument_wrap(
+  ffi.Pointer<CXCursor> cursor,
+  int i,
+) {
+  return _clang_Cursor_getArgument_wrap(
+    cursor,
+    i,
+  );
+}
+
+final _dart_clang_Cursor_getArgument_wrap _clang_Cursor_getArgument_wrap =
+    _dylib.lookupFunction<_c_clang_Cursor_getArgument_wrap,
+        _dart_clang_Cursor_getArgument_wrap>('clang_Cursor_getArgument_wrap');
+
+typedef _c_clang_Cursor_getArgument_wrap = ffi.Pointer<CXCursor> Function(
+  ffi.Pointer<CXCursor> cursor,
+  ffi.Uint32 i,
+);
+
+typedef _dart_clang_Cursor_getArgument_wrap = ffi.Pointer<CXCursor> Function(
+  ffi.Pointer<CXCursor> cursor,
+  int i,
+);
+
+/// Returns the first paragraph of doxygen doc comment.
+ffi.Pointer<CXString> clang_Cursor_getBriefCommentText_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_Cursor_getBriefCommentText_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_Cursor_getBriefCommentText_wrap
+    _clang_Cursor_getBriefCommentText_wrap = _dylib.lookupFunction<
+            _c_clang_Cursor_getBriefCommentText_wrap,
+            _dart_clang_Cursor_getBriefCommentText_wrap>(
+        'clang_Cursor_getBriefCommentText_wrap');
+
+typedef _c_clang_Cursor_getBriefCommentText_wrap = ffi.Pointer<CXString>
+    Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_Cursor_getBriefCommentText_wrap = ffi.Pointer<CXString>
+    Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+int clang_Cursor_getNumArguments_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_Cursor_getNumArguments_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_Cursor_getNumArguments_wrap
+    _clang_Cursor_getNumArguments_wrap = _dylib.lookupFunction<
+            _c_clang_Cursor_getNumArguments_wrap,
+            _dart_clang_Cursor_getNumArguments_wrap>(
+        'clang_Cursor_getNumArguments_wrap');
+
+typedef _c_clang_Cursor_getNumArguments_wrap = ffi.Int32 Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_Cursor_getNumArguments_wrap = int Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+ffi.Pointer<CXType> clang_Type_getNamedType_wrap(
+  ffi.Pointer<CXType> elaboratedType,
+) {
+  return _clang_Type_getNamedType_wrap(
+    elaboratedType,
+  );
+}
+
+final _dart_clang_Type_getNamedType_wrap _clang_Type_getNamedType_wrap =
+    _dylib.lookupFunction<_c_clang_Type_getNamedType_wrap,
+        _dart_clang_Type_getNamedType_wrap>('clang_Type_getNamedType_wrap');
+
+typedef _c_clang_Type_getNamedType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> elaboratedType,
+);
+
+typedef _dart_clang_Type_getNamedType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> elaboratedType,
+);
+
+/// Provides a shared context for creating translation units.
+ffi.Pointer<ffi.Void> clang_createIndex(
+  int excludeDeclarationsFromPCH,
+  int displayDiagnostics,
+) {
+  return _clang_createIndex(
+    excludeDeclarationsFromPCH,
+    displayDiagnostics,
+  );
+}
+
+final _dart_clang_createIndex _clang_createIndex =
+    _dylib.lookupFunction<_c_clang_createIndex, _dart_clang_createIndex>(
+        'clang_createIndex');
+
+typedef _c_clang_createIndex = ffi.Pointer<ffi.Void> Function(
+  ffi.Int32 excludeDeclarationsFromPCH,
+  ffi.Int32 displayDiagnostics,
+);
+
+typedef _dart_clang_createIndex = ffi.Pointer<ffi.Void> Function(
+  int excludeDeclarationsFromPCH,
+  int displayDiagnostics,
+);
+
+/// Destroy a diagnostic.
+void clang_disposeDiagnostic(
+  ffi.Pointer<ffi.Void> Diagnostic,
+) {
+  return _clang_disposeDiagnostic(
+    Diagnostic,
+  );
+}
+
+final _dart_clang_disposeDiagnostic _clang_disposeDiagnostic = _dylib
+    .lookupFunction<_c_clang_disposeDiagnostic, _dart_clang_disposeDiagnostic>(
+        'clang_disposeDiagnostic');
+
+typedef _c_clang_disposeDiagnostic = ffi.Void Function(
+  ffi.Pointer<ffi.Void> Diagnostic,
+);
+
+typedef _dart_clang_disposeDiagnostic = void Function(
+  ffi.Pointer<ffi.Void> Diagnostic,
+);
+
+/// Destroy the given index.
+void clang_disposeIndex(
+  ffi.Pointer<ffi.Void> index,
+) {
+  return _clang_disposeIndex(
+    index,
+  );
+}
+
+final _dart_clang_disposeIndex _clang_disposeIndex =
+    _dylib.lookupFunction<_c_clang_disposeIndex, _dart_clang_disposeIndex>(
+        'clang_disposeIndex');
+
+typedef _c_clang_disposeIndex = ffi.Void Function(
+  ffi.Pointer<ffi.Void> index,
+);
+
+typedef _dart_clang_disposeIndex = void Function(
+  ffi.Pointer<ffi.Void> index,
+);
+
+void clang_disposeString_wrap(
+  ffi.Pointer<CXString> string,
+) {
+  return _clang_disposeString_wrap(
+    string,
+  );
+}
+
+final _dart_clang_disposeString_wrap _clang_disposeString_wrap =
+    _dylib.lookupFunction<_c_clang_disposeString_wrap,
+        _dart_clang_disposeString_wrap>('clang_disposeString_wrap');
+
+typedef _c_clang_disposeString_wrap = ffi.Void Function(
+  ffi.Pointer<CXString> string,
+);
+
+typedef _dart_clang_disposeString_wrap = void Function(
+  ffi.Pointer<CXString> string,
+);
+
+/// Destroy the specified CXTranslationUnit object.
+void clang_disposeTranslationUnit(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+) {
+  return _clang_disposeTranslationUnit(
+    arg0,
+  );
+}
+
+final _dart_clang_disposeTranslationUnit _clang_disposeTranslationUnit =
+    _dylib.lookupFunction<_c_clang_disposeTranslationUnit,
+        _dart_clang_disposeTranslationUnit>('clang_disposeTranslationUnit');
+
+typedef _c_clang_disposeTranslationUnit = ffi.Void Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+);
+
+typedef _dart_clang_disposeTranslationUnit = void Function(
+  ffi.Pointer<CXTranslationUnitImpl> arg0,
+);
+
+ffi.Pointer<CXString> clang_formatDiagnostic_wrap(
+  ffi.Pointer<ffi.Void> diag,
+  int opts,
+) {
+  return _clang_formatDiagnostic_wrap(
+    diag,
+    opts,
+  );
+}
+
+final _dart_clang_formatDiagnostic_wrap _clang_formatDiagnostic_wrap =
+    _dylib.lookupFunction<_c_clang_formatDiagnostic_wrap,
+        _dart_clang_formatDiagnostic_wrap>('clang_formatDiagnostic_wrap');
+
+typedef _c_clang_formatDiagnostic_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<ffi.Void> diag,
+  ffi.Int32 opts,
+);
+
+typedef _dart_clang_formatDiagnostic_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<ffi.Void> diag,
+  int opts,
+);
+
+ffi.Pointer<CXType> clang_getArgType_wrap(
+  ffi.Pointer<CXType> cxtype,
+  int i,
+) {
+  return _clang_getArgType_wrap(
+    cxtype,
+    i,
+  );
+}
+
+final _dart_clang_getArgType_wrap _clang_getArgType_wrap = _dylib
+    .lookupFunction<_c_clang_getArgType_wrap, _dart_clang_getArgType_wrap>(
+        'clang_getArgType_wrap');
+
+typedef _c_clang_getArgType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> cxtype,
+  ffi.Uint32 i,
+);
+
+typedef _dart_clang_getArgType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> cxtype,
+  int i,
+);
+
+ffi.Pointer<CXType> clang_getArrayElementType_wrap(
+  ffi.Pointer<CXType> cxtype,
+) {
+  return _clang_getArrayElementType_wrap(
+    cxtype,
+  );
+}
+
+final _dart_clang_getArrayElementType_wrap _clang_getArrayElementType_wrap =
+    _dylib.lookupFunction<_c_clang_getArrayElementType_wrap,
+        _dart_clang_getArrayElementType_wrap>('clang_getArrayElementType_wrap');
+
+typedef _c_clang_getArrayElementType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+typedef _dart_clang_getArrayElementType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+ffi.Pointer<ffi.Int8> clang_getCString_wrap(
+  ffi.Pointer<CXString> string,
+) {
+  return _clang_getCString_wrap(
+    string,
+  );
+}
+
+final _dart_clang_getCString_wrap _clang_getCString_wrap = _dylib
+    .lookupFunction<_c_clang_getCString_wrap, _dart_clang_getCString_wrap>(
+        'clang_getCString_wrap');
+
+typedef _c_clang_getCString_wrap = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<CXString> string,
+);
+
+typedef _dart_clang_getCString_wrap = ffi.Pointer<ffi.Int8> Function(
+  ffi.Pointer<CXString> string,
+);
+
+ffi.Pointer<CXType> clang_getCanonicalType_wrap(
+  ffi.Pointer<CXType> typerefType,
+) {
+  return _clang_getCanonicalType_wrap(
+    typerefType,
+  );
+}
+
+final _dart_clang_getCanonicalType_wrap _clang_getCanonicalType_wrap =
+    _dylib.lookupFunction<_c_clang_getCanonicalType_wrap,
+        _dart_clang_getCanonicalType_wrap>('clang_getCanonicalType_wrap');
+
+typedef _c_clang_getCanonicalType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> typerefType,
+);
+
+typedef _dart_clang_getCanonicalType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> typerefType,
+);
+
+ffi.Pointer<CXString> clang_getCursorKindSpelling_wrap(
+  int kind,
+) {
+  return _clang_getCursorKindSpelling_wrap(
+    kind,
+  );
+}
+
+final _dart_clang_getCursorKindSpelling_wrap _clang_getCursorKindSpelling_wrap =
+    _dylib.lookupFunction<_c_clang_getCursorKindSpelling_wrap,
+            _dart_clang_getCursorKindSpelling_wrap>(
+        'clang_getCursorKindSpelling_wrap');
+
+typedef _c_clang_getCursorKindSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Int32 kind,
+);
+
+typedef _dart_clang_getCursorKindSpelling_wrap = ffi.Pointer<CXString> Function(
+  int kind,
+);
+
+int clang_getCursorKind_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_getCursorKind_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_getCursorKind_wrap _clang_getCursorKind_wrap =
+    _dylib.lookupFunction<_c_clang_getCursorKind_wrap,
+        _dart_clang_getCursorKind_wrap>('clang_getCursorKind_wrap');
+
+typedef _c_clang_getCursorKind_wrap = ffi.Int32 Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_getCursorKind_wrap = int Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+ffi.Pointer<CXSourceLocation> clang_getCursorLocation_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_getCursorLocation_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_getCursorLocation_wrap _clang_getCursorLocation_wrap =
+    _dylib.lookupFunction<_c_clang_getCursorLocation_wrap,
+        _dart_clang_getCursorLocation_wrap>('clang_getCursorLocation_wrap');
+
+typedef _c_clang_getCursorLocation_wrap = ffi.Pointer<CXSourceLocation>
+    Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_getCursorLocation_wrap = ffi.Pointer<CXSourceLocation>
+    Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+/// The name of parameter, struct, typedef.
+ffi.Pointer<CXString> clang_getCursorSpelling_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_getCursorSpelling_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_getCursorSpelling_wrap _clang_getCursorSpelling_wrap =
+    _dylib.lookupFunction<_c_clang_getCursorSpelling_wrap,
+        _dart_clang_getCursorSpelling_wrap>('clang_getCursorSpelling_wrap');
+
+typedef _c_clang_getCursorSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_getCursorSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+ffi.Pointer<CXType> clang_getCursorType_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_getCursorType_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_getCursorType_wrap _clang_getCursorType_wrap =
+    _dylib.lookupFunction<_c_clang_getCursorType_wrap,
+        _dart_clang_getCursorType_wrap>('clang_getCursorType_wrap');
+
+typedef _c_clang_getCursorType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_getCursorType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+/// Retrieve a diagnostic associated with the given translation unit.
+ffi.Pointer<ffi.Void> clang_getDiagnostic(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+  int Index,
+) {
+  return _clang_getDiagnostic(
+    Unit,
+    Index,
+  );
+}
+
+final _dart_clang_getDiagnostic _clang_getDiagnostic =
+    _dylib.lookupFunction<_c_clang_getDiagnostic, _dart_clang_getDiagnostic>(
+        'clang_getDiagnostic');
+
+typedef _c_clang_getDiagnostic = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+  ffi.Uint32 Index,
+);
+
+typedef _dart_clang_getDiagnostic = ffi.Pointer<ffi.Void> Function(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+  int Index,
+);
+
+int clang_getEnumConstantDeclValue_wrap(
+  ffi.Pointer<CXCursor> cursor,
+) {
+  return _clang_getEnumConstantDeclValue_wrap(
+    cursor,
+  );
+}
+
+final _dart_clang_getEnumConstantDeclValue_wrap
+    _clang_getEnumConstantDeclValue_wrap = _dylib.lookupFunction<
+            _c_clang_getEnumConstantDeclValue_wrap,
+            _dart_clang_getEnumConstantDeclValue_wrap>(
+        'clang_getEnumConstantDeclValue_wrap');
+
+typedef _c_clang_getEnumConstantDeclValue_wrap = ffi.Int64 Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_getEnumConstantDeclValue_wrap = int Function(
+  ffi.Pointer<CXCursor> cursor,
+);
+
+void clang_getFileLocation_wrap(
+  ffi.Pointer<CXSourceLocation> location,
+  ffi.Pointer<ffi.Pointer<ffi.Void>> file,
+  ffi.Pointer<ffi.Uint32> line,
+  ffi.Pointer<ffi.Uint32> column,
+  ffi.Pointer<ffi.Uint32> offset,
+) {
+  return _clang_getFileLocation_wrap(
+    location,
+    file,
+    line,
+    column,
+    offset,
+  );
+}
+
+final _dart_clang_getFileLocation_wrap _clang_getFileLocation_wrap =
+    _dylib.lookupFunction<_c_clang_getFileLocation_wrap,
+        _dart_clang_getFileLocation_wrap>('clang_getFileLocation_wrap');
+
+typedef _c_clang_getFileLocation_wrap = ffi.Void Function(
+  ffi.Pointer<CXSourceLocation> location,
+  ffi.Pointer<ffi.Pointer<ffi.Void>> file,
+  ffi.Pointer<ffi.Uint32> line,
+  ffi.Pointer<ffi.Uint32> column,
+  ffi.Pointer<ffi.Uint32> offset,
+);
+
+typedef _dart_clang_getFileLocation_wrap = void Function(
+  ffi.Pointer<CXSourceLocation> location,
+  ffi.Pointer<ffi.Pointer<ffi.Void>> file,
+  ffi.Pointer<ffi.Uint32> line,
+  ffi.Pointer<ffi.Uint32> column,
+  ffi.Pointer<ffi.Uint32> offset,
+);
+
+ffi.Pointer<CXString> clang_getFileName_wrap(
+  ffi.Pointer<ffi.Void> SFile,
+) {
+  return _clang_getFileName_wrap(
+    SFile,
+  );
+}
+
+final _dart_clang_getFileName_wrap _clang_getFileName_wrap = _dylib
+    .lookupFunction<_c_clang_getFileName_wrap, _dart_clang_getFileName_wrap>(
+        'clang_getFileName_wrap');
+
+typedef _c_clang_getFileName_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<ffi.Void> SFile,
+);
+
+typedef _dart_clang_getFileName_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<ffi.Void> SFile,
+);
+
+int clang_getNumArgTypes_wrap(
+  ffi.Pointer<CXType> cxtype,
+) {
+  return _clang_getNumArgTypes_wrap(
+    cxtype,
+  );
+}
+
+final _dart_clang_getNumArgTypes_wrap _clang_getNumArgTypes_wrap =
+    _dylib.lookupFunction<_c_clang_getNumArgTypes_wrap,
+        _dart_clang_getNumArgTypes_wrap>('clang_getNumArgTypes_wrap');
+
+typedef _c_clang_getNumArgTypes_wrap = ffi.Int32 Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+typedef _dart_clang_getNumArgTypes_wrap = int Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+/// Determine the number of diagnostics produced for the given translation unit.
+int clang_getNumDiagnostics(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+) {
+  return _clang_getNumDiagnostics(
+    Unit,
+  );
+}
+
+final _dart_clang_getNumDiagnostics _clang_getNumDiagnostics = _dylib
+    .lookupFunction<_c_clang_getNumDiagnostics, _dart_clang_getNumDiagnostics>(
+        'clang_getNumDiagnostics');
+
+typedef _c_clang_getNumDiagnostics = ffi.Uint32 Function(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+);
+
+typedef _dart_clang_getNumDiagnostics = int Function(
+  ffi.Pointer<CXTranslationUnitImpl> Unit,
+);
+
+int clang_getNumElements_wrap(
+  ffi.Pointer<CXType> cxtype,
+) {
+  return _clang_getNumElements_wrap(
+    cxtype,
+  );
+}
+
+final _dart_clang_getNumElements_wrap _clang_getNumElements_wrap =
+    _dylib.lookupFunction<_c_clang_getNumElements_wrap,
+        _dart_clang_getNumElements_wrap>('clang_getNumElements_wrap');
+
+typedef _c_clang_getNumElements_wrap = ffi.Uint64 Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+typedef _dart_clang_getNumElements_wrap = int Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+ffi.Pointer<CXType> clang_getPointeeType_wrap(
+  ffi.Pointer<CXType> pointerType,
+) {
+  return _clang_getPointeeType_wrap(
+    pointerType,
+  );
+}
+
+final _dart_clang_getPointeeType_wrap _clang_getPointeeType_wrap =
+    _dylib.lookupFunction<_c_clang_getPointeeType_wrap,
+        _dart_clang_getPointeeType_wrap>('clang_getPointeeType_wrap');
+
+typedef _c_clang_getPointeeType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> pointerType,
+);
+
+typedef _dart_clang_getPointeeType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> pointerType,
+);
+
+ffi.Pointer<CXType> clang_getResultType_wrap(
+  ffi.Pointer<CXType> functionType,
+) {
+  return _clang_getResultType_wrap(
+    functionType,
+  );
+}
+
+final _dart_clang_getResultType_wrap _clang_getResultType_wrap =
+    _dylib.lookupFunction<_c_clang_getResultType_wrap,
+        _dart_clang_getResultType_wrap>('clang_getResultType_wrap');
+
+typedef _c_clang_getResultType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> functionType,
+);
+
+typedef _dart_clang_getResultType_wrap = ffi.Pointer<CXType> Function(
+  ffi.Pointer<CXType> functionType,
+);
+
+ffi.Pointer<CXCursor> clang_getTranslationUnitCursor_wrap(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+) {
+  return _clang_getTranslationUnitCursor_wrap(
+    tu,
+  );
+}
+
+final _dart_clang_getTranslationUnitCursor_wrap
+    _clang_getTranslationUnitCursor_wrap = _dylib.lookupFunction<
+            _c_clang_getTranslationUnitCursor_wrap,
+            _dart_clang_getTranslationUnitCursor_wrap>(
+        'clang_getTranslationUnitCursor_wrap');
+
+typedef _c_clang_getTranslationUnitCursor_wrap = ffi.Pointer<CXCursor> Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+);
+
+typedef _dart_clang_getTranslationUnitCursor_wrap = ffi.Pointer<CXCursor>
+    Function(
+  ffi.Pointer<CXTranslationUnitImpl> tu,
+);
+
+ffi.Pointer<CXCursor> clang_getTypeDeclaration_wrap(
+  ffi.Pointer<CXType> cxtype,
+) {
+  return _clang_getTypeDeclaration_wrap(
+    cxtype,
+  );
+}
+
+final _dart_clang_getTypeDeclaration_wrap _clang_getTypeDeclaration_wrap =
+    _dylib.lookupFunction<_c_clang_getTypeDeclaration_wrap,
+        _dart_clang_getTypeDeclaration_wrap>('clang_getTypeDeclaration_wrap');
+
+typedef _c_clang_getTypeDeclaration_wrap = ffi.Pointer<CXCursor> Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+typedef _dart_clang_getTypeDeclaration_wrap = ffi.Pointer<CXCursor> Function(
+  ffi.Pointer<CXType> cxtype,
+);
+
+ffi.Pointer<CXString> clang_getTypeKindSpelling_wrap(
+  int typeKind,
+) {
+  return _clang_getTypeKindSpelling_wrap(
+    typeKind,
+  );
+}
+
+final _dart_clang_getTypeKindSpelling_wrap _clang_getTypeKindSpelling_wrap =
+    _dylib.lookupFunction<_c_clang_getTypeKindSpelling_wrap,
+        _dart_clang_getTypeKindSpelling_wrap>('clang_getTypeKindSpelling_wrap');
+
+typedef _c_clang_getTypeKindSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Int32 typeKind,
+);
+
+typedef _dart_clang_getTypeKindSpelling_wrap = ffi.Pointer<CXString> Function(
+  int typeKind,
+);
+
+ffi.Pointer<CXString> clang_getTypeSpelling_wrap(
+  ffi.Pointer<CXType> type,
+) {
+  return _clang_getTypeSpelling_wrap(
+    type,
+  );
+}
+
+final _dart_clang_getTypeSpelling_wrap _clang_getTypeSpelling_wrap =
+    _dylib.lookupFunction<_c_clang_getTypeSpelling_wrap,
+        _dart_clang_getTypeSpelling_wrap>('clang_getTypeSpelling_wrap');
+
+typedef _c_clang_getTypeSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<CXType> type,
+);
+
+typedef _dart_clang_getTypeSpelling_wrap = ffi.Pointer<CXString> Function(
+  ffi.Pointer<CXType> type,
+);
+
+ffi.Pointer<CXType> clang_getTypedefDeclUnderlyingType_wrap(
+  ffi.Pointer<CXCursor> cxcursor,
+) {
+  return _clang_getTypedefDeclUnderlyingType_wrap(
+    cxcursor,
+  );
+}
+
+final _dart_clang_getTypedefDeclUnderlyingType_wrap
+    _clang_getTypedefDeclUnderlyingType_wrap = _dylib.lookupFunction<
+            _c_clang_getTypedefDeclUnderlyingType_wrap,
+            _dart_clang_getTypedefDeclUnderlyingType_wrap>(
+        'clang_getTypedefDeclUnderlyingType_wrap');
+
+typedef _c_clang_getTypedefDeclUnderlyingType_wrap = ffi.Pointer<CXType>
+    Function(
+  ffi.Pointer<CXCursor> cxcursor,
+);
+
+typedef _dart_clang_getTypedefDeclUnderlyingType_wrap = ffi.Pointer<CXType>
+    Function(
+  ffi.Pointer<CXCursor> cxcursor,
+);
+
+/// Same as clang_parseTranslationUnit2, but returns the CXTranslationUnit instead of an error code. In case of an error this routine returns a NULL CXTranslationUnit, without further detailed error codes.
+ffi.Pointer<CXTranslationUnitImpl> clang_parseTranslationUnit(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  int options,
+) {
+  return _clang_parseTranslationUnit(
+    CIdx,
+    source_filename,
+    command_line_args,
+    num_command_line_args,
+    unsaved_files,
+    num_unsaved_files,
+    options,
+  );
+}
+
+final _dart_clang_parseTranslationUnit _clang_parseTranslationUnit =
+    _dylib.lookupFunction<_c_clang_parseTranslationUnit,
+        _dart_clang_parseTranslationUnit>('clang_parseTranslationUnit');
+
+typedef _c_clang_parseTranslationUnit = ffi.Pointer<CXTranslationUnitImpl>
+    Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  ffi.Int32 num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  ffi.Uint32 num_unsaved_files,
+  ffi.Uint32 options,
+);
+
+typedef _dart_clang_parseTranslationUnit = ffi.Pointer<CXTranslationUnitImpl>
+    Function(
+  ffi.Pointer<ffi.Void> CIdx,
+  ffi.Pointer<ffi.Int8> source_filename,
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> command_line_args,
+  int num_command_line_args,
+  ffi.Pointer<CXUnsavedFile> unsaved_files,
+  int num_unsaved_files,
+  int options,
+);
+
+/// Visitor is a function pointer with parameters having pointers to cxcursor instead of cxcursor by default.
+int clang_visitChildren_wrap(
+  ffi.Pointer<CXCursor> parent,
+  ffi.Pointer<ffi.NativeFunction<ModifiedCXCursorVisitor>> _modifiedVisitor,
+  ffi.Pointer<ffi.Void> clientData,
+) {
+  return _clang_visitChildren_wrap(
+    parent,
+    _modifiedVisitor,
+    clientData,
+  );
+}
+
+final _dart_clang_visitChildren_wrap _clang_visitChildren_wrap =
+    _dylib.lookupFunction<_c_clang_visitChildren_wrap,
+        _dart_clang_visitChildren_wrap>('clang_visitChildren_wrap');
+
+typedef _c_clang_visitChildren_wrap = ffi.Uint32 Function(
+  ffi.Pointer<CXCursor> parent,
+  ffi.Pointer<ffi.NativeFunction<ModifiedCXCursorVisitor>> _modifiedVisitor,
+  ffi.Pointer<ffi.Void> clientData,
+);
+
+typedef _dart_clang_visitChildren_wrap = int Function(
+  ffi.Pointer<CXCursor> parent,
+  ffi.Pointer<ffi.NativeFunction<ModifiedCXCursorVisitor>> _modifiedVisitor,
+  ffi.Pointer<ffi.Void> clientData,
+);
diff --git a/lib/src/header_parser/data.dart b/lib/src/header_parser/data.dart
new file mode 100644
index 0000000..900c0ff
--- /dev/null
+++ b/lib/src/header_parser/data.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:ffigen/src/config_provider.dart';
+/// Holds all Global shared variables.
+
+/// Holds configurations.
+Config config;
diff --git a/lib/src/header_parser/includer.dart b/lib/src/header_parser/includer.dart
new file mode 100644
index 0000000..23698a5
--- /dev/null
+++ b/lib/src/header_parser/includer.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+import 'package:path/path.dart' as p;
+import 'data.dart';
+
+/// Utility functions to check whether a binding should be parsed or not
+/// based on filters and if a binding is seen already.
+
+// Stores binding names already scene.
+Set<String> _structs = {};
+Set<String> _functions = {};
+Set<String> _enumClass = {};
+Set<String> _typedefC = {};
+
+bool shouldIncludeStruct(String name) {
+  if (_structs.contains(name) || name == '') {
+    return false;
+  } else if (config.structFilters == null ||
+      config.structFilters.shouldInclude(name)) {
+    _structs.add(name);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool shouldIncludeFunc(String name) {
+  if (_functions.contains(name) || name == '') {
+    return false;
+  } else if (config.functionFilters == null ||
+      config.functionFilters.shouldInclude(name)) {
+    _functions.add(name);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool shouldIncludeEnumClass(String name) {
+  if (_enumClass.contains(name) || name == '') {
+    return false;
+  } else if (config.enumClassFilters == null ||
+      config.enumClassFilters.shouldInclude(name)) {
+    _enumClass.add(name);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/// True if a cursor should be included based on header-filter, use for root
+/// declarations.
+bool shouldIncludeRootCursor(String sourceFile) {
+  final name = p.basename(sourceFile);
+
+  if (config.headerFilter.excludedInclusionHeaders.contains(name)) {
+    return false;
+  }
+
+  if (config.headerFilter.includedInclusionHeaders.contains(name)) {
+    return true;
+  }
+
+  // If any includedInclusionHeaders is provided, return false.
+  if (config.headerFilter.includedInclusionHeaders.isNotEmpty) {
+    return false;
+  } else {
+    return true;
+  }
+}
+
+bool isUnseenTypedefC(String name, {@required bool addToSeen}) {
+  if (_typedefC.contains(name)) {
+    return false;
+  } else {
+    if (addToSeen) {
+      _typedefC.add(name);
+    }
+    return true;
+  }
+}
+
+bool isUnseenStruct(String name, {@required bool addToSeen}) {
+  if (_structs.contains(name)) {
+    return false;
+  } else {
+    if (addToSeen) {
+      _structs.add(name);
+    }
+    return true;
+  }
+}
diff --git a/lib/src/header_parser/parser.dart b/lib/src/header_parser/parser.dart
new file mode 100644
index 0000000..eac3c93
--- /dev/null
+++ b/lib/src/header_parser/parser.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'package:ffi/ffi.dart';
+import 'package:ffigen/src/code_generator.dart';
+import 'package:ffigen/src/config_provider.dart';
+import 'package:ffigen/src/header_parser/translation_unit_parser.dart';
+import 'package:logging/logging.dart';
+
+import 'clang_bindings/clang_bindings.dart' as clang;
+import 'data.dart' as data;
+import 'utils.dart';
+
+/// Main entrypoint for header_parser.
+Library parse(Config conf, {bool sort = false}) {
+  initParser(conf);
+
+  final bindings = parseToBindings();
+
+  final library = Library(bindings: bindings);
+
+  if (sort) {
+    library.sort();
+  }
+  return library;
+}
+
+// ===================================================================================
+//           BELOW FUNCTIONS ARE MEANT FOR INTERNAL USE AND TESTING
+// ===================================================================================
+
+var _logger = Logger('parser:parser');
+
+/// initialises parser, clears any previous values.
+void initParser(Config c) {
+  data.config = c;
+
+  clang.init(DynamicLibrary.open(data.config.libclang_dylib_path));
+}
+
+/// Parses source files and adds generated bindings to [bindings].
+List<Binding> parseToBindings() {
+  final index = clang.clang_createIndex(0, 0);
+
+  Pointer<Pointer<Utf8>> clangCmdArgs = nullptr;
+  var cmdLen = 0;
+  if (data.config.compilerOpts != null) {
+    clangCmdArgs = createDynamicStringArray(data.config.compilerOpts);
+    cmdLen = data.config.compilerOpts.length;
+  }
+
+  // Contains all bindings.
+  final bindings = <Binding>[];
+
+  // Log all headers for user.
+  _logger.info('Input Headers: ${data.config.headers}');
+
+  for (final headerLocation in data.config.headers) {
+    _logger.fine('Creating TranslationUnit for header: $headerLocation');
+
+    final tu = clang.clang_parseTranslationUnit(
+      index,
+      Utf8.toUtf8(headerLocation).cast(),
+      clangCmdArgs.cast(),
+      cmdLen,
+      nullptr,
+      0,
+      clang.CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies,
+    );
+
+    if (tu == nullptr) {
+      _logger.severe(
+          "Skipped header/file: $headerLocation, couldn't parse source.");
+      // Skip parsing this header.
+      continue;
+    }
+
+    logTuDiagnostics(tu, _logger, headerLocation);
+    final rootCursor = clang.clang_getTranslationUnitCursor_wrap(tu);
+
+    bindings.addAll(parseTranslationUnit(rootCursor));
+
+    // Cleanup.
+    rootCursor.dispose();
+    clang.clang_disposeTranslationUnit(tu);
+  }
+
+  if (data.config.compilerOpts != null) {
+    clangCmdArgs.dispose(data.config.compilerOpts.length);
+  }
+  clang.clang_disposeIndex(index);
+  return bindings;
+}
diff --git a/lib/src/header_parser/sub_parsers/enumdecl_parser.dart b/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
new file mode 100644
index 0000000..19fd1ce
--- /dev/null
+++ b/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:logging/logging.dart';
+
+import '../clang_bindings/clang_bindings.dart' as clang;
+import '../includer.dart';
+import '../utils.dart';
+
+var _logger = Logger('parser:enumdecl_parser');
+
+/// Temporarily holds a enumClass before its returned by [parseEnumDeclaration].
+EnumClass _enumClass;
+
+/// Parses a function declaration.
+EnumClass parseEnumDeclaration(
+  Pointer<clang.CXCursor> cursor, {
+
+  /// Optionally provide name to use (useful in case struct is inside a typedef).
+  String name,
+}) {
+  _enumClass = null;
+
+  final enumName = name ?? cursor.spelling();
+  if (enumName == '') {
+    _logger.finest('unnamed enum declaration');
+  } else if (shouldIncludeEnumClass(enumName)) {
+    _logger.fine('++++ Adding Enum: ${cursor.completeStringRepr()}');
+    _enumClass = EnumClass(
+      dartDoc: getCursorDocComment(cursor),
+      name: enumName,
+    );
+    _addEnumConstant(cursor);
+  }
+
+  return _enumClass;
+}
+
+void _addEnumConstant(Pointer<clang.CXCursor> cursor) {
+  final resultCode = clang.clang_visitChildren_wrap(
+    cursor,
+    Pointer.fromFunction(
+        _enumCursorVisitor, clang.CXChildVisitResult.CXChildVisit_Break),
+    nullptr,
+  );
+
+  visitChildrenResultChecker(resultCode);
+}
+
+/// Visitor for a enum cursor [clang.CXCursorKind.CXCursor_EnumDecl].
+///
+/// Invoked on every enum directly under rootCursor.
+/// Used for for extracting enum values.
+int _enumCursorVisitor(Pointer<clang.CXCursor> cursor,
+    Pointer<clang.CXCursor> parent, Pointer<Void> clientData) {
+  try {
+    _logger.finest('  enumCursorVisitor: ${cursor.completeStringRepr()}');
+    switch (clang.clang_getCursorKind_wrap(cursor)) {
+      case clang.CXCursorKind.CXCursor_EnumConstantDecl:
+        _addEnumConstantToEnumClass(cursor);
+        break;
+      default:
+        print('invalid enum constant');
+    }
+    cursor.dispose();
+    parent.dispose();
+  } catch (e, s) {
+    _logger.severe(e);
+    _logger.severe(s);
+    rethrow;
+  }
+  return clang.CXChildVisitResult.CXChildVisit_Continue;
+}
+
+/// Adds the parameter to func in [functiondecl_parser.dart].
+void _addEnumConstantToEnumClass(Pointer<clang.CXCursor> cursor) {
+  _enumClass.enumConstants.add(
+    EnumConstant(
+        // Extracting doc comment doesn't always give the right comment
+        // so we are skipping dartdoc for individual enum constants.
+        name: cursor.spelling(),
+        value: clang.clang_getEnumConstantDeclValue_wrap(cursor)),
+  );
+}
diff --git a/lib/src/header_parser/sub_parsers/functiondecl_parser.dart b/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
new file mode 100644
index 0000000..62803f6
--- /dev/null
+++ b/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:logging/logging.dart';
+
+import '../clang_bindings/clang_bindings.dart' as clang;
+import '../includer.dart';
+import '../utils.dart';
+
+var _logger = Logger('parser:functiondecl_parser');
+
+/// Temporarily holds a function before its returned by [parseFunctionDeclaration].
+Func _func;
+
+/// Parses a function declaration.
+Func parseFunctionDeclaration(Pointer<clang.CXCursor> cursor) {
+  _func = null;
+  structByValueParameter = false;
+  unimplementedParameterType = false;
+  constantArrayParameterType = false;
+
+  final name = cursor.spelling();
+  if (shouldIncludeFunc(name)) {
+    _logger.fine('++++ Adding Function: ${cursor.completeStringRepr()}');
+
+    final rt = _getFunctionReturnType(cursor);
+    final parameters = _getParameters(cursor);
+
+    //TODO(3): Remove this when support for Structs by value arrives.
+    if (rt.broadType == BroadType.Struct || structByValueParameter) {
+      _logger.fine(
+          '---- Removed Function, reason: struct pass/return by value: ${cursor.completeStringRepr()}');
+      _logger.warning(
+          "Skipped Function '$name', struct pass/return by value not supported.");
+      return null; // Returning null so that [addToBindings] function excludes this.
+    }
+
+    if (constantArrayParameterType) {
+      _logger.fine(
+          '---- Removed Function, reason: constant array passed to function parameter: ${cursor.completeStringRepr()}');
+      _logger.warning(
+          "Skipped Function '$name', constant array in function parameter not supported.");
+      return null; // Returning null so that [addToBindings] function excludes this.
+    }
+
+    if (rt.getBaseBroadType() == BroadType.Unimplemented ||
+        unimplementedParameterType) {
+      _logger.fine(
+          '---- Removed Function, reason: unsupported return type or parameter type: ${cursor.completeStringRepr()}');
+      _logger.warning(
+          "Skipped Function '$name', function has unsupported return type or parameter type.");
+      return null; // Returning null so that [addToBindings] function excludes this.
+    }
+
+    _func = Func(
+      dartDoc: getCursorDocComment(cursor),
+      name: name,
+      returnType: rt,
+      parameters: parameters,
+    );
+  }
+
+  return _func;
+}
+
+bool structByValueParameter = false;
+bool constantArrayParameterType = false;
+bool unimplementedParameterType = false;
+Type _getFunctionReturnType(Pointer<clang.CXCursor> cursor) {
+  return cursor.returnType().toCodeGenTypeAndDispose();
+}
+
+List<Parameter> _getParameters(Pointer<clang.CXCursor> cursor) {
+  final parameters = <Parameter>[];
+
+  final totalArgs = clang.clang_Cursor_getNumArguments_wrap(cursor);
+  for (var i = 0; i < totalArgs; i++) {
+    final paramCursor = clang.clang_Cursor_getArgument_wrap(cursor, i);
+
+    _logger.finer('===== parameter: ${paramCursor.completeStringRepr()}');
+
+    final pt = _getParameterType(paramCursor);
+    //TODO(3): Remove this when support for Structs by value arrives.
+    if (pt.broadType == BroadType.Struct) {
+      structByValueParameter = true;
+    } else if (pt.broadType == BroadType.ConstantArray) {
+      constantArrayParameterType = true;
+    } else if (pt.getBaseBroadType() == BroadType.Unimplemented) {
+      unimplementedParameterType = true;
+    }
+
+    final pn = paramCursor.spelling();
+
+    /// If [pn] is null or empty, its set to `arg$i` by code_generator.
+    parameters.add(
+      Parameter(
+        name: pn,
+        type: pt,
+      ),
+    );
+    paramCursor.dispose();
+  }
+
+  return parameters;
+}
+
+Type _getParameterType(Pointer<clang.CXCursor> cursor) {
+  return cursor.type().toCodeGenTypeAndDispose();
+}
diff --git a/lib/src/header_parser/sub_parsers/structdecl_parser.dart b/lib/src/header_parser/sub_parsers/structdecl_parser.dart
new file mode 100644
index 0000000..27d8efd
--- /dev/null
+++ b/lib/src/header_parser/sub_parsers/structdecl_parser.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:logging/logging.dart';
+
+import '../clang_bindings/clang_bindings.dart' as clang;
+import '../includer.dart';
+import '../utils.dart';
+
+var _logger = Logger('parser:structdecl_parser');
+
+/// Temporarily holds a struc before its returned by [parseStructDeclaration].
+Struc _struc;
+
+/// Parses a struct declaration.
+Struc parseStructDeclaration(
+  Pointer<clang.CXCursor> cursor, {
+
+  /// Optionally provide name (useful in case struct is inside a typedef).
+  String name,
+
+  /// Option to override shouldInclude methods. (Useful in case of extracting
+  /// structs when they are passed/returned by an included function.)
+  ///
+  /// Check if binding is not already included before setting this to true.
+  bool doInclude = false,
+}) {
+  _struc = null;
+  final structName = name ?? cursor.spelling();
+
+  if (structName == '') {
+    _logger.finest('unnamed structure or typedef structure declaration');
+    return null;
+  } else if (doInclude || shouldIncludeStruct(structName)) {
+    _logger.fine(
+        '++++ Adding Structure: structName: ${structName}, ${cursor.completeStringRepr()}');
+
+    final members = _getMembers(cursor, structName);
+    _struc = Struc(
+      dartDoc: getCursorDocComment(cursor),
+      name: structName,
+      members: members,
+    );
+  }
+
+  return _struc;
+}
+
+List<Member> _members;
+List<Member> _getMembers(Pointer<clang.CXCursor> cursor, String structName) {
+  _members = [];
+  nestedStructMember = false;
+  unimplementedMemberType = false;
+
+  final resultCode = clang.clang_visitChildren_wrap(
+      cursor,
+      Pointer.fromFunction(
+          _structMembersVisitor, clang.CXChildVisitResult.CXChildVisit_Break),
+      nullptr);
+
+  visitChildrenResultChecker(resultCode);
+
+  // Returning null to exclude the struct members as it has a struct by value field.
+  if (nestedStructMember) {
+    _logger.fine(
+        '---- Removed Struct members, reason: struct has struct members ${cursor.completeStringRepr()}');
+    _logger.warning(
+        "Removed All Struct Members from '$structName', Nested Structures not supported.");
+    return null;
+  } else if (unimplementedMemberType) {
+    _logger.fine(
+        '---- Removed Struct members, reason: member with unimplementedtype ${cursor.completeStringRepr()}');
+    _logger.warning(
+        "Removed All Struct Members from '$structName', struct member has an unsupported type.");
+    return null;
+  }
+
+  return _members;
+}
+
+bool nestedStructMember = false;
+bool unimplementedMemberType = false;
+
+/// Visitor for the struct cursor [CXCursorKind.CXCursor_StructDecl].
+///
+/// Child visitor invoked on struct cursor.
+int _structMembersVisitor(Pointer<clang.CXCursor> cursor,
+    Pointer<clang.CXCursor> parent, Pointer<Void> clientData) {
+  try {
+    if (cursor.kind() == clang.CXCursorKind.CXCursor_FieldDecl) {
+      _logger.finer('===== member: ${cursor.completeStringRepr()}');
+
+      final mt = cursor.type().toCodeGenTypeAndDispose();
+
+      //TODO(4): Remove these when support for Structs by value arrives.
+      if (mt.broadType == BroadType.Struct) {
+        // Setting this flag will exclude adding members for this struct's bindings.
+        nestedStructMember = true;
+      } else if (mt.broadType == BroadType.ConstantArray) {
+        if (mt.elementType.broadType == BroadType.Struct) {
+          // Setting this flag will exclude adding members for this struct's bindings.
+          nestedStructMember = true;
+        }
+      }
+
+      if (mt.getBaseBroadType() == BroadType.Unimplemented) {
+        unimplementedMemberType = true;
+      }
+
+      _members.add(
+        Member(
+          name: cursor.spelling(),
+          type: mt,
+        ),
+      );
+    }
+    cursor.dispose();
+    parent.dispose();
+  } catch (e, s) {
+    _logger.severe(e);
+    _logger.severe(s);
+    rethrow;
+  }
+  return clang.CXChildVisitResult.CXChildVisit_Continue;
+}
diff --git a/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart b/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart
new file mode 100644
index 0000000..c68b5e3
--- /dev/null
+++ b/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:logging/logging.dart';
+
+import '../clang_bindings/clang_bindings.dart' as clang;
+import '../sub_parsers/enumdecl_parser.dart';
+import '../sub_parsers/structdecl_parser.dart';
+import '../utils.dart';
+
+var _logger = Logger('parser:typedefdecl_parser');
+
+/// Temporarily holds a binding before its returned by [parseTypedefDeclaration].
+Binding _binding;
+
+/// Temporarily holds parent cursor name.
+String _typedefName;
+
+/// Parses a typedef declaration.
+Binding parseTypedefDeclaration(Pointer<clang.CXCursor> cursor) {
+  _binding = null;
+  // Name of typedef.
+  _typedefName = cursor.spelling();
+
+  final resultCode = clang.clang_visitChildren_wrap(
+    cursor,
+    Pointer.fromFunction(_typedefdeclarationCursorVisitor,
+        clang.CXChildVisitResult.CXChildVisit_Break),
+    nullptr,
+  );
+
+  visitChildrenResultChecker(resultCode);
+
+  return _binding;
+}
+
+/// Visitor for extracting binding for a TypedefDeclarations of a
+/// [clang.CXCursorKind.CXCursor_TypedefDecl].
+///
+/// Visitor invoked on cursor of type declaration returned by
+/// [clang.clang_getTypeDeclaration_wrap].
+int _typedefdeclarationCursorVisitor(Pointer<clang.CXCursor> cursor,
+    Pointer<clang.CXCursor> parent, Pointer<Void> clientData) {
+  try {
+    _logger.finest(
+        'typedefdeclarationCursorVisitor: ${cursor.completeStringRepr()}');
+
+    switch (clang.clang_getCursorKind_wrap(cursor)) {
+      case clang.CXCursorKind.CXCursor_StructDecl:
+        _binding = parseStructDeclaration(cursor, name: _typedefName);
+        break;
+      case clang.CXCursorKind.CXCursor_EnumDecl:
+        _binding = parseEnumDeclaration(cursor, name: _typedefName);
+        break;
+      default:
+        _logger.finest('typedefdeclarationCursorVisitor: Ignored');
+    }
+
+    cursor.dispose();
+    parent.dispose();
+  } catch (e, s) {
+    _logger.severe(e);
+    _logger.severe(s);
+    rethrow;
+  }
+  return clang.CXChildVisitResult.CXChildVisit_Continue;
+}
diff --git a/lib/src/header_parser/translation_unit_parser.dart b/lib/src/header_parser/translation_unit_parser.dart
new file mode 100644
index 0000000..8632b25
--- /dev/null
+++ b/lib/src/header_parser/translation_unit_parser.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:logging/logging.dart';
+
+import 'clang_bindings/clang_bindings.dart' as clang;
+import 'includer.dart';
+import 'sub_parsers/enumdecl_parser.dart';
+import 'sub_parsers/functiondecl_parser.dart';
+import 'sub_parsers/structdecl_parser.dart';
+import 'sub_parsers/typedefdecl_parser.dart';
+import 'utils.dart';
+
+var _logger = Logger('parser:root_parser');
+
+List<Binding> _bindings;
+
+/// Parses the translation unit and returns the generated bindings.
+List<Binding> parseTranslationUnit(Pointer<clang.CXCursor> translationUnitCursor) {
+  _bindings = [];
+
+  final resultCode = clang.clang_visitChildren_wrap(
+    translationUnitCursor,
+    Pointer.fromFunction(
+        _rootCursorVisitor, clang.CXChildVisitResult.CXChildVisit_Break),
+    nullptr,
+  );
+
+  visitChildrenResultChecker(resultCode);
+
+  return _bindings;
+}
+
+/// Child visitor invoked on translationUnitCursor [CXCursorKind.CXCursor_TranslationUnit].
+int _rootCursorVisitor(Pointer<clang.CXCursor> cursor,
+    Pointer<clang.CXCursor> parent, Pointer<Void> clientData) {
+  try {
+    if (shouldIncludeRootCursor(cursor.sourceFileName())) {
+      _logger.finest('rootCursorVisitor: ${cursor.completeStringRepr()}');
+      switch (clang.clang_getCursorKind_wrap(cursor)) {
+        case clang.CXCursorKind.CXCursor_FunctionDecl:
+          addToBindings(parseFunctionDeclaration(cursor));
+          break;
+        case clang.CXCursorKind.CXCursor_TypedefDecl:
+          addToBindings(parseTypedefDeclaration(cursor));
+          break;
+        case clang.CXCursorKind.CXCursor_StructDecl:
+          addToBindings(parseStructDeclaration(cursor));
+          break;
+        case clang.CXCursorKind.CXCursor_EnumDecl:
+          addToBindings(parseEnumDeclaration(cursor));
+          break;
+        default:
+          _logger.finer('rootCursorVisitor: CursorKind not implemented');
+      }
+    } else {
+      _logger.finest(
+          'rootCursorVisitor:(excluded in header-filter) ${cursor.completeStringRepr()}');
+    }
+
+    cursor.dispose();
+    parent.dispose();
+  } catch (e, s) {
+    _logger.severe(e);
+    _logger.severe(s);
+    rethrow;
+  }
+  return clang.CXChildVisitResult.CXChildVisit_Continue;
+}
+
+/// Adds to binding if not null.
+void addToBindings(Binding b) {
+  if (b != null) {
+    _bindings.add(b);
+  }
+}
diff --git a/lib/src/header_parser/type_extractor/cxtypekindmap.dart b/lib/src/header_parser/type_extractor/cxtypekindmap.dart
new file mode 100644
index 0000000..6dd175f
--- /dev/null
+++ b/lib/src/header_parser/type_extractor/cxtypekindmap.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:ffigen/src/header_parser/clang_bindings/clang_bindings.dart'
+    as clang;
+import 'package:ffigen/src/code_generator.dart' show SupportedNativeType;
+
+/// Utility to convert CXType to [code_generator.Type].
+///
+/// Key: CXTypekindEnum, Value: TypeString for code_generator
+var cxTypeKindToSupportedNativeTypes = <int, SupportedNativeType>{
+  clang.CXTypeKind.CXType_Void: SupportedNativeType.Void,
+  clang.CXTypeKind.CXType_UChar: SupportedNativeType.Uint8,
+  clang.CXTypeKind.CXType_UShort: SupportedNativeType.Uint16,
+  clang.CXTypeKind.CXType_UInt: SupportedNativeType.Uint32,
+  clang.CXTypeKind.CXType_ULong: SupportedNativeType.Uint64,
+  clang.CXTypeKind.CXType_ULongLong: SupportedNativeType.Uint64,
+  clang.CXTypeKind.CXType_SChar: SupportedNativeType.Int8,
+  clang.CXTypeKind.CXType_Short: SupportedNativeType.Int16,
+  clang.CXTypeKind.CXType_Int: SupportedNativeType.Int32,
+  clang.CXTypeKind.CXType_Long: SupportedNativeType.Int64,
+  clang.CXTypeKind.CXType_LongLong: SupportedNativeType.Int64,
+  clang.CXTypeKind.CXType_Float: SupportedNativeType.Float,
+  clang.CXTypeKind.CXType_Double: SupportedNativeType.Double,
+  clang.CXTypeKind.CXType_Char_S: SupportedNativeType.Int8,
+  clang.CXTypeKind.CXType_Enum: SupportedNativeType.Int32,
+};
+
+SupportedNativeType get enumNativeType =>
+    cxTypeKindToSupportedNativeTypes[clang.CXTypeKind.CXType_Enum];
+
+var suportedTypedefToSuportedNativeType = <String, SupportedNativeType>{
+  'uint8_t': SupportedNativeType.Uint8,
+  'uint16_t': SupportedNativeType.Uint16,
+  'uint32_t': SupportedNativeType.Uint32,
+  'uint64_t': SupportedNativeType.Uint64,
+  'int8_t': SupportedNativeType.Int8,
+  'int16_t': SupportedNativeType.Int16,
+  'int32_t': SupportedNativeType.Int32,
+  'int64_t': SupportedNativeType.Int64,
+  'intptr_t': SupportedNativeType.IntPtr,
+};
diff --git a/lib/src/header_parser/type_extractor/extractor.dart b/lib/src/header_parser/type_extractor/extractor.dart
new file mode 100644
index 0000000..db37487
--- /dev/null
+++ b/lib/src/header_parser/type_extractor/extractor.dart
@@ -0,0 +1,154 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Extracts code_gen Type from type.
+import 'dart:ffi';
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:logging/logging.dart';
+
+import '../clang_bindings/clang_bindings.dart' as clang;
+import '../data.dart';
+import '../includer.dart';
+import '../sub_parsers/structdecl_parser.dart';
+import '../translation_unit_parser.dart';
+import '../type_extractor/cxtypekindmap.dart';
+import '../utils.dart';
+
+var _logger = Logger('parser:extractor');
+const _padding = '  ';
+
+/// Converts cxtype to a typestring code_generator can accept.
+Type getCodeGenType(Pointer<clang.CXType> cxtype, {String parentName}) {
+  _logger.fine('${_padding}getCodeGenType ${cxtype.completeStringRepr()}');
+  final kind = cxtype.kind();
+
+  switch (kind) {
+    case clang.CXTypeKind.CXType_Pointer:
+      final pt = clang.clang_getPointeeType_wrap(cxtype);
+      final s = getCodeGenType(pt, parentName: parentName);
+      pt.dispose();
+      return Type.pointer(s);
+    case clang.CXTypeKind.CXType_Typedef:
+      // Get name from typedef name if config allows.
+      if (config.useSupportedTypedefs) {
+        final spelling = cxtype.spelling();
+        if (suportedTypedefToSuportedNativeType.containsKey(spelling)) {
+          _logger.fine('  Type Mapped from supported typedef');
+          return Type.nativeType(suportedTypedefToSuportedNativeType[spelling]);
+        }
+      }
+
+      // This is important or we get stuck in infinite recursion.
+      final ct = clang.clang_getCanonicalType_wrap(cxtype);
+
+      final s = getCodeGenType(ct, parentName: parentName ?? cxtype.spelling());
+      ct.dispose();
+      return s;
+    case clang.CXTypeKind.CXType_Elaborated:
+      final et = clang.clang_Type_getNamedType_wrap(cxtype);
+      final s = getCodeGenType(et, parentName: parentName);
+      et.dispose();
+      return s;
+    case clang.CXTypeKind.CXType_Record:
+      return _extractfromRecord(cxtype);
+    case clang.CXTypeKind.CXType_Enum:
+      return Type.nativeType(
+        enumNativeType,
+      );
+    case clang.CXTypeKind
+        .CXType_FunctionProto: // Primarily used for function pointers.
+      return _extractFromFunctionProto(cxtype, parentName);
+    case clang.CXTypeKind
+        .CXType_ConstantArray: // Primarily used for constant array in struct members.
+      return Type.constantArray(
+        clang.clang_getNumElements_wrap(cxtype),
+        clang.clang_getArrayElementType_wrap(cxtype).toCodeGenTypeAndDispose(),
+      );
+    default:
+      if (cxTypeKindToSupportedNativeTypes.containsKey(kind)) {
+        return Type.nativeType(
+          cxTypeKindToSupportedNativeTypes[kind],
+        );
+      } else {
+        _logger.fine(
+            'typedeclarationCursorVisitor: getCodeGenType: Type Not Implemented, ${cxtype.completeStringRepr()}');
+        return Type.unimplemented(
+            'Type: ${cxtype.kindSpelling()} not implemented');
+      }
+  }
+}
+
+Type _extractfromRecord(Pointer<clang.CXType> cxtype) {
+  Type type;
+
+  final cursor = clang.clang_getTypeDeclaration_wrap(cxtype);
+  _logger.fine('${_padding}_extractfromRecord: ${cursor.completeStringRepr()}');
+
+  switch (clang.clang_getCursorKind_wrap(cursor)) {
+    case clang.CXCursorKind.CXCursor_StructDecl:
+      final cxtype = cursor.type();
+      var structName = cursor.spelling();
+      if (structName == '') {
+        // Incase of anonymous structs defined inside a typedef.
+        structName = cxtype.spelling();
+      }
+
+      type = Type.struct(structName);
+
+      // Also add a struct binding, if its unseen.
+      if (isUnseenStruct(structName, addToSeen: true)) {
+        addToBindings(
+            parseStructDeclaration(cursor, name: structName, doInclude: true));
+      }
+
+      cxtype.dispose();
+      break;
+    default:
+      _logger.fine(
+          'typedeclarationCursorVisitor: _extractfromRecord: Not Implemented, ${cursor.completeStringRepr()}');
+      return Type.unimplemented(
+          'Type: ${cxtype.kindSpelling()} not implemented');
+  }
+  cursor.dispose();
+  return type;
+}
+
+// Used for function pointer arguments.
+Type _extractFromFunctionProto(
+    Pointer<clang.CXType> cxtype, String parentName) {
+  var name = parentName;
+
+  // Set a name for typedefc incase it was null or empty.
+  if (name == null || name == '') {
+    name = _getNextUniqueString('_typedefC_noname');
+  }
+
+  if (isUnseenTypedefC(name, addToSeen: true)) {
+    final typedefC = TypedefC(
+      name: name,
+      returnType:
+          clang.clang_getResultType_wrap(cxtype).toCodeGenTypeAndDispose(),
+    );
+    final totalArgs = clang.clang_getNumArgTypes_wrap(cxtype);
+    for (var i = 0; i < totalArgs; i++) {
+      final t = clang.clang_getArgType_wrap(cxtype, i);
+      typedefC.parameters.add(
+        Parameter(name: '', type: t.toCodeGenTypeAndDispose()),
+      );
+    }
+    addToBindings(typedefC);
+  }
+  return Type.nativeFunc(name);
+}
+
+/// Generate a unique string for naming in [TypedefC].
+String _getNextUniqueString(String prefix) {
+  int i = _uniqueStringCounters[prefix] ?? 0;
+  i++;
+  _uniqueStringCounters[prefix] = i;
+  return '${prefix}_$i';
+}
+
+Map<String, int> _uniqueStringCounters = {};
diff --git a/lib/src/header_parser/utils.dart b/lib/src/header_parser/utils.dart
new file mode 100644
index 0000000..254a950
--- /dev/null
+++ b/lib/src/header_parser/utils.dart
@@ -0,0 +1,208 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'package:ffi/ffi.dart';
+import 'package:ffigen/src/code_generator.dart';
+import 'package:logging/logging.dart';
+
+import 'clang_bindings/clang_bindings.dart' as clang;
+import 'data.dart';
+import 'type_extractor/extractor.dart';
+
+/// Check [resultCode] of [clang.clang_visitChildren_wrap].
+///
+/// Throws exception if resultCode is not 0.
+void visitChildrenResultChecker(int resultCode) {
+  if (resultCode != 0) {
+    throw Exception(
+        'Exception thrown in a dart function called via C, use --verbose to see more details');
+  }
+}
+
+/// Logs the warnings/errors returned by clang for a translation unit.
+void logTuDiagnostics(
+  Pointer<clang.CXTranslationUnitImpl> tu,
+  Logger logger,
+  String header,
+) {
+  final total = clang.clang_getNumDiagnostics(tu);
+  if (total == 0) {
+    return;
+  }
+
+  logger.warning('Header $header: Total errors/warnings: $total.');
+  for (var i = 0; i < total; i++) {
+    final diag = clang.clang_getDiagnostic(tu, i);
+    final cxstring = clang.clang_formatDiagnostic_wrap(
+      diag,
+      clang.CXDiagnosticDisplayOptions.CXDiagnostic_DisplaySourceLocation |
+          clang.CXDiagnosticDisplayOptions.CXDiagnostic_DisplayColumn |
+          clang.CXDiagnosticDisplayOptions.CXDiagnostic_DisplayCategoryName,
+    );
+    logger.warning('    ' + cxstring.toStringAndDispose());
+    clang.clang_disposeDiagnostic(diag);
+  }
+}
+
+extension CXCursorExt on Pointer<clang.CXCursor> {
+  /// Returns the kind int from [clang.CXCursorKind].
+  int kind() {
+    return clang.clang_getCursorKind_wrap(this);
+  }
+
+  /// Name of the cursor (E.g function name, Struct name, Parameter name).
+  String spelling() {
+    return clang.clang_getCursorSpelling_wrap(this).toStringAndDispose();
+  }
+
+  /// Spelling for a [clang.CXCursorKind], useful for debug purposes.
+  String kindSpelling() {
+    return clang
+        .clang_getCursorKindSpelling_wrap(clang.clang_getCursorKind_wrap(this))
+        .toStringAndDispose();
+  }
+
+  /// for debug: returns [spelling] [kind] [kindSpelling] [type] [typeSpelling].
+  String completeStringRepr() {
+    final cxtype = type();
+    final s =
+        '(Cursor) spelling: ${spelling()}, kind: ${kind()}, kindSpelling: ${kindSpelling()}, type: ${cxtype.kind()}, typeSpelling: ${cxtype.spelling()}';
+    cxtype.dispose();
+    return s;
+  }
+
+  /// Dispose type using [type.dispose].
+  Pointer<clang.CXType> type() {
+    return clang.clang_getCursorType_wrap(this);
+  }
+
+  /// Only valid for [clang.CXCursorKind.CXCursor_FunctionDecl].
+  ///
+  /// Dispose type using [type.dispose].
+  Pointer<clang.CXType> returnType() {
+    final t = type();
+    final r = clang.clang_getResultType_wrap(t);
+    t.dispose();
+    return r;
+  }
+
+  String sourceFileName() {
+    final cxsource = clang.clang_getCursorLocation_wrap(this);
+    final cxfilePtr = allocate<Pointer<Void>>();
+    final line = allocate<Uint32>();
+    final column = allocate<Uint32>();
+    final offset = allocate<Uint32>();
+
+    // Puts the values in these pointers.
+    clang.clang_getFileLocation_wrap(cxsource, cxfilePtr, line, column, offset);
+    final s =
+        clang.clang_getFileName_wrap(cxfilePtr.value).toStringAndDispose();
+    free(cxsource);
+    free(cxfilePtr);
+    free(line);
+    free(column);
+    free(offset);
+    return s;
+  }
+
+  void dispose() {
+    free(this);
+  }
+}
+
+// TODO(13): Improve generated doc comment.
+String getCursorDocComment(Pointer<clang.CXCursor> cursor) {
+  return config.extractComments
+      ? clang.clang_Cursor_getBriefCommentText_wrap(cursor).toStringAndDispose()
+      : null;
+}
+
+extension CXTypeExt on Pointer<clang.CXType> {
+  /// Get code_gen [Type] representation of [clang.CXType].
+  Type toCodeGenType() {
+    return getCodeGenType(this);
+  }
+
+  /// Get code_gen [Type] representation of [clang.CXType] and dispose the type.
+  Type toCodeGenTypeAndDispose() {
+    final t = getCodeGenType(this);
+    dispose();
+    return t;
+  }
+
+  /// Spelling for a [clang.CXTypeKind], useful for debug purposes.
+  String spelling() {
+    return clang.clang_getTypeSpelling_wrap(this).toStringAndDispose();
+  }
+
+  /// Returns the typeKind int from [clang.CXTypeKind].
+  int kind() {
+    return ref.kind;
+  }
+
+  String kindSpelling() {
+    return clang.clang_getTypeKindSpelling_wrap(kind()).toStringAndDispose();
+  }
+
+  /// For debugging: returns [spelling] [kind] [kindSpelling].
+  String completeStringRepr() {
+    final s =
+        '(Type) spelling: ${spelling()}, kind: ${kind()}, kindSpelling: ${kindSpelling()}';
+    return s;
+  }
+
+  void dispose() {
+    free(this);
+  }
+}
+
+extension CXStringExt on Pointer<clang.CXString> {
+  /// Convert CXString to a Dart string
+  ///
+  /// Make sure to dispose CXstring using dispose method, or use the
+  /// [toStringAndDispose] method.
+  String string() {
+    String s;
+    final cstring = clang.clang_getCString_wrap(this);
+    if (cstring != nullptr) {
+      s = Utf8.fromUtf8(cstring.cast());
+    }
+    return s;
+  }
+
+  /// Converts CXString to dart string and disposes CXString.
+  String toStringAndDispose() {
+    // Note: clang_getCString_wrap returns a const char *, calling free will result in error.
+    final s = string();
+    clang.clang_disposeString_wrap(this);
+    return s;
+  }
+
+  void dispose() {
+    clang.clang_disposeString_wrap(this);
+  }
+}
+
+/// Converts a [List<String>] to [Pointer<Pointer<Utf8>>].
+Pointer<Pointer<Utf8>> createDynamicStringArray(List<String> list) {
+  final nativeCmdArgs = allocate<Pointer<Utf8>>(count: list.length);
+
+  for (var i = 0; i < list.length; i++) {
+    nativeCmdArgs[i] = Utf8.toUtf8(list[i]);
+  }
+
+  return nativeCmdArgs;
+}
+
+extension DynamicCStringArray on Pointer<Pointer<Utf8>> {
+  // Properly disposes a Pointer<Pointer<Utf8>, ensure that sure length is correct.
+  void dispose(int length) {
+    for (var i = 0; i < length; i++) {
+      free(this[i]);
+    }
+    free(this);
+  }
+}
diff --git a/lib/src/strings.dart b/lib/src/strings.dart
new file mode 100644
index 0000000..9d9ff17
--- /dev/null
+++ b/lib/src/strings.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'package:ffigen/src/header_parser/clang_bindings/clang_bindings.dart'
+    as clang;
+
+const output = 'output';
+const libclang_dylib_folder = 'libclang-dylib-folder';
+const headers = 'headers';
+const headerFilter = 'header-filter';
+const compilerOpts = 'compiler-opts';
+const filters = 'filters';
+
+// Declarations.
+const functions = 'functions';
+const structs = 'structs';
+const enums = 'enums';
+
+// Sub-fields of Declarations.
+const include = 'include';
+const exclude = 'exclude';
+
+// Sub-fields of include/exclude.
+const matches = 'matches'; // regex
+const names = 'names'; // hashset
+
+const sizemap = 'size-map';
+
+// Sizemap values.
+const SChar = 'char';
+const UChar = 'unsigned char';
+const Short = 'short';
+const UShort = 'unsigned short';
+const Int = 'int';
+const UInt = 'unsigned int';
+const Long = 'long';
+const ULong = 'unsigned long';
+const LongLong = 'long long';
+const ULongLong = 'unsigned long long';
+const Enum = 'enum';
+
+// Used for validation and extraction of sizemap.
+const sizemap_native_mapping = <String, int>{
+  SChar: clang.CXTypeKind.CXType_SChar,
+  UChar: clang.CXTypeKind.CXType_UChar,
+  Short: clang.CXTypeKind.CXType_Short,
+  UShort: clang.CXTypeKind.CXType_UShort,
+  Int: clang.CXTypeKind.CXType_Int,
+  UInt: clang.CXTypeKind.CXType_UInt,
+  Long: clang.CXTypeKind.CXType_Long,
+  ULong: clang.CXTypeKind.CXType_ULong,
+  LongLong: clang.CXTypeKind.CXType_LongLong,
+  ULongLong: clang.CXTypeKind.CXType_ULongLong,
+  Enum: clang.CXTypeKind.CXType_Enum
+};
+
+// Boolean flags.
+const sort = 'sort';
+const useSupportedTypedefs = 'use-supported-typedefs';
+const warnWhenRemoving = 'warn-when-removing';
+const extractComments = 'extract-comments';
+
+// Dynamic library names.
+const libclang_dylib_linux = 'libwrapped_clang.so';
+const libclang_dylib_macos = 'libwrapped_clang.dylib';
+const libclang_dylib_windows = 'wrapped_clang.dll';
diff --git a/pubspec.yaml b/pubspec.yaml
index 7711721..64ecfbd 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,3 +1,7 @@
+# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
 name: ffigen
 version: 0.0.1
 homepage: https://github.com/dart-lang/ffigen
@@ -6,7 +10,14 @@
 environment:
   sdk: '>=2.7.0 <3.0.0'
 
-#dependencies:
+dependencies:
+  ffi: ^0.1.3
+  yaml: ^2.2.1
+  meta: ^1.1.8
+  args: ^1.6.0
+  logging: ^0.11.4
+  glob: ^1.2.0
+  path: ^1.7.0
 
 dev_dependencies:
   pedantic: ^1.9.0
diff --git a/test/code_generator_test.dart b/test/code_generator_test.dart
new file mode 100644
index 0000000..4312837
--- /dev/null
+++ b/test/code_generator_test.dart
@@ -0,0 +1,646 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('code_generator: ', () {
+    test('Function Binding (primitives, pointers)', () {
+      final library = Library(
+        bindings: [
+          Func(
+            name: 'noParam',
+            dartDoc: 'Just a test function\nheres another line',
+            returnType: Type.nativeType(
+              SupportedNativeType.Int32,
+            ),
+          ),
+          Func(
+            name: 'withPrimitiveParam',
+            parameters: [
+              Parameter(
+                name: 'a',
+                type: Type.nativeType(
+                  SupportedNativeType.Int32,
+                ),
+              ),
+              Parameter(
+                name: 'b',
+                type: Type.nativeType(
+                  SupportedNativeType.Uint8,
+                ),
+              ),
+            ],
+            returnType: Type.nativeType(
+              SupportedNativeType.Char,
+            ),
+          ),
+          Func(
+            name: 'withPointerParam',
+            parameters: [
+              Parameter(
+                name: 'a',
+                type: Type.pointer(
+                  Type.nativeType(
+                    SupportedNativeType.Int32,
+                  ),
+                ),
+              ),
+              Parameter(
+                name: 'b',
+                type: Type.pointer(
+                  Type.pointer(
+                    Type.nativeType(
+                      SupportedNativeType.Uint8,
+                    ),
+                  ),
+                ),
+              ),
+            ],
+            returnType: Type.pointer(
+              Type.nativeType(
+                SupportedNativeType.Double,
+              ),
+            ),
+          ),
+        ],
+      );
+
+      final gen = library.generate();
+
+      // Writing to file for debug purpose.
+      final file = File(
+        'test/debug_generated/Function-Binding-test-output.dart',
+      );
+      try {
+        expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib){
+  _dylib = dylib;
+}
+/// Just a test function
+/// heres another line
+int noParam(
+) {
+  return _noParam(
+  );
+}
+
+final _dart_noParam _noParam = _dylib.lookupFunction<_c_noParam,_dart_noParam>('noParam');
+
+typedef _c_noParam = ffi.Int32 Function(
+);
+
+typedef _dart_noParam = int Function(
+);
+
+int withPrimitiveParam(
+  int a,
+  int b,
+) {
+  return _withPrimitiveParam(
+    a,
+    b,
+  );
+}
+
+final _dart_withPrimitiveParam _withPrimitiveParam = _dylib.lookupFunction<_c_withPrimitiveParam,_dart_withPrimitiveParam>('withPrimitiveParam');
+
+typedef _c_withPrimitiveParam = ffi.Uint8 Function(
+  ffi.Int32 a,
+  ffi.Uint8 b,
+);
+
+typedef _dart_withPrimitiveParam = int Function(
+  int a,
+  int b,
+);
+
+ffi.Pointer<ffi.Double> withPointerParam(
+  ffi.Pointer<ffi.Int32> a,
+  ffi.Pointer<ffi.Pointer<ffi.Uint8>> b,
+) {
+  return _withPointerParam(
+    a,
+    b,
+  );
+}
+
+final _dart_withPointerParam _withPointerParam = _dylib.lookupFunction<_c_withPointerParam,_dart_withPointerParam>('withPointerParam');
+
+typedef _c_withPointerParam = ffi.Pointer<ffi.Double> Function(
+  ffi.Pointer<ffi.Int32> a,
+  ffi.Pointer<ffi.Pointer<ffi.Uint8>> b,
+);
+
+typedef _dart_withPointerParam = ffi.Pointer<ffi.Double> Function(
+  ffi.Pointer<ffi.Int32> a,
+  ffi.Pointer<ffi.Pointer<ffi.Uint8>> b,
+);
+
+''');
+        if (file.existsSync()) {
+          file.delete();
+        }
+      } catch (e) {
+        file.writeAsStringSync(gen);
+        print('Failed test, Debug output: ${file.absolute?.path}');
+        rethrow;
+      }
+    });
+
+    test('Struct Binding (primitives, pointers)', () {
+      final library = Library(
+        bindings: [
+          Struc(
+            name: 'NoMember',
+            dartDoc: 'Just a test struct\nheres another line',
+          ),
+          Struc(
+            name: 'WithPrimitiveMember',
+            members: [
+              Member(
+                name: 'a',
+                type: Type.nativeType(
+                  SupportedNativeType.Int32,
+                ),
+              ),
+              Member(
+                name: 'b',
+                type: Type.nativeType(
+                  SupportedNativeType.Double,
+                ),
+              ),
+              Member(
+                name: 'c',
+                type: Type.nativeType(
+                  SupportedNativeType.Char,
+                ),
+              ),
+            ],
+          ),
+          Struc(
+            name: 'WithPointerMember',
+            members: [
+              Member(
+                name: 'a',
+                type: Type.pointer(
+                  Type.nativeType(
+                    SupportedNativeType.Int32,
+                  ),
+                ),
+              ),
+              Member(
+                name: 'b',
+                type: Type.pointer(
+                  Type.pointer(
+                    Type.nativeType(
+                      SupportedNativeType.Double,
+                    ),
+                  ),
+                ),
+              ),
+              Member(
+                name: 'c',
+                type: Type.nativeType(
+                  SupportedNativeType.Char,
+                ),
+              ),
+            ],
+          ),
+        ],
+      );
+
+      final gen = library.generate();
+
+      // Writing to file for debug purpose.
+      final file = File('test/debug_generated/Struct-Binding-test-output.dart');
+
+      try {
+        expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib){
+  _dylib = dylib;
+}
+/// Just a test struct
+/// heres another line
+class NoMember extends ffi.Struct{
+}
+
+class WithPrimitiveMember extends ffi.Struct{
+  @ffi.Int32()
+  int a;
+
+  @ffi.Double()
+  double b;
+
+  @ffi.Uint8()
+  int c;
+
+}
+
+class WithPointerMember extends ffi.Struct{
+  ffi.Pointer<ffi.Int32> a;
+
+  ffi.Pointer<ffi.Pointer<ffi.Double>> b;
+
+  @ffi.Uint8()
+  int c;
+
+}
+
+''');
+        if (file.existsSync()) {
+          file.delete();
+        }
+      } catch (e) {
+        file.writeAsStringSync(gen);
+        print('Failed test, Debug output: ${file.absolute?.path}');
+        rethrow;
+      }
+    });
+
+    test('Function and Struct Binding (pointer to Struct)', () {
+      final library = Library(
+        bindings: [
+          Struc(
+            name: 'SomeStruc',
+            members: [
+              Member(
+                name: 'a',
+                type: Type.nativeType(
+                  SupportedNativeType.Int32,
+                ),
+              ),
+              Member(
+                name: 'b',
+                type: Type.nativeType(
+                  SupportedNativeType.Double,
+                ),
+              ),
+              Member(
+                name: 'c',
+                type: Type.nativeType(
+                  SupportedNativeType.Char,
+                ),
+              ),
+            ],
+          ),
+          Func(
+            name: 'someFunc',
+            parameters: [
+              Parameter(
+                name: 'some',
+                type: Type.pointer(
+                  Type.pointer(
+                    Type.struct(
+                      'SomeStruc',
+                    ),
+                  ),
+                ),
+              ),
+            ],
+            returnType: Type.pointer(
+              Type.struct(
+                'SomeStruc',
+              ),
+            ),
+          ),
+        ],
+      );
+
+      final gen = library.generate();
+
+      // Writing to file for debug purpose.
+      final file =
+          File('test/debug_generated/Func-n-Struct-Binding-test-output.dart');
+      try {
+        //expect
+        expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib){
+  _dylib = dylib;
+}
+class SomeStruc extends ffi.Struct{
+  @ffi.Int32()
+  int a;
+
+  @ffi.Double()
+  double b;
+
+  @ffi.Uint8()
+  int c;
+
+}
+
+ffi.Pointer<SomeStruc> someFunc(
+  ffi.Pointer<ffi.Pointer<SomeStruc>> some,
+) {
+  return _someFunc(
+    some,
+  );
+}
+
+final _dart_someFunc _someFunc = _dylib.lookupFunction<_c_someFunc,_dart_someFunc>('someFunc');
+
+typedef _c_someFunc = ffi.Pointer<SomeStruc> Function(
+  ffi.Pointer<ffi.Pointer<SomeStruc>> some,
+);
+
+typedef _dart_someFunc = ffi.Pointer<SomeStruc> Function(
+  ffi.Pointer<ffi.Pointer<SomeStruc>> some,
+);
+
+''');
+        if (file.existsSync()) {
+          file.delete();
+        }
+      } catch (e) {
+        file.writeAsStringSync(gen);
+        print('Failed test, Debug output: ${file.absolute?.path}');
+        rethrow;
+      }
+    });
+
+    test('global (primitives, pointers, pointer to struct)', () {
+      final library = Library(
+        bindings: [
+          Global(
+            name: 'test1',
+            type: Type.nativeType(
+              SupportedNativeType.Int32,
+            ),
+          ),
+          Global(
+            name: 'test2',
+            type: Type.pointer(
+              Type.nativeType(
+                SupportedNativeType.Float,
+              ),
+            ),
+          ),
+          Struc(
+            name: 'Some',
+          ),
+          Global(
+            name: 'test5',
+            type: Type.pointer(
+              Type.struct(
+                'Some',
+              ),
+            ),
+          ),
+        ],
+      );
+
+      final gen = library.generate();
+
+      // Writing to file for debug purpose.
+      final file = File(
+        'test/debug_generated/Global-Binding-test-output.dart',
+      );
+      try {
+        expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib){
+  _dylib = dylib;
+}
+final int test1 = _dylib.lookup<ffi.Int32>('test1').value;
+
+final ffi.Pointer<ffi.Float> test2 = _dylib.lookup<ffi.Pointer<ffi.Float>>('test2').value;
+
+class Some extends ffi.Struct{
+}
+
+final ffi.Pointer<Some> test5 = _dylib.lookup<ffi.Pointer<Some>>('test5').value;
+
+''');
+        if (file.existsSync()) {
+          file.delete();
+        }
+      } catch (e) {
+        file.writeAsStringSync(gen);
+        print('Failed test, Debug output: ${file.absolute?.path}');
+        rethrow;
+      }
+    });
+
+    test('constant', () {
+      final library = Library(
+        bindings: [
+          Constant(
+            name: 'test1',
+            type: Type.nativeType(
+              SupportedNativeType.Int32,
+            ),
+            rawValue: '20',
+          ),
+          Constant(
+            name: 'test2',
+            type: Type.nativeType(
+              SupportedNativeType.Float,
+            ),
+            rawValue: '20.0',
+          ),
+        ],
+      );
+
+      final gen = library.generate();
+
+      // Writing to file for debug purpose.
+      final file = File(
+        'test/debug_generated/Constant-test-output.dart',
+      );
+      try {
+        expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib){
+  _dylib = dylib;
+}
+const int test1 = 20;
+
+const double test2 = 20.0;
+
+''');
+        if (file.existsSync()) {
+          file.delete();
+        }
+      } catch (e) {
+        file.writeAsStringSync(gen);
+        print('Failed test, Debug output: ${file.absolute?.path}');
+        rethrow;
+      }
+    });
+
+    test('TypedefC (primitive, pointers, pointer to struct)', () {
+      final library = Library(
+        bindings: [
+          TypedefC(
+            dartDoc: 'just a test',
+            name: 'test1',
+            returnType: Type.nativeType(
+              SupportedNativeType.Int32,
+            ),
+          ),
+          Struc(name: 'SomeStruct'),
+          TypedefC(
+            name: 'test2',
+            returnType: Type.pointer(
+              Type.nativeType(
+                SupportedNativeType.Int32,
+              ),
+            ),
+            parameters: [
+              Parameter(
+                name: 'param1',
+                type: Type.pointer(
+                  Type.struct('SomeStruct'),
+                ),
+              ),
+              Parameter(
+                name: 'param2',
+                type: Type.nativeType(
+                  SupportedNativeType.Char,
+                ),
+              ),
+            ],
+          ),
+        ],
+      );
+
+      final gen = library.generate();
+
+      // Writing to file for debug purpose.
+      final file =
+          File('test/debug_generated/typedef-Binding-test-output.dart');
+      try {
+        expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib){
+  _dylib = dylib;
+}
+/// just a test
+typedef test1 = ffi.Int32 Function(
+);
+
+class SomeStruct extends ffi.Struct{
+}
+
+typedef test2 = ffi.Pointer<ffi.Int32> Function(
+  ffi.Pointer<SomeStruct> param1,
+  ffi.Uint8 param2,
+);
+
+''');
+        if (file.existsSync()) {
+          file.delete();
+        }
+      } catch (e) {
+        file.writeAsStringSync(gen);
+        print('Failed test, Debug output: ${file.absolute?.path}');
+        rethrow;
+      }
+    });
+
+    test('enum_class', () {
+      final library = Library(
+        bindings: [
+          EnumClass(
+            name: 'Constants',
+            dartDoc: 'test line 1\ntest line 2',
+            enumConstants: [
+              EnumConstant(
+                name: 'a',
+                value: 10,
+              ),
+              EnumConstant(name: 'b', value: -1, dartDoc: 'negative'),
+            ],
+          ),
+        ],
+      );
+
+      final gen = library.generate();
+
+      // Writing to file for debug purpose.
+      final file = File(
+        'test/debug_generated/enum-class-test-output.dart',
+      );
+      try {
+        expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib){
+  _dylib = dylib;
+}
+/// test line 1
+/// test line 2
+class Constants {
+  static const int a = 10;
+  /// negative
+  static const int b = -1;
+}
+
+''');
+        if (file.existsSync()) {
+          file.delete();
+        }
+      } catch (e) {
+        file.writeAsStringSync(gen);
+        print('Failed test, Debug output: ${file.absolute?.path}');
+        rethrow;
+      }
+    });
+  });
+}
diff --git a/test/header_parser_tests/functions.h b/test/header_parser_tests/functions.h
new file mode 100644
index 0000000..306ff0f
--- /dev/null
+++ b/test/header_parser_tests/functions.h
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include <stdint.h>
+
+// Simple tests with primitives.
+void func1();
+int32_t func2(int16_t);
+double func3(float, int8_t a, int64_t, int32_t b);
+
+// Tests with pointers to primitives.
+void *func4(int8_t **, double, int32_t ***);
diff --git a/test/header_parser_tests/functions_test.dart b/test/header_parser_tests/functions_test.dart
new file mode 100644
index 0000000..f9e261e
--- /dev/null
+++ b/test/header_parser_tests/functions_test.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:ffigen/src/code_generator/writer.dart';
+import 'package:ffigen/src/header_parser.dart' as parser;
+import 'package:ffigen/src/config_provider.dart';
+import 'package:logging/logging.dart';
+import 'package:test/test.dart';
+
+final writer = Writer();
+
+void main() {
+  group('header_parser', () {
+    Library actual, expected;
+
+    setUpAll(() {
+      expected = expectedLibrary();
+
+      var dylibPath = 'tool/wrapped_libclang/libwrapped_clang.so';
+      if (Platform.isMacOS) {
+        dylibPath = 'tool/wrapped_libclang/libwrapped_clang.dylib';
+      } else if (Platform.isWindows) {
+        dylibPath = 'tool/wrapped_libclang/wrapped_clang.dll';
+      }
+
+      Logger.root.onRecord.listen((log) {
+        print('${log.level.name.padRight(8)}: ${log.message}');
+      });
+
+      actual = parser.parse(
+        Config.raw(
+          libclang_dylib_path: dylibPath,
+          headers: [
+            'test/header_parser_tests/functions.h',
+          ],
+          headerFilter: HeaderFilter(
+            includedInclusionHeaders: {
+              'functions.h',
+            },
+          ),
+        ),
+      );
+    });
+    test('Total bindings count', () {
+      expect(actual.bindings.length, expected.bindings.length);
+    });
+
+    test('func1', () {
+      expect(binding(actual, 'func1'), binding(expected, 'func1'));
+    });
+    test('func2', () {
+      expect(binding(actual, 'func2'), binding(expected, 'func2'));
+    });
+    test('func3', () {
+      expect(binding(actual, 'func3'), binding(expected, 'func3'));
+    });
+
+    test('func4', () {
+      expect(binding(actual, 'func4'), binding(expected, 'func4'));
+    });
+  });
+}
+
+/// Extracts a binding's string from a library.
+String binding(Library lib, String name) {
+  return lib.bindings
+      .firstWhere((element) => element.name == name)
+      .toBindingString(writer)
+      .string;
+}
+
+Library expectedLibrary() {
+  return Library(
+    bindings: [
+      Func(
+        name: 'func1',
+        returnType: Type.nativeType(
+          SupportedNativeType.Void,
+        ),
+      ),
+      Func(
+        name: 'func2',
+        returnType: Type.nativeType(
+          SupportedNativeType.Int32,
+        ),
+        parameters: [
+          Parameter(
+            name: '',
+            type: Type.nativeType(
+              SupportedNativeType.Int16,
+            ),
+          ),
+        ],
+      ),
+      Func(
+        name: 'func3',
+        returnType: Type.nativeType(
+          SupportedNativeType.Double,
+        ),
+        parameters: [
+          Parameter(
+            type: Type.nativeType(
+              SupportedNativeType.Float,
+            ),
+          ),
+          Parameter(
+            name: 'a',
+            type: Type.nativeType(
+              SupportedNativeType.Int8,
+            ),
+          ),
+          Parameter(
+            name: '',
+            type: Type.nativeType(
+              SupportedNativeType.Int64,
+            ),
+          ),
+          Parameter(
+            name: 'b',
+            type: Type.nativeType(
+              SupportedNativeType.Int32,
+            ),
+          ),
+        ],
+      ),
+      Func(
+          name: 'func4',
+          returnType: Type.pointer(Type.nativeType(SupportedNativeType.Void)),
+          parameters: [
+            Parameter(
+                type: Type.pointer(
+                    Type.pointer(Type.nativeType(SupportedNativeType.Int8)))),
+            Parameter(type: Type.nativeType(SupportedNativeType.Double)),
+            Parameter(
+              type: Type.pointer(Type.pointer(
+                  Type.pointer(Type.nativeType(SupportedNativeType.Int32)))),
+            )
+          ]),
+    ],
+  );
+}
diff --git a/test/native_functions_test/build_test_dylib.dart b/test/native_functions_test/build_test_dylib.dart
new file mode 100644
index 0000000..25258f0
--- /dev/null
+++ b/test/native_functions_test/build_test_dylib.dart
@@ -0,0 +1,130 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// =======================================================================
+/// ==== Script to generate dynamic library for native_function_tests =====
+/// =======================================================================
+/// This Script effectively calls the following (but user can provide
+/// command line args which will replace the defaults shown below)-
+///
+/// Linux:
+/// ```
+/// clang -shared -fpic native_functions.c -o native_functions.so
+/// ```
+/// MacOS:
+/// ```
+/// clang -shared -fpic native_functions.c -o native_functions.dylib
+/// ```
+/// Windows:
+/// ```
+/// call clang -shared native_functions.c -o native_functions.dll -Wl,"/DEF:native_functions.def"
+/// del native_functions.exp
+/// del native_functions.lib
+/// ```
+/// =======================================================================
+/// =======================================================================
+/// =======================================================================
+
+import 'dart:io';
+
+import 'package:meta/meta.dart';
+
+const MACOS = 'macos';
+const WINDOWS = 'windows';
+const LINUX = 'linux';
+
+Map<String, Options> platformOptions = {
+  LINUX: Options(
+    outputfilename: 'native_functions.so',
+    sharedFlag: '-shared',
+    inputHeader: 'native_functions.c',
+    fPIC: '-fpic',
+  ),
+  WINDOWS: Options(
+    outputfilename: 'native_functions.dll',
+    sharedFlag: '-shared',
+    inputHeader: 'native_functions.c',
+    moduleDefPath: '-Wl,/DEF:native_functions.def',
+  ),
+  MACOS: Options(
+    outputfilename: 'native_functions.dylib',
+    sharedFlag: '-shared',
+    inputHeader: 'native_functions.c',
+    fPIC: '-fpic',
+  ),
+};
+
+void main(List<String> arguments) {
+  print('Building Dynamic Library for Native Tests... ');
+  final options = getPlatformOptions();
+
+  // Run clang compiler to generate the dynamic library.
+  final ProcessResult result = runClangProcess(options);
+  printSuccess(result, options);
+}
+
+/// Calls the clang compiler.
+ProcessResult runClangProcess(Options options) {
+  final result = Process.runSync(
+    'clang',
+    [
+      options.sharedFlag,
+      options.fPIC,
+      options.inputHeader,
+      '-o',
+      options.outputfilename,
+      options.moduleDefPath,
+    ],
+  );
+  return result;
+}
+
+/// Prints success message (or process error if any).
+void printSuccess(ProcessResult result, Options options) {
+  print(result.stdout);
+  if ((result.stderr as String).isEmpty) {
+    print('Generated file: ${options.outputfilename}');
+  } else {
+    print(result.stderr);
+  }
+}
+
+/// Get options based on current platform.
+Options getPlatformOptions() {
+  if (Platform.isMacOS) {
+    return platformOptions[MACOS];
+  } else if (Platform.isWindows) {
+    return platformOptions[WINDOWS];
+  } else if (Platform.isLinux) {
+    return platformOptions[LINUX];
+  } else {
+    throw Exception('Unknown Platform.');
+  }
+}
+
+/// Hold options which would be passed to clang.
+class Options {
+  /// Name of dynamic library to generate.
+  final String outputfilename;
+
+  /// Tells compiler to generate a shared library.
+  final String sharedFlag;
+
+  /// Flag for generating Position Independant Code (Not used on windows).
+  final String fPIC;
+
+  /// Input file.
+  final String inputHeader;
+
+  /// Path to `.def` file containing symbols to export, windows use only.
+  final String moduleDefPath;
+
+  Options({
+    @required this.outputfilename,
+    @required this.sharedFlag,
+    @required this.inputHeader,
+    this.fPIC = '',
+    this.moduleDefPath = '',
+  });
+}
diff --git a/test/native_functions_test/config.yaml b/test/native_functions_test/config.yaml
new file mode 100644
index 0000000..4af2def
--- /dev/null
+++ b/test/native_functions_test/config.yaml
@@ -0,0 +1,16 @@
+# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# =================== GENERATING TEST BINDINGS ==================
+#    dart ../../bin/generate.dart --config config.yaml
+# ===============================================================
+
+output: 'native_functions_bindings.dart'
+libclang-dylib-folder: '../../tool/wrapped_libclang'
+sort: true
+headers:
+  - 'native_functions.c'
+header-filter:
+  include:
+    - 'native_functions.c'
diff --git a/test/native_functions_test/native_functions.c b/test/native_functions_test/native_functions.c
new file mode 100644
index 0000000..544357e
--- /dev/null
+++ b/test/native_functions_test/native_functions.c
@@ -0,0 +1,27 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include <stdint.h>
+
+uint8_t Function1Uint8(uint8_t x) { return x + 42; }
+
+uint16_t Function1Uint16(uint16_t x) { return x + 42; }
+
+uint32_t Function1Uint32(uint32_t x) { return x + 42; }
+
+uint64_t Function1Uint64(uint64_t x) { return x + 42; }
+
+int8_t Function1Int8(int8_t x) { return x + 42; }
+
+int16_t Function1Int16(int16_t x) { return x + 42; }
+
+int32_t Function1Int32(int32_t x) { return x + 42; }
+
+int64_t Function1Int64(int64_t x) { return x + 42; }
+
+intptr_t Function1IntPtr(intptr_t x) { return x + 42; }
+
+float Function1Float(float x) { return x + 42.0f; }
+
+double Function1Double(double x) { return x + 42.0; }
diff --git a/test/native_functions_test/native_functions.def b/test/native_functions_test/native_functions.def
new file mode 100644
index 0000000..f2d6f91
--- /dev/null
+++ b/test/native_functions_test/native_functions.def
@@ -0,0 +1,16 @@
+; Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+; for details. All rights reserved. Use of this source code is governed by a
+; BSD-style license that can be found in the LICENSE file.
+
+EXPORTS
+Function1Uint8
+Function1Uint16
+Function1Uint32
+Function1Uint64
+Function1Int8
+Function1Int16
+Function1Int32
+Function1Int64
+Function1IntPtr
+Function1Float
+Function1Double
\ No newline at end of file
diff --git a/test/native_functions_test/native_functions_bindings.dart b/test/native_functions_test/native_functions_bindings.dart
new file mode 100644
index 0000000..a9eb1e9
--- /dev/null
+++ b/test/native_functions_test/native_functions_bindings.dart
@@ -0,0 +1,226 @@
+/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib) {
+  _dylib = dylib;
+}
+
+double Function1Double(
+  double x,
+) {
+  return _Function1Double(
+    x,
+  );
+}
+
+final _dart_Function1Double _Function1Double =
+    _dylib.lookupFunction<_c_Function1Double, _dart_Function1Double>(
+        'Function1Double');
+
+typedef _c_Function1Double = ffi.Double Function(
+  ffi.Double x,
+);
+
+typedef _dart_Function1Double = double Function(
+  double x,
+);
+
+double Function1Float(
+  double x,
+) {
+  return _Function1Float(
+    x,
+  );
+}
+
+final _dart_Function1Float _Function1Float = _dylib
+    .lookupFunction<_c_Function1Float, _dart_Function1Float>('Function1Float');
+
+typedef _c_Function1Float = ffi.Float Function(
+  ffi.Float x,
+);
+
+typedef _dart_Function1Float = double Function(
+  double x,
+);
+
+int Function1Int16(
+  int x,
+) {
+  return _Function1Int16(
+    x,
+  );
+}
+
+final _dart_Function1Int16 _Function1Int16 = _dylib
+    .lookupFunction<_c_Function1Int16, _dart_Function1Int16>('Function1Int16');
+
+typedef _c_Function1Int16 = ffi.Int16 Function(
+  ffi.Int16 x,
+);
+
+typedef _dart_Function1Int16 = int Function(
+  int x,
+);
+
+int Function1Int32(
+  int x,
+) {
+  return _Function1Int32(
+    x,
+  );
+}
+
+final _dart_Function1Int32 _Function1Int32 = _dylib
+    .lookupFunction<_c_Function1Int32, _dart_Function1Int32>('Function1Int32');
+
+typedef _c_Function1Int32 = ffi.Int32 Function(
+  ffi.Int32 x,
+);
+
+typedef _dart_Function1Int32 = int Function(
+  int x,
+);
+
+int Function1Int64(
+  int x,
+) {
+  return _Function1Int64(
+    x,
+  );
+}
+
+final _dart_Function1Int64 _Function1Int64 = _dylib
+    .lookupFunction<_c_Function1Int64, _dart_Function1Int64>('Function1Int64');
+
+typedef _c_Function1Int64 = ffi.Int64 Function(
+  ffi.Int64 x,
+);
+
+typedef _dart_Function1Int64 = int Function(
+  int x,
+);
+
+int Function1Int8(
+  int x,
+) {
+  return _Function1Int8(
+    x,
+  );
+}
+
+final _dart_Function1Int8 _Function1Int8 = _dylib
+    .lookupFunction<_c_Function1Int8, _dart_Function1Int8>('Function1Int8');
+
+typedef _c_Function1Int8 = ffi.Int8 Function(
+  ffi.Int8 x,
+);
+
+typedef _dart_Function1Int8 = int Function(
+  int x,
+);
+
+int Function1IntPtr(
+  int x,
+) {
+  return _Function1IntPtr(
+    x,
+  );
+}
+
+final _dart_Function1IntPtr _Function1IntPtr =
+    _dylib.lookupFunction<_c_Function1IntPtr, _dart_Function1IntPtr>(
+        'Function1IntPtr');
+
+typedef _c_Function1IntPtr = ffi.IntPtr Function(
+  ffi.IntPtr x,
+);
+
+typedef _dart_Function1IntPtr = int Function(
+  int x,
+);
+
+int Function1Uint16(
+  int x,
+) {
+  return _Function1Uint16(
+    x,
+  );
+}
+
+final _dart_Function1Uint16 _Function1Uint16 =
+    _dylib.lookupFunction<_c_Function1Uint16, _dart_Function1Uint16>(
+        'Function1Uint16');
+
+typedef _c_Function1Uint16 = ffi.Uint16 Function(
+  ffi.Uint16 x,
+);
+
+typedef _dart_Function1Uint16 = int Function(
+  int x,
+);
+
+int Function1Uint32(
+  int x,
+) {
+  return _Function1Uint32(
+    x,
+  );
+}
+
+final _dart_Function1Uint32 _Function1Uint32 =
+    _dylib.lookupFunction<_c_Function1Uint32, _dart_Function1Uint32>(
+        'Function1Uint32');
+
+typedef _c_Function1Uint32 = ffi.Uint32 Function(
+  ffi.Uint32 x,
+);
+
+typedef _dart_Function1Uint32 = int Function(
+  int x,
+);
+
+int Function1Uint64(
+  int x,
+) {
+  return _Function1Uint64(
+    x,
+  );
+}
+
+final _dart_Function1Uint64 _Function1Uint64 =
+    _dylib.lookupFunction<_c_Function1Uint64, _dart_Function1Uint64>(
+        'Function1Uint64');
+
+typedef _c_Function1Uint64 = ffi.Uint64 Function(
+  ffi.Uint64 x,
+);
+
+typedef _dart_Function1Uint64 = int Function(
+  int x,
+);
+
+int Function1Uint8(
+  int x,
+) {
+  return _Function1Uint8(
+    x,
+  );
+}
+
+final _dart_Function1Uint8 _Function1Uint8 = _dylib
+    .lookupFunction<_c_Function1Uint8, _dart_Function1Uint8>('Function1Uint8');
+
+typedef _c_Function1Uint8 = ffi.Uint8 Function(
+  ffi.Uint8 x,
+);
+
+typedef _dart_Function1Uint8 = int Function(
+  int x,
+);
diff --git a/test/native_functions_test/native_functions_test.dart b/test/native_functions_test/native_functions_test.dart
new file mode 100644
index 0000000..b63fc35
--- /dev/null
+++ b/test/native_functions_test/native_functions_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'dart:io';
+import 'dart:math';
+
+import 'package:test/test.dart';
+import 'native_functions_bindings.dart' as bindings;
+
+void main() {
+  group('Tests for native functions', () {
+    setUpAll(() {
+      var dylibName = 'test/native_functions_test/native_functions.so';
+      if (Platform.isMacOS) {
+        dylibName = 'test/native_functions_test/native_functions.dylib';
+      } else if (Platform.isWindows) {
+        dylibName = r'test\native_functions_test\native_functions.dll';
+      }
+      bindings.init(DynamicLibrary.open(dylibName));
+    });
+    test('uint8_t', () {
+      expect(bindings.Function1Uint8(pow(2, 8).toInt()), 42);
+    });
+    test('uint16_t', () {
+      expect(bindings.Function1Uint16(pow(2, 16).toInt()), 42);
+    });
+    test('uint32_t', () {
+      expect(bindings.Function1Uint32(pow(2, 32).toInt()), 42);
+    });
+    test('uint64_t', () {
+      expect(bindings.Function1Uint64(pow(2, 64).toInt()), 42);
+    });
+    test('int8_t', () {
+      expect(
+          bindings.Function1Int8(pow(2, 7).toInt()), -pow(2, 7).toInt() + 42);
+    });
+    test('int16_t', () {
+      expect(bindings.Function1Int16(pow(2, 15).toInt()),
+          -pow(2, 15).toInt() + 42);
+    });
+    test('int32_t', () {
+      expect(bindings.Function1Int32(pow(2, 31).toInt()),
+          -pow(2, 31).toInt() + 42);
+    });
+    test('int64_t', () {
+      expect(bindings.Function1Int64(pow(2, 63).toInt()),
+          -pow(2, 63).toInt() + 42);
+    });
+    test('intptr_t', () {
+      expect(bindings.Function1IntPtr(0), 42);
+    });
+    test('float', () {
+      expect(bindings.Function1Float(0), 42.0);
+    });
+    test('double', () {
+      expect(bindings.Function1Double(0), 42.0);
+    });
+  });
+}
diff --git a/third_party/cjson_library/.gitignore b/third_party/cjson_library/.gitignore
new file mode 100644
index 0000000..53d01a3
--- /dev/null
+++ b/third_party/cjson_library/.gitignore
@@ -0,0 +1,17 @@
+# CMake generated files and directories.
+CMakeCache.txt
+CMakeFiles/
+CmakeScripts/
+Makefile
+cmake_install.cmake
+
+# Xcode tooling generated via `cmake -G Xcode .`.
+cjson_library.xcodeproj/
+
+# Xcode generated build and output directories.
+cjson_library.build/
+
+# Generated shared library files.
+*.dylib
+*.so.*
+*.dll
diff --git a/third_party/cjson_library/CMakeLists.txt b/third_party/cjson_library/CMakeLists.txt
new file mode 100644
index 0000000..815ba4f
--- /dev/null
+++ b/third_party/cjson_library/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.7 FATAL_ERROR)
+project(cjson_library VERSION 1.0.0 LANGUAGES C)
+add_library(cjson_library SHARED cJSON.c)
+
+set_target_properties(cjson_library PROPERTIES
+    PUBLIC_HEADER cJSON.h
+    VERSION ${PROJECT_VERSION}
+    SOVERSION 1
+    OUTPUT_NAME "cjson"
+    XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Hex_Identity_ID_Goes_Here"
+)
diff --git a/third_party/cjson_library/cJSON.c b/third_party/cjson_library/cJSON.c
new file mode 100644
index 0000000..a198d66
--- /dev/null
+++ b/third_party/cjson_library/cJSON.c
@@ -0,0 +1,2998 @@
+/*
+  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+  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.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+/* disable warnings about old C89 functions in MSVC */
+#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+#if defined(_MSC_VER)
+#pragma warning (push)
+/* disable warning about single line comments in system headers */
+#pragma warning (disable : 4001)
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+
+#ifdef ENABLE_LOCALES
+#include <locale.h>
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+#ifdef __GNUC__
+#pragma GCC visibility pop
+#endif
+
+#include "cJSON.h"
+
+/* define our own boolean type */
+#ifdef true
+#undef true
+#endif
+#define true ((cJSON_bool)1)
+
+#ifdef false
+#undef false
+#endif
+#define false ((cJSON_bool)0)
+
+typedef struct {
+    const unsigned char *json;
+    size_t position;
+} error;
+static error global_error = { NULL, 0 };
+
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
+{
+    return (const char*) (global_error.json + global_error.position);
+}
+
+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) {
+    if (!cJSON_IsString(item)) {
+        return NULL;
+    }
+
+    return item->valuestring;
+}
+
+/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
+#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 12)
+    #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
+#endif
+
+CJSON_PUBLIC(const char*) cJSON_Version(void)
+{
+    static char version[15];
+    sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
+
+    return version;
+}
+
+/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
+static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
+{
+    if ((string1 == NULL) || (string2 == NULL))
+    {
+        return 1;
+    }
+
+    if (string1 == string2)
+    {
+        return 0;
+    }
+
+    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
+    {
+        if (*string1 == '\0')
+        {
+            return 0;
+        }
+    }
+
+    return tolower(*string1) - tolower(*string2);
+}
+
+typedef struct internal_hooks
+{
+    void *(CJSON_CDECL *allocate)(size_t size);
+    void (CJSON_CDECL *deallocate)(void *pointer);
+    void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
+} internal_hooks;
+
+#if defined(_MSC_VER)
+/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
+static void * CJSON_CDECL internal_malloc(size_t size)
+{
+    return malloc(size);
+}
+static void CJSON_CDECL internal_free(void *pointer)
+{
+    free(pointer);
+}
+static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
+{
+    return realloc(pointer, size);
+}
+#else
+#define internal_malloc malloc
+#define internal_free free
+#define internal_realloc realloc
+#endif
+
+/* strlen of character literals resolved at compile time */
+#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
+
+static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
+
+static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
+{
+    size_t length = 0;
+    unsigned char *copy = NULL;
+
+    if (string == NULL)
+    {
+        return NULL;
+    }
+
+    length = strlen((const char*)string) + sizeof("");
+    copy = (unsigned char*)hooks->allocate(length);
+    if (copy == NULL)
+    {
+        return NULL;
+    }
+    memcpy(copy, string, length);
+
+    return copy;
+}
+
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+    if (hooks == NULL)
+    {
+        /* Reset hooks */
+        global_hooks.allocate = malloc;
+        global_hooks.deallocate = free;
+        global_hooks.reallocate = realloc;
+        return;
+    }
+
+    global_hooks.allocate = malloc;
+    if (hooks->malloc_fn != NULL)
+    {
+        global_hooks.allocate = hooks->malloc_fn;
+    }
+
+    global_hooks.deallocate = free;
+    if (hooks->free_fn != NULL)
+    {
+        global_hooks.deallocate = hooks->free_fn;
+    }
+
+    /* use realloc only if both free and malloc are used */
+    global_hooks.reallocate = NULL;
+    if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
+    {
+        global_hooks.reallocate = realloc;
+    }
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
+{
+    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
+    if (node)
+    {
+        memset(node, '\0', sizeof(cJSON));
+    }
+
+    return node;
+}
+
+/* Delete a cJSON structure. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
+{
+    cJSON *next = NULL;
+    while (item != NULL)
+    {
+        next = item->next;
+        if (!(item->type & cJSON_IsReference) && (item->child != NULL))
+        {
+            cJSON_Delete(item->child);
+        }
+        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
+        {
+            global_hooks.deallocate(item->valuestring);
+        }
+        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
+        {
+            global_hooks.deallocate(item->string);
+        }
+        global_hooks.deallocate(item);
+        item = next;
+    }
+}
+
+/* get the decimal point character of the current locale */
+static unsigned char get_decimal_point(void)
+{
+#ifdef ENABLE_LOCALES
+    struct lconv *lconv = localeconv();
+    return (unsigned char) lconv->decimal_point[0];
+#else
+    return '.';
+#endif
+}
+
+typedef struct
+{
+    const unsigned char *content;
+    size_t length;
+    size_t offset;
+    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
+    internal_hooks hooks;
+} parse_buffer;
+
+/* check if the given size is left to read in a given parse buffer (starting with 1) */
+#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
+/* check if the buffer can be accessed at the given index (starting with 0) */
+#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
+#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
+/* get a pointer to the buffer at the position */
+#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
+{
+    double number = 0;
+    unsigned char *after_end = NULL;
+    unsigned char number_c_string[64];
+    unsigned char decimal_point = get_decimal_point();
+    size_t i = 0;
+
+    if ((input_buffer == NULL) || (input_buffer->content == NULL))
+    {
+        return false;
+    }
+
+    /* copy the number into a temporary buffer and replace '.' with the decimal point
+     * of the current locale (for strtod)
+     * This also takes care of '\0' not necessarily being available for marking the end of the input */
+    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
+    {
+        switch (buffer_at_offset(input_buffer)[i])
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            case '+':
+            case '-':
+            case 'e':
+            case 'E':
+                number_c_string[i] = buffer_at_offset(input_buffer)[i];
+                break;
+
+            case '.':
+                number_c_string[i] = decimal_point;
+                break;
+
+            default:
+                goto loop_end;
+        }
+    }
+loop_end:
+    number_c_string[i] = '\0';
+
+    number = strtod((const char*)number_c_string, (char**)&after_end);
+    if (number_c_string == after_end)
+    {
+        return false; /* parse_error */
+    }
+
+    item->valuedouble = number;
+
+    /* use saturation in case of overflow */
+    if (number >= INT_MAX)
+    {
+        item->valueint = INT_MAX;
+    }
+    else if (number <= (double)INT_MIN)
+    {
+        item->valueint = INT_MIN;
+    }
+    else
+    {
+        item->valueint = (int)number;
+    }
+
+    item->type = cJSON_Number;
+
+    input_buffer->offset += (size_t)(after_end - number_c_string);
+    return true;
+}
+
+/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
+{
+    if (number >= INT_MAX)
+    {
+        object->valueint = INT_MAX;
+    }
+    else if (number <= (double)INT_MIN)
+    {
+        object->valueint = INT_MIN;
+    }
+    else
+    {
+        object->valueint = (int)number;
+    }
+
+    return object->valuedouble = number;
+}
+
+typedef struct
+{
+    unsigned char *buffer;
+    size_t length;
+    size_t offset;
+    size_t depth; /* current nesting depth (for formatted printing) */
+    cJSON_bool noalloc;
+    cJSON_bool format; /* is this print a formatted print */
+    internal_hooks hooks;
+} printbuffer;
+
+/* realloc printbuffer if necessary to have at least "needed" bytes more */
+static unsigned char* ensure(printbuffer * const p, size_t needed)
+{
+    unsigned char *newbuffer = NULL;
+    size_t newsize = 0;
+
+    if ((p == NULL) || (p->buffer == NULL))
+    {
+        return NULL;
+    }
+
+    if ((p->length > 0) && (p->offset >= p->length))
+    {
+        /* make sure that offset is valid */
+        return NULL;
+    }
+
+    if (needed > INT_MAX)
+    {
+        /* sizes bigger than INT_MAX are currently not supported */
+        return NULL;
+    }
+
+    needed += p->offset + 1;
+    if (needed <= p->length)
+    {
+        return p->buffer + p->offset;
+    }
+
+    if (p->noalloc) {
+        return NULL;
+    }
+
+    /* calculate new buffer size */
+    if (needed > (INT_MAX / 2))
+    {
+        /* overflow of int, use INT_MAX if possible */
+        if (needed <= INT_MAX)
+        {
+            newsize = INT_MAX;
+        }
+        else
+        {
+            return NULL;
+        }
+    }
+    else
+    {
+        newsize = needed * 2;
+    }
+
+    if (p->hooks.reallocate != NULL)
+    {
+        /* reallocate with realloc if available */
+        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
+        if (newbuffer == NULL)
+        {
+            p->hooks.deallocate(p->buffer);
+            p->length = 0;
+            p->buffer = NULL;
+
+            return NULL;
+        }
+    }
+    else
+    {
+        /* otherwise reallocate manually */
+        newbuffer = (unsigned char*)p->hooks.allocate(newsize);
+        if (!newbuffer)
+        {
+            p->hooks.deallocate(p->buffer);
+            p->length = 0;
+            p->buffer = NULL;
+
+            return NULL;
+        }
+        if (newbuffer)
+        {
+            memcpy(newbuffer, p->buffer, p->offset + 1);
+        }
+        p->hooks.deallocate(p->buffer);
+    }
+    p->length = newsize;
+    p->buffer = newbuffer;
+
+    return newbuffer + p->offset;
+}
+
+/* calculate the new length of the string in a printbuffer and update the offset */
+static void update_offset(printbuffer * const buffer)
+{
+    const unsigned char *buffer_pointer = NULL;
+    if ((buffer == NULL) || (buffer->buffer == NULL))
+    {
+        return;
+    }
+    buffer_pointer = buffer->buffer + buffer->offset;
+
+    buffer->offset += strlen((const char*)buffer_pointer);
+}
+
+/* securely comparison of floating-point variables */
+static cJSON_bool compare_double(double a, double b)
+{
+    return (fabs(a - b) <= CJSON_DOUBLE_PRECISION);
+}
+
+/* Render the number nicely from the given item into a string. */
+static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
+{
+    unsigned char *output_pointer = NULL;
+    double d = item->valuedouble;
+    int length = 0;
+    size_t i = 0;
+    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
+    unsigned char decimal_point = get_decimal_point();
+    double test = 0.0;
+
+    if (output_buffer == NULL)
+    {
+        return false;
+    }
+
+    /* This checks for NaN and Infinity */
+    if ((d * 0) != 0)
+    {
+        length = sprintf((char*)number_buffer, "null");
+    }
+    else
+    {
+        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
+        length = sprintf((char*)number_buffer, "%1.15g", d);
+
+        /* Check whether the original double can be recovered */
+        if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
+        {
+            /* If not, print with 17 decimal places of precision */
+            length = sprintf((char*)number_buffer, "%1.17g", d);
+        }
+    }
+
+    /* sprintf failed or buffer overrun occurred */
+    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
+    {
+        return false;
+    }
+
+    /* reserve appropriate space in the output */
+    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
+    if (output_pointer == NULL)
+    {
+        return false;
+    }
+
+    /* copy the printed number to the output and replace locale
+     * dependent decimal point with '.' */
+    for (i = 0; i < ((size_t)length); i++)
+    {
+        if (number_buffer[i] == decimal_point)
+        {
+            output_pointer[i] = '.';
+            continue;
+        }
+
+        output_pointer[i] = number_buffer[i];
+    }
+    output_pointer[i] = '\0';
+
+    output_buffer->offset += (size_t)length;
+
+    return true;
+}
+
+/* parse 4 digit hexadecimal number */
+static unsigned parse_hex4(const unsigned char * const input)
+{
+    unsigned int h = 0;
+    size_t i = 0;
+
+    for (i = 0; i < 4; i++)
+    {
+        /* parse digit */
+        if ((input[i] >= '0') && (input[i] <= '9'))
+        {
+            h += (unsigned int) input[i] - '0';
+        }
+        else if ((input[i] >= 'A') && (input[i] <= 'F'))
+        {
+            h += (unsigned int) 10 + input[i] - 'A';
+        }
+        else if ((input[i] >= 'a') && (input[i] <= 'f'))
+        {
+            h += (unsigned int) 10 + input[i] - 'a';
+        }
+        else /* invalid */
+        {
+            return 0;
+        }
+
+        if (i < 3)
+        {
+            /* shift left to make place for the next nibble */
+            h = h << 4;
+        }
+    }
+
+    return h;
+}
+
+/* converts a UTF-16 literal to UTF-8
+ * A literal can be one or two sequences of the form \uXXXX */
+static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
+{
+    long unsigned int codepoint = 0;
+    unsigned int first_code = 0;
+    const unsigned char *first_sequence = input_pointer;
+    unsigned char utf8_length = 0;
+    unsigned char utf8_position = 0;
+    unsigned char sequence_length = 0;
+    unsigned char first_byte_mark = 0;
+
+    if ((input_end - first_sequence) < 6)
+    {
+        /* input ends unexpectedly */
+        goto fail;
+    }
+
+    /* get the first utf16 sequence */
+    first_code = parse_hex4(first_sequence + 2);
+
+    /* check that the code is valid */
+    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
+    {
+        goto fail;
+    }
+
+    /* UTF16 surrogate pair */
+    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
+    {
+        const unsigned char *second_sequence = first_sequence + 6;
+        unsigned int second_code = 0;
+        sequence_length = 12; /* \uXXXX\uXXXX */
+
+        if ((input_end - second_sequence) < 6)
+        {
+            /* input ends unexpectedly */
+            goto fail;
+        }
+
+        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
+        {
+            /* missing second half of the surrogate pair */
+            goto fail;
+        }
+
+        /* get the second utf16 sequence */
+        second_code = parse_hex4(second_sequence + 2);
+        /* check that the code is valid */
+        if ((second_code < 0xDC00) || (second_code > 0xDFFF))
+        {
+            /* invalid second half of the surrogate pair */
+            goto fail;
+        }
+
+
+        /* calculate the unicode codepoint from the surrogate pair */
+        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
+    }
+    else
+    {
+        sequence_length = 6; /* \uXXXX */
+        codepoint = first_code;
+    }
+
+    /* encode as UTF-8
+     * takes at maximum 4 bytes to encode:
+     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+    if (codepoint < 0x80)
+    {
+        /* normal ascii, encoding 0xxxxxxx */
+        utf8_length = 1;
+    }
+    else if (codepoint < 0x800)
+    {
+        /* two bytes, encoding 110xxxxx 10xxxxxx */
+        utf8_length = 2;
+        first_byte_mark = 0xC0; /* 11000000 */
+    }
+    else if (codepoint < 0x10000)
+    {
+        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
+        utf8_length = 3;
+        first_byte_mark = 0xE0; /* 11100000 */
+    }
+    else if (codepoint <= 0x10FFFF)
+    {
+        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+        utf8_length = 4;
+        first_byte_mark = 0xF0; /* 11110000 */
+    }
+    else
+    {
+        /* invalid unicode codepoint */
+        goto fail;
+    }
+
+    /* encode as utf8 */
+    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
+    {
+        /* 10xxxxxx */
+        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
+        codepoint >>= 6;
+    }
+    /* encode first byte */
+    if (utf8_length > 1)
+    {
+        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
+    }
+    else
+    {
+        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
+    }
+
+    *output_pointer += utf8_length;
+
+    return sequence_length;
+
+fail:
+    return 0;
+}
+
+/* Parse the input text into an unescaped cinput, and populate item. */
+static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
+{
+    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
+    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
+    unsigned char *output_pointer = NULL;
+    unsigned char *output = NULL;
+
+    /* not a string */
+    if (buffer_at_offset(input_buffer)[0] != '\"')
+    {
+        goto fail;
+    }
+
+    {
+        /* calculate approximate size of the output (overestimate) */
+        size_t allocation_length = 0;
+        size_t skipped_bytes = 0;
+        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
+        {
+            /* is escape sequence */
+            if (input_end[0] == '\\')
+            {
+                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
+                {
+                    /* prevent buffer overflow when last input character is a backslash */
+                    goto fail;
+                }
+                skipped_bytes++;
+                input_end++;
+            }
+            input_end++;
+        }
+        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
+        {
+            goto fail; /* string ended unexpectedly */
+        }
+
+        /* This is at most how much we need for the output */
+        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
+        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
+        if (output == NULL)
+        {
+            goto fail; /* allocation failure */
+        }
+    }
+
+    output_pointer = output;
+    /* loop through the string literal */
+    while (input_pointer < input_end)
+    {
+        if (*input_pointer != '\\')
+        {
+            *output_pointer++ = *input_pointer++;
+        }
+        /* escape sequence */
+        else
+        {
+            unsigned char sequence_length = 2;
+            if ((input_end - input_pointer) < 1)
+            {
+                goto fail;
+            }
+
+            switch (input_pointer[1])
+            {
+                case 'b':
+                    *output_pointer++ = '\b';
+                    break;
+                case 'f':
+                    *output_pointer++ = '\f';
+                    break;
+                case 'n':
+                    *output_pointer++ = '\n';
+                    break;
+                case 'r':
+                    *output_pointer++ = '\r';
+                    break;
+                case 't':
+                    *output_pointer++ = '\t';
+                    break;
+                case '\"':
+                case '\\':
+                case '/':
+                    *output_pointer++ = input_pointer[1];
+                    break;
+
+                /* UTF-16 literal */
+                case 'u':
+                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
+                    if (sequence_length == 0)
+                    {
+                        /* failed to convert UTF16-literal to UTF-8 */
+                        goto fail;
+                    }
+                    break;
+
+                default:
+                    goto fail;
+            }
+            input_pointer += sequence_length;
+        }
+    }
+
+    /* zero terminate the output */
+    *output_pointer = '\0';
+
+    item->type = cJSON_String;
+    item->valuestring = (char*)output;
+
+    input_buffer->offset = (size_t) (input_end - input_buffer->content);
+    input_buffer->offset++;
+
+    return true;
+
+fail:
+    if (output != NULL)
+    {
+        input_buffer->hooks.deallocate(output);
+    }
+
+    if (input_pointer != NULL)
+    {
+        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
+    }
+
+    return false;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
+{
+    const unsigned char *input_pointer = NULL;
+    unsigned char *output = NULL;
+    unsigned char *output_pointer = NULL;
+    size_t output_length = 0;
+    /* numbers of additional characters needed for escaping */
+    size_t escape_characters = 0;
+
+    if (output_buffer == NULL)
+    {
+        return false;
+    }
+
+    /* empty string */
+    if (input == NULL)
+    {
+        output = ensure(output_buffer, sizeof("\"\""));
+        if (output == NULL)
+        {
+            return false;
+        }
+        strcpy((char*)output, "\"\"");
+
+        return true;
+    }
+
+    /* set "flag" to 1 if something needs to be escaped */
+    for (input_pointer = input; *input_pointer; input_pointer++)
+    {
+        switch (*input_pointer)
+        {
+            case '\"':
+            case '\\':
+            case '\b':
+            case '\f':
+            case '\n':
+            case '\r':
+            case '\t':
+                /* one character escape sequence */
+                escape_characters++;
+                break;
+            default:
+                if (*input_pointer < 32)
+                {
+                    /* UTF-16 escape sequence uXXXX */
+                    escape_characters += 5;
+                }
+                break;
+        }
+    }
+    output_length = (size_t)(input_pointer - input) + escape_characters;
+
+    output = ensure(output_buffer, output_length + sizeof("\"\""));
+    if (output == NULL)
+    {
+        return false;
+    }
+
+    /* no characters have to be escaped */
+    if (escape_characters == 0)
+    {
+        output[0] = '\"';
+        memcpy(output + 1, input, output_length);
+        output[output_length + 1] = '\"';
+        output[output_length + 2] = '\0';
+
+        return true;
+    }
+
+    output[0] = '\"';
+    output_pointer = output + 1;
+    /* copy the string */
+    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
+    {
+        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
+        {
+            /* normal character, copy */
+            *output_pointer = *input_pointer;
+        }
+        else
+        {
+            /* character needs to be escaped */
+            *output_pointer++ = '\\';
+            switch (*input_pointer)
+            {
+                case '\\':
+                    *output_pointer = '\\';
+                    break;
+                case '\"':
+                    *output_pointer = '\"';
+                    break;
+                case '\b':
+                    *output_pointer = 'b';
+                    break;
+                case '\f':
+                    *output_pointer = 'f';
+                    break;
+                case '\n':
+                    *output_pointer = 'n';
+                    break;
+                case '\r':
+                    *output_pointer = 'r';
+                    break;
+                case '\t':
+                    *output_pointer = 't';
+                    break;
+                default:
+                    /* escape and print as unicode codepoint */
+                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
+                    output_pointer += 4;
+                    break;
+            }
+        }
+    }
+    output[output_length + 1] = '\"';
+    output[output_length + 2] = '\0';
+
+    return true;
+}
+
+/* Invoke print_string_ptr (which is useful) on an item. */
+static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
+{
+    return print_string_ptr((unsigned char*)item->valuestring, p);
+}
+
+/* Predeclare these prototypes. */
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
+
+/* Utility to jump whitespace and cr/lf */
+static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
+{
+    if ((buffer == NULL) || (buffer->content == NULL))
+    {
+        return NULL;
+    }
+
+    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
+    {
+       buffer->offset++;
+    }
+
+    if (buffer->offset == buffer->length)
+    {
+        buffer->offset--;
+    }
+
+    return buffer;
+}
+
+/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
+static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
+{
+    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
+    {
+        return NULL;
+    }
+
+    if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
+    {
+        buffer->offset += 3;
+    }
+
+    return buffer;
+}
+
+/* Parse an object - create a new root, and populate. */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
+{
+    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
+    cJSON *item = NULL;
+
+    /* reset error position */
+    global_error.json = NULL;
+    global_error.position = 0;
+
+    if (value == NULL)
+    {
+        goto fail;
+    }
+
+    buffer.content = (const unsigned char*)value;
+    buffer.length = strlen((const char*)value) + sizeof("");
+    buffer.offset = 0;
+    buffer.hooks = global_hooks;
+
+    item = cJSON_New_Item(&global_hooks);
+    if (item == NULL) /* memory fail */
+    {
+        goto fail;
+    }
+
+    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
+    {
+        /* parse failure. ep is set. */
+        goto fail;
+    }
+
+    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+    if (require_null_terminated)
+    {
+        buffer_skip_whitespace(&buffer);
+        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
+        {
+            goto fail;
+        }
+    }
+    if (return_parse_end)
+    {
+        *return_parse_end = (const char*)buffer_at_offset(&buffer);
+    }
+
+    return item;
+
+fail:
+    if (item != NULL)
+    {
+        cJSON_Delete(item);
+    }
+
+    if (value != NULL)
+    {
+        error local_error;
+        local_error.json = (const unsigned char*)value;
+        local_error.position = 0;
+
+        if (buffer.offset < buffer.length)
+        {
+            local_error.position = buffer.offset;
+        }
+        else if (buffer.length > 0)
+        {
+            local_error.position = buffer.length - 1;
+        }
+
+        if (return_parse_end != NULL)
+        {
+            *return_parse_end = (const char*)local_error.json + local_error.position;
+        }
+
+        global_error = local_error;
+    }
+
+    return NULL;
+}
+
+/* Default options for cJSON_Parse */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
+{
+    return cJSON_ParseWithOpts(value, 0, 0);
+}
+
+#define cjson_min(a, b) ((a < b) ? a : b)
+
+static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
+{
+    static const size_t default_buffer_size = 256;
+    printbuffer buffer[1];
+    unsigned char *printed = NULL;
+
+    memset(buffer, 0, sizeof(buffer));
+
+    /* create buffer */
+    buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
+    buffer->length = default_buffer_size;
+    buffer->format = format;
+    buffer->hooks = *hooks;
+    if (buffer->buffer == NULL)
+    {
+        goto fail;
+    }
+
+    /* print the value */
+    if (!print_value(item, buffer))
+    {
+        goto fail;
+    }
+    update_offset(buffer);
+
+    /* check if reallocate is available */
+    if (hooks->reallocate != NULL)
+    {
+        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
+        if (printed == NULL) {
+            goto fail;
+        }
+        buffer->buffer = NULL;
+    }
+    else /* otherwise copy the JSON over to a new buffer */
+    {
+        printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
+        if (printed == NULL)
+        {
+            goto fail;
+        }
+        memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
+        printed[buffer->offset] = '\0'; /* just to be sure */
+
+        /* free the buffer */
+        hooks->deallocate(buffer->buffer);
+    }
+
+    return printed;
+
+fail:
+    if (buffer->buffer != NULL)
+    {
+        hooks->deallocate(buffer->buffer);
+    }
+
+    if (printed != NULL)
+    {
+        hooks->deallocate(printed);
+    }
+
+    return NULL;
+}
+
+/* Render a cJSON item/entity/structure to text. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
+{
+    return (char*)print(item, true, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
+{
+    return (char*)print(item, false, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
+{
+    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+    if (prebuffer < 0)
+    {
+        return NULL;
+    }
+
+    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
+    if (!p.buffer)
+    {
+        return NULL;
+    }
+
+    p.length = (size_t)prebuffer;
+    p.offset = 0;
+    p.noalloc = false;
+    p.format = fmt;
+    p.hooks = global_hooks;
+
+    if (!print_value(item, &p))
+    {
+        global_hooks.deallocate(p.buffer);
+        return NULL;
+    }
+
+    return (char*)p.buffer;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
+{
+    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+    if ((length < 0) || (buffer == NULL))
+    {
+        return false;
+    }
+
+    p.buffer = (unsigned char*)buffer;
+    p.length = (size_t)length;
+    p.offset = 0;
+    p.noalloc = true;
+    p.format = format;
+    p.hooks = global_hooks;
+
+    return print_value(item, &p);
+}
+
+/* Parser core - when encountering text, process appropriately. */
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
+{
+    if ((input_buffer == NULL) || (input_buffer->content == NULL))
+    {
+        return false; /* no input */
+    }
+
+    /* parse the different types of values */
+    /* null */
+    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
+    {
+        item->type = cJSON_NULL;
+        input_buffer->offset += 4;
+        return true;
+    }
+    /* false */
+    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
+    {
+        item->type = cJSON_False;
+        input_buffer->offset += 5;
+        return true;
+    }
+    /* true */
+    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
+    {
+        item->type = cJSON_True;
+        item->valueint = 1;
+        input_buffer->offset += 4;
+        return true;
+    }
+    /* string */
+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
+    {
+        return parse_string(item, input_buffer);
+    }
+    /* number */
+    if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
+    {
+        return parse_number(item, input_buffer);
+    }
+    /* array */
+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
+    {
+        return parse_array(item, input_buffer);
+    }
+    /* object */
+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
+    {
+        return parse_object(item, input_buffer);
+    }
+
+    return false;
+}
+
+/* Render a value to text. */
+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
+{
+    unsigned char *output = NULL;
+
+    if ((item == NULL) || (output_buffer == NULL))
+    {
+        return false;
+    }
+
+    switch ((item->type) & 0xFF)
+    {
+        case cJSON_NULL:
+            output = ensure(output_buffer, 5);
+            if (output == NULL)
+            {
+                return false;
+            }
+            strcpy((char*)output, "null");
+            return true;
+
+        case cJSON_False:
+            output = ensure(output_buffer, 6);
+            if (output == NULL)
+            {
+                return false;
+            }
+            strcpy((char*)output, "false");
+            return true;
+
+        case cJSON_True:
+            output = ensure(output_buffer, 5);
+            if (output == NULL)
+            {
+                return false;
+            }
+            strcpy((char*)output, "true");
+            return true;
+
+        case cJSON_Number:
+            return print_number(item, output_buffer);
+
+        case cJSON_Raw:
+        {
+            size_t raw_length = 0;
+            if (item->valuestring == NULL)
+            {
+                return false;
+            }
+
+            raw_length = strlen(item->valuestring) + sizeof("");
+            output = ensure(output_buffer, raw_length);
+            if (output == NULL)
+            {
+                return false;
+            }
+            memcpy(output, item->valuestring, raw_length);
+            return true;
+        }
+
+        case cJSON_String:
+            return print_string(item, output_buffer);
+
+        case cJSON_Array:
+            return print_array(item, output_buffer);
+
+        case cJSON_Object:
+            return print_object(item, output_buffer);
+
+        default:
+            return false;
+    }
+}
+
+/* Build an array from input text. */
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
+{
+    cJSON *head = NULL; /* head of the linked list */
+    cJSON *current_item = NULL;
+
+    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
+    {
+        return false; /* to deeply nested */
+    }
+    input_buffer->depth++;
+
+    if (buffer_at_offset(input_buffer)[0] != '[')
+    {
+        /* not an array */
+        goto fail;
+    }
+
+    input_buffer->offset++;
+    buffer_skip_whitespace(input_buffer);
+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
+    {
+        /* empty array */
+        goto success;
+    }
+
+    /* check if we skipped to the end of the buffer */
+    if (cannot_access_at_index(input_buffer, 0))
+    {
+        input_buffer->offset--;
+        goto fail;
+    }
+
+    /* step back to character in front of the first element */
+    input_buffer->offset--;
+    /* loop through the comma separated array elements */
+    do
+    {
+        /* allocate next item */
+        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+        if (new_item == NULL)
+        {
+            goto fail; /* allocation failure */
+        }
+
+        /* attach next item to list */
+        if (head == NULL)
+        {
+            /* start the linked list */
+            current_item = head = new_item;
+        }
+        else
+        {
+            /* add to the end and advance */
+            current_item->next = new_item;
+            new_item->prev = current_item;
+            current_item = new_item;
+        }
+
+        /* parse next value */
+        input_buffer->offset++;
+        buffer_skip_whitespace(input_buffer);
+        if (!parse_value(current_item, input_buffer))
+        {
+            goto fail; /* failed to parse value */
+        }
+        buffer_skip_whitespace(input_buffer);
+    }
+    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
+    {
+        goto fail; /* expected end of array */
+    }
+
+success:
+    input_buffer->depth--;
+
+    item->type = cJSON_Array;
+    item->child = head;
+
+    input_buffer->offset++;
+
+    return true;
+
+fail:
+    if (head != NULL)
+    {
+        cJSON_Delete(head);
+    }
+
+    return false;
+}
+
+/* Render an array to text */
+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
+{
+    unsigned char *output_pointer = NULL;
+    size_t length = 0;
+    cJSON *current_element = item->child;
+
+    if (output_buffer == NULL)
+    {
+        return false;
+    }
+
+    /* Compose the output array. */
+    /* opening square bracket */
+    output_pointer = ensure(output_buffer, 1);
+    if (output_pointer == NULL)
+    {
+        return false;
+    }
+
+    *output_pointer = '[';
+    output_buffer->offset++;
+    output_buffer->depth++;
+
+    while (current_element != NULL)
+    {
+        if (!print_value(current_element, output_buffer))
+        {
+            return false;
+        }
+        update_offset(output_buffer);
+        if (current_element->next)
+        {
+            length = (size_t) (output_buffer->format ? 2 : 1);
+            output_pointer = ensure(output_buffer, length + 1);
+            if (output_pointer == NULL)
+            {
+                return false;
+            }
+            *output_pointer++ = ',';
+            if(output_buffer->format)
+            {
+                *output_pointer++ = ' ';
+            }
+            *output_pointer = '\0';
+            output_buffer->offset += length;
+        }
+        current_element = current_element->next;
+    }
+
+    output_pointer = ensure(output_buffer, 2);
+    if (output_pointer == NULL)
+    {
+        return false;
+    }
+    *output_pointer++ = ']';
+    *output_pointer = '\0';
+    output_buffer->depth--;
+
+    return true;
+}
+
+/* Build an object from the text. */
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
+{
+    cJSON *head = NULL; /* linked list head */
+    cJSON *current_item = NULL;
+
+    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
+    {
+        return false; /* to deeply nested */
+    }
+    input_buffer->depth++;
+
+    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
+    {
+        goto fail; /* not an object */
+    }
+
+    input_buffer->offset++;
+    buffer_skip_whitespace(input_buffer);
+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
+    {
+        goto success; /* empty object */
+    }
+
+    /* check if we skipped to the end of the buffer */
+    if (cannot_access_at_index(input_buffer, 0))
+    {
+        input_buffer->offset--;
+        goto fail;
+    }
+
+    /* step back to character in front of the first element */
+    input_buffer->offset--;
+    /* loop through the comma separated array elements */
+    do
+    {
+        /* allocate next item */
+        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+        if (new_item == NULL)
+        {
+            goto fail; /* allocation failure */
+        }
+
+        /* attach next item to list */
+        if (head == NULL)
+        {
+            /* start the linked list */
+            current_item = head = new_item;
+        }
+        else
+        {
+            /* add to the end and advance */
+            current_item->next = new_item;
+            new_item->prev = current_item;
+            current_item = new_item;
+        }
+
+        /* parse the name of the child */
+        input_buffer->offset++;
+        buffer_skip_whitespace(input_buffer);
+        if (!parse_string(current_item, input_buffer))
+        {
+            goto fail; /* failed to parse name */
+        }
+        buffer_skip_whitespace(input_buffer);
+
+        /* swap valuestring and string, because we parsed the name */
+        current_item->string = current_item->valuestring;
+        current_item->valuestring = NULL;
+
+        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
+        {
+            goto fail; /* invalid object */
+        }
+
+        /* parse the value */
+        input_buffer->offset++;
+        buffer_skip_whitespace(input_buffer);
+        if (!parse_value(current_item, input_buffer))
+        {
+            goto fail; /* failed to parse value */
+        }
+        buffer_skip_whitespace(input_buffer);
+    }
+    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
+    {
+        goto fail; /* expected end of object */
+    }
+
+success:
+    input_buffer->depth--;
+
+    item->type = cJSON_Object;
+    item->child = head;
+
+    input_buffer->offset++;
+    return true;
+
+fail:
+    if (head != NULL)
+    {
+        cJSON_Delete(head);
+    }
+
+    return false;
+}
+
+/* Render an object to text. */
+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
+{
+    unsigned char *output_pointer = NULL;
+    size_t length = 0;
+    cJSON *current_item = item->child;
+
+    if (output_buffer == NULL)
+    {
+        return false;
+    }
+
+    /* Compose the output: */
+    length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
+    output_pointer = ensure(output_buffer, length + 1);
+    if (output_pointer == NULL)
+    {
+        return false;
+    }
+
+    *output_pointer++ = '{';
+    output_buffer->depth++;
+    if (output_buffer->format)
+    {
+        *output_pointer++ = '\n';
+    }
+    output_buffer->offset += length;
+
+    while (current_item)
+    {
+        if (output_buffer->format)
+        {
+            size_t i;
+            output_pointer = ensure(output_buffer, output_buffer->depth);
+            if (output_pointer == NULL)
+            {
+                return false;
+            }
+            for (i = 0; i < output_buffer->depth; i++)
+            {
+                *output_pointer++ = '\t';
+            }
+            output_buffer->offset += output_buffer->depth;
+        }
+
+        /* print key */
+        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
+        {
+            return false;
+        }
+        update_offset(output_buffer);
+
+        length = (size_t) (output_buffer->format ? 2 : 1);
+        output_pointer = ensure(output_buffer, length);
+        if (output_pointer == NULL)
+        {
+            return false;
+        }
+        *output_pointer++ = ':';
+        if (output_buffer->format)
+        {
+            *output_pointer++ = '\t';
+        }
+        output_buffer->offset += length;
+
+        /* print value */
+        if (!print_value(current_item, output_buffer))
+        {
+            return false;
+        }
+        update_offset(output_buffer);
+
+        /* print comma if not last */
+        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
+        output_pointer = ensure(output_buffer, length + 1);
+        if (output_pointer == NULL)
+        {
+            return false;
+        }
+        if (current_item->next)
+        {
+            *output_pointer++ = ',';
+        }
+
+        if (output_buffer->format)
+        {
+            *output_pointer++ = '\n';
+        }
+        *output_pointer = '\0';
+        output_buffer->offset += length;
+
+        current_item = current_item->next;
+    }
+
+    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
+    if (output_pointer == NULL)
+    {
+        return false;
+    }
+    if (output_buffer->format)
+    {
+        size_t i;
+        for (i = 0; i < (output_buffer->depth - 1); i++)
+        {
+            *output_pointer++ = '\t';
+        }
+    }
+    *output_pointer++ = '}';
+    *output_pointer = '\0';
+    output_buffer->depth--;
+
+    return true;
+}
+
+/* Get Array size/item / object item. */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
+{
+    cJSON *child = NULL;
+    size_t size = 0;
+
+    if (array == NULL)
+    {
+        return 0;
+    }
+
+    child = array->child;
+
+    while(child != NULL)
+    {
+        size++;
+        child = child->next;
+    }
+
+    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
+
+    return (int)size;
+}
+
+static cJSON* get_array_item(const cJSON *array, size_t index)
+{
+    cJSON *current_child = NULL;
+
+    if (array == NULL)
+    {
+        return NULL;
+    }
+
+    current_child = array->child;
+    while ((current_child != NULL) && (index > 0))
+    {
+        index--;
+        current_child = current_child->next;
+    }
+
+    return current_child;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
+{
+    if (index < 0)
+    {
+        return NULL;
+    }
+
+    return get_array_item(array, (size_t)index);
+}
+
+static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
+{
+    cJSON *current_element = NULL;
+
+    if ((object == NULL) || (name == NULL))
+    {
+        return NULL;
+    }
+
+    current_element = object->child;
+    if (case_sensitive)
+    {
+        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
+        {
+            current_element = current_element->next;
+        }
+    }
+    else
+    {
+        while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
+        {
+            current_element = current_element->next;
+        }
+    }
+
+    if ((current_element == NULL) || (current_element->string == NULL)) {
+        return NULL;
+    }
+
+    return current_element;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
+{
+    return get_object_item(object, string, false);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
+{
+    return get_object_item(object, string, true);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
+{
+    return cJSON_GetObjectItem(object, string) ? 1 : 0;
+}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev, cJSON *item)
+{
+    prev->next = item;
+    item->prev = prev;
+}
+
+/* Utility for handling references. */
+static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
+{
+    cJSON *reference = NULL;
+    if (item == NULL)
+    {
+        return NULL;
+    }
+
+    reference = cJSON_New_Item(hooks);
+    if (reference == NULL)
+    {
+        return NULL;
+    }
+
+    memcpy(reference, item, sizeof(cJSON));
+    reference->string = NULL;
+    reference->type |= cJSON_IsReference;
+    reference->next = reference->prev = NULL;
+    return reference;
+}
+
+static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
+{
+    cJSON *child = NULL;
+
+    if ((item == NULL) || (array == NULL))
+    {
+        return false;
+    }
+
+    child = array->child;
+    /*
+     * To find the last item int array quickly, we use prev in array
+     */
+    if (child == NULL)
+    {
+        /* list is empty, start new one */
+        array->child = item;
+        item->prev = item;
+        item->next = NULL;
+    }
+    else
+    {
+        /* append to the end */
+        if (child->prev)
+        {
+            suffix_object(child->prev, item);
+            array->child->prev = item;
+        }
+        else
+        {
+            while (child->next)
+            {
+                child = child->next;
+            }
+            suffix_object(child, item);
+            array->child->prev = item;
+        }
+    }
+    return true;
+}
+
+/* Add item to array/object. */
+CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
+{
+    add_item_to_array(array, item);
+}
+
+#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+    #pragma GCC diagnostic push
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+/* helper function to cast away const */
+static void* cast_away_const(const void* string)
+{
+    return (void*)string;
+}
+#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+    #pragma GCC diagnostic pop
+#endif
+
+
+static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
+{
+    char *new_key = NULL;
+    int new_type = cJSON_Invalid;
+
+    if ((object == NULL) || (string == NULL) || (item == NULL))
+    {
+        return false;
+    }
+
+    if (constant_key)
+    {
+        new_key = (char*)cast_away_const(string);
+        new_type = item->type | cJSON_StringIsConst;
+    }
+    else
+    {
+        new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
+        if (new_key == NULL)
+        {
+            return false;
+        }
+
+        new_type = item->type & ~cJSON_StringIsConst;
+    }
+
+    if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
+    {
+        hooks->deallocate(item->string);
+    }
+
+    item->string = new_key;
+    item->type = new_type;
+
+    return add_item_to_array(object, item);
+}
+
+CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+{
+    add_item_to_object(object, string, item, &global_hooks, false);
+}
+
+/* Add an item to an object with constant string as key */
+CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
+{
+    add_item_to_object(object, string, item, &global_hooks, true);
+}
+
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+{
+    if (array == NULL)
+    {
+        return;
+    }
+
+    add_item_to_array(array, create_reference(item, &global_hooks));
+}
+
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
+{
+    if ((object == NULL) || (string == NULL))
+    {
+        return;
+    }
+
+    add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
+{
+    cJSON *null = cJSON_CreateNull();
+    if (add_item_to_object(object, name, null, &global_hooks, false))
+    {
+        return null;
+    }
+
+    cJSON_Delete(null);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
+{
+    cJSON *true_item = cJSON_CreateTrue();
+    if (add_item_to_object(object, name, true_item, &global_hooks, false))
+    {
+        return true_item;
+    }
+
+    cJSON_Delete(true_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
+{
+    cJSON *false_item = cJSON_CreateFalse();
+    if (add_item_to_object(object, name, false_item, &global_hooks, false))
+    {
+        return false_item;
+    }
+
+    cJSON_Delete(false_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
+{
+    cJSON *bool_item = cJSON_CreateBool(boolean);
+    if (add_item_to_object(object, name, bool_item, &global_hooks, false))
+    {
+        return bool_item;
+    }
+
+    cJSON_Delete(bool_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
+{
+    cJSON *number_item = cJSON_CreateNumber(number);
+    if (add_item_to_object(object, name, number_item, &global_hooks, false))
+    {
+        return number_item;
+    }
+
+    cJSON_Delete(number_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
+{
+    cJSON *string_item = cJSON_CreateString(string);
+    if (add_item_to_object(object, name, string_item, &global_hooks, false))
+    {
+        return string_item;
+    }
+
+    cJSON_Delete(string_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
+{
+    cJSON *raw_item = cJSON_CreateRaw(raw);
+    if (add_item_to_object(object, name, raw_item, &global_hooks, false))
+    {
+        return raw_item;
+    }
+
+    cJSON_Delete(raw_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
+{
+    cJSON *object_item = cJSON_CreateObject();
+    if (add_item_to_object(object, name, object_item, &global_hooks, false))
+    {
+        return object_item;
+    }
+
+    cJSON_Delete(object_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
+{
+    cJSON *array = cJSON_CreateArray();
+    if (add_item_to_object(object, name, array, &global_hooks, false))
+    {
+        return array;
+    }
+
+    cJSON_Delete(array);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
+{
+    if ((parent == NULL) || (item == NULL))
+    {
+        return NULL;
+    }
+
+    if (item->prev != NULL)
+    {
+        /* not the first element */
+        item->prev->next = item->next;
+    }
+    if (item->next != NULL)
+    {
+        /* not the last element */
+        item->next->prev = item->prev;
+    }
+
+    if (item == parent->child)
+    {
+        /* first element */
+        parent->child = item->next;
+    }
+    /* make sure the detached item doesn't point anywhere anymore */
+    item->prev = NULL;
+    item->next = NULL;
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
+{
+    if (which < 0)
+    {
+        return NULL;
+    }
+
+    return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
+{
+    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
+{
+    cJSON *to_detach = cJSON_GetObjectItem(object, string);
+
+    return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+    cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
+
+    return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
+{
+    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+    cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
+}
+
+/* Replace array/object items with new ones. */
+CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+    cJSON *after_inserted = NULL;
+
+    if (which < 0)
+    {
+        return;
+    }
+
+    after_inserted = get_array_item(array, (size_t)which);
+    if (after_inserted == NULL)
+    {
+        add_item_to_array(array, newitem);
+        return;
+    }
+
+    newitem->next = after_inserted;
+    newitem->prev = after_inserted->prev;
+    after_inserted->prev = newitem;
+    if (after_inserted == array->child)
+    {
+        array->child = newitem;
+    }
+    else
+    {
+        newitem->prev->next = newitem;
+    }
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
+{
+    if ((parent == NULL) || (replacement == NULL) || (item == NULL))
+    {
+        return false;
+    }
+
+    if (replacement == item)
+    {
+        return true;
+    }
+
+    replacement->next = item->next;
+    replacement->prev = item->prev;
+
+    if (replacement->next != NULL)
+    {
+        replacement->next->prev = replacement;
+    }
+
+    if (parent->child == item)
+    {
+        parent->child = replacement;
+    }
+    else
+    {   /*
+         * To find the last item int array quickly, we use prev in array.
+         * We can't modify the last item's next pointer where this item was the parent's child
+         */
+        if (replacement->prev != NULL)
+        {
+            replacement->prev->next = replacement;
+        }
+    }
+
+    item->next = NULL;
+    item->prev = NULL;
+    cJSON_Delete(item);
+
+    return true;
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+    if (which < 0)
+    {
+        return;
+    }
+
+    cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
+}
+
+static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
+{
+    if ((replacement == NULL) || (string == NULL))
+    {
+        return false;
+    }
+
+    /* replace the name in the replacement */
+    if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
+    {
+        cJSON_free(replacement->string);
+    }
+    replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+    replacement->type &= ~cJSON_StringIsConst;
+
+    cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
+
+    return true;
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
+{
+    replace_item_in_object(object, string, newitem, false);
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
+{
+    replace_item_in_object(object, string, newitem, true);
+}
+
+/* Create basic types: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_NULL;
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_True;
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_False;
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = boolean ? cJSON_True : cJSON_False;
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_Number;
+        item->valuedouble = num;
+
+        /* use saturation in case of overflow */
+        if (num >= INT_MAX)
+        {
+            item->valueint = INT_MAX;
+        }
+        else if (num <= (double)INT_MIN)
+        {
+            item->valueint = INT_MIN;
+        }
+        else
+        {
+            item->valueint = (int)num;
+        }
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_String;
+        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+        if(!item->valuestring)
+        {
+            cJSON_Delete(item);
+            return NULL;
+        }
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if (item != NULL)
+    {
+        item->type = cJSON_String | cJSON_IsReference;
+        item->valuestring = (char*)cast_away_const(string);
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if (item != NULL) {
+        item->type = cJSON_Object | cJSON_IsReference;
+        item->child = (cJSON*)cast_away_const(child);
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if (item != NULL) {
+        item->type = cJSON_Array | cJSON_IsReference;
+        item->child = (cJSON*)cast_away_const(child);
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_Raw;
+        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
+        if(!item->valuestring)
+        {
+            cJSON_Delete(item);
+            return NULL;
+        }
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type=cJSON_Array;
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if (item)
+    {
+        item->type = cJSON_Object;
+    }
+
+    return item;
+}
+
+/* Create Arrays: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
+{
+    size_t i = 0;
+    cJSON *n = NULL;
+    cJSON *p = NULL;
+    cJSON *a = NULL;
+
+    if ((count < 0) || (numbers == NULL))
+    {
+        return NULL;
+    }
+
+    a = cJSON_CreateArray();
+    for(i = 0; a && (i < (size_t)count); i++)
+    {
+        n = cJSON_CreateNumber(numbers[i]);
+        if (!n)
+        {
+            cJSON_Delete(a);
+            return NULL;
+        }
+        if(!i)
+        {
+            a->child = n;
+        }
+        else
+        {
+            suffix_object(p, n);
+        }
+        p = n;
+    }
+
+    return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
+{
+    size_t i = 0;
+    cJSON *n = NULL;
+    cJSON *p = NULL;
+    cJSON *a = NULL;
+
+    if ((count < 0) || (numbers == NULL))
+    {
+        return NULL;
+    }
+
+    a = cJSON_CreateArray();
+
+    for(i = 0; a && (i < (size_t)count); i++)
+    {
+        n = cJSON_CreateNumber((double)numbers[i]);
+        if(!n)
+        {
+            cJSON_Delete(a);
+            return NULL;
+        }
+        if(!i)
+        {
+            a->child = n;
+        }
+        else
+        {
+            suffix_object(p, n);
+        }
+        p = n;
+    }
+
+    return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
+{
+    size_t i = 0;
+    cJSON *n = NULL;
+    cJSON *p = NULL;
+    cJSON *a = NULL;
+
+    if ((count < 0) || (numbers == NULL))
+    {
+        return NULL;
+    }
+
+    a = cJSON_CreateArray();
+
+    for(i = 0;a && (i < (size_t)count); i++)
+    {
+        n = cJSON_CreateNumber(numbers[i]);
+        if(!n)
+        {
+            cJSON_Delete(a);
+            return NULL;
+        }
+        if(!i)
+        {
+            a->child = n;
+        }
+        else
+        {
+            suffix_object(p, n);
+        }
+        p = n;
+    }
+
+    return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
+{
+    size_t i = 0;
+    cJSON *n = NULL;
+    cJSON *p = NULL;
+    cJSON *a = NULL;
+
+    if ((count < 0) || (strings == NULL))
+    {
+        return NULL;
+    }
+
+    a = cJSON_CreateArray();
+
+    for (i = 0; a && (i < (size_t)count); i++)
+    {
+        n = cJSON_CreateString(strings[i]);
+        if(!n)
+        {
+            cJSON_Delete(a);
+            return NULL;
+        }
+        if(!i)
+        {
+            a->child = n;
+        }
+        else
+        {
+            suffix_object(p,n);
+        }
+        p = n;
+    }
+
+    return a;
+}
+
+/* Duplication */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
+{
+    cJSON *newitem = NULL;
+    cJSON *child = NULL;
+    cJSON *next = NULL;
+    cJSON *newchild = NULL;
+
+    /* Bail on bad ptr */
+    if (!item)
+    {
+        goto fail;
+    }
+    /* Create new item */
+    newitem = cJSON_New_Item(&global_hooks);
+    if (!newitem)
+    {
+        goto fail;
+    }
+    /* Copy over all vars */
+    newitem->type = item->type & (~cJSON_IsReference);
+    newitem->valueint = item->valueint;
+    newitem->valuedouble = item->valuedouble;
+    if (item->valuestring)
+    {
+        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
+        if (!newitem->valuestring)
+        {
+            goto fail;
+        }
+    }
+    if (item->string)
+    {
+        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
+        if (!newitem->string)
+        {
+            goto fail;
+        }
+    }
+    /* If non-recursive, then we're done! */
+    if (!recurse)
+    {
+        return newitem;
+    }
+    /* Walk the ->next chain for the child. */
+    child = item->child;
+    while (child != NULL)
+    {
+        newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
+        if (!newchild)
+        {
+            goto fail;
+        }
+        if (next != NULL)
+        {
+            /* If newitem->child already set, then crosswire ->prev and ->next and move on */
+            next->next = newchild;
+            newchild->prev = next;
+            next = newchild;
+        }
+        else
+        {
+            /* Set newitem->child and move to it */
+            newitem->child = newchild;
+            next = newchild;
+        }
+        child = child->next;
+    }
+
+    return newitem;
+
+fail:
+    if (newitem != NULL)
+    {
+        cJSON_Delete(newitem);
+    }
+
+    return NULL;
+}
+
+static void skip_oneline_comment(char **input)
+{
+    *input += static_strlen("//");
+
+    for (; (*input)[0] != '\0'; ++(*input))
+    {
+        if ((*input)[0] == '\n') {
+            *input += static_strlen("\n");
+            return;
+        }
+    }
+}
+
+static void skip_multiline_comment(char **input)
+{
+    *input += static_strlen("/*");
+
+    for (; (*input)[0] != '\0'; ++(*input))
+    {
+        if (((*input)[0] == '*') && ((*input)[1] == '/'))
+        {
+            *input += static_strlen("*/");
+            return;
+        }
+    }
+}
+
+static void minify_string(char **input, char **output) {
+    (*output)[0] = (*input)[0];
+    *input += static_strlen("\"");
+    *output += static_strlen("\"");
+
+
+    for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
+        (*output)[0] = (*input)[0];
+
+        if ((*input)[0] == '\"') {
+            (*output)[0] = '\"';
+            *input += static_strlen("\"");
+            *output += static_strlen("\"");
+            return;
+        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
+            (*output)[1] = (*input)[1];
+            *input += static_strlen("\"");
+            *output += static_strlen("\"");
+        }
+    }
+}
+
+CJSON_PUBLIC(void) cJSON_Minify(char *json)
+{
+    char *into = json;
+
+    if (json == NULL)
+    {
+        return;
+    }
+
+    while (json[0] != '\0')
+    {
+        switch (json[0])
+        {
+            case ' ':
+            case '\t':
+            case '\r':
+            case '\n':
+                json++;
+                break;
+
+            case '/':
+                if (json[1] == '/')
+                {
+                    skip_oneline_comment(&json);
+                }
+                else if (json[1] == '*')
+                {
+                    skip_multiline_comment(&json);
+                } else {
+                    json++;
+                }
+                break;
+
+            case '\"':
+                minify_string(&json, (char**)&into);
+                break;
+
+            default:
+                into[0] = json[0];
+                json++;
+                into++;
+        }
+    }
+
+    /* and null-terminate. */
+    *into = '\0';
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Invalid;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_False;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xff) == cJSON_True;
+}
+
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & (cJSON_True | cJSON_False)) != 0;
+}
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_NULL;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Number;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_String;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Array;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Object;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Raw;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
+{
+    if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
+    {
+        return false;
+    }
+
+    /* check if type is valid */
+    switch (a->type & 0xFF)
+    {
+        case cJSON_False:
+        case cJSON_True:
+        case cJSON_NULL:
+        case cJSON_Number:
+        case cJSON_String:
+        case cJSON_Raw:
+        case cJSON_Array:
+        case cJSON_Object:
+            break;
+
+        default:
+            return false;
+    }
+
+    /* identical objects are equal */
+    if (a == b)
+    {
+        return true;
+    }
+
+    switch (a->type & 0xFF)
+    {
+        /* in these cases and equal type is enough */
+        case cJSON_False:
+        case cJSON_True:
+        case cJSON_NULL:
+            return true;
+
+        case cJSON_Number:
+            if (compare_double(a->valuedouble, b->valuedouble))
+            {
+                return true;
+            }
+            return false;
+
+        case cJSON_String:
+        case cJSON_Raw:
+            if ((a->valuestring == NULL) || (b->valuestring == NULL))
+            {
+                return false;
+            }
+            if (strcmp(a->valuestring, b->valuestring) == 0)
+            {
+                return true;
+            }
+
+            return false;
+
+        case cJSON_Array:
+        {
+            cJSON *a_element = a->child;
+            cJSON *b_element = b->child;
+
+            for (; (a_element != NULL) && (b_element != NULL);)
+            {
+                if (!cJSON_Compare(a_element, b_element, case_sensitive))
+                {
+                    return false;
+                }
+
+                a_element = a_element->next;
+                b_element = b_element->next;
+            }
+
+            /* one of the arrays is longer than the other */
+            if (a_element != b_element) {
+                return false;
+            }
+
+            return true;
+        }
+
+        case cJSON_Object:
+        {
+            cJSON *a_element = NULL;
+            cJSON *b_element = NULL;
+            cJSON_ArrayForEach(a_element, a)
+            {
+                /* TODO This has O(n^2) runtime, which is horrible! */
+                b_element = get_object_item(b, a_element->string, case_sensitive);
+                if (b_element == NULL)
+                {
+                    return false;
+                }
+
+                if (!cJSON_Compare(a_element, b_element, case_sensitive))
+                {
+                    return false;
+                }
+            }
+
+            /* doing this twice, once on a and b to prevent true comparison if a subset of b
+             * TODO: Do this the proper way, this is just a fix for now */
+            cJSON_ArrayForEach(b_element, b)
+            {
+                a_element = get_object_item(a, b_element->string, case_sensitive);
+                if (a_element == NULL)
+                {
+                    return false;
+                }
+
+                if (!cJSON_Compare(b_element, a_element, case_sensitive))
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        default:
+            return false;
+    }
+}
+
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
+{
+    return global_hooks.allocate(size);
+}
+
+CJSON_PUBLIC(void) cJSON_free(void *object)
+{
+    global_hooks.deallocate(object);
+}
diff --git a/third_party/cjson_library/cJSON.h b/third_party/cjson_library/cJSON.h
new file mode 100644
index 0000000..9d28b24
--- /dev/null
+++ b/third_party/cjson_library/cJSON.h
@@ -0,0 +1,292 @@
+/*
+  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+  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.
+*/
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
+#define __WINDOWS__
+#endif
+
+#ifdef __WINDOWS__
+
+/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention.  For windows you have 3 define options:
+
+CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
+CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
+CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
+
+For *nix builds that support visibility attribute, you can define similar behavior by
+
+setting default visibility to hidden by adding
+-fvisibility=hidden (for gcc)
+or
+-xldscope=hidden (for sun cc)
+to CFLAGS
+
+then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
+
+*/
+
+#define CJSON_CDECL __cdecl
+#define CJSON_STDCALL __stdcall
+
+/* export symbols by default, this is necessary for copy pasting the C and header file */
+#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_EXPORT_SYMBOLS
+#endif
+
+#if defined(CJSON_HIDE_SYMBOLS)
+#define CJSON_PUBLIC(type)   type CJSON_STDCALL
+#elif defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_PUBLIC(type)   __declspec(dllexport) type CJSON_STDCALL
+#elif defined(CJSON_IMPORT_SYMBOLS)
+#define CJSON_PUBLIC(type)   __declspec(dllimport) type CJSON_STDCALL
+#endif
+#else /* !__WINDOWS__ */
+#define CJSON_CDECL
+#define CJSON_STDCALL
+
+#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
+#define CJSON_PUBLIC(type)   __attribute__((visibility("default"))) type
+#else
+#define CJSON_PUBLIC(type) type
+#endif
+#endif
+
+/* project version */
+#define CJSON_VERSION_MAJOR 1
+#define CJSON_VERSION_MINOR 7
+#define CJSON_VERSION_PATCH 12
+
+#include <stddef.h>
+
+/* cJSON Types: */
+#define cJSON_Invalid (0)
+#define cJSON_False  (1 << 0)
+#define cJSON_True   (1 << 1)
+#define cJSON_NULL   (1 << 2)
+#define cJSON_Number (1 << 3)
+#define cJSON_String (1 << 4)
+#define cJSON_Array  (1 << 5)
+#define cJSON_Object (1 << 6)
+#define cJSON_Raw    (1 << 7) /* raw json */
+
+#define cJSON_IsReference 256
+#define cJSON_StringIsConst 512
+
+/* The cJSON structure: */
+typedef struct cJSON
+{
+    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+    struct cJSON *next;
+    struct cJSON *prev;
+    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+    struct cJSON *child;
+
+    /* The type of the item, as above. */
+    int type;
+
+    /* The item's string, if type==cJSON_String  and type == cJSON_Raw */
+    char *valuestring;
+    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
+    int valueint;
+    /* The item's number, if type==cJSON_Number */
+    double valuedouble;
+
+    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+    char *string;
+} cJSON;
+
+typedef struct cJSON_Hooks
+{
+      /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
+      void *(CJSON_CDECL *malloc_fn)(size_t sz);
+      void (CJSON_CDECL *free_fn)(void *ptr);
+} cJSON_Hooks;
+
+typedef int cJSON_bool;
+
+/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
+ * This is to prevent stack overflows. */
+#ifndef CJSON_NESTING_LIMIT
+#define CJSON_NESTING_LIMIT 1000
+#endif
+
+/* Precision of double variables comparison */
+#ifndef CJSON_DOUBLE_PRECISION
+#define CJSON_DOUBLE_PRECISION .0000000000000001
+#endif
+
+/* returns the version of cJSON as a string */
+CJSON_PUBLIC(const char*) cJSON_Version(void);
+
+/* Supply malloc, realloc and free functions to cJSON */
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
+
+/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
+
+/* Render a cJSON entity to text for transfer/storage. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
+/* Render a cJSON entity to text for transfer/storage without any formatting. */
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
+/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
+/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
+/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
+/* Delete a cJSON entity and all subentities. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
+
+/* Returns the number of items in an array (or object). */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
+/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
+/* Get item "string" from object. Case insensitive. */
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
+
+/* Check if the item is a string and return its valuestring */
+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
+
+/* These functions check the type of an item */
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
+
+/* These calls create a cJSON item of the appropriate type. */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
+/* raw json */
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
+
+/* Create a string where valuestring references a string so
+ * it will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
+/* Create an object/array that only references it's elements so
+ * they will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
+
+/* These utilities create an Array of count items.
+ * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
+
+/* Append item to the specified array/object. */
+CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
+ * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
+ * writing to `item->string` */
+CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+
+/* Remove/Detach items from Arrays/Objects. */
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
+
+/* Update array items. */
+CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
+CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
+
+/* Duplicate a cJSON item */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
+ * need to be released. With recurse!=0, it will duplicate any children connected to the item.
+ * The item->next and ->prev pointers are always zero on return from Duplicate. */
+/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
+ * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
+
+/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
+ * The input pointer json cannot point to a read-only address area, such as a string constant, 
+ * but should point to a readable and writable adress area. */
+CJSON_PUBLIC(void) cJSON_Minify(char *json);
+
+/* Helper functions for creating and adding items to an object at the same time.
+ * They return the added item or NULL on failure. */
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
+
+/* When assigning an integer value, it needs to be propagated to valuedouble too. */
+#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
+/* helper for the cJSON_SetNumberValue macro */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
+#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
+
+/* Macro for iterating over an array or object */
+#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
+
+/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
+CJSON_PUBLIC(void) cJSON_free(void *object);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tool/libclang_config.yaml b/tool/libclang_config.yaml
new file mode 100644
index 0000000..575a440
--- /dev/null
+++ b/tool/libclang_config.yaml
@@ -0,0 +1,76 @@
+# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Config file for generating the libclang bindings used by this package.
+
+# ===================== GENERATING BINDINGS =====================
+#    cd to `tool`, and run -
+#    dart ../bin/generate.dart --config libclang_config.yaml
+# ===============================================================
+
+output: '../lib/src/header_parser/clang_bindings/clang_bindings.dart'
+libclang-dylib-folder: 'wrapped_libclang'
+sort: true
+compiler-opts: '-I/usr/lib/llvm-9/include/ -I/usr/lib/llvm-10/include/ -I/usr/local/opt/llvm/include/ -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/'
+headers:
+  - 'wrapped_libclang/wrapper.c'
+header-filter:
+  include:
+    - wrapper.c
+    - Index.h
+    - CXString.h
+
+enums:
+  include:
+    names:
+      - CXChildVisitResult
+      - CXCursorKind
+      - CXTypeKind
+      - CXDiagnosticDisplayOptions
+      - CXTranslationUnit_Flags
+
+structs:
+  include:
+    names:
+      - CXCursor
+      - CXType
+
+functions:
+  include:
+    names:
+      - clang_createIndex
+      - clang_disposeIndex
+      - clang_getNumDiagnostics
+      - clang_getDiagnostic
+      - clang_disposeDiagnostic
+      - clang_parseTranslationUnit
+      - clang_disposeTranslationUnit
+      - clang_getCString_wrap
+      - clang_disposeString_wrap
+      - clang_getCursorKind_wrap
+      - clang_getCursorKindSpelling_wrap
+      - clang_getCursorType_wrap
+      - clang_getTypeSpelling_wrap
+      - clang_getTypeKindSpelling_wrap
+      - clang_getResultType_wrap
+      - clang_getPointeeType_wrap
+      - clang_getCanonicalType_wrap
+      - clang_Type_getNamedType_wrap
+      - clang_getTypeDeclaration_wrap
+      - clang_getTypedefDeclUnderlyingType_wrap
+      - clang_getCursorSpelling_wrap
+      - clang_getTranslationUnitCursor_wrap
+      - clang_formatDiagnostic_wrap
+      - clang_visitChildren_wrap
+      - clang_Cursor_getNumArguments_wrap
+      - clang_Cursor_getArgument_wrap
+      - clang_getNumArgTypes_wrap
+      - clang_getArgType_wrap
+      - clang_getEnumConstantDeclValue_wrap
+      - clang_Cursor_getBriefCommentText_wrap
+      - clang_getCursorLocation_wrap
+      - clang_getFileLocation_wrap
+      - clang_getFileName_wrap
+      - clang_getNumElements_wrap
+      - clang_getArrayElementType_wrap
diff --git a/tool/wrapped_libclang/.gitignore b/tool/wrapped_libclang/.gitignore
new file mode 100644
index 0000000..2b64ac7
--- /dev/null
+++ b/tool/wrapped_libclang/.gitignore
@@ -0,0 +1,12 @@
+# general gitignore for CMake.
+CMakeLists.txt.user
+CMakeCache.txt
+CMakeFiles
+CMakeScripts
+Testing
+Makefile
+cmake_install.cmake
+install_manifest.txt
+compile_commands.json
+CTestTestfile.cmake
+_deps
diff --git a/tool/wrapped_libclang/build.dart b/tool/wrapped_libclang/build.dart
new file mode 100644
index 0000000..20971b1
--- /dev/null
+++ b/tool/wrapped_libclang/build.dart
@@ -0,0 +1,216 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// =======================================================================
+/// =============== Build script to generate dyamic library ===============
+/// =======================================================================
+/// This Script effectively calls the following (but user can provide
+/// command line args which will replace the defaults shown below)-
+///
+/// Linux:
+/// ```
+/// clang -I/usr/lib/llvm-9/include/ -I/usr/lib/llvm-10/include/ -lclang -shared -fpic wrapper.c -o libwrapped_clang.so
+/// ```
+/// MacOS:
+/// ```
+/// clang -I/usr/local/opt/llvm/include/ -L/usr/local/opt/llvm/lib/ -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ -v -lclang -shared -fpic wrapper.c -o libwrapped_clang.dylib
+/// ```
+/// Windows:
+/// ```
+/// clang -IC:\Progra~1\LLVM\include -LC:\Progra~1\LLVM\lib -llibclang -shared wrapper.c -o wrapped_clang.dll -Wl,/DEF:wrapper.def
+/// del wrapped_clang.exp
+/// del wrapped_clang.lib
+/// ```
+/// =======================================================================
+/// =======================================================================
+/// =======================================================================
+
+import 'dart:io';
+import 'package:args/args.dart';
+import 'package:meta/meta.dart';
+
+const MACOS = 'macos';
+const WINDOWS = 'windows';
+const LINUX = 'linux';
+
+/// Default platform options.
+Map<String, Options> platformOptions = {
+  LINUX: Options(
+    outputfilename: 'libwrapped_clang.so',
+    sharedFlag: '-shared',
+    inputHeader: 'wrapper.c',
+    fPIC: '-fpic',
+    ldLibFlag: '-lclang',
+    headerIncludes: [
+      '-I/usr/lib/llvm-9/include/',
+      '-I/usr/lib/llvm-10/include/',
+    ],
+  ),
+  WINDOWS: Options(
+    outputfilename: 'wrapped_clang.dll',
+    sharedFlag: '-shared',
+    inputHeader: 'wrapper.c',
+    moduleDefPath: '-Wl,/DEF:wrapper.def',
+    ldLibFlag: '-llibclang',
+    headerIncludes: [
+      r'-IC:\Progra~1\LLVM\include',
+    ],
+    libIncludes: [
+      r'-LC:\Progra~1\LLVM\lib',
+    ],
+  ),
+  MACOS: Options(
+    outputfilename: 'libwrapped_clang.dylib',
+    sharedFlag: '-shared',
+    inputHeader: 'wrapper.c',
+    fPIC: '-fpic',
+    ldLibFlag: '-lclang',
+    headerIncludes: [
+      '-I/usr/local/opt/llvm/include/',
+      '-I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/',
+    ],
+    libIncludes: [
+      '-L/usr/local/opt/llvm/lib/',
+    ],
+  ),
+};
+
+void main(List<String> arguments) {
+  print('Building Dynamic Library for libclang wrapper... ');
+  final options = getPlatformOptions();
+
+  // Updates header/lib includes in platform options.
+  changeIncludesUsingCmdArgs(arguments, options);
+
+  // Run clang compiler to generate the dynamic library.
+  final ProcessResult result = runClangProcess(options);
+  printSuccess(result, options);
+}
+
+/// Calls the clang compiler.
+ProcessResult runClangProcess(Options options) {
+  final result = Process.runSync(
+    'clang',
+    [
+      ...options.headerIncludes,
+      ...options.libIncludes,
+      options.ldLibFlag,
+      options.sharedFlag,
+      options.fPIC,
+      options.inputHeader,
+      '-o',
+      options.outputfilename,
+      options.moduleDefPath,
+    ],
+  );
+  return result;
+}
+
+/// Prints success message (or process error if any).
+void printSuccess(ProcessResult result, Options options) {
+  print(result.stdout);
+  if ((result.stderr as String).isEmpty) {
+    print('Generated file: ${options.outputfilename}');
+  } else {
+    print(result.stderr);
+  }
+}
+
+ArgResults getArgResults(List<String> args) {
+  final parser = ArgParser(allowTrailingOptions: true);
+  parser.addSeparator(
+      'Build Script to generate dynamic library used by this package:');
+  parser.addMultiOption('include-header',
+      abbr: 'I', help: 'Path to header include directories');
+  parser.addMultiOption('include-lib',
+      abbr: 'L', help: 'Path to library include directories');
+  parser.addFlag(
+    'help',
+    abbr: 'h',
+    help: 'prints this usage',
+    negatable: false,
+  );
+
+  ArgResults results;
+  try {
+    results = parser.parse(args);
+
+    if (results.wasParsed('help')) {
+      print(parser.usage);
+      exit(0);
+    }
+  } catch (e) {
+    print(e);
+    print(parser.usage);
+    exit(1);
+  }
+
+  return results;
+}
+
+/// Use cmd args(if any) to change header/lib include paths.
+void changeIncludesUsingCmdArgs(List<String> arguments, Options options) {
+  final argResult = getArgResults(arguments);
+  if (argResult.wasParsed('include-header')) {
+    options.headerIncludes = (argResult['include-header'] as List<String>)
+        .map((header) => '-I$header')
+        .toList();
+  }
+  if (argResult.wasParsed('include-lib')) {
+    options.libIncludes = (argResult['include-lib'] as List<String>)
+        .map((lib) => '-L$lib')
+        .toList();
+  }
+}
+
+/// Get options based on current platform.
+Options getPlatformOptions() {
+  if (Platform.isMacOS) {
+    return platformOptions[MACOS];
+  } else if (Platform.isWindows) {
+    return platformOptions[WINDOWS];
+  } else if (Platform.isLinux) {
+    return platformOptions[LINUX];
+  } else {
+    throw Exception('Unknown Platform.');
+  }
+}
+
+/// Hold options which would be passed to clang.
+class Options {
+  /// Name of dynamic library to generate.
+  final String outputfilename;
+
+  /// Tells compiler to generate a shared library.
+  final String sharedFlag;
+
+  /// Flag for generating Position Independant Code (Not used on windows).
+  final String fPIC;
+
+  /// Input file.
+  final String inputHeader;
+
+  /// Path to `.def` file containing symbols to export, windows use only.
+  final String moduleDefPath;
+
+  /// Path to header files.
+  List<String> headerIncludes;
+
+  /// Path to dynamic/static libraries
+  List<String> libIncludes;
+
+  /// Linker flag for linking to libclang.
+  final String ldLibFlag;
+
+  Options({
+    @required this.outputfilename,
+    @required this.sharedFlag,
+    @required this.inputHeader,
+    @required this.ldLibFlag,
+    this.headerIncludes = const [],
+    this.libIncludes = const [],
+    this.fPIC = '',
+    this.moduleDefPath = '',
+  });
+}
diff --git a/tool/wrapped_libclang/wrapper.c b/tool/wrapped_libclang/wrapper.c
new file mode 100644
index 0000000..2e0e375
--- /dev/null
+++ b/tool/wrapped_libclang/wrapper.c
@@ -0,0 +1,274 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include <clang-c/Index.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// utility.
+#define aloc(T) ((T *)malloc(sizeof(T)))
+CXCursor *ptrToCXCursor(CXCursor t)
+{
+    CXCursor *c = aloc(CXCursor);
+    *c = t;
+    return c;
+}
+CXString *ptrToCXString(CXString t)
+{
+    CXString *c = aloc(CXString);
+    *c = t;
+    return c;
+}
+CXType *ptrToCXType(CXType t)
+{
+    CXType *c = aloc(CXType);
+    *c = t;
+    return c;
+}
+CXSourceLocation *ptrToCXSourceLocation(CXSourceLocation t)
+{
+    CXSourceLocation *c = aloc(CXSourceLocation);
+    *c = t;
+    return c;
+}
+// START ===== Functions for testing libclang behavior in C.
+enum CXChildVisitResult visitor_for_test_in_c(CXCursor cursor, CXCursor parent, CXClientData clientData)
+{
+    printf("Cursor- kind: %s, name: %s\n", clang_getCString(clang_getCursorKindSpelling(clang_getCursorKind(cursor))), clang_getCString(clang_getCursorSpelling(cursor)));
+    return CXChildVisit_Continue;
+}
+int test_in_c()
+{
+    printf("==========================run==========================\n");
+    CXIndex Index = clang_createIndex(0, 0);
+    CXTranslationUnit TU = clang_parseTranslationUnit(Index,
+                                                      "./test.h", 0, 0, NULL, 0, CXTranslationUnit_None);
+
+    if (TU == NULL)
+    {
+        printf("Error creating TU\n");
+        return 0;
+    }
+
+    CXCursor root = clang_getTranslationUnitCursor(TU);
+
+    unsigned a = clang_visitChildren(root, visitor_for_test_in_c, NULL);
+
+    clang_disposeTranslationUnit(TU);
+    clang_disposeIndex(Index);
+    printf("\n==========================end==========================\n");
+    return 0;
+}
+// END ===== Functions for testing libclang behavior in C ============================
+
+// START ===== WRAPPER FUNCTIONS =====================
+
+const char *clang_getCString_wrap(CXString *string)
+{
+    const char *a = clang_getCString(*string);
+
+    return a;
+}
+
+void clang_disposeString_wrap(CXString *string)
+{
+    clang_disposeString(*string);
+    free(string);
+    return;
+}
+
+enum CXCursorKind clang_getCursorKind_wrap(CXCursor *cursor)
+{
+    return clang_getCursorKind(*cursor);
+}
+
+CXString *clang_getCursorKindSpelling_wrap(enum CXCursorKind kind)
+{
+    return ptrToCXString(clang_getCursorKindSpelling(kind));
+}
+
+CXType *clang_getCursorType_wrap(CXCursor *cursor)
+{
+    return ptrToCXType(clang_getCursorType(*cursor));
+}
+
+CXString *clang_getTypeSpelling_wrap(CXType *type)
+{
+    return ptrToCXString(clang_getTypeSpelling(*type));
+}
+
+CXString *clang_getTypeKindSpelling_wrap(enum CXTypeKind typeKind)
+{
+    return ptrToCXString(clang_getTypeKindSpelling(typeKind));
+}
+
+CXType *clang_getResultType_wrap(CXType *functionType)
+{
+    return ptrToCXType(clang_getResultType(*functionType));
+}
+
+CXType *clang_getPointeeType_wrap(CXType *pointerType)
+{
+    return ptrToCXType(clang_getPointeeType(*pointerType));
+}
+
+CXType *clang_getCanonicalType_wrap(CXType *typerefType)
+{
+    return ptrToCXType(clang_getCanonicalType(*typerefType));
+}
+
+CXType *clang_Type_getNamedType_wrap(CXType *elaboratedType)
+{
+    return ptrToCXType(clang_Type_getNamedType(*elaboratedType));
+}
+
+CXCursor *clang_getTypeDeclaration_wrap(CXType *cxtype)
+{
+    return ptrToCXCursor(clang_getTypeDeclaration(*cxtype));
+}
+
+CXType *clang_getTypedefDeclUnderlyingType_wrap(CXCursor *cxcursor)
+{
+    return ptrToCXType(clang_getTypedefDeclUnderlyingType(*cxcursor));
+}
+
+/** The name of parameter, struct, typedef. */
+CXString *clang_getCursorSpelling_wrap(CXCursor *cursor)
+{
+    return ptrToCXString(clang_getCursorSpelling(*cursor));
+}
+
+CXCursor *clang_getTranslationUnitCursor_wrap(CXTranslationUnit tu)
+{
+    return ptrToCXCursor(clang_getTranslationUnitCursor(tu));
+}
+
+CXString *clang_formatDiagnostic_wrap(CXDiagnostic diag, int opts)
+{
+    return ptrToCXString(clang_formatDiagnostic(diag, opts));
+}
+
+// alternative typedef for [CXCursorVisitor] using pointer for passing cursor and parent
+// instead of passing by value
+typedef enum CXChildVisitResult (*ModifiedCXCursorVisitor)(CXCursor *cursor,
+                                                           CXCursor *parent,
+                                                           CXClientData client_data);
+
+// holds Pointers to Dart function received from [clang_visitChildren_wrap]
+// called in [_visitorWrap]
+struct _stackForVisitChildren
+{
+    ModifiedCXCursorVisitor modifiedVisitor;
+    struct _stackForVisitChildren *link;
+} * _visitorTop, *_visitorTemp;
+void _push(ModifiedCXCursorVisitor modifiedVisitor)
+{
+    if (_visitorTop == NULL)
+    {
+        _visitorTop = (struct _stackForVisitChildren *)malloc(1 * sizeof(struct _stackForVisitChildren));
+        _visitorTop->link = NULL;
+        _visitorTop->modifiedVisitor = modifiedVisitor;
+    }
+    else
+    {
+        _visitorTemp = (struct _stackForVisitChildren *)malloc(1 * sizeof(struct _stackForVisitChildren));
+        _visitorTemp->link = _visitorTop;
+        _visitorTemp->modifiedVisitor = modifiedVisitor;
+        _visitorTop = _visitorTemp;
+    }
+}
+void _pop()
+{
+    _visitorTemp = _visitorTop;
+
+    if (_visitorTemp == NULL)
+    {
+        printf("\n Error, Wrapper.C : Trying to pop from empty stack");
+        return;
+    }
+    else
+        _visitorTemp = _visitorTop->link;
+    free(_visitorTop);
+    _visitorTop = _visitorTemp;
+}
+ModifiedCXCursorVisitor _top()
+{
+    return _visitorTop->modifiedVisitor;
+}
+// Do not write binding for this function.
+// used by [clang_visitChildren_wrap].
+enum CXChildVisitResult
+_visitorwrap(CXCursor cursor, CXCursor parent, CXClientData clientData)
+{
+    enum CXChildVisitResult e = (_top()(ptrToCXCursor(cursor), ptrToCXCursor(parent), clientData));
+    return e;
+}
+
+/** Visitor is a function pointer with parameters having pointers to cxcursor
+* instead of cxcursor by default. */
+unsigned clang_visitChildren_wrap(CXCursor *parent, ModifiedCXCursorVisitor _modifiedVisitor, CXClientData clientData)
+{
+    _push(_modifiedVisitor);
+    unsigned a = clang_visitChildren(*parent, _visitorwrap, clientData);
+    _pop();
+    return a;
+}
+
+int clang_Cursor_getNumArguments_wrap(CXCursor *cursor)
+{
+    return clang_Cursor_getNumArguments(*cursor);
+}
+
+CXCursor *clang_Cursor_getArgument_wrap(CXCursor *cursor, unsigned i)
+{
+    return ptrToCXCursor(clang_Cursor_getArgument(*cursor, i));
+}
+
+int clang_getNumArgTypes_wrap(CXType *cxtype)
+{
+    return clang_getNumArgTypes(*cxtype);
+}
+
+CXType *clang_getArgType_wrap(CXType *cxtype, unsigned i)
+{
+    return ptrToCXType(clang_getArgType(*cxtype, i));
+}
+
+long long clang_getEnumConstantDeclValue_wrap(CXCursor *cursor)
+{
+    return clang_getEnumConstantDeclValue(*cursor);
+}
+
+/** Returns the first paragraph of doxygen doc comment. */
+CXString *clang_Cursor_getBriefCommentText_wrap(CXCursor *cursor)
+{
+    return ptrToCXString(clang_Cursor_getBriefCommentText(*cursor));
+}
+
+CXSourceLocation *clang_getCursorLocation_wrap(CXCursor *cursor)
+{
+    return ptrToCXSourceLocation(clang_getCursorLocation(*cursor));
+}
+
+void clang_getFileLocation_wrap(CXSourceLocation *location, CXFile *file, unsigned *line, unsigned *column, unsigned *offset)
+{
+    return clang_getFileLocation(*location, file, line, column, offset);
+}
+
+CXString *clang_getFileName_wrap(CXFile SFile)
+{
+    return ptrToCXString(clang_getFileName(SFile));
+}
+
+unsigned long long clang_getNumElements_wrap(CXType *cxtype)
+{
+    return clang_getNumElements(*cxtype);
+}
+
+CXType *clang_getArrayElementType_wrap(CXType *cxtype)
+{
+    return ptrToCXType(clang_getArrayElementType(*cxtype));
+}
+
+// END ===== WRAPPER FUNCTIONS =====================
diff --git a/tool/wrapped_libclang/wrapper.def b/tool/wrapped_libclang/wrapper.def
new file mode 100644
index 0000000..36902ae
--- /dev/null
+++ b/tool/wrapped_libclang/wrapper.def
@@ -0,0 +1,352 @@
+; Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+; for details. All rights reserved. Use of this source code is governed by a
+; BSD-style license that can be found in the LICENSE file.
+
+EXPORTS
+clang_getCString
+clang_disposeString
+clang_disposeStringSet
+clang_createIndex
+clang_disposeIndex
+clang_CXIndex_setGlobalOptions
+clang_CXIndex_getGlobalOptions
+clang_CXIndex_setInvocationEmissionPathOption
+clang_getFileName
+clang_getFileTime
+clang_getFileUniqueID
+clang_isFileMultipleIncludeGuarded
+clang_getFile
+clang_getFileContents
+clang_File_isEqual
+clang_File_tryGetRealPathName
+clang_getNullLocation
+clang_equalLocations
+clang_getLocation
+clang_getLocationForOffset
+clang_Location_isInSystemHeader
+clang_Location_isFromMainFile
+clang_getNullRange
+clang_getRange
+clang_equalRanges
+clang_Range_isNull
+clang_getExpansionLocation
+clang_getPresumedLocation
+clang_getInstantiationLocation
+clang_getSpellingLocation
+clang_getFileLocation
+clang_getRangeStart
+clang_getRangeEnd
+clang_getSkippedRanges
+clang_getAllSkippedRanges
+clang_disposeSourceRangeList
+clang_getNumDiagnosticsInSet
+clang_getDiagnosticInSet
+clang_loadDiagnostics
+clang_disposeDiagnosticSet
+clang_getChildDiagnostics
+clang_getNumDiagnostics
+clang_getDiagnostic
+clang_getDiagnosticSetFromTU
+clang_disposeDiagnostic
+clang_formatDiagnostic
+clang_defaultDiagnosticDisplayOptions
+clang_getDiagnosticSeverity
+clang_getDiagnosticLocation
+clang_getDiagnosticSpelling
+clang_getDiagnosticOption
+clang_getDiagnosticCategory
+clang_getDiagnosticCategoryName
+clang_getDiagnosticCategoryText
+clang_getDiagnosticNumRanges
+clang_getDiagnosticRange
+clang_getDiagnosticNumFixIts
+clang_getDiagnosticFixIt
+clang_getTranslationUnitSpelling
+clang_createTranslationUnitFromSourceFile
+clang_createTranslationUnit
+clang_createTranslationUnit2
+clang_defaultEditingTranslationUnitOptions
+clang_parseTranslationUnit
+clang_parseTranslationUnit2
+clang_parseTranslationUnit2FullArgv
+clang_defaultSaveOptions
+clang_saveTranslationUnit
+clang_suspendTranslationUnit
+clang_disposeTranslationUnit
+clang_defaultReparseOptions
+clang_reparseTranslationUnit
+clang_getTUResourceUsageName
+clang_getCXTUResourceUsage
+clang_disposeCXTUResourceUsage
+clang_getTranslationUnitTargetInfo
+clang_TargetInfo_dispose
+clang_TargetInfo_getTriple
+clang_TargetInfo_getPointerWidth
+clang_getNullCursor
+clang_getTranslationUnitCursor
+clang_equalCursors
+clang_Cursor_isNull
+clang_hashCursor
+clang_getCursorKind
+clang_isDeclaration
+clang_isInvalidDeclaration
+clang_isReference
+clang_isExpression
+clang_isStatement
+clang_isAttribute
+clang_Cursor_hasAttrs
+clang_isInvalid
+clang_isTranslationUnit
+clang_isPreprocessing
+clang_isUnexposed
+clang_getCursorLinkage
+clang_getCursorVisibility
+clang_getCursorAvailability
+clang_getCursorPlatformAvailability
+clang_disposeCXPlatformAvailability
+clang_getCursorLanguage
+clang_getCursorTLSKind
+clang_Cursor_getTranslationUnit
+clang_createCXCursorSet
+clang_disposeCXCursorSet
+clang_CXCursorSet_contains
+clang_CXCursorSet_insert
+clang_getCursorSemanticParent
+clang_getCursorLexicalParent
+clang_getOverriddenCursors
+clang_disposeOverriddenCursors
+clang_getIncludedFile
+clang_getCursor
+clang_getCursorLocation
+clang_getCursorExtent
+clang_getCursorType
+clang_getTypeSpelling
+clang_getTypedefDeclUnderlyingType
+clang_getEnumDeclIntegerType
+clang_getEnumConstantDeclValue
+clang_getEnumConstantDeclUnsignedValue
+clang_getFieldDeclBitWidth
+clang_Cursor_getNumArguments
+clang_Cursor_getArgument
+clang_Cursor_getNumTemplateArguments
+clang_Cursor_getTemplateArgumentKind
+clang_Cursor_getTemplateArgumentType
+clang_Cursor_getTemplateArgumentValue
+clang_Cursor_getTemplateArgumentUnsignedValue
+clang_equalTypes
+clang_getCanonicalType
+clang_isConstQualifiedType
+clang_Cursor_isMacroFunctionLike
+clang_Cursor_isMacroBuiltin
+clang_Cursor_isFunctionInlined
+clang_isVolatileQualifiedType
+clang_isRestrictQualifiedType
+clang_getAddressSpace
+clang_getTypedefName
+clang_getPointeeType
+clang_getTypeDeclaration
+clang_getDeclObjCTypeEncoding
+clang_Type_getObjCEncoding
+clang_getTypeKindSpelling
+clang_getFunctionTypeCallingConv
+clang_getResultType
+clang_getExceptionSpecificationType
+clang_getNumArgTypes
+clang_getArgType
+clang_Type_getObjCObjectBaseType
+clang_Type_getNumObjCProtocolRefs
+clang_Type_getObjCProtocolDecl
+clang_Type_getNumObjCTypeArgs
+clang_Type_getObjCTypeArg
+clang_isFunctionTypeVariadic
+clang_getCursorResultType
+clang_getCursorExceptionSpecificationType
+clang_isPODType
+clang_getElementType
+clang_getNumElements
+clang_getArrayElementType
+clang_getArraySize
+clang_Type_getNamedType
+clang_Type_isTransparentTagTypedef
+clang_Type_getNullability
+clang_Type_getAlignOf
+clang_Type_getClassType
+clang_Type_getSizeOf
+clang_Type_getOffsetOf
+clang_Type_getModifiedType
+clang_Cursor_getOffsetOfField
+clang_Cursor_isAnonymous
+clang_Cursor_isAnonymousRecordDecl
+clang_Cursor_isInlineNamespace
+clang_Type_getNumTemplateArguments
+clang_Type_getTemplateArgumentAsType
+clang_Type_getCXXRefQualifier
+clang_Cursor_isBitField
+clang_isVirtualBase
+clang_getCXXAccessSpecifier
+clang_Cursor_getStorageClass
+clang_getNumOverloadedDecls
+clang_getOverloadedDecl
+clang_getIBOutletCollectionType
+clang_visitChildren
+clang_getCursorUSR
+clang_constructUSR_ObjCClass
+clang_constructUSR_ObjCCategory
+clang_constructUSR_ObjCProtocol
+clang_constructUSR_ObjCIvar
+clang_constructUSR_ObjCMethod
+clang_constructUSR_ObjCProperty
+clang_getCursorSpelling
+clang_Cursor_getSpellingNameRange
+clang_PrintingPolicy_getProperty
+clang_PrintingPolicy_setProperty
+clang_getCursorPrintingPolicy
+clang_PrintingPolicy_dispose
+clang_getCursorPrettyPrinted
+clang_getCursorDisplayName
+clang_getCursorReferenced
+clang_getCursorDefinition
+clang_isCursorDefinition
+clang_getCanonicalCursor
+clang_Cursor_getObjCSelectorIndex
+clang_Cursor_isDynamicCall
+clang_Cursor_getReceiverType
+clang_Cursor_getObjCPropertyAttributes
+clang_Cursor_getObjCPropertyGetterName
+clang_Cursor_getObjCPropertySetterName
+clang_Cursor_getObjCDeclQualifiers
+clang_Cursor_isObjCOptional
+clang_Cursor_isVariadic
+clang_Cursor_isExternalSymbol
+clang_Cursor_getCommentRange
+clang_Cursor_getRawCommentText
+clang_Cursor_getBriefCommentText
+clang_Cursor_getMangling
+clang_Cursor_getCXXManglings
+clang_Cursor_getObjCManglings
+clang_Cursor_getModule
+clang_getModuleForFile
+clang_Module_getASTFile
+clang_Module_getParent
+clang_Module_getName
+clang_Module_getFullName
+clang_Module_isSystem
+clang_Module_getNumTopLevelHeaders
+clang_Module_getTopLevelHeader
+clang_CXXConstructor_isConvertingConstructor
+clang_CXXConstructor_isCopyConstructor
+clang_CXXConstructor_isDefaultConstructor
+clang_CXXConstructor_isMoveConstructor
+clang_CXXField_isMutable
+clang_CXXMethod_isDefaulted
+clang_CXXMethod_isPureVirtual
+clang_CXXMethod_isStatic
+clang_CXXMethod_isVirtual
+clang_CXXRecord_isAbstract
+clang_EnumDecl_isScoped
+clang_CXXMethod_isConst
+clang_getTemplateCursorKind
+clang_getSpecializedCursorTemplate
+clang_getCursorReferenceNameRange
+clang_getToken
+clang_getTokenKind
+clang_getTokenSpelling
+clang_getTokenLocation
+clang_getTokenExtent
+clang_tokenize
+clang_annotateTokens
+clang_disposeTokens
+clang_getCursorKindSpelling
+clang_getDefinitionSpellingAndExtent
+clang_enableStackTraces
+clang_executeOnThread
+clang_getCompletionChunkKind
+clang_getCompletionChunkText
+clang_getCompletionChunkCompletionString
+clang_getNumCompletionChunks
+clang_getCompletionPriority
+clang_getCompletionAvailability
+clang_getCompletionNumAnnotations
+clang_getCompletionAnnotation
+clang_getCompletionParent
+clang_getCompletionBriefComment
+clang_getCursorCompletionString
+clang_getCompletionNumFixIts
+clang_getCompletionFixIt
+clang_defaultCodeCompleteOptions
+clang_codeCompleteAt
+clang_sortCodeCompletionResults
+clang_disposeCodeCompleteResults
+clang_codeCompleteGetNumDiagnostics
+clang_codeCompleteGetDiagnostic
+clang_codeCompleteGetContexts
+clang_codeCompleteGetContainerKind
+clang_codeCompleteGetContainerUSR
+clang_codeCompleteGetObjCSelector
+clang_getClangVersion
+clang_toggleCrashRecovery
+clang_getInclusions
+clang_Cursor_Evaluate
+clang_EvalResult_getKind
+clang_EvalResult_getAsInt
+clang_EvalResult_getAsLongLong
+clang_EvalResult_isUnsignedInt
+clang_EvalResult_getAsUnsigned
+clang_EvalResult_getAsDouble
+clang_EvalResult_getAsStr
+clang_EvalResult_dispose
+clang_getRemappings
+clang_getRemappingsFromFileList
+clang_remap_getNumFiles
+clang_remap_getFilenames
+clang_remap_dispose
+clang_findReferencesInFile
+clang_findIncludesInFile
+clang_index_isEntityObjCContainerKind
+clang_index_getObjCContainerDeclInfo
+clang_index_getObjCInterfaceDeclInfo
+clang_index_getObjCCategoryDeclInfo
+clang_index_getObjCProtocolRefListInfo
+clang_index_getObjCPropertyDeclInfo
+clang_index_getIBOutletCollectionAttrInfo
+clang_index_getCXXClassDeclInfo
+clang_index_getClientContainer
+clang_index_setClientContainer
+clang_index_getClientEntity
+clang_index_setClientEntity
+clang_IndexAction_create
+clang_IndexAction_dispose
+clang_indexSourceFile
+clang_indexSourceFileFullArgv
+clang_indexTranslationUnit
+clang_indexLoc_getFileLocation
+clang_indexLoc_getCXSourceLocation
+clang_Type_visitFields
+clang_getCString_wrap
+clang_disposeString_wrap
+clang_getCursorKind_wrap
+clang_getCursorKindSpelling_wrap
+clang_getCursorType_wrap
+clang_getTypeSpelling_wrap
+clang_getTypeKindSpelling_wrap
+clang_getResultType_wrap
+clang_getPointeeType_wrap
+clang_getCanonicalType_wrap
+clang_Type_getNamedType_wrap
+clang_getTypeDeclaration_wrap
+clang_getTypedefDeclUnderlyingType_wrap
+clang_getCursorSpelling_wrap
+clang_getTranslationUnitCursor_wrap
+clang_formatDiagnostic_wrap
+clang_visitChildren_wrap
+clang_Cursor_getNumArguments_wrap
+clang_Cursor_getArgument_wrap
+clang_getNumArgTypes_wrap
+clang_getArgType_wrap
+clang_getEnumConstantDeclValue_wrap
+clang_Cursor_getBriefCommentText_wrap
+clang_getCursorLocation_wrap
+clang_getFileLocation_wrap
+clang_getFileName_wrap
+clang_getNumElements_wrap
+clang_getArrayElementType_wrap