summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDemitri Swan <demitriswan@gmail.com>2019-10-23 15:39:02 +0000
committerDemitri Swan <demitriswan@gmail.com>2019-10-23 15:39:02 +0000
commitaab6e8ad3228aed05f090264b078e30bbbd72c0b (patch)
treeefee1f4074c05e524fb03ecdaafe9f883f7eb133
initial commit
-rw-r--r--.gitignore10
-rw-r--r--CODEOWNERS1
-rw-r--r--Doxyfile2494
-rw-r--r--LICENSE13
-rw-r--r--Makefile35
-rw-r--r--README.md73
-rw-r--r--VERSION1
-rw-r--r--appveyor.yml9
-rwxr-xr-xauto78
-rw-r--r--autolib/autolib.sh8
-rw-r--r--autolib/build.sh32
-rwxr-xr-xautolib/cmd/build83
-rwxr-xr-xautolib/cmd/clean73
-rwxr-xr-xautolib/cmd/dev98
-rwxr-xr-xautolib/cmd/docs69
-rwxr-xr-xautolib/cmd/package74
-rwxr-xr-xautolib/cmd/smoke68
-rwxr-xr-xautolib/cmd/test92
-rw-r--r--autolib/env.sh9
-rw-r--r--autolib/output.sh20
-rw-r--r--autolib/test.sh39
-rw-r--r--docker/Dockerfile21
-rw-r--r--docker/Makefile2
-rw-r--r--docs/annotated.html80
-rw-r--r--docs/bc_s.pngbin0 -> 676 bytes
-rw-r--r--docs/bdwn.pngbin0 -> 147 bytes
-rw-r--r--docs/classes.html84
-rw-r--r--docs/closed.pngbin0 -> 132 bytes
-rw-r--r--docs/dir_000003_000000.html75
-rw-r--r--docs/dir_21619567660c3332e6a61228c76007f9.html83
-rw-r--r--docs/dir_21619567660c3332e6a61228c76007f9_dep.dot12
-rw-r--r--docs/dir_21619567660c3332e6a61228c76007f9_dep.map6
-rw-r--r--docs/dir_21619567660c3332e6a61228c76007f9_dep.md51
-rw-r--r--docs/dir_21619567660c3332e6a61228c76007f9_dep.pngbin0 -> 3190 bytes
-rw-r--r--docs/dir_2c63f04010e7ff462eba5e344f58cd21.html83
-rw-r--r--docs/dir_83821d63a26a6eb889c4977bd95ca990.html116
-rw-r--r--docs/dir_8d140c3a8bac3cd45205c9ea74fd211f.html86
-rw-r--r--docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.dot11
-rw-r--r--docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.map6
-rw-r--r--docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.md51
-rw-r--r--docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.pngbin0 -> 3178 bytes
-rw-r--r--docs/doc.pngbin0 -> 746 bytes
-rw-r--r--docs/doxygen.css1596
-rw-r--r--docs/doxygen.pngbin0 -> 3779 bytes
-rw-r--r--docs/dynsections.js97
-rw-r--r--docs/files.html97
-rw-r--r--docs/folderclosed.pngbin0 -> 616 bytes
-rw-r--r--docs/folderopen.pngbin0 -> 597 bytes
-rw-r--r--docs/functions.html79
-rw-r--r--docs/functions_vars.html79
-rw-r--r--docs/globals.html243
-rw-r--r--docs/globals_defs.html85
-rw-r--r--docs/globals_enum.html76
-rw-r--r--docs/globals_eval.html88
-rw-r--r--docs/globals_func.html198
-rw-r--r--docs/globals_type.html100
-rw-r--r--docs/globals_vars.html79
-rw-r--r--docs/graph_legend.dot22
-rw-r--r--docs/graph_legend.html104
-rw-r--r--docs/graph_legend.md51
-rw-r--r--docs/graph_legend.pngbin0 -> 19906 bytes
-rw-r--r--docs/index.html119
-rw-r--r--docs/jquery.js87
-rw-r--r--docs/menu.js26
-rw-r--r--docs/menudata.js19
-rw-r--r--docs/nav_f.pngbin0 -> 153 bytes
-rw-r--r--docs/nav_g.pngbin0 -> 95 bytes
-rw-r--r--docs/nav_h.pngbin0 -> 98 bytes
-rw-r--r--docs/open.pngbin0 -> 123 bytes
-rw-r--r--docs/pages.html80
-rw-r--r--docs/prom_8h.html117
-rw-r--r--docs/prom_8h__dep__incl.dot8
-rw-r--r--docs/prom_8h__dep__incl.map3
-rw-r--r--docs/prom_8h__dep__incl.md51
-rw-r--r--docs/prom_8h__dep__incl.pngbin0 -> 3688 bytes
-rw-r--r--docs/prom_8h__incl.dot51
-rw-r--r--docs/prom_8h__incl.map14
-rw-r--r--docs/prom_8h__incl.md51
-rw-r--r--docs/prom_8h__incl.pngbin0 -> 80659 bytes
-rw-r--r--docs/prom_8h_source.html89
-rw-r--r--docs/prom__alloc_8h.html190
-rw-r--r--docs/prom__alloc_8h__dep__incl.map3
-rw-r--r--docs/prom__alloc_8h__dep__incl.md51
-rw-r--r--docs/prom__alloc_8h__dep__incl.pngbin0 -> 3809 bytes
-rw-r--r--docs/prom__alloc_8h__incl.map2
-rw-r--r--docs/prom__alloc_8h__incl.md51
-rw-r--r--docs/prom__alloc_8h__incl.pngbin0 -> 4704 bytes
-rw-r--r--docs/prom__alloc_8h_source.html79
-rw-r--r--docs/prom__collector_8h.html207
-rw-r--r--docs/prom__collector_8h__dep__incl.dot13
-rw-r--r--docs/prom__collector_8h__dep__incl.map4
-rw-r--r--docs/prom__collector_8h__dep__incl.md51
-rw-r--r--docs/prom__collector_8h__dep__incl.pngbin0 -> 11379 bytes
-rw-r--r--docs/prom__collector_8h__incl.dot18
-rw-r--r--docs/prom__collector_8h__incl.map6
-rw-r--r--docs/prom__collector_8h__incl.md51
-rw-r--r--docs/prom__collector_8h__incl.pngbin0 -> 10708 bytes
-rw-r--r--docs/prom__collector_8h_source.html89
-rw-r--r--docs/prom__collector__registry_8h.html304
-rw-r--r--docs/prom__collector__registry_8h__dep__incl.dot10
-rw-r--r--docs/prom__collector__registry_8h__dep__incl.map3
-rw-r--r--docs/prom__collector__registry_8h__dep__incl.md51
-rw-r--r--docs/prom__collector__registry_8h__dep__incl.pngbin0 -> 5013 bytes
-rw-r--r--docs/prom__collector__registry_8h__incl.dot22
-rw-r--r--docs/prom__collector__registry_8h__incl.map7
-rw-r--r--docs/prom__collector__registry_8h__incl.md51
-rw-r--r--docs/prom__collector__registry_8h__incl.pngbin0 -> 16344 bytes
-rw-r--r--docs/prom__collector__registry_8h_source.html94
-rw-r--r--docs/prom__counter_8h.html155
-rw-r--r--docs/prom__counter_8h__dep__incl.dot10
-rw-r--r--docs/prom__counter_8h__dep__incl.map3
-rw-r--r--docs/prom__counter_8h__dep__incl.md51
-rw-r--r--docs/prom__counter_8h__dep__incl.pngbin0 -> 4157 bytes
-rw-r--r--docs/prom__counter_8h__incl.dot18
-rw-r--r--docs/prom__counter_8h__incl.map5
-rw-r--r--docs/prom__counter_8h__incl.md51
-rw-r--r--docs/prom__counter_8h__incl.pngbin0 -> 10760 bytes
-rw-r--r--docs/prom__counter_8h_source.html86
-rw-r--r--docs/prom__errors_8h.html136
-rw-r--r--docs/prom__errors_8h__dep__incl.dot40
-rw-r--r--docs/prom__errors_8h__dep__incl.map11
-rw-r--r--docs/prom__errors_8h__dep__incl.md51
-rw-r--r--docs/prom__errors_8h__dep__incl.pngbin0 -> 85437 bytes
-rw-r--r--docs/prom__errors_8h_source.html82
-rw-r--r--docs/prom__gauge_8h.html167
-rw-r--r--docs/prom__gauge_8h__dep__incl.dot10
-rw-r--r--docs/prom__gauge_8h__dep__incl.map3
-rw-r--r--docs/prom__gauge_8h__dep__incl.md51
-rw-r--r--docs/prom__gauge_8h__dep__incl.pngbin0 -> 4350 bytes
-rw-r--r--docs/prom__gauge_8h__incl.dot18
-rw-r--r--docs/prom__gauge_8h__incl.map5
-rw-r--r--docs/prom__gauge_8h__incl.md51
-rw-r--r--docs/prom__gauge_8h__incl.pngbin0 -> 10919 bytes
-rw-r--r--docs/prom__gauge_8h_source.html89
-rw-r--r--docs/prom__histogram_8h.html153
-rw-r--r--docs/prom__histogram_8h__dep__incl.dot10
-rw-r--r--docs/prom__histogram_8h__dep__incl.map3
-rw-r--r--docs/prom__histogram_8h__dep__incl.md51
-rw-r--r--docs/prom__histogram_8h__dep__incl.pngbin0 -> 4240 bytes
-rw-r--r--docs/prom__histogram_8h__incl.dot20
-rw-r--r--docs/prom__histogram_8h__incl.map6
-rw-r--r--docs/prom__histogram_8h__incl.md51
-rw-r--r--docs/prom__histogram_8h__incl.pngbin0 -> 12699 bytes
-rw-r--r--docs/prom__histogram_8h_source.html87
-rw-r--r--docs/prom__histogram__buckets_8h.html232
-rw-r--r--docs/prom__histogram__buckets_8h__dep__incl.dot13
-rw-r--r--docs/prom__histogram__buckets_8h__dep__incl.map4
-rw-r--r--docs/prom__histogram__buckets_8h__dep__incl.md51
-rw-r--r--docs/prom__histogram__buckets_8h__dep__incl.pngbin0 -> 10678 bytes
-rw-r--r--docs/prom__histogram__buckets_8h_source.html87
-rw-r--r--docs/prom__linked__list_8h_source.html79
-rw-r--r--docs/prom__map_8h_source.html79
-rw-r--r--docs/prom__metric_8h.html212
-rw-r--r--docs/prom__metric_8h__dep__incl.dot26
-rw-r--r--docs/prom__metric_8h__dep__incl.map8
-rw-r--r--docs/prom__metric_8h__dep__incl.md51
-rw-r--r--docs/prom__metric_8h__dep__incl.pngbin0 -> 40392 bytes
-rw-r--r--docs/prom__metric_8h__incl.dot13
-rw-r--r--docs/prom__metric_8h__incl.map4
-rw-r--r--docs/prom__metric_8h__incl.md51
-rw-r--r--docs/prom__metric_8h__incl.pngbin0 -> 7736 bytes
-rw-r--r--docs/prom__metric_8h_source.html86
-rw-r--r--docs/prom__metric__sample_8h.html217
-rw-r--r--docs/prom__metric__sample_8h__dep__incl.dot29
-rw-r--r--docs/prom__metric__sample_8h__dep__incl.map9
-rw-r--r--docs/prom__metric__sample_8h__dep__incl.md51
-rw-r--r--docs/prom__metric__sample_8h__dep__incl.pngbin0 -> 47933 bytes
-rw-r--r--docs/prom__metric__sample_8h__incl.dot8
-rw-r--r--docs/prom__metric__sample_8h__incl.map3
-rw-r--r--docs/prom__metric__sample_8h__incl.md51
-rw-r--r--docs/prom__metric__sample_8h__incl.pngbin0 -> 4292 bytes
-rw-r--r--docs/prom__metric__sample_8h_source.html83
-rw-r--r--docs/prom__metric__sample__histogram_8h.html118
-rw-r--r--docs/prom__metric__sample__histogram_8h__dep__incl.dot28
-rw-r--r--docs/prom__metric__sample__histogram_8h__dep__incl.map9
-rw-r--r--docs/prom__metric__sample__histogram_8h__dep__incl.md51
-rw-r--r--docs/prom__metric__sample__histogram_8h__dep__incl.pngbin0 -> 48584 bytes
-rw-r--r--docs/prom__metric__sample__histogram_8h__incl.dot8
-rw-r--r--docs/prom__metric__sample__histogram_8h__incl.map3
-rw-r--r--docs/prom__metric__sample__histogram_8h__incl.md51
-rw-r--r--docs/prom__metric__sample__histogram_8h__incl.pngbin0 -> 4841 bytes
-rw-r--r--docs/prom__metric__sample__histogram_8h_source.html81
-rw-r--r--docs/promhttp_8h.html178
-rw-r--r--docs/promhttp_8h__incl.dot57
-rw-r--r--docs/promhttp_8h__incl.map2
-rw-r--r--docs/promhttp_8h__incl.md51
-rw-r--r--docs/promhttp_8h__incl.pngbin0 -> 4744 bytes
-rw-r--r--docs/promhttp_8h_source.html82
-rw-r--r--docs/search/all_0.html26
-rw-r--r--docs/search/all_0.js4
-rw-r--r--docs/search/all_1.html26
-rw-r--r--docs/search/all_1.js72
-rw-r--r--docs/search/all_2.html26
-rw-r--r--docs/search/all_2.js4
-rw-r--r--docs/search/all_3.html26
-rw-r--r--docs/search/all_3.js4
-rw-r--r--docs/search/all_4.html26
-rw-r--r--docs/search/all_4.js4
-rw-r--r--docs/search/classes_0.html26
-rw-r--r--docs/search/classes_0.js4
-rw-r--r--docs/search/close.pngbin0 -> 273 bytes
-rw-r--r--docs/search/defines_0.html26
-rw-r--r--docs/search/defines_0.js7
-rw-r--r--docs/search/enums_0.html26
-rw-r--r--docs/search/enums_0.js4
-rw-r--r--docs/search/enumvalues_0.html26
-rw-r--r--docs/search/enumvalues_0.js8
-rw-r--r--docs/search/files_0.html26
-rw-r--r--docs/search/files_0.js15
-rw-r--r--docs/search/functions_0.html26
-rw-r--r--docs/search/functions_0.js44
-rw-r--r--docs/search/mag_sel.pngbin0 -> 563 bytes
-rw-r--r--docs/search/nomatches.html12
-rw-r--r--docs/search/pages_0.html26
-rw-r--r--docs/search/pages_0.js4
-rw-r--r--docs/search/pages_1.html26
-rw-r--r--docs/search/pages_1.js4
-rw-r--r--docs/search/search.css271
-rw-r--r--docs/search/search.js791
-rw-r--r--docs/search/search_l.pngbin0 -> 604 bytes
-rw-r--r--docs/search/search_m.pngbin0 -> 158 bytes
-rw-r--r--docs/search/search_r.pngbin0 -> 612 bytes
-rw-r--r--docs/search/searchdata.js36
-rw-r--r--docs/search/typedefs_0.html26
-rw-r--r--docs/search/typedefs_0.js12
-rw-r--r--docs/search/variables_0.html26
-rw-r--r--docs/search/variables_0.js4
-rw-r--r--docs/search/variables_1.html26
-rw-r--r--docs/search/variables_1.js5
-rw-r--r--docs/search/variables_2.html26
-rw-r--r--docs/search/variables_2.js4
-rw-r--r--docs/splitbar.pngbin0 -> 314 bytes
-rw-r--r--docs/structprom__histogram__buckets-members.html80
-rw-r--r--docs/structprom__histogram__buckets.html93
-rw-r--r--docs/sync_off.pngbin0 -> 853 bytes
-rw-r--r--docs/sync_on.pngbin0 -> 845 bytes
-rw-r--r--docs/tab_a.pngbin0 -> 142 bytes
-rw-r--r--docs/tab_b.pngbin0 -> 169 bytes
-rw-r--r--docs/tab_h.pngbin0 -> 177 bytes
-rw-r--r--docs/tab_s.pngbin0 -> 184 bytes
-rw-r--r--docs/tabs.css1
-rw-r--r--docs/todo.html79
-rw-r--r--example/Makefile39
-rw-r--r--example/bar.c32
-rw-r--r--example/bar.h18
-rw-r--r--example/foo.c33
-rw-r--r--example/foo.h19
-rw-r--r--example/main.c104
-rw-r--r--prom/CMakeLists.txt138
-rw-r--r--prom/include/prom.h134
-rw-r--r--prom/include/prom_alloc.h48
-rw-r--r--prom/include/prom_collector.h79
-rw-r--r--prom/include/prom_collector_registry.h95
-rw-r--r--prom/include/prom_counter.h63
-rw-r--r--prom/include/prom_gauge.h80
-rw-r--r--prom/include/prom_histogram.h58
-rw-r--r--prom/include/prom_histogram_buckets.h74
-rw-r--r--prom/include/prom_linked_list.h30
-rw-r--r--prom/include/prom_map.h26
-rw-r--r--prom/include/prom_metric.h55
-rw-r--r--prom/include/prom_metric_sample.h51
-rw-r--r--prom/include/prom_metric_sample_histogram.h36
-rw-r--r--prom/src/prom_assert.h28
-rw-r--r--prom/src/prom_collector.c275
-rw-r--r--prom/src/prom_collector_registry.c226
-rw-r--r--prom/src/prom_collector_registry_i.h26
-rw-r--r--prom/src/prom_collector_registry_t.h41
-rw-r--r--prom/src/prom_collector_t.h34
-rw-r--r--prom/src/prom_counter.c70
-rw-r--r--prom/src/prom_errors.h26
-rw-r--r--prom/src/prom_gauge.c106
-rw-r--r--prom/src/prom_histogram.c81
-rw-r--r--prom/src/prom_histogram_buckets.c101
-rw-r--r--prom/src/prom_linked_list.c222
-rw-r--r--prom/src/prom_linked_list_i.h96
-rw-r--r--prom/src/prom_linked_list_t.h60
-rw-r--r--prom/src/prom_log.h28
-rw-r--r--prom/src/prom_map.c473
-rw-r--r--prom/src/prom_map_i.h40
-rw-r--r--prom/src/prom_map_t.h48
-rw-r--r--prom/src/prom_metric.c268
-rw-r--r--prom/src/prom_metric_formatter.c281
-rw-r--r--prom/src/prom_metric_formatter_i.h92
-rw-r--r--prom/src/prom_metric_formatter_t.h28
-rw-r--r--prom/src/prom_metric_i.h49
-rw-r--r--prom/src/prom_metric_sample.c99
-rw-r--r--prom/src/prom_metric_sample_histogram.c554
-rw-r--r--prom/src/prom_metric_sample_histogram_i.h50
-rw-r--r--prom/src/prom_metric_sample_histogram_t.h39
-rw-r--r--prom/src/prom_metric_sample_i.h50
-rw-r--r--prom/src/prom_metric_sample_t.h33
-rw-r--r--prom/src/prom_metric_t.h63
-rw-r--r--prom/src/prom_process_fds.c77
-rw-r--r--prom/src/prom_process_fds_i.h25
-rw-r--r--prom/src/prom_process_fds_t.h24
-rw-r--r--prom/src/prom_process_limits.c489
-rw-r--r--prom/src/prom_process_limits_i.h68
-rw-r--r--prom/src/prom_process_limits_t.h46
-rw-r--r--prom/src/prom_process_stat.c198
-rw-r--r--prom/src/prom_process_stat_i.h29
-rw-r--r--prom/src/prom_process_stat_t.h89
-rw-r--r--prom/src/prom_procfs.c104
-rw-r--r--prom/src/prom_procfs_i.h27
-rw-r--r--prom/src/prom_procfs_t.h29
-rw-r--r--prom/src/prom_string_builder.c155
-rw-r--r--prom/src/prom_string_builder_i.h82
-rw-r--r--prom/src/prom_string_builder_t.h30
-rw-r--r--prom/test/CMakeLists.txt69
-rw-r--r--prom/test/fixtures/limits17
-rw-r--r--prom/test/fixtures/stat1
-rw-r--r--prom/test/prom_collector_registry_test.c116
-rw-r--r--prom/test/prom_collector_test.c44
-rw-r--r--prom/test/prom_counter_test.c60
-rw-r--r--prom/test/prom_gauge_test.c116
-rw-r--r--prom/test/prom_histogram_buckets_test.c54
-rw-r--r--prom/test/prom_histogram_test.c84
-rw-r--r--prom/test/prom_linked_list_test.c107
-rw-r--r--prom/test/prom_map_test.c101
-rw-r--r--prom/test/prom_metric_formatter_test.c117
-rw-r--r--prom/test/prom_metric_sample_test.c75
-rw-r--r--prom/test/prom_metric_test.c48
-rw-r--r--prom/test/prom_process_limits_test.c217
-rw-r--r--prom/test/prom_procfs_test.c31
-rw-r--r--prom/test/prom_string_builder_test.c63
-rw-r--r--prom/test/prom_test_helpers.c18
-rw-r--r--prom/test/prom_test_helpers.h33
-rw-r--r--promhttp/CMakeLists.txt76
-rw-r--r--promhttp/include/promhttp.h46
-rw-r--r--promhttp/src/promhttp.c79
-rw-r--r--promtest/CMakeLists.txt101
-rw-r--r--promtest/test/promtest.c29
-rw-r--r--promtest/test/promtest_counter.c182
-rw-r--r--promtest/test/promtest_counter.h29
-rw-r--r--promtest/test/promtest_gauge.c182
-rw-r--r--promtest/test/promtest_gauge.h29
-rw-r--r--promtest/test/promtest_helpers.c65
-rw-r--r--promtest/test/promtest_helpers.h40
-rw-r--r--vendor/Unity-2.4.3/.gitattributes30
-rw-r--r--vendor/Unity-2.4.3/.gitignore9
-rw-r--r--vendor/Unity-2.4.3/.travis.yml29
-rw-r--r--vendor/Unity-2.4.3/README.md231
-rw-r--r--vendor/Unity-2.4.3/auto/colour_prompt.rb118
-rw-r--r--vendor/Unity-2.4.3/auto/colour_reporter.rb39
-rw-r--r--vendor/Unity-2.4.3/auto/generate_config.yml36
-rw-r--r--vendor/Unity-2.4.3/auto/generate_module.rb308
-rw-r--r--vendor/Unity-2.4.3/auto/generate_test_runner.rb454
-rw-r--r--vendor/Unity-2.4.3/auto/parse_output.rb220
-rwxr-xr-xvendor/Unity-2.4.3/auto/stylize_as_junit.rb252
-rw-r--r--vendor/Unity-2.4.3/auto/test_file_filter.rb25
-rw-r--r--vendor/Unity-2.4.3/auto/type_sanitizer.rb6
-rw-r--r--vendor/Unity-2.4.3/auto/unity_test_summary.py139
-rw-r--r--vendor/Unity-2.4.3/auto/unity_test_summary.rb136
-rw-r--r--vendor/Unity-2.4.3/auto/unity_to_junit.py146
-rw-r--r--vendor/Unity-2.4.3/docs/ThrowTheSwitchCodingStandard.md207
-rw-r--r--vendor/Unity-2.4.3/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdfbin0 -> 144467 bytes
-rw-r--r--vendor/Unity-2.4.3/docs/UnityAssertionsReference.md770
-rw-r--r--vendor/Unity-2.4.3/docs/UnityConfigurationGuide.md435
-rw-r--r--vendor/Unity-2.4.3/docs/UnityGettingStartedGuide.md191
-rw-r--r--vendor/Unity-2.4.3/docs/UnityHelperScriptsGuide.md254
-rw-r--r--vendor/Unity-2.4.3/docs/license.txt21
-rw-r--r--vendor/Unity-2.4.3/examples/example_1/makefile71
-rw-r--r--vendor/Unity-2.4.3/examples/example_1/readme.txt5
-rw-r--r--vendor/Unity-2.4.3/examples/example_1/src/ProductionCode.c24
-rw-r--r--vendor/Unity-2.4.3/examples/example_1/src/ProductionCode.h3
-rw-r--r--vendor/Unity-2.4.3/examples/example_1/src/ProductionCode2.c11
-rw-r--r--vendor/Unity-2.4.3/examples/example_1/src/ProductionCode2.h2
-rw-r--r--vendor/Unity-2.4.3/examples/example_1/test/TestProductionCode.c62
-rw-r--r--vendor/Unity-2.4.3/examples/example_1/test/TestProductionCode2.c31
-rw-r--r--vendor/Unity-2.4.3/examples/example_1/test/test_runners/TestProductionCode2_Runner.c53
-rw-r--r--vendor/Unity-2.4.3/examples/example_1/test/test_runners/TestProductionCode_Runner.c57
-rw-r--r--vendor/Unity-2.4.3/examples/example_2/makefile70
-rw-r--r--vendor/Unity-2.4.3/examples/example_2/readme.txt5
-rw-r--r--vendor/Unity-2.4.3/examples/example_2/src/ProductionCode.c24
-rw-r--r--vendor/Unity-2.4.3/examples/example_2/src/ProductionCode.h3
-rw-r--r--vendor/Unity-2.4.3/examples/example_2/src/ProductionCode2.c11
-rw-r--r--vendor/Unity-2.4.3/examples/example_2/src/ProductionCode2.h2
-rw-r--r--vendor/Unity-2.4.3/examples/example_2/test/TestProductionCode.c64
-rw-r--r--vendor/Unity-2.4.3/examples/example_2/test/TestProductionCode2.c33
-rw-r--r--vendor/Unity-2.4.3/examples/example_2/test/test_runners/TestProductionCode2_Runner.c9
-rw-r--r--vendor/Unity-2.4.3/examples/example_2/test/test_runners/TestProductionCode_Runner.c11
-rw-r--r--vendor/Unity-2.4.3/examples/example_2/test/test_runners/all_tests.c12
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/helper/UnityHelper.c10
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/helper/UnityHelper.h12
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/rakefile.rb43
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/rakefile_helper.rb249
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/readme.txt13
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/src/ProductionCode.c24
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/src/ProductionCode.h3
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/src/ProductionCode2.c11
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/src/ProductionCode2.h2
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/target_gcc_32.yml46
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/test/TestProductionCode.c62
-rw-r--r--vendor/Unity-2.4.3/examples/example_3/test/TestProductionCode2.c31
-rw-r--r--vendor/Unity-2.4.3/examples/unity_config.h239
-rw-r--r--vendor/Unity-2.4.3/extras/eclipse/error_parsers.txt26
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/rakefile.rb48
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/rakefile_helper.rb178
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/readme.txt9
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/src/unity_fixture.c432
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/src/unity_fixture.h83
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/src/unity_fixture_internals.h51
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/src/unity_fixture_malloc_overrides.h47
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/test/Makefile75
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/test/main/AllTests.c22
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/test/template_fixture_tests.c39
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/test/unity_fixture_Test.c543
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/test/unity_fixture_TestRunner.c57
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/test/unity_output_Spy.c57
-rw-r--r--vendor/Unity-2.4.3/extras/fixture/test/unity_output_Spy.h17
-rw-r--r--vendor/Unity-2.4.3/release/build.info2
-rw-r--r--vendor/Unity-2.4.3/release/version.info2
-rw-r--r--vendor/Unity-2.4.3/src/unity.c1570
-rw-r--r--vendor/Unity-2.4.3/src/unity.h503
-rw-r--r--vendor/Unity-2.4.3/src/unity_internals.h872
-rw-r--r--vendor/Unity-2.4.3/test/.rubocop.yml58
-rw-r--r--vendor/Unity-2.4.3/test/Makefile66
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_cmd.c61
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_def.c57
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_head1.c55
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_head1.h15
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_mock_cmd.c80
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_mock_def.c76
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_mock_head1.c75
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_mock_head1.h13
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_mock_new1.c89
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_mock_new2.c89
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_mock_param.c77
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_mock_run1.c89
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_mock_run2.c89
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_mock_yaml.c90
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_new1.c67
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_new2.c70
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_param.c58
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_run1.c67
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_run2.c70
-rw-r--r--vendor/Unity-2.4.3/test/expectdata/testsample_yaml.c71
-rw-r--r--vendor/Unity-2.4.3/test/rakefile125
-rw-r--r--vendor/Unity-2.4.3/test/rakefile_helper.rb260
-rw-r--r--vendor/Unity-2.4.3/test/spec/generate_module_existing_file_spec.rb158
-rw-r--r--vendor/Unity-2.4.3/test/targets/clang_file.yml78
-rw-r--r--vendor/Unity-2.4.3/test/targets/clang_strict.yml78
-rw-r--r--vendor/Unity-2.4.3/test/targets/gcc_32.yml49
-rw-r--r--vendor/Unity-2.4.3/test/targets/gcc_64.yml50
-rw-r--r--vendor/Unity-2.4.3/test/targets/gcc_auto_limits.yml47
-rw-r--r--vendor/Unity-2.4.3/test/targets/gcc_auto_stdint.yml59
-rw-r--r--vendor/Unity-2.4.3/test/targets/gcc_manual_math.yml47
-rw-r--r--vendor/Unity-2.4.3/test/targets/hitech_picc18.yml101
-rw-r--r--vendor/Unity-2.4.3/test/targets/iar_arm_v4.yml90
-rw-r--r--vendor/Unity-2.4.3/test/targets/iar_arm_v5.yml80
-rw-r--r--vendor/Unity-2.4.3/test/targets/iar_arm_v5_3.yml80
-rw-r--r--vendor/Unity-2.4.3/test/targets/iar_armcortex_LM3S9B92_v5_4.yml94
-rw-r--r--vendor/Unity-2.4.3/test/targets/iar_cortexm3_v5.yml84
-rw-r--r--vendor/Unity-2.4.3/test/targets/iar_msp430.yml95
-rw-r--r--vendor/Unity-2.4.3/test/targets/iar_sh2a_v6.yml86
-rw-r--r--vendor/Unity-2.4.3/test/testdata/CException.h11
-rw-r--r--vendor/Unity-2.4.3/test/testdata/Defs.h8
-rw-r--r--vendor/Unity-2.4.3/test/testdata/cmock.h14
-rw-r--r--vendor/Unity-2.4.3/test/testdata/mockMock.h13
-rw-r--r--vendor/Unity-2.4.3/test/testdata/testRunnerGenerator.c183
-rw-r--r--vendor/Unity-2.4.3/test/testdata/testRunnerGeneratorSmall.c67
-rw-r--r--vendor/Unity-2.4.3/test/testdata/testRunnerGeneratorWithMocks.c192
-rw-r--r--vendor/Unity-2.4.3/test/tests/test_generate_test_runner.rb1252
-rw-r--r--vendor/Unity-2.4.3/test/tests/testparameterized.c110
-rw-r--r--vendor/Unity-2.4.3/test/tests/testunity.c5337
-rw-r--r--vendor/parson/.gitignore3
-rw-r--r--vendor/parson/CMakeLists.txt24
-rw-r--r--vendor/parson/LICENSE21
-rw-r--r--vendor/parson/Makefile20
-rw-r--r--vendor/parson/README.md149
-rw-r--r--vendor/parson/package.json12
-rw-r--r--vendor/parson/parson.c2060
-rw-r--r--vendor/parson/parson.h240
-rw-r--r--vendor/parson/tests.c684
-rw-r--r--vendor/parson/tests/test_1_1.txt59
-rw-r--r--vendor/parson/tests/test_1_2.txt1
-rw-r--r--vendor/parson/tests/test_1_3.txt6
-rw-r--r--vendor/parson/tests/test_2.txt33
-rw-r--r--vendor/parson/tests/test_2_comments.txt43
-rw-r--r--vendor/parson/tests/test_2_pretty.txt51
-rw-r--r--vendor/parson/tests/test_5.txt15
-rw-r--r--vendor/src/Unity-stamp/Unity-mkdir0
-rw-r--r--vendor/src/Unity-stamp/Unity-urlinfo.txt3
-rw-r--r--vendor/src/Unity-stamp/download-Unity.cmake162
-rw-r--r--vendor/src/Unity-stamp/extract-Unity.cmake58
-rw-r--r--vendor/src/Unity-stamp/verify-Unity.cmake0
485 files changed, 46031 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..87bb3e3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+.vscode
+prom/build/*
+promhttp/build/*
+promtest/build/*
+tty.gif
+ttyrecord
+_CPack_Packages/
+*deb
+*tar.gz
+*vgcore* \ No newline at end of file
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644
index 0000000..d23ad52
--- /dev/null
+++ b/CODEOWNERS
@@ -0,0 +1 @@
+* @digitalocean/timeseries \ No newline at end of file
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..d4ce057
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,2494 @@
+# Doxyfile 1.8.13
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "prometheus-client-c"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER = "0.1.0"
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "Prometheus client for the C programming language"
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = "docs/"
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 0.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 0
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = prom/include promhttp/include
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
+# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.idl \
+ *.ddl \
+ *.odl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.cs \
+ *.d \
+ *.php \
+ *.php4 \
+ *.php5 \
+ *.phtml \
+ *.inc \
+ *.m \
+ *.markdown \
+ *.md \
+ *.mm \
+ *.dox \
+ *.py \
+ *.pyw \
+ *.f90 \
+ *.f95 \
+ *.f03 \
+ *.f08 \
+ *.f \
+ *.for \
+ *.tcl \
+ *.vhd \
+ *.vhdl \
+ *.ucf \
+ *.qsf
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse-libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: YES.
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
+# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
+# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..772abba
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License. \ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..8b89f2e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,35 @@
+
+SHELL = /bin/bash
+
+build_and_test: docker clean build test package smoke
+.PHONY: build_and_test
+
+all: build_and_test docs
+.PHONY: all
+
+docker:
+ pushd docker && make
+.PHONY: docker
+
+clean: docker
+ ./auto dev -e auto -a clean
+
+build: clean
+ ./auto dev -e auto -a build -a -t
+.PHONY: build
+
+test: build
+ ./auto dev -e auto -a test
+.PHONY: test
+
+package: test
+ ./auto dev -e auto -a package
+.PHONY: smoke
+
+smoke: package
+ ./auto dev -e auto -a smoke
+.PHONY: smoke
+
+docs: smoke
+ ./auto dev -e auto -a docs
+.PHONY: package
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0d12b56
--- /dev/null
+++ b/README.md
@@ -0,0 +1,73 @@
+# prometheus-client-c
+
+This project provides shared libraries for instrumenting software via [Prometheus](https://prometheus.io)
+
+* libprom - Provides the core API. Resources such as counters, gauges, histograms, and
+ collector registries can be found here. This library has no dependencies on third-party
+ libraries; however, it does rely on pthreads native to POSIX systems.
+* libpromhttp - Provides a simple web handler to expose Prometheus metrics for scraping.
+ This library has a dependency on libmircohttpd.
+
+Documentation can be found
+[at the documentation site](https://digitalocean.github.io/prometheus-client-c/)
+and an example can be found under example/. Check under the releases tab for tarballs and debian installers
+
+## Versioning
+
+This project generally follows [semantic versioning](https://semver.org). For each version you can find a corresponding
+release under the releases type. Do not expect the master branch to maintain alignment with the latest release. It may
+contain changes not yet released.
+
+## Development
+
+The only development dependencies required to get started are Docker, Make and Bash. Navigate to the root fo this
+project directory and execute `make`. This process will build the development container, build libprom and libpromhttp,
+run the unit tests and execute the smoke tests.
+
+The stages of the development workflow are automated via `auto` which can be found in the root of this project directory.
+Execute `./auto -h` for information regarding the different subcommands. Information for each subcommand can be
+obtained by executing `./auto CMD -h`.
+
+## Contributing
+
+Thank you for your interest in contributing to prometheus-client-c! There two primary ways to get involved with this
+project: documentation and code modifications. In either case, the process is identical.
+
+### General Rules for Contribution
+
+* Open An Issue: Before opening a PR or starting any work, open an issue. In the issue, describe the problem you
+want to fix and how you would like to fix it. The level of detail should match the relative size of the proposed change.
+This will allow us to work together to determine the best path forward towards a sound solution.
+
+* Open a Pull Request: After you have gotten confirmation on your proposed change it's time to get to work! Create a
+fork and make all of your updates in said fork. For each commit, you must prefix the commit with the associated issue.
+For example: `#12 - Fixing typo in documentation`. Before opening a pull request, review the commit log for your fork.
+If any of your commit messages are extraneous, squash said commits using `git rebase`. Once you're happy with your
+changes and your commit log, open a pull request against the master branch.
+
+* Engage in the Code Review: After submitting your pull request, there may be some requests for changes. If you have
+any questions or concerns, please do not hesitate to make them known. The code review process is a bidirectional
+communication process so please do not be shy. Speak up!
+
+### Coding Rules for Contribution
+
+* Please follow the general coding style already present in the project.
+ * We use a 120 character margin, so please honor this margin by breaking long statements and expressions over multiple
+ lines.
+ * Indent with 2 spaces instead of tabs.
+ * Every struct must have a constructor function and destructor function.
+ * Every method must pass a pointer to the target struct as the first argument.
+ * Every function that is not a constructor or destructor and does not return a value must return an int to signify
+ success with 0 and failure with non-zero.
+ * Every function name must begin with the library name. For example, all functions within prom must begin with `prom_`
+ and all functions within promhttp must begin with `promhttp_`.
+ * All l-values must be underscore delimited (i.e. snake-case).
+ * All macros must be captilalized.
+ * Every pointer reference must be assigned a NULL value after it is destroyed either by prom_free or its
+ corresponding destructor function.
+* All new functions must introduce a corresponding suite of unit tests.
+* If you add functionality to an existing function, be sure to add a corresponding unit test to verify correctness.
+
+## Misc
+
+* Language level: C11
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..6c6aa7c
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.1.0 \ No newline at end of file
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..304d16d
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,9 @@
+image: ubuntu
+
+build: off
+
+services:
+- docker
+
+test_script:
+ - make \ No newline at end of file
diff --git a/auto b/auto
new file mode 100755
index 0000000..4aaa6ba
--- /dev/null
+++ b/auto
@@ -0,0 +1,78 @@
+#!/usr/bin/env bash
+
+########################################################################################################################
+# Meta
+########################################################################################################################
+
+# Propagate environment variables
+if [[ "$AUTO_DEBUG" == "1" ]]; then
+ set -x
+ export AUTO_DEBUG=1
+fi
+
+PROJECT_ROOT=$(pushd $(dirname $0) > /dev/null; echo $PWD; popd > /dev/null)
+PROGRAM_NAME="$(basename $0)"
+
+usage(){
+ cat <<EOF
+
+$PROGRAM_NAME [command [options...]]
+
+Provide developer workflow automation
+
+$PROGRAM_NAME command -h for help
+
+COMMANDS
+
+$(commands)
+
+ENVIRONMENT
+
+AUTO_DEBUG Set to 1 to enable and 0 to disable
+
+EOF
+}
+
+########################################################################################################################
+# End Meta
+########################################################################################################################
+
+declare -i DEV=${DEV:=1} && export DEV
+declare lib="$(dirname ${BASH_SOURCE[0]})/autolib"
+source "${lib}/autolib.sh"
+
+commands(){
+ while read cmd; do
+ printf "${cmd} - "
+ source "${lib}/cmd/${cmd}"
+ echo "$short"
+ done < <(ls -1 "${lib}/cmd")
+}
+
+main(){
+ if [[ "$PROJECT_ROOT" != "$PWD" ]]; then
+ echo "You must execute auto within the PROJECT_ROOT $PROJECT_ROOT"
+ exit 1
+ fi
+ if (($# < 1)); then
+ usage
+ exit 1
+ fi
+ local cmd=$1
+ case "$cmd" in
+ ( -h | --help | help ) {
+ usage
+ exit 0
+ } ;;
+ ( build | dev | test | package | docs | clean | smoke ) {
+ shift
+ exec "${lib}/cmd/${cmd}" $@ || exit $?
+ } ;;
+ ( * ) {
+ usage
+ exit 1
+ } ;;
+ esac
+}
+
+[[ $BASH_SOURCE == $0 ]] && main $@ \ No newline at end of file
diff --git a/autolib/autolib.sh b/autolib/autolib.sh
new file mode 100644
index 0000000..54ff558
--- /dev/null
+++ b/autolib/autolib.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+lib="$(dirname ${BASH_SOURCE[0]})"
+
+source "${lib}/output.sh"
+source "${lib}/build.sh"
+source "${lib}/env.sh"
+source "${lib}/test.sh" \ No newline at end of file
diff --git a/autolib/build.sh b/autolib/build.sh
new file mode 100644
index 0000000..42ec7de
--- /dev/null
+++ b/autolib/build.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+lib="$(dirname ${BASH_SOURCE[0]})"
+
+source "${lib}/env.sh"
+source "${lib}/output.sh"
+
+# build all libraries
+autolib_build() {
+ local lib=$1
+ local build_test=$2
+
+ if [[ ! -d ${lib}/build ]]; then
+ mkdir ${lib}/build || {
+ autolib_output_error "Failed to create build directory"
+ return 1
+ }
+ fi
+ pushd ${lib}/build > /dev/null || return $?
+ autolib_output_banner "${lib}: CMake Build Stage"
+ # YOU MUST set TEST to 1 in order to build the tests
+ TEST=$build_test cmake -v .. || {
+ autolib_output_error "${lib}: CMake Failure"
+ return 1
+ }
+ autolib_output_banner "${lib}: Make Build Stage"
+ make || {
+ autolib_output_error "${lib} Make Failure"
+ return 1
+ }
+ popd > /dev/null || return $?
+} \ No newline at end of file
diff --git a/autolib/cmd/build b/autolib/cmd/build
new file mode 100755
index 0000000..f65d62f
--- /dev/null
+++ b/autolib/cmd/build
@@ -0,0 +1,83 @@
+#!/usr/bin/env bash
+
+########################################################################################################################
+# Meta
+########################################################################################################################
+
+# Propagate environment variables
+if [[ "$AUTO_DEBUG" == "1" ]]; then
+ set -x
+ export AUTO_DEBUG=1
+fi
+
+PROGRAM_NAME=$(basename $0)
+
+short="Build the project"
+read -d '' long <<EOF
+
+You MUST execute this command within the development container.
+
+-t Include the test build for testing
+
+EOF
+
+
+usage(){
+ cat <<EOF
+
+$PROGRAM_NAME [-h]
+
+$short
+
+DESCRIPTION
+
+$long
+EOF
+}
+
+########################################################################################################################
+# End Meta
+########################################################################################################################
+
+source "$(dirname ${BASH_SOURCE[0]})/../autolib.sh"
+
+declare AUTOLIB_BUILD_TEST=0
+declare AUTOLIB_TEST_LIB
+
+run(){
+ autolib_check_dev || return $?
+ autolib_output_banner "Executing ${PROGRAM_NAME}"
+ declare -a libs
+ if [ -z "$AUTOLIB_TEST_LIB" ]; then
+ libs+=(prom promhttp)
+ else
+ libs+=($AUTOLIB_TEST_LIB)
+ fi
+
+ for lib in ${libs[@]}; do
+ autolib_build "$lib" "$AUTOLIB_BUILD_TEST" || return $?
+ done
+ autolib_output_success "Build Complete"
+}
+
+main(){
+ while getopts 'hl:t' opt; do
+ case "$opt" in
+ ( h ) {
+ usage && exit 0
+ } ;;
+ ( t ) {
+ AUTOLIB_BUILD_TEST=1
+ } ;;
+ ( l ) {
+ AUTOLIB_TEST_LIB="$OPTARG"
+ } ;;
+ ( * ) {
+ usage && exit 1
+ } ;;
+ esac
+ done
+ run $@ || exit $?
+}
+
+[[ $BASH_SOURCE == $0 ]] && main $@ \ No newline at end of file
diff --git a/autolib/cmd/clean b/autolib/cmd/clean
new file mode 100755
index 0000000..46e2b28
--- /dev/null
+++ b/autolib/cmd/clean
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+
+########################################################################################################################
+# Meta
+########################################################################################################################
+
+# Propagate environment variables
+if [[ "$AUTO_DEBUG" == "1" ]]; then
+ set -x
+ export AUTO_DEBUG=1
+fi
+
+PROGRAM_NAME="$(basename $0)"
+
+short="Clean the development environment"
+
+read -d '' long <<EOF
+You MUST execute this command from your development workstation. You
+MUST NOT execute this command from an existing docker container.
+EOF
+
+usage() {
+ cat <<EOF
+
+$PROGRAM_NAME [-h]
+
+$short
+
+DESCRIPTION
+
+$long
+
+EOF
+}
+
+########################################################################################################################
+# End Meta
+########################################################################################################################
+
+source $(dirname ${BASH_SOURCE[0]})/../autolib.sh
+
+
+run(){
+ local r
+ autolib_check_dev || return $?
+ autolib_output_banner "Executing ${PROGRAM_NAME}"
+
+ pushd "$(dirname ${BASH_SOURCE[0]})/../.." > /dev/null || return $?
+ for pkg in libprom-dev libpromhttp-dev; do
+ if dpkg --list | grep -q libprom-dev; then
+ dpkg --remove "$pkg"
+ fi
+ done
+ rm -rf prom/build/*
+ rm -rf promhttp/build/*
+ popd > /dev/null || return $?
+}
+
+main(){
+ while getopts "h" opt; do
+ case $opt in
+ ( h ) {
+ usage && exit 0
+ } ;;
+ ( * ) {
+ usage && exit 1
+ }
+ esac
+ done
+ run $@; exit $?
+}
+
+[[ $BASH_SOURCE == $0 ]] && main $@ \ No newline at end of file
diff --git a/autolib/cmd/dev b/autolib/cmd/dev
new file mode 100755
index 0000000..f051f62
--- /dev/null
+++ b/autolib/cmd/dev
@@ -0,0 +1,98 @@
+#!/usr/bin/env bash
+
+########################################################################################################################
+# Meta
+########################################################################################################################
+
+# Propagate environment variables
+if [[ "$AUTO_DEBUG" == "1" ]]; then
+ set -x
+ export AUTO_DEBUG=1
+fi
+
+PROGRAM_NAME="$(basename $0)"
+
+short="Initialize the development environment"
+
+read -d '' long <<EOF
+You MUST execute this command from your development workstation. You
+MUST NOT execute this command from an existing docker container.
+
+-e Execute the following executable
+-a Pass an argument to the executable given by -e. You may specify
+ this flag multiple times. The order is preserved.
+EOF
+
+usage() {
+ cat <<EOF
+
+$PROGRAM_NAME [-h | -e EXECUTABLE [-a ARG1 -a ARG2 ...]]
+
+$short
+
+DESCRIPTION
+
+$long
+
+EOF
+}
+
+########################################################################################################################
+# End Meta
+########################################################################################################################
+
+source $(dirname ${BASH_SOURCE[0]})/../autolib.sh
+
+declare DOCKER_EXEC
+declare -a DOCKER_EXEC_ARGS
+
+run(){
+ local r
+ if ! { docker image list | grep -q prometheus-client-c-dev; }; then
+ autolib_output_banner "Building development container"
+ pushd docker > /dev/null || return $?
+ make || {
+ r=$?
+ outlib_output_error "Docker Build Failure"
+ return $r
+ }
+ popd > /dev/null
+ fi
+
+ autolib_output_banner "Entering development environment"
+ declare -a args
+ args+=(--name prometheus-client-c-dev) # Give the running container a name to use instead of the ID
+ args+=(--interactive) # Interactive shell
+ args+=(--tty) # We'll need a tty
+ args+=(--volume "${PWD}:/code") # Mount code into the container
+ args+=(--env DEV=1) # Enables check if executing in dev environment
+ args+=(--net host) # Use host networking
+ args+=(--cap-add=SYS_PTRACE) # Required for valgrind and gdb
+ args+=(--security-opt seccomp=unconfined) # Required for debugging
+ args+=(--rm) # Remove when done
+
+ docker run ${args[@]} prometheus-client-c-dev ${DOCKER_EXEC} ${DOCKER_EXEC_ARGS[@]} || {
+ r=$?
+ autolib_output_error "Failed to enter development environment"
+ return $r
+ }
+}
+
+main(){
+ while getopts "he:a:" opt; do
+ case $opt in
+ ( h ) {
+ usage && exit 0
+ } ;;
+ ( e ) {
+ DOCKER_EXEC="$OPTARG"
+ } ;;
+ ( a ) {
+ DOCKER_EXEC_ARGS+=($OPTARG)
+ } ;;
+ esac
+ done
+ run $@; exit $?
+}
+
+[[ $BASH_SOURCE == $0 ]] && main $@ \ No newline at end of file
diff --git a/autolib/cmd/docs b/autolib/cmd/docs
new file mode 100755
index 0000000..207f459
--- /dev/null
+++ b/autolib/cmd/docs
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+
+########################################################################################################################
+# Meta
+########################################################################################################################
+
+# Propagate environment variables
+if [[ "$AUTO_DEBUG" == "1" ]]; then
+ set -x
+ export AUTO_DEBUG=1
+fi
+
+PROGRAM_NAME="$(basename $0)"
+
+short="Generate the documentation"
+
+read -d '' long <<EOF
+You MUST execute this command from your development workstation. You MUST NOT
+execute this command from an existing docker container.
+EOF
+
+usage() {
+ cat <<EOF
+
+$PROGRAM_NAME [-h]
+
+$short
+
+DESCRIPTION
+
+$long
+
+EOF
+}
+
+########################################################################################################################
+# End Meta
+########################################################################################################################
+
+source $(dirname ${BASH_SOURCE[0]})/../autolib.sh
+
+run(){
+ local r
+ autolib_check_dev || return $?
+ autolib_output_banner "Executing ${PROGRAM_NAME}"
+ doxygen Doxyfile || {
+ r=$?
+ autolib_output_error "Failed to generate Doxygen documentation"
+ return $r
+ }
+ if [ -d /tmp/html ]; then rm -rf /tmp/html; fi
+ mv docs/html /tmp/
+ rm -r docs/latex
+ cp -R /tmp/html/* docs/
+ autolib_output_success "Doxygen documentation generation complete"
+}
+
+main(){
+ while getopts "h" opt; do
+ case $opt in
+ ( h ) {
+ usage && exit 0
+ } ;;
+ esac
+ done
+ run $@; exit $?
+}
+
+[[ $BASH_SOURCE == $0 ]] && main $@ \ No newline at end of file
diff --git a/autolib/cmd/package b/autolib/cmd/package
new file mode 100755
index 0000000..8beef1c
--- /dev/null
+++ b/autolib/cmd/package
@@ -0,0 +1,74 @@
+#!/usr/bin/env bash
+
+########################################################################################################################
+# Meta
+########################################################################################################################
+
+# Propagate environment variables
+if [[ "$AUTO_DEBUG" == "1" ]]; then
+ set -x
+ export AUTO_DEBUG=1
+fi
+
+PROGRAM_NAME="$(basename $0)"
+
+short="Package prometheus-client-c"
+
+read -d '' long <<EOF
+You MUST execute this command from your development workstation. You MUST NOT
+execute this command from an existing docker container.
+EOF
+
+usage() {
+ cat <<EOF
+
+$PROGRAM_NAME [-h]
+
+$short
+
+DESCRIPTION
+
+$long
+
+EOF
+}
+
+########################################################################################################################
+# End Meta
+########################################################################################################################
+
+source $(dirname ${BASH_SOURCE[0]})/../autolib.sh
+
+run(){
+ local r
+ autolib_check_dev || return $?
+ autolib_output_banner "Executing ${PROGRAM_NAME}AME}"
+
+ for lib in ${LIBS[@]}; do
+ pushd ${lib} > /dev/null || return $?
+ cpack \
+ --config build/CPackConfig.cmake \
+ -D "CPACK_DEBIAN_PACKAGE_MAINTAINER=Demitri Swan" \
+ -D "CPACK_PACKAGE_CONTACT=dswan@digitalocean.com" || {
+
+ r=$?
+ autolib_output_error "${lib}: Package build failed"
+ return $r
+ }
+ popd > /dev/null || return $?
+ done
+ autolib_output_success "Package build success"
+}
+
+main(){
+ while getopts "h" opt; do
+ case $opt in
+ ( h ) {
+ usage && exit 0
+ } ;;
+ esac
+ done
+ run $@; exit $?
+}
+
+[[ $BASH_SOURCE == $0 ]] && main $@ \ No newline at end of file
diff --git a/autolib/cmd/smoke b/autolib/cmd/smoke
new file mode 100755
index 0000000..52fe33b
--- /dev/null
+++ b/autolib/cmd/smoke
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+
+########################################################################################################################
+# Meta
+########################################################################################################################
+
+# Propagate environment variables
+if [[ "$AUTO_DEBUG" == "1" ]]; then
+ set -x
+ export AUTO_DEBUG=1
+fi
+
+PROGRAM_NAME=$(basename $0)
+
+short="Extinguish smoke"
+read -d '' long <<EOF
+
+You MUST execute this command within the development container.
+
+EOF
+
+usage(){
+ cat <<EOF
+
+$PROGRAM_NAME [-h]
+
+$short
+
+DESCRIPTION
+
+$long
+EOF
+}
+
+########################################################################################################################
+# End Meta
+########################################################################################################################
+
+source "$(dirname ${BASH_SOURCE[0]})/../autolib.sh"
+
+run(){
+ autolib_check_dev || return $?
+ autolib_output_banner "Executing ${PROGRAM_NAME}"
+ if [ ! -d promtest/build ]; then mkdir promtest/build; fi
+ pushd promtest/build > /dev/null
+ { cmake .. && make && ARGS=' --track-origins=yes --output-on-failure=yes --verbose' make test; } || {
+ autolib_output_error "Smoke test failure"
+ return 1
+ }
+ autolib_output_success "Smoke test pass"
+ popd > /dev/null
+}
+
+main(){
+ while getopts 'h' opt; do
+ case "$opt" in
+ ( h ) {
+ usage && exit 0
+ } ;;
+ ( * ) {
+ usage && exit 1
+ } ;;
+ esac
+ done
+ run $@ || exit $?
+}
+
+[[ $BASH_SOURCE == $0 ]] && main $@ \ No newline at end of file
diff --git a/autolib/cmd/test b/autolib/cmd/test
new file mode 100755
index 0000000..99b65be
--- /dev/null
+++ b/autolib/cmd/test
@@ -0,0 +1,92 @@
+#!/usr/bin/env bash
+
+########################################################################################################################
+# Meta
+########################################################################################################################
+
+# Propagate environment variables
+if [[ "$AUTO_DEBUG" == "1" ]]; then
+ set -x
+ export AUTO_DEBUG=1
+fi
+
+PROGRAM_NAME=$(basename $0)
+
+short="Test the project"
+read -d '' long <<EOF
+
+You MUST execute this command within the development container.
+
+EOF
+
+usage(){
+ cat <<EOF
+
+$PROGRAM_NAME [-h] [-m] [-t]
+
+$short
+
+OPTIONS
+
+-t Run the unit/integration tests only
+-m Run the memory tests only
+
+DESCRIPTION
+
+$long
+EOF
+}
+
+########################################################################################################################
+# End Meta
+########################################################################################################################
+
+source "$(dirname ${BASH_SOURCE[0]})/../autolib.sh"
+
+declare -i AUTO_TEST_MEM_ONLY=0
+declare -i AUTO_TEST_TESTS_ONLY=0
+
+run(){
+ autolib_check_dev || return $?
+ autolib_output_banner "Executing ${PROGRAM_NAME}"
+ for lib in prom; do
+ if (( AUTO_TEST_MEM_ONLY == 0 && AUTO_TEST_TESTS_ONLY == 0 )); then
+ { autolib_test "${lib}" && autolib_mem_test "${lib}"; } || return $?
+ fi
+
+ if (( AUTO_TEST_MEM_ONLY == 1 )); then
+ autolib_mem_test "${lib}" || return $?
+ fi
+
+ if (( AUTO_TEST_TESTS_ONLY == 1 )); then
+ autolib_test "${lib}" || return $?
+ fi
+ done
+}
+
+main(){
+ while getopts 'hmts' opt; do
+ case "$opt" in
+ ( h ) {
+ usage && exit 0
+ } ;;
+ ( m ) {
+ AUTO_TEST_MEM_ONLY=1
+ } ;;
+ ( t ) {
+ AUTO_TEST_TESTS_ONLY=1
+ } ;;
+ ( * ) {
+ usage && exit 1
+ } ;;
+ esac
+ done
+ local total=$((AUTO_TEST_MEM_ONLY + AUTO_TEST_TESTS_ONLY))
+ if (( total > 1 )); then
+ usage
+ exit 1
+ fi
+ run $@ || exit $?
+}
+
+[[ $BASH_SOURCE == $0 ]] && main $@ \ No newline at end of file
diff --git a/autolib/env.sh b/autolib/env.sh
new file mode 100644
index 0000000..431b8b3
--- /dev/null
+++ b/autolib/env.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+autolib_check_dev(){
+ local dev=${DEV:=0}
+ if (( dev == 0 )); then
+ autolib_output_err "Not executing in the Docker environment"
+ return 1
+ fi
+} \ No newline at end of file
diff --git a/autolib/output.sh b/autolib/output.sh
new file mode 100644
index 0000000..18207cd
--- /dev/null
+++ b/autolib/output.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+# Print a stage. Pass a string to be enveloped in a banner.
+autolib_output_banner(){
+ echo -e "\n\033[1m########################################################################\033[0m" >&2
+ echo -e "\033[1m> $@\033[0m" >&2
+ echo -e "\033[1m########################################################################\033[0m\n" >&2
+}
+
+autolib_output_error() {
+ echo -e "\033[1;31mERROR: $@\033[0m" >&2
+}
+
+autolib_output_success() {
+ echo -e "\033[1;32mSUCCESS: $@\033[0m" >&2
+}
+
+autolib_output_warn() {
+ echo -e "\033[1;33mWARN: $@\033[0m" >&2
+} \ No newline at end of file
diff --git a/autolib/test.sh b/autolib/test.sh
new file mode 100644
index 0000000..dd30f76
--- /dev/null
+++ b/autolib/test.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+
+lib="$(dirname ${BASH_SOURCE[0]})"
+
+source "${lib}/output.sh"
+
+autolib_test() {
+ local library="$1"
+ local r
+ pushd ${lib}/build > /dev/null || return $?
+ autolib_output_banner "${library}: Starting Tests"
+ ARGS=' --track-origins=yes --output-on-failure=yes --verbose' make test && {
+ r=$?
+ autolib_output_success "${library}: Test Pass"
+ } || {
+ r=$?
+ autolib_output_error "${library}: Test Failure"
+ }
+ popd > /dev/null || return $?
+ return $r
+}
+
+autolib_mem_test() {
+ local library="$1"
+ local r
+ pushd ${library} > /dev/null || return $?
+ autolib_output_banner "${library}: Starting MemTests"
+ while read test_file; do
+ valgrind --leak-check=full --error-exitcode=1 --num-callers=30 "$test_file" && {
+ r=$?
+ autolib_output_success "${library} ${test_file}: MemTest Pass"
+ } || {
+ r=$?
+ autolib_output_error "${library} ${test_file}: MemTest Failure"
+ }
+ done < <(find build -maxdepth 1 -regex ".*prom.*test$")
+ popd > /dev/null || return $?
+ return $r
+} \ No newline at end of file
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 0000000..a27d2e7
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,21 @@
+FROM ubuntu:18.04
+
+RUN apt-get update && \
+ apt-get install -y apt-utils && \
+ apt-get install -y curl tar build-essential git pkg-config gdb valgrind gcc libmicrohttpd-dev doxygen graphviz && \
+ curl -L https://dl.google.com/go/go1.13.1.linux-amd64.tar.gz 2> /dev/null | tar xzvf - -C /usr/local && \
+ mkdir -p /gopath/{src,bin} && \
+ echo 'export GOPATH=/gopath' > /root/.bash_profile && \
+ echo 'export PATH=$PATH:/usr/local/go/bin:/gopath/bin' > /root/.bash_profile && \
+ printf '#!/usr/bin/env bash\nsource /root/.bash_profile\nexec /bin/bash $@\n' > /entrypoint && \
+ chmod +x /entrypoint && \
+ GOPATH=/gopath /usr/local/go/bin/go get github.com/prometheus/prom2json && \
+ GOPATH=/gopath /usr/local/go/bin/go install github.com/prometheus/prom2json/cmd/prom2json && \
+ GOPATH=/gopath /usr/local/go/bin/go get github.com/git-chglog/git-chglog && \
+ GOPATH=/gopath /usr/local/go/bin/go install github.com/git-chglog/git-chglog/cmd/git-chglog && \
+ curl -L https://github.com/Kitware/CMake/releases/download/v3.15.0-rc1/cmake-3.15.0-rc1.tar.gz | tar xzvf - -C /tmp/ && \
+ cd /tmp/cmake-3.15.0-rc1 && ./bootstrap && make && make install && \
+ rm -rf /var/lib/apt/lists/*
+
+WORKDIR /code
+ENTRYPOINT ["/entrypoint"] \ No newline at end of file
diff --git a/docker/Makefile b/docker/Makefile
new file mode 100644
index 0000000..375bb2b
--- /dev/null
+++ b/docker/Makefile
@@ -0,0 +1,2 @@
+docker:
+ docker build -t prometheus-client-c-dev . \ No newline at end of file
diff --git a/docs/annotated.html b/docs/annotated.html
new file mode 100644
index 0000000..bf22cde
--- /dev/null
+++ b/docs/annotated.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: Class List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">Class List</div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here are the classes, structs, unions and interfaces with brief descriptions:</div><div class="directory">
+<table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="structprom__histogram__buckets.html" target="_self">prom_histogram_buckets</a></td><td class="desc"></td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/bc_s.png b/docs/bc_s.png
new file mode 100644
index 0000000..224b29a
--- /dev/null
+++ b/docs/bc_s.png
Binary files differ
diff --git a/docs/bdwn.png b/docs/bdwn.png
new file mode 100644
index 0000000..940a0b9
--- /dev/null
+++ b/docs/bdwn.png
Binary files differ
diff --git a/docs/classes.html b/docs/classes.html
new file mode 100644
index 0000000..82584db
--- /dev/null
+++ b/docs/classes.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: Class Index</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">Class Index</div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="qindex"><a class="qindex" href="#letter_p">p</a></div>
+<table class="classindex">
+<tr><td rowspan="2" valign="bottom"><a name="letter_p"></a><table border="0" cellspacing="0" cellpadding="0"><tr><td><div class="ah">&#160;&#160;p&#160;&#160;</div></td></tr></table>
+</td><td></td></tr>
+<tr><td></td></tr>
+<tr><td valign="top"><a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets</a>&#160;&#160;&#160;</td><td></td></tr>
+<tr><td></td><td></td></tr>
+</table>
+<div class="qindex"><a class="qindex" href="#letter_p">p</a></div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/closed.png b/docs/closed.png
new file mode 100644
index 0000000..98cc2c9
--- /dev/null
+++ b/docs/closed.png
Binary files differ
diff --git a/docs/dir_000003_000000.html b/docs/dir_000003_000000.html
new file mode 100644
index 0000000..f0ce765
--- /dev/null
+++ b/docs/dir_000003_000000.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: promhttp/include -&gt; prom Relation</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_21619567660c3332e6a61228c76007f9.html">promhttp</a></li><li class="navelem"><a class="el" href="dir_8d140c3a8bac3cd45205c9ea74fd211f.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="contents">
+<h3>include &rarr; prom Relation</h3><table class="dirtab"><tr class="dirtab"><th class="dirtab">File in promhttp/include</th><th class="dirtab">Includes file in prom</th></tr><tr class="dirtab"><td class="dirtab"><a class="el" href="promhttp_8h.html">promhttp.h</a></td><td class="dirtab"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a>&#160;/&#160;<a class="el" href="prom_8h.html">prom.h</a></td></tr></table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/dir_21619567660c3332e6a61228c76007f9.html b/docs/dir_21619567660c3332e6a61228c76007f9.html
new file mode 100644
index 0000000..ca466b9
--- /dev/null
+++ b/docs/dir_21619567660c3332e6a61228c76007f9.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: promhttp Directory Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_21619567660c3332e6a61228c76007f9.html">promhttp</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">promhttp Directory Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="subdirs"></a>
+Directories</h2></td></tr>
+</table>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/dir_21619567660c3332e6a61228c76007f9_dep.dot b/docs/dir_21619567660c3332e6a61228c76007f9_dep.dot
new file mode 100644
index 0000000..34aead6
--- /dev/null
+++ b/docs/dir_21619567660c3332e6a61228c76007f9_dep.dot
@@ -0,0 +1,12 @@
+digraph "promhttp" {
+ compound=true
+ node [ fontsize="10", fontname="Helvetica"];
+ edge [ labelfontsize="10", labelfontname="Helvetica"];
+ subgraph clusterdir_21619567660c3332e6a61228c76007f9 {
+ graph [ bgcolor="#eeeeff", pencolor="black", label="" URL="dir_21619567660c3332e6a61228c76007f9.html"];
+ dir_21619567660c3332e6a61228c76007f9 [shape=plaintext label="promhttp"];
+ dir_8d140c3a8bac3cd45205c9ea74fd211f [shape=box label="include" color="black" fillcolor="white" style="filled" URL="dir_8d140c3a8bac3cd45205c9ea74fd211f.html"];
+ }
+ dir_2c63f04010e7ff462eba5e344f58cd21 [shape=box label="prom" fillcolor="white" style="filled" color="red" URL="dir_2c63f04010e7ff462eba5e344f58cd21.html"];
+ dir_8d140c3a8bac3cd45205c9ea74fd211f->dir_2c63f04010e7ff462eba5e344f58cd21 [headlabel="1", labeldistance=1.5 headhref="dir_000003_000000.html"];
+}
diff --git a/docs/dir_21619567660c3332e6a61228c76007f9_dep.map b/docs/dir_21619567660c3332e6a61228c76007f9_dep.map
new file mode 100644
index 0000000..90600f2
--- /dev/null
+++ b/docs/dir_21619567660c3332e6a61228c76007f9_dep.map
@@ -0,0 +1,6 @@
+<map id="promhttp" name="promhttp">
+<area shape="rect" id="node2" href="dir_8d140c3a8bac3cd45205c9ea74fd211f.html" title="include" alt="" coords="27,27,99,75"/>
+<area shape="rect" id="node3" href="dir_2c63f04010e7ff462eba5e344f58cd21.html" title="prom" alt="" coords="27,123,99,171"/>
+<area shape="rect" id="edge1-headlabel" href="dir_000003_000000.html" title="1" alt="" coords="66,97,76,111"/>
+<area shape="rect" id="clust1" href="dir_21619567660c3332e6a61228c76007f9.html" alt="" coords="16,16,216,85"/>
+</map>
diff --git a/docs/dir_21619567660c3332e6a61228c76007f9_dep.md5 b/docs/dir_21619567660c3332e6a61228c76007f9_dep.md5
new file mode 100644
index 0000000..d92ba69
--- /dev/null
+++ b/docs/dir_21619567660c3332e6a61228c76007f9_dep.md5
@@ -0,0 +1 @@
+5a733acb8d15f543b6a2b5e7983b6f1e \ No newline at end of file
diff --git a/docs/dir_21619567660c3332e6a61228c76007f9_dep.png b/docs/dir_21619567660c3332e6a61228c76007f9_dep.png
new file mode 100644
index 0000000..d39190e
--- /dev/null
+++ b/docs/dir_21619567660c3332e6a61228c76007f9_dep.png
Binary files differ
diff --git a/docs/dir_2c63f04010e7ff462eba5e344f58cd21.html b/docs/dir_2c63f04010e7ff462eba5e344f58cd21.html
new file mode 100644
index 0000000..085aebe
--- /dev/null
+++ b/docs/dir_2c63f04010e7ff462eba5e344f58cd21.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom Directory Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom Directory Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="subdirs"></a>
+Directories</h2></td></tr>
+</table>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/dir_83821d63a26a6eb889c4977bd95ca990.html b/docs/dir_83821d63a26a6eb889c4977bd95ca990.html
new file mode 100644
index 0000000..8fb32e0
--- /dev/null
+++ b/docs/dir_83821d63a26a6eb889c4977bd95ca990.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include Directory Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">include Directory Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="files"></a>
+Files</h2></td></tr>
+<tr class="memitem:prom_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom_8h.html">prom.h</a> <a href="prom_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:prom_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight">Include <a class="el" href="prom_8h.html" title="Include prom.h to include the entire public API. ">prom.h</a> to include the entire public API. <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:prom__alloc_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__alloc_8h.html">prom_alloc.h</a> <a href="prom__alloc_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:prom__alloc_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight">memory management <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:prom__collector_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector_8h.html">prom_collector.h</a> <a href="prom__collector_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:prom__collector_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight">A Prometheus collector returns a collection of metrics. <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:prom__collector__registry_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html">prom_collector_registry.h</a> <a href="prom__collector__registry_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:prom__collector__registry_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight">The collector registry registers collectors for metric exposition. <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:prom__counter_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__counter_8h.html">prom_counter.h</a> <a href="prom__counter_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:prom__counter_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight"><a href="https://prometheus.io/docs/concepts/metric_types/#counter">https://prometheus.io/docs/concepts/metric_types/#counter</a> <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:prom__gauge_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__gauge_8h.html">prom_gauge.h</a> <a href="prom__gauge_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:prom__gauge_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight"><a href="https://prometheus.io/docs/concepts/metric_types/#gauge">https://prometheus.io/docs/concepts/metric_types/#gauge</a> <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:prom__histogram_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__histogram_8h.html">prom_histogram.h</a> <a href="prom__histogram_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:prom__histogram_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight"><a href="https://prometheus.io/docs/concepts/metric_types/#histogram">https://prometheus.io/docs/concepts/metric_types/#histogram</a> <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:prom__histogram__buckets_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__histogram__buckets_8h.html">prom_histogram_buckets.h</a> <a href="prom__histogram__buckets_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:prom__histogram__buckets_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight"><a href="https://prometheus.io/docs/concepts/metric_types/#histogram">https://prometheus.io/docs/concepts/metric_types/#histogram</a> <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:prom__metric_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric_8h.html">prom_metric.h</a> <a href="prom__metric_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:prom__metric_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight">Functions for retrieving metric samples from metrics given an ordered set of labels. <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:prom__metric__sample_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric__sample_8h.html">prom_metric_sample.h</a> <a href="prom__metric__sample_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:prom__metric__sample_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight">Functions for interfacting with metric samples directly. <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:prom__metric__sample__histogram_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric__sample__histogram_8h.html">prom_metric_sample_histogram.h</a> <a href="prom__metric__sample__histogram_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:prom__metric__sample__histogram_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight">Functions for interacting with histogram metric samples directly. <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f.html b/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f.html
new file mode 100644
index 0000000..4f31cf1
--- /dev/null
+++ b/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: promhttp/include Directory Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_21619567660c3332e6a61228c76007f9.html">promhttp</a></li><li class="navelem"><a class="el" href="dir_8d140c3a8bac3cd45205c9ea74fd211f.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">include Directory Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="files"></a>
+Files</h2></td></tr>
+<tr class="memitem:promhttp_8h"><td class="memItemLeft" align="right" valign="top">file &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="promhttp_8h.html">promhttp.h</a> <a href="promhttp_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:promhttp_8h"><td class="mdescLeft">&#160;</td><td class="mdescRight">Provides a HTTP endpoint for metric exposition References: <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.dot b/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.dot
new file mode 100644
index 0000000..b65c06e
--- /dev/null
+++ b/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.dot
@@ -0,0 +1,11 @@
+digraph "promhttp/include" {
+ compound=true
+ node [ fontsize="10", fontname="Helvetica"];
+ edge [ labelfontsize="10", labelfontname="Helvetica"];
+ subgraph clusterdir_21619567660c3332e6a61228c76007f9 {
+ graph [ bgcolor="#ddddee", pencolor="black", label="promhttp" fontname="Helvetica", fontsize="10", URL="dir_21619567660c3332e6a61228c76007f9.html"]
+ dir_8d140c3a8bac3cd45205c9ea74fd211f [shape=box, label="include", style="filled", fillcolor="#eeeeff", pencolor="black", URL="dir_8d140c3a8bac3cd45205c9ea74fd211f.html"];
+ }
+ dir_2c63f04010e7ff462eba5e344f58cd21 [shape=box label="prom" fillcolor="white" style="filled" color="red" URL="dir_2c63f04010e7ff462eba5e344f58cd21.html"];
+ dir_8d140c3a8bac3cd45205c9ea74fd211f->dir_2c63f04010e7ff462eba5e344f58cd21 [headlabel="1", labeldistance=1.5 headhref="dir_000003_000000.html"];
+}
diff --git a/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.map b/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.map
new file mode 100644
index 0000000..5081380
--- /dev/null
+++ b/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.map
@@ -0,0 +1,6 @@
+<map id="promhttp/include" name="promhttp/include">
+<area shape="rect" id="node1" href="dir_8d140c3a8bac3cd45205c9ea74fd211f.html" title="include" alt="" coords="27,52,99,100"/>
+<area shape="rect" id="node2" href="dir_2c63f04010e7ff462eba5e344f58cd21.html" title="prom" alt="" coords="27,148,99,196"/>
+<area shape="rect" id="edge1-headlabel" href="dir_000003_000000.html" title="1" alt="" coords="66,122,76,137"/>
+<area shape="rect" id="clust1" href="dir_21619567660c3332e6a61228c76007f9.html" title="promhttp" alt="" coords="16,16,109,111"/>
+</map>
diff --git a/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.md5 b/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.md5
new file mode 100644
index 0000000..76b9734
--- /dev/null
+++ b/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.md5
@@ -0,0 +1 @@
+409e6884fb8a90bc89f51c346dd9a368 \ No newline at end of file
diff --git a/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.png b/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.png
new file mode 100644
index 0000000..db4e49e
--- /dev/null
+++ b/docs/dir_8d140c3a8bac3cd45205c9ea74fd211f_dep.png
Binary files differ
diff --git a/docs/doc.png b/docs/doc.png
new file mode 100644
index 0000000..17edabf
--- /dev/null
+++ b/docs/doc.png
Binary files differ
diff --git a/docs/doxygen.css b/docs/doxygen.css
new file mode 100644
index 0000000..4f1ab91
--- /dev/null
+++ b/docs/doxygen.css
@@ -0,0 +1,1596 @@
+/* The standard CSS for doxygen 1.8.13 */
+
+body, table, div, p, dl {
+ font: 400 14px/22px Roboto,sans-serif;
+}
+
+p.reference, p.definition {
+ font: 400 14px/22px Roboto,sans-serif;
+}
+
+/* @group Heading Levels */
+
+h1.groupheader {
+ font-size: 150%;
+}
+
+.title {
+ font: 400 14px/28px Roboto,sans-serif;
+ font-size: 150%;
+ font-weight: bold;
+ margin: 10px 2px;
+}
+
+h2.groupheader {
+ border-bottom: 1px solid #879ECB;
+ color: #354C7B;
+ font-size: 150%;
+ font-weight: normal;
+ margin-top: 1.75em;
+ padding-top: 8px;
+ padding-bottom: 4px;
+ width: 100%;
+}
+
+h3.groupheader {
+ font-size: 100%;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ -webkit-transition: text-shadow 0.5s linear;
+ -moz-transition: text-shadow 0.5s linear;
+ -ms-transition: text-shadow 0.5s linear;
+ -o-transition: text-shadow 0.5s linear;
+ transition: text-shadow 0.5s linear;
+ margin-right: 15px;
+}
+
+h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {
+ text-shadow: 0 0 15px cyan;
+}
+
+dt {
+ font-weight: bold;
+}
+
+div.multicol {
+ -moz-column-gap: 1em;
+ -webkit-column-gap: 1em;
+ -moz-column-count: 3;
+ -webkit-column-count: 3;
+}
+
+p.startli, p.startdd {
+ margin-top: 2px;
+}
+
+p.starttd {
+ margin-top: 0px;
+}
+
+p.endli {
+ margin-bottom: 0px;
+}
+
+p.enddd {
+ margin-bottom: 4px;
+}
+
+p.endtd {
+ margin-bottom: 2px;
+}
+
+/* @end */
+
+caption {
+ font-weight: bold;
+}
+
+span.legend {
+ font-size: 70%;
+ text-align: center;
+}
+
+h3.version {
+ font-size: 90%;
+ text-align: center;
+}
+
+div.qindex, div.navtab{
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
+ text-align: center;
+}
+
+div.qindex, div.navpath {
+ width: 100%;
+ line-height: 140%;
+}
+
+div.navtab {
+ margin-right: 15px;
+}
+
+/* @group Link Styling */
+
+a {
+ color: #3D578C;
+ font-weight: normal;
+ text-decoration: none;
+}
+
+.contents a:visited {
+ color: #4665A2;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+a.qindex {
+ font-weight: bold;
+}
+
+a.qindexHL {
+ font-weight: bold;
+ background-color: #9CAFD4;
+ color: #ffffff;
+ border: 1px double #869DCA;
+}
+
+.contents a.qindexHL:visited {
+ color: #ffffff;
+}
+
+a.el {
+ font-weight: bold;
+}
+
+a.elRef {
+}
+
+a.code, a.code:visited, a.line, a.line:visited {
+ color: #4665A2;
+}
+
+a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
+ color: #4665A2;
+}
+
+/* @end */
+
+dl.el {
+ margin-left: -1cm;
+}
+
+pre.fragment {
+ border: 1px solid #C4CFE5;
+ background-color: #FBFCFD;
+ padding: 4px 6px;
+ margin: 4px 8px 4px 2px;
+ overflow: auto;
+ word-wrap: break-word;
+ font-size: 9pt;
+ line-height: 125%;
+ font-family: monospace, fixed;
+ font-size: 105%;
+}
+
+div.fragment {
+ padding: 0px;
+ margin: 4px 8px 4px 2px;
+ background-color: #FBFCFD;
+ border: 1px solid #C4CFE5;
+}
+
+div.line {
+ font-family: monospace, fixed;
+ font-size: 13px;
+ min-height: 13px;
+ line-height: 1.0;
+ text-wrap: unrestricted;
+ white-space: -moz-pre-wrap; /* Moz */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ white-space: pre-wrap; /* CSS3 */
+ word-wrap: break-word; /* IE 5.5+ */
+ text-indent: -53px;
+ padding-left: 53px;
+ padding-bottom: 0px;
+ margin: 0px;
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
+}
+
+div.line:after {
+ content:"\000A";
+ white-space: pre;
+}
+
+div.line.glow {
+ background-color: cyan;
+ box-shadow: 0 0 10px cyan;
+}
+
+
+span.lineno {
+ padding-right: 4px;
+ text-align: right;
+ border-right: 2px solid #0F0;
+ background-color: #E8E8E8;
+ white-space: pre;
+}
+span.lineno a {
+ background-color: #D8D8D8;
+}
+
+span.lineno a:hover {
+ background-color: #C8C8C8;
+}
+
+.lineno {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+div.ah, span.ah {
+ background-color: black;
+ font-weight: bold;
+ color: #ffffff;
+ margin-bottom: 3px;
+ margin-top: 3px;
+ padding: 0.2em;
+ border: solid thin #333;
+ border-radius: 0.5em;
+ -webkit-border-radius: .5em;
+ -moz-border-radius: .5em;
+ box-shadow: 2px 2px 3px #999;
+ -webkit-box-shadow: 2px 2px 3px #999;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));
+ background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000 110%);
+}
+
+div.classindex ul {
+ list-style: none;
+ padding-left: 0;
+}
+
+div.classindex span.ai {
+ display: inline-block;
+}
+
+div.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ font-weight: bold;
+}
+
+div.groupText {
+ margin-left: 16px;
+ font-style: italic;
+}
+
+body {
+ background-color: white;
+ color: black;
+ margin: 0;
+}
+
+div.contents {
+ margin-top: 10px;
+ margin-left: 12px;
+ margin-right: 8px;
+}
+
+td.indexkey {
+ background-color: #EBEFF6;
+ font-weight: bold;
+ border: 1px solid #C4CFE5;
+ margin: 2px 0px 2px 0;
+ padding: 2px 10px;
+ white-space: nowrap;
+ vertical-align: top;
+}
+
+td.indexvalue {
+ background-color: #EBEFF6;
+ border: 1px solid #C4CFE5;
+ padding: 2px 10px;
+ margin: 2px 0px;
+}
+
+tr.memlist {
+ background-color: #EEF1F7;
+}
+
+p.formulaDsp {
+ text-align: center;
+}
+
+img.formulaDsp {
+
+}
+
+img.formulaInl {
+ vertical-align: middle;
+}
+
+div.center {
+ text-align: center;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+}
+
+div.center img {
+ border: 0px;
+}
+
+address.footer {
+ text-align: right;
+ padding-right: 12px;
+}
+
+img.footer {
+ border: 0px;
+ vertical-align: middle;
+}
+
+/* @group Code Colorization */
+
+span.keyword {
+ color: #008000
+}
+
+span.keywordtype {
+ color: #604020
+}
+
+span.keywordflow {
+ color: #e08000
+}
+
+span.comment {
+ color: #800000
+}
+
+span.preprocessor {
+ color: #806020
+}
+
+span.stringliteral {
+ color: #002080
+}
+
+span.charliteral {
+ color: #008080
+}
+
+span.vhdldigit {
+ color: #ff00ff
+}
+
+span.vhdlchar {
+ color: #000000
+}
+
+span.vhdlkeyword {
+ color: #700070
+}
+
+span.vhdllogic {
+ color: #ff0000
+}
+
+blockquote {
+ background-color: #F7F8FB;
+ border-left: 2px solid #9CAFD4;
+ margin: 0 24px 0 4px;
+ padding: 0 12px 0 16px;
+}
+
+/* @end */
+
+/*
+.search {
+ color: #003399;
+ font-weight: bold;
+}
+
+form.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+
+input.search {
+ font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #e8eef2;
+}
+*/
+
+td.tiny {
+ font-size: 75%;
+}
+
+.dirtab {
+ padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #A3B4D7;
+}
+
+th.dirtab {
+ background: #EBEFF6;
+ font-weight: bold;
+}
+
+hr {
+ height: 0px;
+ border: none;
+ border-top: 1px solid #4A6AAA;
+}
+
+hr.footer {
+ height: 1px;
+}
+
+/* @group Member Descriptions */
+
+table.memberdecls {
+ border-spacing: 0px;
+ padding: 0px;
+}
+
+.memberdecls td, .fieldtable tr {
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
+}
+
+.memberdecls td.glow, .fieldtable tr.glow {
+ background-color: cyan;
+ box-shadow: 0 0 15px cyan;
+}
+
+.mdescLeft, .mdescRight,
+.memItemLeft, .memItemRight,
+.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
+ background-color: #F9FAFC;
+ border: none;
+ margin: 4px;
+ padding: 1px 0 0 8px;
+}
+
+.mdescLeft, .mdescRight {
+ padding: 0px 8px 4px 8px;
+ color: #555;
+}
+
+.memSeparator {
+ border-bottom: 1px solid #DEE4F0;
+ line-height: 1px;
+ margin: 0px;
+ padding: 0px;
+}
+
+.memItemLeft, .memTemplItemLeft {
+ white-space: nowrap;
+}
+
+.memItemRight {
+ width: 100%;
+}
+
+.memTemplParams {
+ color: #4665A2;
+ white-space: nowrap;
+ font-size: 80%;
+}
+
+/* @end */
+
+/* @group Member Details */
+
+/* Styles for detailed member documentation */
+
+.memtitle {
+ padding: 8px;
+ border-top: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ margin-bottom: -1px;
+ background-image: url('nav_f.png');
+ background-repeat: repeat-x;
+ background-color: #E2E8F2;
+ line-height: 1.25;
+ font-weight: 300;
+ float:left;
+}
+
+.permalink
+{
+ font-size: 65%;
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.memtemplate {
+ font-size: 80%;
+ color: #4665A2;
+ font-weight: normal;
+ margin-left: 9px;
+}
+
+.memnav {
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+
+.mempage {
+ width: 100%;
+}
+
+.memitem {
+ padding: 0;
+ margin-bottom: 10px;
+ margin-right: 5px;
+ -webkit-transition: box-shadow 0.5s linear;
+ -moz-transition: box-shadow 0.5s linear;
+ -ms-transition: box-shadow 0.5s linear;
+ -o-transition: box-shadow 0.5s linear;
+ transition: box-shadow 0.5s linear;
+ display: table !important;
+ width: 100%;
+}
+
+.memitem.glow {
+ box-shadow: 0 0 15px cyan;
+}
+
+.memname {
+ font-weight: 400;
+ margin-left: 6px;
+}
+
+.memname td {
+ vertical-align: bottom;
+}
+
+.memproto, dl.reflist dt {
+ border-top: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 0px 6px 0px;
+ color: #253555;
+ font-weight: bold;
+ text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+ background-color: #DFE5F1;
+ /* opera specific markup */
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ border-top-right-radius: 4px;
+ /* firefox specific markup */
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ -moz-border-radius-topright: 4px;
+ /* webkit specific markup */
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ -webkit-border-top-right-radius: 4px;
+
+}
+
+.overload {
+ font-family: "courier new",courier,monospace;
+ font-size: 65%;
+}
+
+.memdoc, dl.reflist dd {
+ border-bottom: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 10px 2px 10px;
+ background-color: #FBFCFD;
+ border-top-width: 0;
+ background-image:url('nav_g.png');
+ background-repeat:repeat-x;
+ background-color: #FFFFFF;
+ /* opera specific markup */
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ /* firefox specific markup */
+ -moz-border-radius-bottomleft: 4px;
+ -moz-border-radius-bottomright: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ /* webkit specific markup */
+ -webkit-border-bottom-left-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+dl.reflist dt {
+ padding: 5px;
+}
+
+dl.reflist dd {
+ margin: 0px 0px 10px 0px;
+ padding: 5px;
+}
+
+.paramkey {
+ text-align: right;
+}
+
+.paramtype {
+ white-space: nowrap;
+}
+
+.paramname {
+ color: #602020;
+ white-space: nowrap;
+}
+.paramname em {
+ font-style: normal;
+}
+.paramname code {
+ line-height: 14px;
+}
+
+.params, .retval, .exception, .tparams {
+ margin-left: 0px;
+ padding-left: 0px;
+}
+
+.params .paramname, .retval .paramname {
+ font-weight: bold;
+ vertical-align: top;
+}
+
+.params .paramtype {
+ font-style: italic;
+ vertical-align: top;
+}
+
+.params .paramdir {
+ font-family: "courier new",courier,monospace;
+ vertical-align: top;
+}
+
+table.mlabels {
+ border-spacing: 0px;
+}
+
+td.mlabels-left {
+ width: 100%;
+ padding: 0px;
+}
+
+td.mlabels-right {
+ vertical-align: bottom;
+ padding: 0px;
+ white-space: nowrap;
+}
+
+span.mlabels {
+ margin-left: 8px;
+}
+
+span.mlabel {
+ background-color: #728DC1;
+ border-top:1px solid #5373B4;
+ border-left:1px solid #5373B4;
+ border-right:1px solid #C4CFE5;
+ border-bottom:1px solid #C4CFE5;
+ text-shadow: none;
+ color: white;
+ margin-right: 4px;
+ padding: 2px 3px;
+ border-radius: 3px;
+ font-size: 7pt;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+
+
+
+/* @end */
+
+/* these are for tree view inside a (index) page */
+
+div.directory {
+ margin: 10px 0px;
+ border-top: 1px solid #9CAFD4;
+ border-bottom: 1px solid #9CAFD4;
+ width: 100%;
+}
+
+.directory table {
+ border-collapse:collapse;
+}
+
+.directory td {
+ margin: 0px;
+ padding: 0px;
+ vertical-align: top;
+}
+
+.directory td.entry {
+ white-space: nowrap;
+ padding-right: 6px;
+ padding-top: 3px;
+}
+
+.directory td.entry a {
+ outline:none;
+}
+
+.directory td.entry a img {
+ border: none;
+}
+
+.directory td.desc {
+ width: 100%;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 3px;
+ border-left: 1px solid rgba(0,0,0,0.05);
+}
+
+.directory tr.even {
+ padding-left: 6px;
+ background-color: #F7F8FB;
+}
+
+.directory img {
+ vertical-align: -30%;
+}
+
+.directory .levels {
+ white-space: nowrap;
+ width: 100%;
+ text-align: right;
+ font-size: 9pt;
+}
+
+.directory .levels span {
+ cursor: pointer;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: #3D578C;
+}
+
+.arrow {
+ color: #9CAFD4;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ cursor: pointer;
+ font-size: 80%;
+ display: inline-block;
+ width: 16px;
+ height: 22px;
+}
+
+.icon {
+ font-family: Arial, Helvetica;
+ font-weight: bold;
+ font-size: 12px;
+ height: 14px;
+ width: 16px;
+ display: inline-block;
+ background-color: #728DC1;
+ color: white;
+ text-align: center;
+ border-radius: 4px;
+ margin-left: 2px;
+ margin-right: 2px;
+}
+
+.icona {
+ width: 24px;
+ height: 22px;
+ display: inline-block;
+}
+
+.iconfopen {
+ width: 24px;
+ height: 18px;
+ margin-bottom: 4px;
+ background-image:url('folderopen.png');
+ background-position: 0px -4px;
+ background-repeat: repeat-y;
+ vertical-align:top;
+ display: inline-block;
+}
+
+.iconfclosed {
+ width: 24px;
+ height: 18px;
+ margin-bottom: 4px;
+ background-image:url('folderclosed.png');
+ background-position: 0px -4px;
+ background-repeat: repeat-y;
+ vertical-align:top;
+ display: inline-block;
+}
+
+.icondoc {
+ width: 24px;
+ height: 18px;
+ margin-bottom: 4px;
+ background-image:url('doc.png');
+ background-position: 0px -4px;
+ background-repeat: repeat-y;
+ vertical-align:top;
+ display: inline-block;
+}
+
+table.directory {
+ font: 400 14px Roboto,sans-serif;
+}
+
+/* @end */
+
+div.dynheader {
+ margin-top: 8px;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+address {
+ font-style: normal;
+ color: #2A3D61;
+}
+
+table.doxtable caption {
+ caption-side: top;
+}
+
+table.doxtable {
+ border-collapse:collapse;
+ margin-top: 4px;
+ margin-bottom: 4px;
+}
+
+table.doxtable td, table.doxtable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+table.doxtable th {
+ background-color: #374F7F;
+ color: #FFFFFF;
+ font-size: 110%;
+ padding-bottom: 4px;
+ padding-top: 5px;
+}
+
+table.fieldtable {
+ /*width: 100%;*/
+ margin-bottom: 10px;
+ border: 1px solid #A8B8D9;
+ border-spacing: 0px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+ box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+}
+
+.fieldtable td, .fieldtable th {
+ padding: 3px 7px 2px;
+}
+
+.fieldtable td.fieldtype, .fieldtable td.fieldname {
+ white-space: nowrap;
+ border-right: 1px solid #A8B8D9;
+ border-bottom: 1px solid #A8B8D9;
+ vertical-align: top;
+}
+
+.fieldtable td.fieldname {
+ padding-top: 3px;
+}
+
+.fieldtable td.fielddoc {
+ border-bottom: 1px solid #A8B8D9;
+ /*width: 100%;*/
+}
+
+.fieldtable td.fielddoc p:first-child {
+ margin-top: 0px;
+}
+
+.fieldtable td.fielddoc p:last-child {
+ margin-bottom: 2px;
+}
+
+.fieldtable tr:last-child td {
+ border-bottom: none;
+}
+
+.fieldtable th {
+ background-image:url('nav_f.png');
+ background-repeat:repeat-x;
+ background-color: #E2E8F2;
+ font-size: 90%;
+ color: #253555;
+ padding-bottom: 4px;
+ padding-top: 5px;
+ text-align:left;
+ font-weight: 400;
+ -moz-border-radius-topleft: 4px;
+ -moz-border-radius-topright: 4px;
+ -webkit-border-top-left-radius: 4px;
+ -webkit-border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ border-bottom: 1px solid #A8B8D9;
+}
+
+
+.tabsearch {
+ top: 0px;
+ left: 10px;
+ height: 36px;
+ background-image: url('tab_b.png');
+ z-index: 101;
+ overflow: hidden;
+ font-size: 13px;
+}
+
+.navpath ul
+{
+ font-size: 11px;
+ background-image:url('tab_b.png');
+ background-repeat:repeat-x;
+ background-position: 0 -5px;
+ height:30px;
+ line-height:30px;
+ color:#8AA0CC;
+ border:solid 1px #C2CDE4;
+ overflow:hidden;
+ margin:0px;
+ padding:0px;
+}
+
+.navpath li
+{
+ list-style-type:none;
+ float:left;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:url('bc_s.png');
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
+}
+
+.navpath li.navelem a
+{
+ height:32px;
+ display:block;
+ text-decoration: none;
+ outline: none;
+ color: #283A5D;
+ font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
+ text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+ text-decoration: none;
+}
+
+.navpath li.navelem a:hover
+{
+ color:#6884BD;
+}
+
+.navpath li.footer
+{
+ list-style-type:none;
+ float:right;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:none;
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
+ font-size: 8pt;
+}
+
+
+div.summary
+{
+ float: right;
+ font-size: 8pt;
+ padding-right: 5px;
+ width: 50%;
+ text-align: right;
+}
+
+div.summary a
+{
+ white-space: nowrap;
+}
+
+table.classindex
+{
+ margin: 10px;
+ white-space: nowrap;
+ margin-left: 3%;
+ margin-right: 3%;
+ width: 94%;
+ border: 0;
+ border-spacing: 0;
+ padding: 0;
+}
+
+div.ingroups
+{
+ font-size: 8pt;
+ width: 50%;
+ text-align: left;
+}
+
+div.ingroups a
+{
+ white-space: nowrap;
+}
+
+div.header
+{
+ background-image:url('nav_h.png');
+ background-repeat:repeat-x;
+ background-color: #F9FAFC;
+ margin: 0px;
+ border-bottom: 1px solid #C4CFE5;
+}
+
+div.headertitle
+{
+ padding: 5px 5px 5px 10px;
+}
+
+dl
+{
+ padding: 0 0 0 10px;
+}
+
+/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */
+dl.section
+{
+ margin-left: 0px;
+ padding-left: 0px;
+}
+
+dl.note
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #D0C000;
+}
+
+dl.warning, dl.attention
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #FF0000;
+}
+
+dl.pre, dl.post, dl.invariant
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00D000;
+}
+
+dl.deprecated
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #505050;
+}
+
+dl.todo
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00C0E0;
+}
+
+dl.test
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #3030E0;
+}
+
+dl.bug
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #C08050;
+}
+
+dl.section dd {
+ margin-bottom: 6px;
+}
+
+
+#projectlogo
+{
+ text-align: center;
+ vertical-align: bottom;
+ border-collapse: separate;
+}
+
+#projectlogo img
+{
+ border: 0px none;
+}
+
+#projectalign
+{
+ vertical-align: middle;
+}
+
+#projectname
+{
+ font: 300% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 2px 0px;
+}
+
+#projectbrief
+{
+ font: 120% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#projectnumber
+{
+ font: 50% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#titlearea
+{
+ padding: 0px;
+ margin: 0px;
+ width: 100%;
+ border-bottom: 1px solid #5373B4;
+}
+
+.image
+{
+ text-align: center;
+}
+
+.dotgraph
+{
+ text-align: center;
+}
+
+.mscgraph
+{
+ text-align: center;
+}
+
+.plantumlgraph
+{
+ text-align: center;
+}
+
+.diagraph
+{
+ text-align: center;
+}
+
+.caption
+{
+ font-weight: bold;
+}
+
+div.zoom
+{
+ border: 1px solid #90A5CE;
+}
+
+dl.citelist {
+ margin-bottom:50px;
+}
+
+dl.citelist dt {
+ color:#334975;
+ float:left;
+ font-weight:bold;
+ margin-right:10px;
+ padding:5px;
+}
+
+dl.citelist dd {
+ margin:2px 0;
+ padding:5px 0;
+}
+
+div.toc {
+ padding: 14px 25px;
+ background-color: #F4F6FA;
+ border: 1px solid #D8DFEE;
+ border-radius: 7px 7px 7px 7px;
+ float: right;
+ height: auto;
+ margin: 0 8px 10px 10px;
+ width: 200px;
+}
+
+div.toc li {
+ background: url("bdwn.png") no-repeat scroll 0 5px transparent;
+ font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif;
+ margin-top: 5px;
+ padding-left: 10px;
+ padding-top: 2px;
+}
+
+div.toc h3 {
+ font: bold 12px/1.2 Arial,FreeSans,sans-serif;
+ color: #4665A2;
+ border-bottom: 0 none;
+ margin: 0;
+}
+
+div.toc ul {
+ list-style: none outside none;
+ border: medium none;
+ padding: 0px;
+}
+
+div.toc li.level1 {
+ margin-left: 0px;
+}
+
+div.toc li.level2 {
+ margin-left: 15px;
+}
+
+div.toc li.level3 {
+ margin-left: 30px;
+}
+
+div.toc li.level4 {
+ margin-left: 45px;
+}
+
+.inherit_header {
+ font-weight: bold;
+ color: gray;
+ cursor: pointer;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.inherit_header td {
+ padding: 6px 0px 2px 5px;
+}
+
+.inherit {
+ display: none;
+}
+
+tr.heading h2 {
+ margin-top: 12px;
+ margin-bottom: 4px;
+}
+
+/* tooltip related style info */
+
+.ttc {
+ position: absolute;
+ display: none;
+}
+
+#powerTip {
+ cursor: default;
+ white-space: nowrap;
+ background-color: white;
+ border: 1px solid gray;
+ border-radius: 4px 4px 4px 4px;
+ box-shadow: 1px 1px 7px gray;
+ display: none;
+ font-size: smaller;
+ max-width: 80%;
+ opacity: 0.9;
+ padding: 1ex 1em 1em;
+ position: absolute;
+ z-index: 2147483647;
+}
+
+#powerTip div.ttdoc {
+ color: grey;
+ font-style: italic;
+}
+
+#powerTip div.ttname a {
+ font-weight: bold;
+}
+
+#powerTip div.ttname {
+ font-weight: bold;
+}
+
+#powerTip div.ttdeci {
+ color: #006318;
+}
+
+#powerTip div {
+ margin: 0px;
+ padding: 0px;
+ font: 12px/16px Roboto,sans-serif;
+}
+
+#powerTip:before, #powerTip:after {
+ content: "";
+ position: absolute;
+ margin: 0px;
+}
+
+#powerTip.n:after, #powerTip.n:before,
+#powerTip.s:after, #powerTip.s:before,
+#powerTip.w:after, #powerTip.w:before,
+#powerTip.e:after, #powerTip.e:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.nw:after, #powerTip.nw:before,
+#powerTip.sw:after, #powerTip.sw:before {
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+}
+
+#powerTip.n:after, #powerTip.s:after,
+#powerTip.w:after, #powerTip.e:after,
+#powerTip.nw:after, #powerTip.ne:after,
+#powerTip.sw:after, #powerTip.se:after {
+ border-color: rgba(255, 255, 255, 0);
+}
+
+#powerTip.n:before, #powerTip.s:before,
+#powerTip.w:before, #powerTip.e:before,
+#powerTip.nw:before, #powerTip.ne:before,
+#powerTip.sw:before, #powerTip.se:before {
+ border-color: rgba(128, 128, 128, 0);
+}
+
+#powerTip.n:after, #powerTip.n:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.nw:after, #powerTip.nw:before {
+ top: 100%;
+}
+
+#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after {
+ border-top-color: #ffffff;
+ border-width: 10px;
+ margin: 0px -10px;
+}
+#powerTip.n:before {
+ border-top-color: #808080;
+ border-width: 11px;
+ margin: 0px -11px;
+}
+#powerTip.n:after, #powerTip.n:before {
+ left: 50%;
+}
+
+#powerTip.nw:after, #powerTip.nw:before {
+ right: 14px;
+}
+
+#powerTip.ne:after, #powerTip.ne:before {
+ left: 14px;
+}
+
+#powerTip.s:after, #powerTip.s:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.sw:after, #powerTip.sw:before {
+ bottom: 100%;
+}
+
+#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after {
+ border-bottom-color: #ffffff;
+ border-width: 10px;
+ margin: 0px -10px;
+}
+
+#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before {
+ border-bottom-color: #808080;
+ border-width: 11px;
+ margin: 0px -11px;
+}
+
+#powerTip.s:after, #powerTip.s:before {
+ left: 50%;
+}
+
+#powerTip.sw:after, #powerTip.sw:before {
+ right: 14px;
+}
+
+#powerTip.se:after, #powerTip.se:before {
+ left: 14px;
+}
+
+#powerTip.e:after, #powerTip.e:before {
+ left: 100%;
+}
+#powerTip.e:after {
+ border-left-color: #ffffff;
+ border-width: 10px;
+ top: 50%;
+ margin-top: -10px;
+}
+#powerTip.e:before {
+ border-left-color: #808080;
+ border-width: 11px;
+ top: 50%;
+ margin-top: -11px;
+}
+
+#powerTip.w:after, #powerTip.w:before {
+ right: 100%;
+}
+#powerTip.w:after {
+ border-right-color: #ffffff;
+ border-width: 10px;
+ top: 50%;
+ margin-top: -10px;
+}
+#powerTip.w:before {
+ border-right-color: #808080;
+ border-width: 11px;
+ top: 50%;
+ margin-top: -11px;
+}
+
+@media print
+{
+ #top { display: none; }
+ #side-nav { display: none; }
+ #nav-path { display: none; }
+ body { overflow:visible; }
+ h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }
+ .summary { display: none; }
+ .memitem { page-break-inside: avoid; }
+ #doc-content
+ {
+ margin-left:0 !important;
+ height:auto !important;
+ width:auto !important;
+ overflow:inherit;
+ display:inline;
+ }
+}
+
+/* @group Markdown */
+
+/*
+table.markdownTable {
+ border-collapse:collapse;
+ margin-top: 4px;
+ margin-bottom: 4px;
+}
+
+table.markdownTable td, table.markdownTable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+table.markdownTableHead tr {
+}
+
+table.markdownTableBodyLeft td, table.markdownTable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+th.markdownTableHeadLeft th.markdownTableHeadRight th.markdownTableHeadCenter th.markdownTableHeadNone {
+ background-color: #374F7F;
+ color: #FFFFFF;
+ font-size: 110%;
+ padding-bottom: 4px;
+ padding-top: 5px;
+}
+
+th.markdownTableHeadLeft {
+ text-align: left
+}
+
+th.markdownTableHeadRight {
+ text-align: right
+}
+
+th.markdownTableHeadCenter {
+ text-align: center
+}
+*/
+
+table.markdownTable {
+ border-collapse:collapse;
+ margin-top: 4px;
+ margin-bottom: 4px;
+}
+
+table.markdownTable td, table.markdownTable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+table.markdownTable tr {
+}
+
+th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone {
+ background-color: #374F7F;
+ color: #FFFFFF;
+ font-size: 110%;
+ padding-bottom: 4px;
+ padding-top: 5px;
+}
+
+th.markdownTableHeadLeft, td.markdownTableBodyLeft {
+ text-align: left
+}
+
+th.markdownTableHeadRight, td.markdownTableBodyRight {
+ text-align: right
+}
+
+th.markdownTableHeadCenter, td.markdownTableBodyCenter {
+ text-align: center
+}
+
+
+/* @end */
diff --git a/docs/doxygen.png b/docs/doxygen.png
new file mode 100644
index 0000000..3ff17d8
--- /dev/null
+++ b/docs/doxygen.png
Binary files differ
diff --git a/docs/dynsections.js b/docs/dynsections.js
new file mode 100644
index 0000000..85e1836
--- /dev/null
+++ b/docs/dynsections.js
@@ -0,0 +1,97 @@
+function toggleVisibility(linkObj)
+{
+ var base = $(linkObj).attr('id');
+ var summary = $('#'+base+'-summary');
+ var content = $('#'+base+'-content');
+ var trigger = $('#'+base+'-trigger');
+ var src=$(trigger).attr('src');
+ if (content.is(':visible')===true) {
+ content.hide();
+ summary.show();
+ $(linkObj).addClass('closed').removeClass('opened');
+ $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png');
+ } else {
+ content.show();
+ summary.hide();
+ $(linkObj).removeClass('closed').addClass('opened');
+ $(trigger).attr('src',src.substring(0,src.length-10)+'open.png');
+ }
+ return false;
+}
+
+function updateStripes()
+{
+ $('table.directory tr').
+ removeClass('even').filter(':visible:even').addClass('even');
+}
+
+function toggleLevel(level)
+{
+ $('table.directory tr').each(function() {
+ var l = this.id.split('_').length-1;
+ var i = $('#img'+this.id.substring(3));
+ var a = $('#arr'+this.id.substring(3));
+ if (l<level+1) {
+ i.removeClass('iconfopen iconfclosed').addClass('iconfopen');
+ a.html('&#9660;');
+ $(this).show();
+ } else if (l==level+1) {
+ i.removeClass('iconfclosed iconfopen').addClass('iconfclosed');
+ a.html('&#9658;');
+ $(this).show();
+ } else {
+ $(this).hide();
+ }
+ });
+ updateStripes();
+}
+
+function toggleFolder(id)
+{
+ // the clicked row
+ var currentRow = $('#row_'+id);
+
+ // all rows after the clicked row
+ var rows = currentRow.nextAll("tr");
+
+ var re = new RegExp('^row_'+id+'\\d+_$', "i"); //only one sub
+
+ // only match elements AFTER this one (can't hide elements before)
+ var childRows = rows.filter(function() { return this.id.match(re); });
+
+ // first row is visible we are HIDING
+ if (childRows.filter(':first').is(':visible')===true) {
+ // replace down arrow by right arrow for current row
+ var currentRowSpans = currentRow.find("span");
+ currentRowSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
+ currentRowSpans.filter(".arrow").html('&#9658;');
+ rows.filter("[id^=row_"+id+"]").hide(); // hide all children
+ } else { // we are SHOWING
+ // replace right arrow by down arrow for current row
+ var currentRowSpans = currentRow.find("span");
+ currentRowSpans.filter(".iconfclosed").removeClass("iconfclosed").addClass("iconfopen");
+ currentRowSpans.filter(".arrow").html('&#9660;');
+ // replace down arrows by right arrows for child rows
+ var childRowsSpans = childRows.find("span");
+ childRowsSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
+ childRowsSpans.filter(".arrow").html('&#9658;');
+ childRows.show(); //show all children
+ }
+ updateStripes();
+}
+
+
+function toggleInherit(id)
+{
+ var rows = $('tr.inherit.'+id);
+ var img = $('tr.inherit_header.'+id+' img');
+ var src = $(img).attr('src');
+ if (rows.filter(':first').is(':visible')===true) {
+ rows.css('display','none');
+ $(img).attr('src',src.substring(0,src.length-8)+'closed.png');
+ } else {
+ rows.css('display','table-row'); // using show() causes jump in firefox
+ $(img).attr('src',src.substring(0,src.length-10)+'open.png');
+ }
+}
+
diff --git a/docs/files.html b/docs/files.html
new file mode 100644
index 0000000..7d49ecd
--- /dev/null
+++ b/docs/files.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: File List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">File List</div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here is a list of all documented files with brief descriptions:</div><div class="directory">
+<div class="levels">[detail level <span onclick="javascript:toggleLevel(1);">1</span><span onclick="javascript:toggleLevel(2);">2</span><span onclick="javascript:toggleLevel(3);">3</span>]</div><table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:0px;display:inline-block;">&#160;</span><span id="arr_0_" class="arrow" onclick="toggleFolder('0_')">&#9660;</span><span id="img_0_" class="iconfopen" onclick="toggleFolder('0_')">&#160;</span><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html" target="_self">prom</a></td><td class="desc"></td></tr>
+<tr id="row_0_0_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span id="arr_0_0_" class="arrow" onclick="toggleFolder('0_0_')">&#9660;</span><span id="img_0_0_" class="iconfopen" onclick="toggleFolder('0_0_')">&#160;</span><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html" target="_self">include</a></td><td class="desc"></td></tr>
+<tr id="row_0_0_0_" class="even"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom_8h_source.html"><span class="icondoc"></span></a><a class="el" href="prom_8h.html" target="_self">prom.h</a></td><td class="desc">Include <a class="el" href="prom_8h.html" title="Include prom.h to include the entire public API. ">prom.h</a> to include the entire public API </td></tr>
+<tr id="row_0_0_1_"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__alloc_8h_source.html"><span class="icondoc"></span></a><a class="el" href="prom__alloc_8h.html" target="_self">prom_alloc.h</a></td><td class="desc">Memory management </td></tr>
+<tr id="row_0_0_2_" class="even"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__collector_8h_source.html"><span class="icondoc"></span></a><a class="el" href="prom__collector_8h.html" target="_self">prom_collector.h</a></td><td class="desc">A Prometheus collector returns a collection of metrics </td></tr>
+<tr id="row_0_0_3_"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__collector__registry_8h_source.html"><span class="icondoc"></span></a><a class="el" href="prom__collector__registry_8h.html" target="_self">prom_collector_registry.h</a></td><td class="desc">The collector registry registers collectors for metric exposition </td></tr>
+<tr id="row_0_0_4_" class="even"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__counter_8h_source.html"><span class="icondoc"></span></a><a class="el" href="prom__counter_8h.html" target="_self">prom_counter.h</a></td><td class="desc">Https://prometheus.io/docs/concepts/metric_types/#counter </td></tr>
+<tr id="row_0_0_5_"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__gauge_8h_source.html"><span class="icondoc"></span></a><a class="el" href="prom__gauge_8h.html" target="_self">prom_gauge.h</a></td><td class="desc">Https://prometheus.io/docs/concepts/metric_types/#gauge </td></tr>
+<tr id="row_0_0_6_" class="even"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__histogram_8h_source.html"><span class="icondoc"></span></a><a class="el" href="prom__histogram_8h.html" target="_self">prom_histogram.h</a></td><td class="desc">Https://prometheus.io/docs/concepts/metric_types/#histogram </td></tr>
+<tr id="row_0_0_7_"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__histogram__buckets_8h_source.html"><span class="icondoc"></span></a><a class="el" href="prom__histogram__buckets_8h.html" target="_self">prom_histogram_buckets.h</a></td><td class="desc">Https://prometheus.io/docs/concepts/metric_types/#histogram </td></tr>
+<tr id="row_0_0_8_" class="even"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__linked__list_8h_source.html"><span class="icondoc"></span></a><b>prom_linked_list.h</b></td><td class="desc"></td></tr>
+<tr id="row_0_0_9_"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__map_8h_source.html"><span class="icondoc"></span></a><b>prom_map.h</b></td><td class="desc"></td></tr>
+<tr id="row_0_0_10_" class="even"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__metric_8h_source.html"><span class="icondoc"></span></a><a class="el" href="prom__metric_8h.html" target="_self">prom_metric.h</a></td><td class="desc">Functions for retrieving metric samples from metrics given an ordered set of labels </td></tr>
+<tr id="row_0_0_11_"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__metric__sample_8h_source.html"><span class="icondoc"></span></a><a class="el" href="prom__metric__sample_8h.html" target="_self">prom_metric_sample.h</a></td><td class="desc">Functions for interfacting with metric samples directly </td></tr>
+<tr id="row_0_0_12_" class="even"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="prom__metric__sample__histogram_8h_source.html"><span class="icondoc"></span></a><a class="el" href="prom__metric__sample__histogram_8h.html" target="_self">prom_metric_sample_histogram.h</a></td><td class="desc">Functions for interacting with histogram metric samples directly </td></tr>
+<tr id="row_1_"><td class="entry"><span style="width:0px;display:inline-block;">&#160;</span><span id="arr_1_" class="arrow" onclick="toggleFolder('1_')">&#9660;</span><span id="img_1_" class="iconfopen" onclick="toggleFolder('1_')">&#160;</span><a class="el" href="dir_21619567660c3332e6a61228c76007f9.html" target="_self">promhttp</a></td><td class="desc"></td></tr>
+<tr id="row_1_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span id="arr_1_0_" class="arrow" onclick="toggleFolder('1_0_')">&#9660;</span><span id="img_1_0_" class="iconfopen" onclick="toggleFolder('1_0_')">&#160;</span><a class="el" href="dir_8d140c3a8bac3cd45205c9ea74fd211f.html" target="_self">include</a></td><td class="desc"></td></tr>
+<tr id="row_1_0_0_"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><a href="promhttp_8h_source.html"><span class="icondoc"></span></a><a class="el" href="promhttp_8h.html" target="_self">promhttp.h</a></td><td class="desc">Provides a HTTP endpoint for metric exposition References: </td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/folderclosed.png b/docs/folderclosed.png
new file mode 100644
index 0000000..bb8ab35
--- /dev/null
+++ b/docs/folderclosed.png
Binary files differ
diff --git a/docs/folderopen.png b/docs/folderopen.png
new file mode 100644
index 0000000..d6c7f67
--- /dev/null
+++ b/docs/folderopen.png
Binary files differ
diff --git a/docs/functions.html b/docs/functions.html
new file mode 100644
index 0000000..dd9be60
--- /dev/null
+++ b/docs/functions.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: Class Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+<div class="textblock">Here is a list of all documented class members with links to the class documentation for each member:</div><ul>
+<li>count
+: <a class="el" href="structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621">prom_histogram_buckets</a>
+</li>
+<li>upper_bounds
+: <a class="el" href="structprom__histogram__buckets.html#a8abda07c4930e15a3dff8a86e3164344">prom_histogram_buckets</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/functions_vars.html b/docs/functions_vars.html
new file mode 100644
index 0000000..12c187b
--- /dev/null
+++ b/docs/functions_vars.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: Class Members - Variables</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;<ul>
+<li>count
+: <a class="el" href="structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621">prom_histogram_buckets</a>
+</li>
+<li>upper_bounds
+: <a class="el" href="structprom__histogram__buckets.html#a8abda07c4930e15a3dff8a86e3164344">prom_histogram_buckets</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/globals.html b/docs/globals.html
new file mode 100644
index 0000000..2c2629c
--- /dev/null
+++ b/docs/globals.html
@@ -0,0 +1,243 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+<div class="textblock">Here is a list of all documented file members with links to the documentation:</div>
+
+<h3><a id="index_p"></a>- p -</h3><ul>
+<li>prom_collect_fn
+: <a class="el" href="prom__collector_8h.html#af87330edd48cdb8e1074517e734b1e40">prom_collector.h</a>
+</li>
+<li>prom_collector_add_metric()
+: <a class="el" href="prom__collector_8h.html#abd87021bd63f759d55642685a74874ee">prom_collector.h</a>
+</li>
+<li>prom_collector_destroy()
+: <a class="el" href="prom__collector_8h.html#a037b72b2edb81a477999a7dfc08758c7">prom_collector.h</a>
+</li>
+<li>prom_collector_destroy_generic()
+: <a class="el" href="prom__collector_8h.html#a12c297cce0a30ee4149f2b486d9f0337">prom_collector.h</a>
+</li>
+<li>prom_collector_new()
+: <a class="el" href="prom__collector_8h.html#a4300cf33b6f8e4457df385c3d2a51a4b">prom_collector.h</a>
+</li>
+<li>prom_collector_process_new()
+: <a class="el" href="prom__collector_8h.html#af50746bb4af87eda617fa08237e3834e">prom_collector.h</a>
+</li>
+<li>prom_collector_registry_bridge()
+: <a class="el" href="prom__collector__registry_8h.html#a0149a2702ae0b3ff39d57904d613c14f">prom_collector_registry.h</a>
+</li>
+<li>PROM_COLLECTOR_REGISTRY_DEFAULT
+: <a class="el" href="prom__collector__registry_8h.html#a6092b48e150390c1927da5fe8914981b">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_default_init()
+: <a class="el" href="prom__collector__registry_8h.html#aaf1421bd744f0dbbdaba7e64cec11f54">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_destroy()
+: <a class="el" href="prom__collector__registry_8h.html#ad3854e6e40b6f741fde53dc65f0ecd87">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_enable_process_metrics()
+: <a class="el" href="prom__collector__registry_8h.html#a0d59bf988de4ee29e076910fa7135071">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_must_register_metric()
+: <a class="el" href="prom__collector__registry_8h.html#a113683f4e15ad9240a37ed2139ddaea6">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_new()
+: <a class="el" href="prom__collector__registry_8h.html#ab5d622258998978c528253f07e2903b8">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_register_collector()
+: <a class="el" href="prom__collector__registry_8h.html#a42203da085c6c6f2bc3ba31501683882">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_register_metric()
+: <a class="el" href="prom__collector__registry_8h.html#aa735fa0fbe03d6d9a0d11eb4792ec761">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_t
+: <a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_validate_metric_name()
+: <a class="el" href="prom__collector__registry_8h.html#acf002221c3239584723f9fb15c53e15e">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_set_collect_fn()
+: <a class="el" href="prom__collector_8h.html#a9929cb81f4fb49ffca8aa880a4699650">prom_collector.h</a>
+</li>
+<li>prom_collector_t
+: <a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector.h</a>
+</li>
+<li>prom_counter_add()
+: <a class="el" href="prom__counter_8h.html#addd8a7efc39e17d30b2267e5a0a626db">prom_counter.h</a>
+</li>
+<li>prom_counter_destroy()
+: <a class="el" href="prom__counter_8h.html#ac36abc71c11df1e774c8c102b1fdb78d">prom_counter.h</a>
+</li>
+<li>prom_counter_inc()
+: <a class="el" href="prom__counter_8h.html#a315695fdd8b9b6fa59904bb2e35bfa35">prom_counter.h</a>
+</li>
+<li>prom_counter_new()
+: <a class="el" href="prom__counter_8h.html#a3302a9f1a3556d17af9af29729be2651">prom_counter.h</a>
+</li>
+<li>prom_counter_t
+: <a class="el" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter.h</a>
+</li>
+<li>prom_free
+: <a class="el" href="prom__alloc_8h.html#a19b2231f9b45a520bbbcf046ed5d81ef">prom_alloc.h</a>
+</li>
+<li>prom_gauge_add()
+: <a class="el" href="prom__gauge_8h.html#a96bc5b32abee5f99fbd4ae11bebd44c8">prom_gauge.h</a>
+</li>
+<li>prom_gauge_dec()
+: <a class="el" href="prom__gauge_8h.html#aa351ef4f2d917d7dae914df6d81c547b">prom_gauge.h</a>
+</li>
+<li>prom_gauge_destroy()
+: <a class="el" href="prom__gauge_8h.html#a2fc5dc11239cefdf59ae978be4bfd789">prom_gauge.h</a>
+</li>
+<li>prom_gauge_inc()
+: <a class="el" href="prom__gauge_8h.html#ad953b12ea1f8a3c3b7a39e6c260d07a2">prom_gauge.h</a>
+</li>
+<li>prom_gauge_new()
+: <a class="el" href="prom__gauge_8h.html#a5ecd07c83cf0981944a9256914571d70">prom_gauge.h</a>
+</li>
+<li>prom_gauge_set()
+: <a class="el" href="prom__gauge_8h.html#a04210b18bfb89aa6f3ddc72d7851a528">prom_gauge.h</a>
+</li>
+<li>prom_gauge_sub()
+: <a class="el" href="prom__gauge_8h.html#a7ae193d586176bff82a39cd65e2bc999">prom_gauge.h</a>
+</li>
+<li>prom_gauge_t
+: <a class="el" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge.h</a>
+</li>
+<li>prom_histogram_buckets_count()
+: <a class="el" href="prom__histogram__buckets_8h.html#a92158192cfe9a71a98dbb1d9adc8508a">prom_histogram_buckets.h</a>
+</li>
+<li>prom_histogram_buckets_destroy()
+: <a class="el" href="prom__histogram__buckets_8h.html#a36bc3312f8f479bbd6eb92fa3b1a5033">prom_histogram_buckets.h</a>
+</li>
+<li>prom_histogram_buckets_exponential()
+: <a class="el" href="prom__histogram__buckets_8h.html#a164da4101785b6fa2a292a964c232f12">prom_histogram_buckets.h</a>
+</li>
+<li>prom_histogram_buckets_linear()
+: <a class="el" href="prom__histogram__buckets_8h.html#aa1adc550bf8999a27f6a26769d6bfc72">prom_histogram_buckets.h</a>
+</li>
+<li>prom_histogram_default_buckets
+: <a class="el" href="prom__histogram__buckets_8h.html#aa8d61c1abc355eb54173b27cb1b50a5d">prom_histogram_buckets.h</a>
+</li>
+<li>prom_histogram_destroy()
+: <a class="el" href="prom__histogram_8h.html#af9067b27e7ab2abd815af0614bb35357">prom_histogram.h</a>
+</li>
+<li>prom_histogram_new()
+: <a class="el" href="prom__histogram_8h.html#ad42681e59e727f9e3d43bf0cdbba9a1b">prom_histogram.h</a>
+</li>
+<li>prom_histogram_observe()
+: <a class="el" href="prom__histogram_8h.html#a274e4b869c7d9239e9f47b3898210fbe">prom_histogram.h</a>
+</li>
+<li>prom_histogram_t
+: <a class="el" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram.h</a>
+</li>
+<li>prom_malloc
+: <a class="el" href="prom__alloc_8h.html#ae1613c091e07daa2bfa4303ef5628827">prom_alloc.h</a>
+</li>
+<li>prom_metric_sample_add()
+: <a class="el" href="prom__metric__sample_8h.html#a3f8674d6c8ee2c27eb7504d602110daa">prom_metric_sample.h</a>
+</li>
+<li>prom_metric_sample_from_labels()
+: <a class="el" href="prom__metric_8h.html#a2c33d7e03b430a2903bf122fbeeb89de">prom_metric.h</a>
+</li>
+<li>prom_metric_sample_histogram_from_labels()
+: <a class="el" href="prom__metric_8h.html#a3b76680b4a7177eebc864f3b3be1e935">prom_metric.h</a>
+</li>
+<li>prom_metric_sample_histogram_observe()
+: <a class="el" href="prom__metric__sample__histogram_8h.html#a20a030bf6be56211c87c9feb520a3761">prom_metric_sample_histogram.h</a>
+</li>
+<li>prom_metric_sample_histogram_t
+: <a class="el" href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f">prom_metric_sample_histogram.h</a>
+</li>
+<li>prom_metric_sample_set()
+: <a class="el" href="prom__metric__sample_8h.html#a0c5f0c66599282c2ee2c042ae4574db3">prom_metric_sample.h</a>
+</li>
+<li>prom_metric_sample_sub()
+: <a class="el" href="prom__metric__sample_8h.html#a1965caa1626c308bc1cb23995e90a0a7">prom_metric_sample.h</a>
+</li>
+<li>prom_metric_sample_t
+: <a class="el" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample.h</a>
+</li>
+<li>prom_metric_t
+: <a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric.h</a>
+</li>
+<li>prom_realloc
+: <a class="el" href="prom__alloc_8h.html#aab8dc4629c851a8c59cc721bd2f7c6f3">prom_alloc.h</a>
+</li>
+<li>prom_strdup
+: <a class="el" href="prom__alloc_8h.html#a21faa2fafc84c8ca25467fe9cb0a55f3">prom_alloc.h</a>
+</li>
+<li>promhttp_set_active_collector_registry()
+: <a class="el" href="promhttp_8h.html#a712a45634bc22724fef9bedcb2841e00">promhttp.h</a>
+</li>
+<li>promhttp_start_daemon()
+: <a class="el" href="promhttp_8h.html#a699ecc3aa11ed601269722f43da2823e">promhttp.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/globals_defs.html b/docs/globals_defs.html
new file mode 100644
index 0000000..a0da162
--- /dev/null
+++ b/docs/globals_defs.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;<ul>
+<li>prom_free
+: <a class="el" href="prom__alloc_8h.html#a19b2231f9b45a520bbbcf046ed5d81ef">prom_alloc.h</a>
+</li>
+<li>prom_malloc
+: <a class="el" href="prom__alloc_8h.html#ae1613c091e07daa2bfa4303ef5628827">prom_alloc.h</a>
+</li>
+<li>prom_realloc
+: <a class="el" href="prom__alloc_8h.html#aab8dc4629c851a8c59cc721bd2f7c6f3">prom_alloc.h</a>
+</li>
+<li>prom_strdup
+: <a class="el" href="prom__alloc_8h.html#a21faa2fafc84c8ca25467fe9cb0a55f3">prom_alloc.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/globals_enum.html b/docs/globals_enum.html
new file mode 100644
index 0000000..75948fb
--- /dev/null
+++ b/docs/globals_enum.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;<ul>
+<li>prom_return_code
+: <a class="el" href="prom__errors_8h.html#ae9dcc70f3217ae6f5cd331dbdef06602">prom_errors.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/globals_eval.html b/docs/globals_eval.html
new file mode 100644
index 0000000..7308d55
--- /dev/null
+++ b/docs/globals_eval.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;<ul>
+<li>PROM_COLLECTOR_REGISTRATION_FAILURE
+: <a class="el" href="prom__errors_8h.html#a3b3873fa7ceb3c9e4a8d714771fb4830a23269fa188cfe85113887765ae300781">prom_errors.h</a>
+</li>
+<li>PROM_FAILURE
+: <a class="el" href="prom__errors_8h.html#a3b3873fa7ceb3c9e4a8d714771fb4830a20d1dda215f590d375c018ecabb065cc">prom_errors.h</a>
+</li>
+<li>PROM_INVALID_METRIC_TYPE
+: <a class="el" href="prom__errors_8h.html#a3b3873fa7ceb3c9e4a8d714771fb4830a11a15b66987a9d455f369a94101205fc">prom_errors.h</a>
+</li>
+<li>PROM_METRIC_REGISTRATION_FAILURE
+: <a class="el" href="prom__errors_8h.html#a3b3873fa7ceb3c9e4a8d714771fb4830ae3ad35c6d86de06362db4735e0805416">prom_errors.h</a>
+</li>
+<li>PROM_SUCCESS
+: <a class="el" href="prom__errors_8h.html#a3b3873fa7ceb3c9e4a8d714771fb4830a4860821c9dc1ba212354b29a48b8c59c">prom_errors.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/globals_func.html b/docs/globals_func.html
new file mode 100644
index 0000000..3417c7e
--- /dev/null
+++ b/docs/globals_func.html
@@ -0,0 +1,198 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;
+
+<h3><a id="index_p"></a>- p -</h3><ul>
+<li>prom_collector_add_metric()
+: <a class="el" href="prom__collector_8h.html#abd87021bd63f759d55642685a74874ee">prom_collector.h</a>
+</li>
+<li>prom_collector_destroy()
+: <a class="el" href="prom__collector_8h.html#a037b72b2edb81a477999a7dfc08758c7">prom_collector.h</a>
+</li>
+<li>prom_collector_destroy_generic()
+: <a class="el" href="prom__collector_8h.html#a12c297cce0a30ee4149f2b486d9f0337">prom_collector.h</a>
+</li>
+<li>prom_collector_new()
+: <a class="el" href="prom__collector_8h.html#a4300cf33b6f8e4457df385c3d2a51a4b">prom_collector.h</a>
+</li>
+<li>prom_collector_process_new()
+: <a class="el" href="prom__collector_8h.html#af50746bb4af87eda617fa08237e3834e">prom_collector.h</a>
+</li>
+<li>prom_collector_registry_bridge()
+: <a class="el" href="prom__collector__registry_8h.html#a0149a2702ae0b3ff39d57904d613c14f">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_default_init()
+: <a class="el" href="prom__collector__registry_8h.html#aaf1421bd744f0dbbdaba7e64cec11f54">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_destroy()
+: <a class="el" href="prom__collector__registry_8h.html#ad3854e6e40b6f741fde53dc65f0ecd87">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_enable_process_metrics()
+: <a class="el" href="prom__collector__registry_8h.html#a0d59bf988de4ee29e076910fa7135071">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_must_register_metric()
+: <a class="el" href="prom__collector__registry_8h.html#a113683f4e15ad9240a37ed2139ddaea6">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_new()
+: <a class="el" href="prom__collector__registry_8h.html#ab5d622258998978c528253f07e2903b8">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_register_collector()
+: <a class="el" href="prom__collector__registry_8h.html#a42203da085c6c6f2bc3ba31501683882">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_register_metric()
+: <a class="el" href="prom__collector__registry_8h.html#aa735fa0fbe03d6d9a0d11eb4792ec761">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_registry_validate_metric_name()
+: <a class="el" href="prom__collector__registry_8h.html#acf002221c3239584723f9fb15c53e15e">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_set_collect_fn()
+: <a class="el" href="prom__collector_8h.html#a9929cb81f4fb49ffca8aa880a4699650">prom_collector.h</a>
+</li>
+<li>prom_counter_add()
+: <a class="el" href="prom__counter_8h.html#addd8a7efc39e17d30b2267e5a0a626db">prom_counter.h</a>
+</li>
+<li>prom_counter_destroy()
+: <a class="el" href="prom__counter_8h.html#ac36abc71c11df1e774c8c102b1fdb78d">prom_counter.h</a>
+</li>
+<li>prom_counter_inc()
+: <a class="el" href="prom__counter_8h.html#a315695fdd8b9b6fa59904bb2e35bfa35">prom_counter.h</a>
+</li>
+<li>prom_counter_new()
+: <a class="el" href="prom__counter_8h.html#a3302a9f1a3556d17af9af29729be2651">prom_counter.h</a>
+</li>
+<li>prom_gauge_add()
+: <a class="el" href="prom__gauge_8h.html#a96bc5b32abee5f99fbd4ae11bebd44c8">prom_gauge.h</a>
+</li>
+<li>prom_gauge_dec()
+: <a class="el" href="prom__gauge_8h.html#aa351ef4f2d917d7dae914df6d81c547b">prom_gauge.h</a>
+</li>
+<li>prom_gauge_destroy()
+: <a class="el" href="prom__gauge_8h.html#a2fc5dc11239cefdf59ae978be4bfd789">prom_gauge.h</a>
+</li>
+<li>prom_gauge_inc()
+: <a class="el" href="prom__gauge_8h.html#ad953b12ea1f8a3c3b7a39e6c260d07a2">prom_gauge.h</a>
+</li>
+<li>prom_gauge_new()
+: <a class="el" href="prom__gauge_8h.html#a5ecd07c83cf0981944a9256914571d70">prom_gauge.h</a>
+</li>
+<li>prom_gauge_set()
+: <a class="el" href="prom__gauge_8h.html#a04210b18bfb89aa6f3ddc72d7851a528">prom_gauge.h</a>
+</li>
+<li>prom_gauge_sub()
+: <a class="el" href="prom__gauge_8h.html#a7ae193d586176bff82a39cd65e2bc999">prom_gauge.h</a>
+</li>
+<li>prom_histogram_buckets_count()
+: <a class="el" href="prom__histogram__buckets_8h.html#a92158192cfe9a71a98dbb1d9adc8508a">prom_histogram_buckets.h</a>
+</li>
+<li>prom_histogram_buckets_destroy()
+: <a class="el" href="prom__histogram__buckets_8h.html#a36bc3312f8f479bbd6eb92fa3b1a5033">prom_histogram_buckets.h</a>
+</li>
+<li>prom_histogram_buckets_exponential()
+: <a class="el" href="prom__histogram__buckets_8h.html#a164da4101785b6fa2a292a964c232f12">prom_histogram_buckets.h</a>
+</li>
+<li>prom_histogram_buckets_linear()
+: <a class="el" href="prom__histogram__buckets_8h.html#aa1adc550bf8999a27f6a26769d6bfc72">prom_histogram_buckets.h</a>
+</li>
+<li>prom_histogram_destroy()
+: <a class="el" href="prom__histogram_8h.html#af9067b27e7ab2abd815af0614bb35357">prom_histogram.h</a>
+</li>
+<li>prom_histogram_new()
+: <a class="el" href="prom__histogram_8h.html#ad42681e59e727f9e3d43bf0cdbba9a1b">prom_histogram.h</a>
+</li>
+<li>prom_histogram_observe()
+: <a class="el" href="prom__histogram_8h.html#a274e4b869c7d9239e9f47b3898210fbe">prom_histogram.h</a>
+</li>
+<li>prom_metric_sample_add()
+: <a class="el" href="prom__metric__sample_8h.html#a3f8674d6c8ee2c27eb7504d602110daa">prom_metric_sample.h</a>
+</li>
+<li>prom_metric_sample_from_labels()
+: <a class="el" href="prom__metric_8h.html#a2c33d7e03b430a2903bf122fbeeb89de">prom_metric.h</a>
+</li>
+<li>prom_metric_sample_histogram_from_labels()
+: <a class="el" href="prom__metric_8h.html#a3b76680b4a7177eebc864f3b3be1e935">prom_metric.h</a>
+</li>
+<li>prom_metric_sample_histogram_observe()
+: <a class="el" href="prom__metric__sample__histogram_8h.html#a20a030bf6be56211c87c9feb520a3761">prom_metric_sample_histogram.h</a>
+</li>
+<li>prom_metric_sample_set()
+: <a class="el" href="prom__metric__sample_8h.html#a0c5f0c66599282c2ee2c042ae4574db3">prom_metric_sample.h</a>
+</li>
+<li>prom_metric_sample_sub()
+: <a class="el" href="prom__metric__sample_8h.html#a1965caa1626c308bc1cb23995e90a0a7">prom_metric_sample.h</a>
+</li>
+<li>promhttp_set_active_collector_registry()
+: <a class="el" href="promhttp_8h.html#a712a45634bc22724fef9bedcb2841e00">promhttp.h</a>
+</li>
+<li>promhttp_start_daemon()
+: <a class="el" href="promhttp_8h.html#a699ecc3aa11ed601269722f43da2823e">promhttp.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/globals_type.html b/docs/globals_type.html
new file mode 100644
index 0000000..33fd01e
--- /dev/null
+++ b/docs/globals_type.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;<ul>
+<li>prom_collect_fn
+: <a class="el" href="prom__collector_8h.html#af87330edd48cdb8e1074517e734b1e40">prom_collector.h</a>
+</li>
+<li>prom_collector_registry_t
+: <a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry.h</a>
+</li>
+<li>prom_collector_t
+: <a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector.h</a>
+</li>
+<li>prom_counter_t
+: <a class="el" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter.h</a>
+</li>
+<li>prom_gauge_t
+: <a class="el" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge.h</a>
+</li>
+<li>prom_histogram_t
+: <a class="el" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram.h</a>
+</li>
+<li>prom_metric_sample_histogram_t
+: <a class="el" href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f">prom_metric_sample_histogram.h</a>
+</li>
+<li>prom_metric_sample_t
+: <a class="el" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample.h</a>
+</li>
+<li>prom_metric_t
+: <a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/globals_vars.html b/docs/globals_vars.html
new file mode 100644
index 0000000..2e44c52
--- /dev/null
+++ b/docs/globals_vars.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;<ul>
+<li>PROM_COLLECTOR_REGISTRY_DEFAULT
+: <a class="el" href="prom__collector__registry_8h.html#a6092b48e150390c1927da5fe8914981b">prom_collector_registry.h</a>
+</li>
+<li>prom_histogram_default_buckets
+: <a class="el" href="prom__histogram__buckets_8h.html#aa8d61c1abc355eb54173b27cb1b50a5d">prom_histogram_buckets.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/graph_legend.dot b/docs/graph_legend.dot
new file mode 100644
index 0000000..789df56
--- /dev/null
+++ b/docs/graph_legend.dot
@@ -0,0 +1,22 @@
+digraph "Graph Legend"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node9 [shape="box",label="Inherited",fontsize="10",height=0.2,width=0.4,fontname="Helvetica",fillcolor="grey75",style="filled" fontcolor="black"];
+ Node10 -> Node9 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node10 [shape="box",label="PublicBase",fontsize="10",height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classPublicBase.html"];
+ Node11 -> Node10 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node11 [shape="box",label="Truncated",fontsize="10",height=0.2,width=0.4,fontname="Helvetica",color="red",URL="$classTruncated.html"];
+ Node13 -> Node9 [dir="back",color="darkgreen",fontsize="10",style="solid",fontname="Helvetica"];
+ Node13 [shape="box",label="ProtectedBase",fontsize="10",height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classProtectedBase.html"];
+ Node14 -> Node9 [dir="back",color="firebrick4",fontsize="10",style="solid",fontname="Helvetica"];
+ Node14 [shape="box",label="PrivateBase",fontsize="10",height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classPrivateBase.html"];
+ Node15 -> Node9 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node15 [shape="box",label="Undocumented",fontsize="10",height=0.2,width=0.4,fontname="Helvetica",color="grey75"];
+ Node16 -> Node9 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node16 [shape="box",label="Templ< int >",fontsize="10",height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classTempl.html"];
+ Node17 -> Node16 [dir="back",color="orange",fontsize="10",style="dashed",label="< int >",fontname="Helvetica"];
+ Node17 [shape="box",label="Templ< T >",fontsize="10",height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classTempl.html"];
+ Node18 -> Node9 [dir="back",color="darkorchid3",fontsize="10",style="dashed",label="m_usedClass",fontname="Helvetica"];
+ Node18 [shape="box",label="Used",fontsize="10",height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classUsed.html"];
+}
diff --git a/docs/graph_legend.html b/docs/graph_legend.html
new file mode 100644
index 0000000..b685edb
--- /dev/null
+++ b/docs/graph_legend.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: Graph Legend</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">Graph Legend</div> </div>
+</div><!--header-->
+<div class="contents">
+<p>This page explains how to interpret the graphs that are generated by doxygen.</p>
+<p>Consider the following example: </p><div class="fragment"><div class="line">/*! Invisible class because of truncation */</div><div class="line">class Invisible { };</div><div class="line"></div><div class="line">/*! Truncated class, inheritance relation is hidden */</div><div class="line">class Truncated : public Invisible { };</div><div class="line"></div><div class="line">/* Class not documented with doxygen comments */</div><div class="line">class Undocumented { };</div><div class="line"></div><div class="line">/*! Class that is inherited using public inheritance */</div><div class="line">class PublicBase : public Truncated { };</div><div class="line"></div><div class="line">/*! A template class */</div><div class="line">template&lt;class T&gt; class Templ { };</div><div class="line"></div><div class="line">/*! Class that is inherited using protected inheritance */</div><div class="line">class ProtectedBase { };</div><div class="line"></div><div class="line">/*! Class that is inherited using private inheritance */</div><div class="line">class PrivateBase { };</div><div class="line"></div><div class="line">/*! Class that is used by the Inherited class */</div><div class="line">class Used { };</div><div class="line"></div><div class="line">/*! Super class that inherits a number of other classes */</div><div class="line">class Inherited : public PublicBase,</div><div class="line"> protected ProtectedBase,</div><div class="line"> private PrivateBase,</div><div class="line"> public Undocumented,</div><div class="line"> public Templ&lt;int&gt;</div><div class="line">{</div><div class="line"> private:</div><div class="line"> Used *m_usedClass;</div><div class="line">};</div></div><!-- fragment --><p> This will result in the following graph:</p>
+<center><div class="image">
+<img src="graph_legend.png"/>
+</div>
+</center><p>The boxes in the above graph have the following meaning: </p>
+<ul>
+<li>
+A filled gray box represents the struct or class for which the graph is generated. </li>
+<li>
+A box with a black border denotes a documented struct or class. </li>
+<li>
+A box with a gray border denotes an undocumented struct or class. </li>
+<li>
+A box with a red border denotes a documented struct or class forwhich not all inheritance/containment relations are shown. A graph is truncated if it does not fit within the specified boundaries. </li>
+</ul>
+<p>The arrows have the following meaning: </p>
+<ul>
+<li>
+A dark blue arrow is used to visualize a public inheritance relation between two classes. </li>
+<li>
+A dark green arrow is used for protected inheritance. </li>
+<li>
+A dark red arrow is used for private inheritance. </li>
+<li>
+A purple dashed arrow is used if a class is contained or used by another class. The arrow is labelled with the variable(s) through which the pointed class or struct is accessible. </li>
+<li>
+A yellow dashed arrow denotes a relation between a template instance and the template class it was instantiated from. The arrow is labelled with the template parameters of the instance. </li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/graph_legend.md5 b/docs/graph_legend.md5
new file mode 100644
index 0000000..a06ed05
--- /dev/null
+++ b/docs/graph_legend.md5
@@ -0,0 +1 @@
+387ff8eb65306fa251338d3c9bd7bfff \ No newline at end of file
diff --git a/docs/graph_legend.png b/docs/graph_legend.png
new file mode 100644
index 0000000..93e2541
--- /dev/null
+++ b/docs/graph_legend.png
Binary files differ
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..5cef448
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: Welcome to the documentation site for prometheus-client-c!</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">Welcome to the documentation site for prometheus-client-c! </div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="toc"><h3>Table of Contents</h3>
+<ul><li class="level1"><a href="#Introduction">Introduction</a></li>
+<li class="level1"><a href="#Creating-and-Registering-Metrics">Creating and Registering Metrics</a></li>
+<li class="level1"><a href="#Updating-Metric-Sample-Values">Updating Metric Sample Values</a></li>
+<li class="level1"><a href="#Program-Initialization">Program Initialization</a></li>
+<li class="level1"><a href="#Metric-Exposition-Over-HTTP">Metric Exposition Over HTTP</a></li>
+<li class="level1"><a href="#Where-To-Go-From-Here">Where to Go From Here?</a></li>
+</ul>
+</div>
+<div class="textblock"><h1><a class="anchor" id="Introduction"></a>
+Introduction</h1>
+<p>prometheus-client-c is a small suite of Prometheus client libraries targeted for the C programming language. In this brief tutorial you will learn how to create and register metrics, update metric samples, and expose metrics over HTTP.</p>
+<h1><a class="anchor" id="Creating-and-Registering-Metrics"></a>
+Creating and Registering Metrics</h1>
+<p>prometheus-client-c supports the following metric types:</p>
+<ul>
+<li><a href="https://prometheus.io/docs/concepts/metric_types/#counter">Counter</a></li>
+<li><a href="https://prometheus.io/docs/concepts/metric_types/#gauge">Gauge</a></li>
+<li><a href="https://prometheus.io/docs/concepts/metric_types/#histogram">Histogram</a></li>
+</ul>
+<p>To get started using one of the metric types, declare the metric at file scope. For example:</p>
+<div class="fragment"><div class="line"><span class="preprocessor">#incldue &quot;prom.h&quot;</span></div><div class="line"></div><div class="line"><a class="code" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a> *my_counter;</div></div><!-- fragment --><p>Next, create a metric initialization function. You can create the metric and register it with the default metric collector registry in one chain of functions. A metric collector is responsible for collecting metrics and returning them. A metric collector registry is declared in global scope and contains metric collectors. More on this later...</p>
+<p>To create a metric and register it with the default metric collector registry in one shot, you may chain the metric constructor into the prom_collector_registry_must_register_metric function. For example:</p>
+<div class="fragment"><div class="line"><span class="keywordtype">void</span> foo_metric_init(<span class="keywordtype">void</span>) {</div><div class="line"> my_counter = <a class="code" href="prom__collector__registry_8h.html#a113683f4e15ad9240a37ed2139ddaea6">prom_collector_registry_must_register_metric</a>(<a class="code" href="prom__counter_8h.html#a3302a9f1a3556d17af9af29729be2651">prom_counter_new</a>(<span class="stringliteral">&quot;my_counter&quot;</span>, <span class="stringliteral">&quot;counts things&quot;</span>, 0, NULL));</div><div class="line">}</div></div><!-- fragment --><p>The first argument to prom_counter_new is the counter name. The second argument is the counter description. The third argument is the number of metric labels. In this case, we will only have one metric sample for this metric so we pass 0 to specify that no labels will be used. The 4th argument is an array of strings storing the metric labels. Since we have none, we pass NULL. A call to foo_metric_init within the program's main function will initialize the metrics for the file we just created to the default prometheus metric collector registery called PROM_COLLECTOR_REGISTRY_DEFAULT</p>
+<h1><a class="anchor" id="Updating-Metric-Sample-Values"></a>
+Updating Metric Sample Values</h1>
+<p>Now that we have a metric configured for creation and registration, we can update our metric within any of the functions of the file in which it was declared. For example:</p>
+<div class="fragment"><div class="line"><span class="keywordtype">void</span> my_lib_do_something(<span class="keywordtype">void</span>) {</div><div class="line"> printf(<span class="stringliteral">&quot;I did a really important thing!\n&quot;</span>);</div><div class="line"> <a class="code" href="prom__counter_8h.html#a315695fdd8b9b6fa59904bb2e35bfa35">prom_counter_inc</a>(my_counter, NULL);</div><div class="line">}</div></div><!-- fragment --><p>This function will increment the default metric sample for my_counter. Since we are not using metric labels, we pass NULL as the second argument.</p>
+<h1><a class="anchor" id="Program-Initialization"></a>
+Program Initialization</h1>
+<p>At the start of the program's main function you need to do two things:</p>
+<ul>
+<li>Initialize the default metric collector registry:</li>
+</ul>
+<div class="fragment"><div class="line"><a class="code" href="prom__collector__registry_8h.html#aaf1421bd744f0dbbdaba7e64cec11f54">prom_collector_registry_default_init</a>();</div></div><!-- fragment --><ul>
+<li>For each file containing prometheus metrics, call its corresponding metric initialization function</li>
+</ul>
+<div class="fragment"><div class="line">foo_metric_init()</div></div><!-- fragment --><p>After initialization is complete, you may proceed to do work and update your metrics.</p>
+<h1><a class="anchor" id="Metric-Exposition-Over-HTTP"></a>
+Metric Exposition Over HTTP</h1>
+<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000001">Todo:</a></b></dt><dd>Describe how to use libpromhttp to expose metrics over HTTP</dd></dl>
+<h1><a class="anchor" id="Where-To-Go-From-Here"></a>
+Where to Go From Here?</h1>
+<p>Take a look at the <a href="https://github.internal.digitalocean.com/pages/timeseries/prometheus-client-c/files.html">Files</a> tab in this documentation site for more information about the public API available to you. Also, you can take a look at the examples directory at the <a href="https://github.internal.digitalocean.com/timeseries/prometheus-client-c">Github repository</a> for inspiration. </p>
+</div></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/jquery.js b/docs/jquery.js
new file mode 100644
index 0000000..f5343ed
--- /dev/null
+++ b/docs/jquery.js
@@ -0,0 +1,87 @@
+/*!
+ * jQuery JavaScript Library v1.7.1
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Mon Nov 21 21:11:03 2011 -0500
+ */
+(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b4<b3;b4++){if((b9=arguments[b4])!=null){for(b2 in b9){b0=b5[b2];b1=b9[b2];if(b5===b1){continue}if(b8&&b1&&(bF.isPlainObject(b1)||(b6=bF.isArray(b1)))){if(b6){b6=false;b7=b0&&bF.isArray(b0)?b0:[]}else{b7=b0&&bF.isPlainObject(b0)?b0:{}}b5[b2]=bF.extend(b8,b7,b1)}else{if(b1!==L){b5[b2]=b1}}}}}return b5};bF.extend({noConflict:function(b0){if(bb.$===bF){bb.$=bH}if(b0&&bb.jQuery===bF){bb.jQuery=bU}return bF},isReady:false,readyWait:1,holdReady:function(b0){if(b0){bF.readyWait++}else{bF.ready(true)}},ready:function(b0){if((b0===true&&!--bF.readyWait)||(b0!==true&&!bF.isReady)){if(!av.body){return setTimeout(bF.ready,1)}bF.isReady=true;if(b0!==true&&--bF.readyWait>0){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b4<b5;){if(b6.apply(b3[b4++],b2)===false){break}}}}else{if(b0){for(b1 in b3){if(b6.call(b3[b1],b1,b3[b1])===false){break}}}else{for(;b4<b5;){if(b6.call(b3[b4],b4,b3[b4++])===false){break}}}}return b3},trim:bO?function(b0){return b0==null?"":bO.call(b0)}:function(b0){return b0==null?"":b0.toString().replace(bI,"").replace(bE,"")},makeArray:function(b3,b1){var b0=b1||[];if(b3!=null){var b2=bF.type(b3);if(b3.length==null||b2==="string"||b2==="function"||b2==="regexp"||bF.isWindow(b3)){bz.call(b0,b3)}else{bF.merge(b0,b3)}}return b0},inArray:function(b2,b3,b1){var b0;if(b3){if(bv){return bv.call(b3,b2,b1)}b0=b3.length;b1=b1?b1<0?Math.max(0,b0+b1):b1:0;for(;b1<b0;b1++){if(b1 in b3&&b3[b1]===b2){return b1}}}return -1},merge:function(b4,b2){var b3=b4.length,b1=0;if(typeof b2.length==="number"){for(var b0=b2.length;b1<b0;b1++){b4[b3++]=b2[b1]}}else{while(b2[b1]!==L){b4[b3++]=b2[b1++]}}b4.length=b3;return b4},grep:function(b1,b6,b0){var b2=[],b5;b0=!!b0;for(var b3=0,b4=b1.length;b3<b4;b3++){b5=!!b6(b1[b3],b3);if(b0!==b5){b2.push(b1[b3])}}return b2},map:function(b0,b7,b8){var b5,b6,b4=[],b2=0,b1=b0.length,b3=b0 instanceof bF||b1!==L&&typeof b1==="number"&&((b1>0&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b2<b1;b2++){b5=b7(b0[b2],b2,b8);if(b5!=null){b4[b4.length]=b5}}}else{for(b6 in b0){b5=b7(b0[b6],b6,b8);if(b5!=null){b4[b4.length]=b5}}}return b4.concat.apply([],b4)},guid:1,proxy:function(b4,b3){if(typeof b3==="string"){var b2=b4[b3];b3=b4;b4=b2}if(!bF.isFunction(b4)){return L}var b0=bK.call(arguments,2),b1=function(){return b4.apply(b3,b0.concat(bK.call(arguments)))};b1.guid=b4.guid=b4.guid||b1.guid||bF.guid++;return b1},access:function(b0,b8,b6,b2,b5,b7){var b1=b0.length;if(typeof b8==="object"){for(var b3 in b8){bF.access(b0,b3,b8[b3],b2,b5,b6)}return b0}if(b6!==L){b2=!b7&&b2&&bF.isFunction(b6);for(var b4=0;b4<b1;b4++){b5(b0[b4],b8,b2?b6.call(b0[b4],b4,b5(b0[b4],b8)):b6,b7)}return b0}return b1?b5(b0[0],b8):L},now:function(){return(new Date()).getTime()},uaMatch:function(b1){b1=b1.toLowerCase();var b0=by.exec(b1)||bR.exec(b1)||bQ.exec(b1)||b1.indexOf("compatible")<0&&bS.exec(b1)||[];return{browser:b0[1]||"",version:b0[2]||"0"}},sub:function(){function b0(b3,b4){return new b0.fn.init(b3,b4)}bF.extend(true,b0,this);b0.superclass=this;b0.fn=b0.prototype=this();b0.fn.constructor=b0;b0.sub=this.sub;b0.fn.init=function b2(b3,b4){if(b4&&b4 instanceof bF&&!(b4 instanceof b0)){b4=b0(b4)}return bF.fn.init.call(this,b3,b4,b1)};b0.fn.init.prototype=b0.fn;var b1=b0(av);return b0},browser:{}});bF.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(b1,b0){bx["[object "+b0+"]"]=b0.toLowerCase()});bV=bF.uaMatch(bX);if(bV.browser){bF.browser[bV.browser]=true;bF.browser.version=bV.version}if(bF.browser.webkit){bF.browser.safari=true}if(bM.test("\xA0")){bI=/^[\s\xA0]+/;bE=/[\s\xA0]+$/}bD=bF(av);if(av.addEventListener){e=function(){av.removeEventListener("DOMContentLoaded",e,false);bF.ready()}}else{if(av.attachEvent){e=function(){if(av.readyState==="complete"){av.detachEvent("onreadystatechange",e);bF.ready()}}}}function bw(){if(bF.isReady){return}try{av.documentElement.doScroll("left")}catch(b0){setTimeout(bw,1);return}bF.ready()}return bF})();var a2={};function X(e){var bv=a2[e]={},bw,bx;e=e.split(/\s+/);for(bw=0,bx=e.length;bw<bx;bw++){bv[e[bw]]=true}return bv}b.Callbacks=function(bw){bw=bw?(a2[bw]||X(bw)):{};var bB=[],bC=[],bx,by,bv,bz,bA,bE=function(bF){var bG,bJ,bI,bH,bK;for(bG=0,bJ=bF.length;bG<bJ;bG++){bI=bF[bG];bH=b.type(bI);if(bH==="array"){bE(bI)}else{if(bH==="function"){if(!bw.unique||!bD.has(bI)){bB.push(bI)}}}}},e=function(bG,bF){bF=bF||[];bx=!bw.memory||[bG,bF];by=true;bA=bv||0;bv=0;bz=bB.length;for(;bB&&bA<bz;bA++){if(bB[bA].apply(bG,bF)===false&&bw.stopOnFalse){bx=true;break}}by=false;if(bB){if(!bw.once){if(bC&&bC.length){bx=bC.shift();bD.fireWith(bx[0],bx[1])}}else{if(bx===true){bD.disable()}else{bB=[]}}}},bD={add:function(){if(bB){var bF=bB.length;bE(arguments);if(by){bz=bB.length}else{if(bx&&bx!==true){bv=bF;e(bx[0],bx[1])}}}return this},remove:function(){if(bB){var bF=arguments,bH=0,bI=bF.length;for(;bH<bI;bH++){for(var bG=0;bG<bB.length;bG++){if(bF[bH]===bB[bG]){if(by){if(bG<=bz){bz--;if(bG<=bA){bA--}}}bB.splice(bG--,1);if(bw.unique){break}}}}}return this},has:function(bG){if(bB){var bF=0,bH=bB.length;for(;bF<bH;bF++){if(bG===bB[bF]){return true}}}return false},empty:function(){bB=[];return this},disable:function(){bB=bC=bx=L;return this},disabled:function(){return !bB},lock:function(){bC=L;if(!bx||bx===true){bD.disable()}return this},locked:function(){return !bC},fireWith:function(bG,bF){if(bC){if(by){if(!bw.once){bC.push([bG,bF])}}else{if(!(bw.once&&bx)){e(bG,bF)}}}return this},fire:function(){bD.fireWith(this,arguments);return this},fired:function(){return !!bx}};return bD};var aJ=[].slice;b.extend({Deferred:function(by){var bx=b.Callbacks("once memory"),bw=b.Callbacks("once memory"),bv=b.Callbacks("memory"),e="pending",bA={resolve:bx,reject:bw,notify:bv},bC={done:bx.add,fail:bw.add,progress:bv.add,state:function(){return e},isResolved:bx.fired,isRejected:bw.fired,then:function(bE,bD,bF){bB.done(bE).fail(bD).progress(bF);return this},always:function(){bB.done.apply(bB,arguments).fail.apply(bB,arguments);return this},pipe:function(bF,bE,bD){return b.Deferred(function(bG){b.each({done:[bF,"resolve"],fail:[bE,"reject"],progress:[bD,"notify"]},function(bI,bL){var bH=bL[0],bK=bL[1],bJ;if(b.isFunction(bH)){bB[bI](function(){bJ=bH.apply(this,arguments);if(bJ&&b.isFunction(bJ.promise)){bJ.promise().then(bG.resolve,bG.reject,bG.notify)}else{bG[bK+"With"](this===bB?bG:this,[bJ])}})}else{bB[bI](bG[bK])}})}).promise()},promise:function(bE){if(bE==null){bE=bC}else{for(var bD in bC){bE[bD]=bC[bD]}}return bE}},bB=bC.promise({}),bz;for(bz in bA){bB[bz]=bA[bz].fire;bB[bz+"With"]=bA[bz].fireWith}bB.done(function(){e="resolved"},bw.disable,bv.lock).fail(function(){e="rejected"},bx.disable,bv.lock);if(by){by.call(bB,bB)}return bB},when:function(bA){var bx=aJ.call(arguments,0),bv=0,e=bx.length,bB=new Array(e),bw=e,by=e,bC=e<=1&&bA&&b.isFunction(bA.promise)?bA:b.Deferred(),bE=bC.promise();function bD(bF){return function(bG){bx[bF]=arguments.length>1?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv<e;bv++){if(bx[bv]&&bx[bv].promise&&b.isFunction(bx[bv].promise)){bx[bv].promise().then(bD(bv),bC.reject,bz(bv))}else{--bw}}if(!bw){bC.resolveWith(bC,bx)}}else{if(bC!==bA){bC.resolveWith(bC,e?[bA]:[])}}return bE}});b.support=(function(){var bJ,bI,bF,bG,bx,bE,bA,bD,bz,bK,bB,by,bw,bv=av.createElement("div"),bH=av.documentElement;bv.setAttribute("className","t");bv.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav></:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="<div "+e+"><div></div></div><table "+e+" cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="<div style='width:4px;'></div>";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA<bz;bA++){delete bB[bv[bA]]}if(!(by?S:b.isEmptyObject)(bB)){return}}}if(!by){delete e[bw].data;if(!S(e[bw])){return}}if(b.support.deleteExpando||!e.setInterval){delete e[bw]}else{e[bw]=null}if(bD){if(b.support.deleteExpando){delete bx[bC]}else{if(bx.removeAttribute){bx.removeAttribute(bC)}else{bx[bC]=null}}}},_data:function(bv,e,bw){return b.data(bv,e,bw,true)},acceptData:function(bv){if(bv.nodeName){var e=b.noData[bv.nodeName.toLowerCase()];if(e){return !(e===true||bv.getAttribute("classid")!==e)}}return true}});b.fn.extend({data:function(by,bA){var bB,e,bw,bz=null;if(typeof by==="undefined"){if(this.length){bz=b.data(this[0]);if(this[0].nodeType===1&&!b._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var bx=0,bv=e.length;bx<bv;bx++){bw=e[bx].name;if(bw.indexOf("data-")===0){bw=b.camelCase(bw.substring(5));a5(this[0],bw,bz[bw])}}b._data(this[0],"parsedAttrs",true)}}return bz}else{if(typeof by==="object"){return this.each(function(){b.data(this,by)})}}bB=by.split(".");bB[1]=bB[1]?"."+bB[1]:"";if(bA===L){bz=this.triggerHandler("getData"+bB[1]+"!",[bB[0]]);if(bz===L&&this.length){bz=b.data(this[0],by);bz=a5(this[0],by,bz)}return bz===L&&bB[1]?this.data(bB[0]):bz}else{return this.each(function(){var bC=b(this),bD=[bB[0],bA];bC.triggerHandler("setData"+bB[1]+"!",bD);b.data(this,by,bA);bC.triggerHandler("changeData"+bB[1]+"!",bD)})}},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function a5(bx,bw,by){if(by===L&&bx.nodeType===1){var bv="data-"+bw.replace(aA,"-$1").toLowerCase();by=bx.getAttribute(bv);if(typeof by==="string"){try{by=by==="true"?true:by==="false"?false:by==="null"?null:b.isNumeric(by)?parseFloat(by):aS.test(by)?b.parseJSON(by):by}catch(bz){}b.data(bx,bw,by)}else{by=L}}return by}function S(bv){for(var e in bv){if(e==="data"&&b.isEmptyObject(bv[e])){continue}if(e!=="toJSON"){return false}}return true}function bi(by,bx,bA){var bw=bx+"defer",bv=bx+"queue",e=bx+"mark",bz=b._data(by,bw);if(bz&&(bA==="queue"||!b._data(by,bv))&&(bA==="mark"||!b._data(by,e))){setTimeout(function(){if(!b._data(by,bv)&&!b._data(by,e)){b.removeData(by,bw,true);bz.fire()}},0)}}b.extend({_mark:function(bv,e){if(bv){e=(e||"fx")+"mark";b._data(bv,e,(b._data(bv,e)||0)+1)}},_unmark:function(by,bx,bv){if(by!==true){bv=bx;bx=by;by=false}if(bx){bv=bv||"fx";var e=bv+"mark",bw=by?0:((b._data(bx,e)||1)-1);if(bw){b._data(bx,e,bw)}else{b.removeData(bx,e,true);bi(bx,bv,"mark")}}},queue:function(bv,e,bx){var bw;if(bv){e=(e||"fx")+"queue";bw=b._data(bv,e);if(bx){if(!bw||b.isArray(bx)){bw=b._data(bv,e,b.makeArray(bx))}else{bw.push(bx)}}return bw||[]}},dequeue:function(by,bx){bx=bx||"fx";var bv=b.queue(by,bx),bw=bv.shift(),e={};if(bw==="inprogress"){bw=bv.shift()}if(bw){if(bx==="fx"){bv.unshift("inprogress")}b._data(by,bx+".run",e);bw.call(by,function(){b.dequeue(by,bx)},e)}if(!bv.length){b.removeData(by,bx+"queue "+bx+".run",true);bi(by,bx,"queue")}}});b.fn.extend({queue:function(e,bv){if(typeof e!=="string"){bv=e;e="fx"}if(bv===L){return b.queue(this[0],e)}return this.each(function(){var bw=b.queue(this,e,bv);if(e==="fx"&&bw[0]!=="inprogress"){b.dequeue(this,e)}})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(bv,e){bv=b.fx?b.fx.speeds[bv]||bv:bv;e=e||"fx";return this.queue(e,function(bx,bw){var by=setTimeout(bx,bv);bw.stop=function(){clearTimeout(by)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(bD,bw){if(typeof bD!=="string"){bw=bD;bD=L}bD=bD||"fx";var e=b.Deferred(),bv=this,by=bv.length,bB=1,bz=bD+"defer",bA=bD+"queue",bC=bD+"mark",bx;function bE(){if(!(--bB)){e.resolveWith(bv,[bv])}}while(by--){if((bx=b.data(bv[by],bz,L,true)||(b.data(bv[by],bA,L,true)||b.data(bv[by],bC,L,true))&&b.data(bv[by],bz,b.Callbacks("once memory"),true))){bB++;bx.add(bE)}}bE();return e.promise()}});var aP=/[\n\t\r]/g,af=/\s+/,aU=/\r/g,g=/^(?:button|input)$/i,D=/^(?:button|input|object|select|textarea)$/i,l=/^a(?:rea)?$/i,ao=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,F=b.support.getSetAttribute,be,aY,aF;b.fn.extend({attr:function(e,bv){return b.access(this,e,bv,true,b.attr)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,bv){return b.access(this,e,bv,true,b.prop)},removeProp:function(e){e=b.propFix[e]||e;return this.each(function(){try{this[e]=L;delete this[e]}catch(bv){}})},addClass:function(by){var bA,bw,bv,bx,bz,bB,e;if(b.isFunction(by)){return this.each(function(bC){b(this).addClass(by.call(this,bC,this.className))})}if(by&&typeof by==="string"){bA=by.split(af);for(bw=0,bv=this.length;bw<bv;bw++){bx=this[bw];if(bx.nodeType===1){if(!bx.className&&bA.length===1){bx.className=by}else{bz=" "+bx.className+" ";for(bB=0,e=bA.length;bB<e;bB++){if(!~bz.indexOf(" "+bA[bB]+" ")){bz+=bA[bB]+" "}}bx.className=b.trim(bz)}}}}return this},removeClass:function(bz){var bA,bw,bv,by,bx,bB,e;if(b.isFunction(bz)){return this.each(function(bC){b(this).removeClass(bz.call(this,bC,this.className))})}if((bz&&typeof bz==="string")||bz===L){bA=(bz||"").split(af);for(bw=0,bv=this.length;bw<bv;bw++){by=this[bw];if(by.nodeType===1&&by.className){if(bz){bx=(" "+by.className+" ").replace(aP," ");for(bB=0,e=bA.length;bB<e;bB++){bx=bx.replace(" "+bA[bB]+" "," ")}by.className=b.trim(bx)}else{by.className=""}}}}return this},toggleClass:function(bx,bv){var bw=typeof bx,e=typeof bv==="boolean";if(b.isFunction(bx)){return this.each(function(by){b(this).toggleClass(bx.call(this,by,this.className,bv),bv)})}return this.each(function(){if(bw==="string"){var bA,bz=0,by=b(this),bB=bv,bC=bx.split(af);while((bA=bC[bz++])){bB=e?bB:!by.hasClass(bA);by[bB?"addClass":"removeClass"](bA)}}else{if(bw==="undefined"||bw==="boolean"){if(this.className){b._data(this,"__className__",this.className)}this.className=this.className||bx===false?"":b._data(this,"__className__")||""}}})},hasClass:function(e){var bx=" "+e+" ",bw=0,bv=this.length;for(;bw<bv;bw++){if(this[bw].nodeType===1&&(" "+this[bw].className+" ").replace(aP," ").indexOf(bx)>-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv<bz;bv++){bx=bC[bv];if(bx.selected&&(b.support.optDisabled?!bx.disabled:bx.getAttribute("disabled")===null)&&(!bx.parentNode.disabled||!b.nodeName(bx.parentNode,"optgroup"))){bA=b(bx).val();if(bw){return bA}bB.push(bA)}}if(bw&&!bB.length&&bC.length){return b(bC[by]).val()}return bB},set:function(bv,bw){var e=b.makeArray(bw);b(bv).find("option").each(function(){this.selected=b.inArray(b(this).val(),e)>=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType;if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw<e;bw++){bv=bA[bw];if(bv){by=b.propFix[bv]||bv;b.attr(bx,bv,"");bx.removeAttribute(F?bv:by);if(ao.test(bv)&&by in bx){bx[by]=false}}}}},attrHooks:{type:{set:function(e,bv){if(g.test(e.nodeName)&&e.parentNode){b.error("type property can't be changed")}else{if(!b.support.radioValue&&bv==="radio"&&b.nodeName(e,"input")){var bw=e.value;e.setAttribute("type",bv);if(bw){e.value=bw}return bv}}}},value:{get:function(bv,e){if(be&&b.nodeName(bv,"button")){return be.get(bv,e)}return e in bv?bv.value:null},set:function(bv,bw,e){if(be&&b.nodeName(bv,"button")){return be.set(bv,bw,e)}bv.value=bw}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(bz,bx,bA){var bw,e,by,bv=bz.nodeType;if(!bz||bv===3||bv===8||bv===2){return}by=bv!==1||!b.isXMLDoc(bz);if(by){bx=b.propFix[bx]||bx;e=b.propHooks[bx]}if(bA!==L){if(e&&"set" in e&&(bw=e.set(bz,bA,bx))!==L){return bw}else{return(bz[bx]=bA)}}else{if(e&&"get" in e&&(bw=e.get(bz,bx))!==null){return bw}else{return bz[bx]}}},propHooks:{tabIndex:{get:function(bv){var e=bv.getAttributeNode("tabindex");return e&&e.specified?parseInt(e.value,10):D.test(bv.nodeName)||l.test(bv.nodeName)&&bv.href?0:L}}}});b.attrHooks.tabindex=b.propHooks.tabIndex;aY={get:function(bv,e){var bx,bw=b.prop(bv,e);return bw===true||typeof bw!=="boolean"&&(bx=bv.getAttributeNode(e))&&bx.nodeValue!==false?e.toLowerCase():L},set:function(bv,bx,e){var bw;if(bx===false){b.removeAttr(bv,e)}else{bw=b.propFix[e]||e;if(bw in bv){bv[bw]=true}bv.setAttribute(e,e.toLowerCase())}return e}};if(!F){aF={name:true,id:true};be=b.valHooks.button={get:function(bw,bv){var e;e=bw.getAttributeNode(bv);return e&&(aF[bv]?e.nodeValue!=="":e.specified)?e.nodeValue:L},set:function(bw,bx,bv){var e=bw.getAttributeNode(bv);if(!e){e=av.createAttribute(bv);bw.setAttributeNode(e)}return(e.nodeValue=bx+"")}};b.attrHooks.tabindex.set=be.set;b.each(["width","height"],function(bv,e){b.attrHooks[e]=b.extend(b.attrHooks[e],{set:function(bw,bx){if(bx===""){bw.setAttribute(e,"auto");return bx}}})});b.attrHooks.contenteditable={get:be.get,set:function(bv,bw,e){if(bw===""){bw="false"}be.set(bv,bw,e)}}}if(!b.support.hrefNormalized){b.each(["href","src","width","height"],function(bv,e){b.attrHooks[e]=b.extend(b.attrHooks[e],{get:function(bx){var bw=bx.getAttribute(e,2);return bw===null?L:bw}})})}if(!b.support.style){b.attrHooks.style={get:function(e){return e.style.cssText.toLowerCase()||L},set:function(e,bv){return(e.style.cssText=""+bv)}}}if(!b.support.optSelected){b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(bv){var e=bv.parentNode;if(e){e.selectedIndex;if(e.parentNode){e.parentNode.selectedIndex}}return null}})}if(!b.support.enctype){b.propFix.enctype="encoding"}if(!b.support.checkOn){b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return e.getAttribute("value")===null?"on":e.value}}})}b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,bv){if(b.isArray(bv)){return(e.checked=b.inArray(b(e).val(),bv)>=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI<bC.length;bI++){bH=n.exec(bC[bI])||[];bF=bH[1];e=(bH[2]||"").split(".").sort();bE=b.event.special[bF]||{};bF=(by?bE.delegateType:bE.bindType)||bF;bE=b.event.special[bF]||{};bG=b.extend({type:bF,origType:bH[1],data:bA,handler:bJ,guid:bJ.guid,selector:by,quick:Y(by),namespace:e.join(".")},bv);bw=bK[bF];if(!bw){bw=bK[bF]=[];bw.delegateCount=0;if(!bE.setup||bE.setup.call(bx,bA,e,bB)===false){if(bx.addEventListener){bx.addEventListener(bF,bB,false)}else{if(bx.attachEvent){bx.attachEvent("on"+bF,bB)}}}}if(bE.add){bE.add.call(bx,bG);if(!bG.handler.guid){bG.handler.guid=bJ.guid}}if(by){bw.splice(bw.delegateCount++,0,bG)}else{bw.push(bG)}b.event.global[bF]=true}bx=null},global:{},remove:function(bJ,bE,bv,bH,bB){var bI=b.hasData(bJ)&&b._data(bJ),bF,bx,bz,bL,bC,bA,bG,bw,by,bK,bD,e;if(!bI||!(bw=bI.events)){return}bE=b.trim(bt(bE||"")).split(" ");for(bF=0;bF<bE.length;bF++){bx=n.exec(bE[bF])||[];bz=bL=bx[1];bC=bx[2];if(!bz){for(bz in bw){b.event.remove(bJ,bz+bE[bF],bv,bH,true)}continue}by=b.event.special[bz]||{};bz=(bH?by.delegateType:by.bindType)||bz;bD=bw[bz]||[];bA=bD.length;bC=bC?new RegExp("(^|\\.)"+bC.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(bG=0;bG<bD.length;bG++){e=bD[bG];if((bB||bL===e.origType)&&(!bv||bv.guid===e.guid)&&(!bC||bC.test(e.namespace))&&(!bH||bH===e.selector||bH==="**"&&e.selector)){bD.splice(bG--,1);if(e.selector){bD.delegateCount--}if(by.remove){by.remove.call(bJ,e)}}}if(bD.length===0&&bA!==bD.length){if(!by.teardown||by.teardown.call(bJ,bC)===false){b.removeEvent(bJ,bz,bI.handle)}delete bw[bz]}}if(b.isEmptyObject(bw)){bK=bI.handle;if(bK){bK.elem=null}b.removeData(bJ,["events","handle"],true)}},customEvent:{getData:true,setData:true,changeData:true},trigger:function(bv,bD,bA,bJ){if(bA&&(bA.nodeType===3||bA.nodeType===8)){return}var bG=bv.type||bv,bx=[],e,bw,bC,bH,bz,by,bF,bE,bB,bI;if(T.test(bG+b.event.triggered)){return}if(bG.indexOf("!")>=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bC<bB.length&&!bv.isPropagationStopped();bC++){bH=bB[bC][0];bv.type=bB[bC][1];bE=(b._data(bH,"events")||{})[bv.type]&&b._data(bH,"handle");if(bE){bE.apply(bH,bD)}bE=by&&bH[by];if(bE&&b.acceptData(bH)&&bE.apply(bH,bD)===false){bv.preventDefault()}}bv.type=bG;if(!bJ&&!bv.isDefaultPrevented()){if((!bF._default||bF._default.apply(bA.ownerDocument,bD)===false)&&!(bG==="click"&&b.nodeName(bA,"a"))&&b.acceptData(bA)){if(by&&bA[bG]&&((bG!=="focus"&&bG!=="blur")||bv.target.offsetWidth!==0)&&!b.isWindow(bA)){bz=bA[by];if(bz){bA[by]=null}b.event.triggered=bG;bA[bG]();b.event.triggered=L;if(bz){bA[by]=bz}}}}return bv.result},dispatch:function(e){e=b.event.fix(e||bb.event);var bz=((b._data(this,"events")||{})[e.type]||[]),bA=bz.delegateCount,bG=[].slice.call(arguments,0),by=!e.exclusive&&!e.namespace,bH=[],bC,bB,bK,bx,bF,bE,bv,bD,bI,bw,bJ;bG[0]=e;e.delegateTarget=this;if(bA&&!e.target.disabled&&!(e.button&&e.type==="click")){bx=b(this);bx.context=this.ownerDocument||this;for(bK=e.target;bK!=this;bK=bK.parentNode||this){bE={};bD=[];bx[0]=bK;for(bC=0;bC<bA;bC++){bI=bz[bC];bw=bI.selector;if(bE[bw]===L){bE[bw]=(bI.quick?j(bK,bI.quick):bx.is(bw))}if(bE[bw]){bD.push(bI)}}if(bD.length){bH.push({elem:bK,matches:bD})}}}if(bz.length>bA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC<bH.length&&!e.isPropagationStopped();bC++){bv=bH[bC];e.currentTarget=bv.elem;for(bB=0;bB<bv.matches.length&&!e.isImmediatePropagationStopped();bB++){bI=bv.matches[bB];if(by||(!e.namespace&&!bI.namespace)||e.namespace_re&&e.namespace_re.test(bI.namespace)){e.data=bI.data;e.handleObj=bI;bF=((b.event.special[bI.origType]||{}).handle||bI.handler).apply(bv.elem,bG);if(bF!==L){e.result=bF;if(bF===false){e.preventDefault();e.stopPropagation()}}}}}return e.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(bv,e){if(bv.which==null){bv.which=e.charCode!=null?e.charCode:e.keyCode}return bv}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(bx,bw){var by,bz,e,bv=bw.button,bA=bw.fromElement;if(bx.pageX==null&&bw.clientX!=null){by=bx.target.ownerDocument||av;bz=by.documentElement;e=by.body;bx.pageX=bw.clientX+(bz&&bz.scrollLeft||e&&e.scrollLeft||0)-(bz&&bz.clientLeft||e&&e.clientLeft||0);bx.pageY=bw.clientY+(bz&&bz.scrollTop||e&&e.scrollTop||0)-(bz&&bz.clientTop||e&&e.clientTop||0)}if(!bx.relatedTarget&&bA){bx.relatedTarget=bA===bx.target?bw.toElement:bA}if(!bx.which&&bv!==L){bx.which=(bv&1?1:(bv&2?3:(bv&4?2:0)))}return bx}},fix:function(bw){if(bw[b.expando]){return bw}var bv,bz,e=bw,bx=b.event.fixHooks[bw.type]||{},by=bx.props?this.props.concat(bx.props):this.props;bw=b.Event(e);for(bv=by.length;bv;){bz=by[--bv];bw[bz]=e[bz]}if(!bw.target){bw.target=e.srcElement||av}if(bw.target.nodeType===3){bw.target=bw.target.parentNode}if(bw.metaKey===L){bw.metaKey=bw.ctrlKey}return bx.filter?bx.filter(bw,e):bw},special:{ready:{setup:b.bindReady},load:{noBubble:true},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(bw,bv,e){if(b.isWindow(this)){this.onbeforeunload=e}},teardown:function(bv,e){if(this.onbeforeunload===e){this.onbeforeunload=null}}}},simulate:function(bw,by,bx,bv){var bz=b.extend(new b.Event(),bx,{type:bw,isSimulated:true,originalEvent:{}});if(bv){b.event.trigger(bz,null,by)}else{b.event.dispatch.call(by,bz)}if(bz.isDefaultPrevented()){bx.preventDefault()}}};b.event.handle=b.event.dispatch;b.removeEvent=av.removeEventListener?function(bv,e,bw){if(bv.removeEventListener){bv.removeEventListener(e,bw,false)}}:function(bv,e,bw){if(bv.detachEvent){bv.detachEvent("on"+e,bw)}};b.Event=function(bv,e){if(!(this instanceof b.Event)){return new b.Event(bv,e)}if(bv&&bv.type){this.originalEvent=bv;this.type=bv.type;this.isDefaultPrevented=(bv.defaultPrevented||bv.returnValue===false||bv.getPreventDefault&&bv.getPreventDefault())?i:bk}else{this.type=bv}if(e){b.extend(this,e)}this.timeStamp=bv&&bv.timeStamp||b.now();this[b.expando]=true};function bk(){return false}function i(){return true}b.Event.prototype={preventDefault:function(){this.isDefaultPrevented=i;var bv=this.originalEvent;if(!bv){return}if(bv.preventDefault){bv.preventDefault()}else{bv.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=i;var bv=this.originalEvent;if(!bv){return}if(bv.stopPropagation){bv.stopPropagation()}bv.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=i;this.stopPropagation()},isDefaultPrevented:bk,isPropagationStopped:bk,isImmediatePropagationStopped:bk};b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(bv,e){b.event.special[bv]={delegateType:e,bindType:e,handle:function(bz){var bB=this,bA=bz.relatedTarget,by=bz.handleObj,bw=by.selector,bx;if(!bA||(bA!==bB&&!b.contains(bB,bA))){bz.type=by.origType;bx=by.handler.apply(this,arguments);bz.type=e}return bx}}});if(!b.support.submitBubbles){b.event.special.submit={setup:function(){if(b.nodeName(this,"form")){return false}b.event.add(this,"click._submit keypress._submit",function(bx){var bw=bx.target,bv=b.nodeName(bw,"input")||b.nodeName(bw,"button")?bw.form:L;if(bv&&!bv._submit_attached){b.event.add(bv,"submit._submit",function(e){if(this.parentNode&&!e.isTrigger){b.event.simulate("submit",this.parentNode,e,true)}});bv._submit_attached=true}})},teardown:function(){if(b.nodeName(this,"form")){return false}b.event.remove(this,"._submit")}}}if(!b.support.changeBubbles){b.event.special.change={setup:function(){if(bd.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio"){b.event.add(this,"propertychange._change",function(e){if(e.originalEvent.propertyName==="checked"){this._just_changed=true}});b.event.add(this,"click._change",function(e){if(this._just_changed&&!e.isTrigger){this._just_changed=false;b.event.simulate("change",this,e,true)}})}return false}b.event.add(this,"beforeactivate._change",function(bw){var bv=bw.target;if(bd.test(bv.nodeName)&&!bv._change_attached){b.event.add(bv,"change._change",function(e){if(this.parentNode&&!e.isSimulated&&!e.isTrigger){b.event.simulate("change",this.parentNode,e,true)}});bv._change_attached=true}})},handle:function(bv){var e=bv.target;if(this!==e||bv.isSimulated||bv.isTrigger||(e.type!=="radio"&&e.type!=="checkbox")){return bv.handleObj.handler.apply(this,arguments)}},teardown:function(){b.event.remove(this,"._change");return bd.test(this.nodeName)}}}if(!b.support.focusinBubbles){b.each({focus:"focusin",blur:"focusout"},function(bx,e){var bv=0,bw=function(by){b.event.simulate(e,by.target,b.event.fix(by),true)};b.event.special[e]={setup:function(){if(bv++===0){av.addEventListener(bx,bw,true)}},teardown:function(){if(--bv===0){av.removeEventListener(bx,bw,true)}}}})}b.fn.extend({on:function(bw,e,bz,by,bv){var bA,bx;if(typeof bw==="object"){if(typeof e!=="string"){bz=e;e=L}for(bx in bw){this.on(bx,e,bz,bw[bx],bv)}return this}if(bz==null&&by==null){by=e;bz=e=L}else{if(by==null){if(typeof e==="string"){by=bz;bz=L}else{by=bz;bz=e;e=L}}}if(by===false){by=bk}else{if(!by){return this}}if(bv===1){bA=by;by=function(bB){b().off(bB);return bA.apply(this,arguments)};by.guid=bA.guid||(bA.guid=b.guid++)}return this.each(function(){b.event.add(this,bw,by,bz,e)})},one:function(bv,e,bx,bw){return this.on.call(this,bv,e,bx,bw,1)},off:function(bw,e,by){if(bw&&bw.preventDefault&&bw.handleObj){var bv=bw.handleObj;b(bw.delegateTarget).off(bv.namespace?bv.type+"."+bv.namespace:bv.type,bv.selector,bv.handler);return this}if(typeof bw==="object"){for(var bx in bw){this.off(bx,e,bw[bx])}return this}if(e===false||typeof e==="function"){by=e;e=L}if(by===false){by=bk}return this.each(function(){b.event.remove(this,bw,by,e)})},bind:function(e,bw,bv){return this.on(e,null,bw,bv)},unbind:function(e,bv){return this.off(e,null,bv)},live:function(e,bw,bv){b(this.context).on(e,this.selector,bw,bv);return this},die:function(e,bv){b(this.context).off(e,this.selector||"**",bv);return this},delegate:function(e,bv,bx,bw){return this.on(bv,e,bx,bw)},undelegate:function(e,bv,bw){return arguments.length==1?this.off(e,"**"):this.off(bv,e,bw)},trigger:function(e,bv){return this.each(function(){b.event.trigger(e,bv,this)})},triggerHandler:function(e,bv){if(this[0]){return b.event.trigger(e,bv,this[0],true)}},toggle:function(bx){var bv=arguments,e=bx.guid||b.guid++,bw=0,by=function(bz){var bA=(b._data(this,"lastToggle"+bx.guid)||0)%bw;b._data(this,"lastToggle"+bx.guid,bA+1);bz.preventDefault();return bv[bA].apply(this,arguments)||false};by.guid=e;while(bw<bv.length){bv[bw++].guid=e}return this.click(by)},hover:function(e,bv){return this.mouseenter(e).mouseleave(bv||e)}});b.each(("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu").split(" "),function(bv,e){b.fn[e]=function(bx,bw){if(bw==null){bw=bx;bx=null}return arguments.length>0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}});
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e<bR.length;e++){if(bR[e]===bR[e-1]){bR.splice(e--,1)}}}}return bR};by.matches=function(e,bR){return by(e,null,null,bR)};by.matchesSelector=function(e,bR){return by(bR,null,null,[e]).length>0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS<bU;bS++){bV=bE.order[bS];if((bT=bE.leftMatch[bV].exec(bX))){bR=bT[1];bT.splice(1,1);if(bR.substr(bR.length-1)!=="\\"){bT[1]=(bT[1]||"").replace(bK,"");bW=bE.find[bV](bT,e,bY);if(bW!=null){bX=bX.replace(bE.match[bV],"");break}}}}if(!bW){bW=typeof e.getElementsByTagName!=="undefined"?e.getElementsByTagName("*"):[]}return{set:bW,expr:bX}};by.filter=function(b1,b0,b4,bU){var bW,e,bZ,b6,b3,bR,bT,bV,b2,bS=b1,b5=[],bY=b0,bX=b0&&b0[0]&&by.isXML(b0[0]);while(b1&&b0.length){for(bZ in bE.filter){if((bW=bE.leftMatch[bZ].exec(b1))!=null&&bW[2]){bR=bE.filter[bZ];bT=bW[1];e=false;bW.splice(1,1);if(bT.substr(bT.length-1)==="\\"){continue}if(bY===b5){b5=[]}if(bE.preFilter[bZ]){bW=bE.preFilter[bZ](bW,bY,b4,b5,bU,bX);if(!bW){e=b6=true}else{if(bW===true){continue}}}if(bW){for(bV=0;(b3=bY[bV])!=null;bV++){if(b3){b6=bR(b3,bW,bV,bY);b2=bU^b6;if(b4&&b6!=null){if(b2){e=true}else{bY[bV]=false}}else{if(b2){b5.push(b3);e=true}}}}}if(b6!==L){if(!b4){bY=b5}b1=b1.replace(bE.match[bZ],"");if(!e){return[]}break}}}if(b1===bS){if(e==null){by.error(b1)}else{break}}bS=b1}return bY};by.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)};var bw=by.getText=function(bU){var bS,bT,e=bU.nodeType,bR="";if(e){if(e===1||e===9){if(typeof bU.textContent==="string"){return bU.textContent}else{if(typeof bU.innerText==="string"){return bU.innerText.replace(bO,"")}else{for(bU=bU.firstChild;bU;bU=bU.nextSibling){bR+=bw(bU)}}}}else{if(e===3||e===4){return bU.nodeValue}}}else{for(bS=0;(bT=bU[bS]);bS++){if(bT.nodeType!==8){bR+=bw(bT)}}}return bR};var bE=by.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(e){return e.getAttribute("href")},type:function(e){return e.getAttribute("type")}},relative:{"+":function(bW,bR){var bT=typeof bR==="string",bV=bT&&!bQ.test(bR),bX=bT&&!bV;if(bV){bR=bR.toLowerCase()}for(var bS=0,e=bW.length,bU;bS<e;bS++){if((bU=bW[bS])){while((bU=bU.previousSibling)&&bU.nodeType!==1){}bW[bS]=bX||bU&&bU.nodeName.toLowerCase()===bR?bU||false:bU===bR}}if(bX){by.filter(bR,bW,true)}},">":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS<e;bS++){bV=bW[bS];if(bV){var bT=bV.parentNode;bW[bS]=bT.nodeName.toLowerCase()===bR?bT:false}}}else{for(;bS<e;bS++){bV=bW[bS];if(bV){bW[bS]=bU?bV.parentNode:bV.parentNode===bR}}if(bU){by.filter(bR,bW,true)}}},"":function(bT,bR,bV){var bU,bS=bI++,e=bN;if(typeof bR==="string"&&!bQ.test(bR)){bR=bR.toLowerCase();bU=bR;e=bv}e("parentNode",bR,bS,bT,bU,bV)},"~":function(bT,bR,bV){var bU,bS=bI++,e=bN;if(typeof bR==="string"&&!bQ.test(bR)){bR=bR.toLowerCase();bU=bR;e=bv}e("previousSibling",bR,bS,bT,bU,bV)}},find:{ID:function(bR,bS,bT){if(typeof bS.getElementById!=="undefined"&&!bT){var e=bS.getElementById(bR[1]);return e&&e.parentNode?[e]:[]}},NAME:function(bS,bV){if(typeof bV.getElementsByName!=="undefined"){var bR=[],bU=bV.getElementsByName(bS[1]);for(var bT=0,e=bU.length;bT<e;bT++){if(bU[bT].getAttribute("name")===bS[1]){bR.push(bU[bT])}}return bR.length===0?null:bR}},TAG:function(e,bR){if(typeof bR.getElementsByTagName!=="undefined"){return bR.getElementsByTagName(e[1])}}},preFilter:{CLASS:function(bT,bR,bS,e,bW,bX){bT=" "+bT[1].replace(bK,"")+" ";if(bX){return bT}for(var bU=0,bV;(bV=bR[bU])!=null;bU++){if(bV){if(bW^(bV.className&&(" "+bV.className+" ").replace(/[\t\n\r]/g," ").indexOf(bT)>=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1},lt:function(bS,bR,e){return bR<e[3]-0},gt:function(bS,bR,e){return bR>e[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV<bU;bV++){if(bT[bV]===bS){return false}}return true}else{by.error(e)}}}},CHILD:function(bS,bU){var bT,b0,bW,bZ,e,bV,bY,bX=bU[1],bR=bS;switch(bX){case"only":case"first":while((bR=bR.previousSibling)){if(bR.nodeType===1){return false}}if(bX==="first"){return true}bR=bS;case"last":while((bR=bR.nextSibling)){if(bR.nodeType===1){return false}}return true;case"nth":bT=bU[2];b0=bU[3];if(bT===1&&b0===0){return true}bW=bU[0];bZ=bS.parentNode;if(bZ&&(bZ[bC]!==bW||!bS.nodeIndex)){bV=0;for(bR=bZ.firstChild;bR;bR=bR.nextSibling){if(bR.nodeType===1){bR.nodeIndex=++bV}}bZ[bC]=bW}bY=bS.nodeIndex-b0;if(bT===0){return bY===0}else{return(bY%bT===0&&bY/bT>=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS<e;bS++){bR.push(bU[bS])}}else{for(;bU[bS];bS++){bR.push(bU[bS])}}}return bR}}var bJ,bG;if(av.documentElement.compareDocumentPosition){bJ=function(bR,e){if(bR===e){bB=true;return 0}if(!bR.compareDocumentPosition||!e.compareDocumentPosition){return bR.compareDocumentPosition?-1:1}return bR.compareDocumentPosition(e)&4?-1:1}}else{bJ=function(bY,bX){if(bY===bX){bB=true;return 0}else{if(bY.sourceIndex&&bX.sourceIndex){return bY.sourceIndex-bX.sourceIndex}}var bV,bR,bS=[],e=[],bU=bY.parentNode,bW=bX.parentNode,bZ=bU;if(bU===bW){return bG(bY,bX)}else{if(!bU){return -1}else{if(!bW){return 1}}}while(bZ){bS.unshift(bZ);bZ=bZ.parentNode}bZ=bW;while(bZ){e.unshift(bZ);bZ=bZ.parentNode}bV=bS.length;bR=e.length;for(var bT=0;bT<bV&&bT<bR;bT++){if(bS[bT]!==e[bT]){return bG(bS[bT],e[bT])}}return bT===bV?bG(bY,e[bT],-1):bG(bS[bT],bX,1)};bG=function(bR,e,bS){if(bR===e){return bS}var bT=bR.nextSibling;while(bT){if(bT===e){return -1}bT=bT.nextSibling}return 1}}(function(){var bR=av.createElement("div"),bS="script"+(new Date()).getTime(),e=av.documentElement;bR.innerHTML="<a name='"+bS+"'/>";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="<a href='#'></a>";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="<p class='TEST'></p>";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="<div class='test e'></div><div class='test'></div>";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT<bS;bT++){var e=bZ[bT];if(e){var bU=false;e=e[bR];while(e){if(e[bC]===bV){bU=bZ[e.sizset];break}if(e.nodeType===1&&!bY){e[bC]=bV;e.sizset=bT}if(e.nodeName.toLowerCase()===bW){bU=e;break}e=e[bR]}bZ[bT]=bU}}}function bN(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT<bS;bT++){var e=bZ[bT];if(e){var bU=false;e=e[bR];while(e){if(e[bC]===bV){bU=bZ[e.sizset];break}if(e.nodeType===1){if(!bY){e[bC]=bV;e.sizset=bT}if(typeof bW!=="string"){if(e===bW){bU=true;break}}else{if(by.filter(bW,[e]).length>0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT<bR;bT++){by(bS,bY[bT],bX,bW)}return by.filter(bU,bX)};by.attr=b.attr;by.selectors.attrMap={};b.find=by;b.expr=by.selectors;b.expr[":"]=b.expr.filters;b.unique=by.uniqueSort;b.text=by.getText;b.isXMLDoc=by.isXML;b.contains=by.contains})();var ab=/Until$/,aq=/^(?:parents|prevUntil|prevAll)/,a9=/,/,bp=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,H=b.expr.match.POS,ay={children:true,contents:true,next:true,prev:true};b.fn.extend({find:function(e){var bw=this,by,bv;if(typeof e!=="string"){return b(e).filter(function(){for(by=0,bv=bw.length;by<bv;by++){if(b.contains(bw[by],this)){return true}}})}var bx=this.pushStack("","find",e),bA,bB,bz;for(by=0,bv=this.length;by<bv;by++){bA=bx.length;b.find(e,this[by],bx);if(by>0){for(bB=bA;bB<bx.length;bB++){for(bz=0;bz<bA;bz++){if(bx[bz]===bx[bB]){bx.splice(bB--,1);break}}}}}return bx},has:function(bv){var e=b(bv);return this.filter(function(){for(var bx=0,bw=e.length;bx<bw;bx++){if(b.contains(this,e[bx])){return true}}})},not:function(e){return this.pushStack(aG(this,e,false),"not",e)},filter:function(e){return this.pushStack(aG(this,e,true),"filter",e)},is:function(e){return !!e&&(typeof e==="string"?H.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw<by.length;bw++){if(b(bz).is(by[bw])){bv.push({selector:by[bw],elem:bz,level:bB})}}bz=bz.parentNode;bB++}return bv}var bA=H.test(by)||typeof by!=="string"?b(by,bx||this.context):0;for(bw=0,e=this.length;bw<e;bw++){bz=this[bw];while(bz){if(bA?bA.index(bz)>-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/<tbody/i,W=/<|&#?\w+;/,ae=/<(?:script|style)/i,O=/<(?:script|object|embed|option|style)/i,ah=new RegExp("<(?:"+aR+")","i"),o=/checked\s*(?:[^=]|=\s*.checked.)/i,bm=/\/(java|ecma)script/i,aN=/^\s*<!(?:\[CDATA\[|\-\-)/,ax={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},ac=a(av);ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div<div>","</div>"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1></$2>");try{for(var bw=0,bv=this.length;bw<bv;bw++){if(this[bw].nodeType===1){b.cleanData(this[bw].getElementsByTagName("*"));this[bw].innerHTML=bx}}}catch(by){this.empty().append(bx)}}else{if(b.isFunction(bx)){this.each(function(bz){var e=b(this);e.html(bx.call(this,bz,e.html()))})}else{this.empty().append(bx)}}}return this},replaceWith:function(e){if(this[0]&&this[0].parentNode){if(b.isFunction(e)){return this.each(function(bx){var bw=b(this),bv=bw.html();bw.replaceWith(e.call(this,bx,bv))})}if(typeof e!=="string"){e=b(e).detach()}return this.each(function(){var bw=this.nextSibling,bv=this.parentNode;b(this).remove();if(bw){b(bw).before(e)}else{b(bv).append(e)}})}else{return this.length?this.pushStack(b(b.isFunction(e)?e():e),"replaceWith",e):this}},detach:function(e){return this.remove(e,true)},domManip:function(bB,bF,bE){var bx,by,bA,bD,bC=bB[0],bv=[];if(!b.support.checkClone&&arguments.length===3&&typeof bC==="string"&&o.test(bC)){return this.each(function(){b(this).domManip(bB,bF,bE,true)})}if(b.isFunction(bC)){return this.each(function(bH){var bG=b(this);bB[0]=bC.call(this,bH,bF?bG.html():L);bG.domManip(bB,bF,bE)})}if(this[0]){bD=bC&&bC.parentNode;if(b.support.parentNode&&bD&&bD.nodeType===11&&bD.childNodes.length===this.length){bx={fragment:bD}}else{bx=b.buildFragment(bB,this,bv)}bA=bx.fragment;if(bA.childNodes.length===1){by=bA=bA.firstChild}else{by=bA.firstChild}if(by){bF=bF&&b.nodeName(by,"tr");for(var bw=0,e=this.length,bz=e-1;bw<e;bw++){bE.call(bF?ba(this[bw],by):this[bw],bx.cacheable||(e>1&&bw<bz)?b.clone(bA,true,true):bA)}}if(bv.length){b.each(bv,bo)}}return this}});function ba(e,bv){return b.nodeName(e,"table")?(e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody"))):e}function t(bB,bv){if(bv.nodeType!==1||!b.hasData(bB)){return}var by,bx,e,bA=b._data(bB),bz=b._data(bv,bA),bw=bA.events;if(bw){delete bz.handle;bz.events={};for(by in bw){for(bx=0,e=bw[by].length;bx<e;bx++){b.event.add(bv,by+(bw[by][bx].namespace?".":"")+bw[by][bx].namespace,bw[by][bx],bw[by][bx].data)}}}if(bz.data){bz.data=b.extend({},bz.data)}}function ai(bv,e){var bw;if(e.nodeType!==1){return}if(e.clearAttributes){e.clearAttributes()}if(e.mergeAttributes){e.mergeAttributes(bv)}bw=e.nodeName.toLowerCase();if(bw==="object"){e.outerHTML=bv.outerHTML}else{if(bw==="input"&&(bv.type==="checkbox"||bv.type==="radio")){if(bv.checked){e.defaultChecked=e.checked=bv.checked}if(e.value!==bv.value){e.value=bv.value}}else{if(bw==="option"){e.selected=bv.defaultSelected}else{if(bw==="input"||bw==="textarea"){e.defaultValue=bv.defaultValue}}}}e.removeAttribute(b.expando)}b.buildFragment=function(bz,bx,bv){var by,e,bw,bA,bB=bz[0];if(bx&&bx[0]){bA=bx[0].ownerDocument||bx[0]}if(!bA.createDocumentFragment){bA=av}if(bz.length===1&&typeof bB==="string"&&bB.length<512&&bA===av&&bB.charAt(0)==="<"&&!O.test(bB)&&(b.support.checkClone||!o.test(bB))&&(b.support.html5Clone||!ah.test(bB))){e=true;bw=b.fragments[bB];if(bw&&bw!==1){by=bw}}if(!by){by=bA.createDocumentFragment();b.clean(bz,bA,by,bv)}if(e){b.fragments[bB]=bw?by:1}return{fragment:by,cacheable:e}};b.fragments={};b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,bv){b.fn[e]=function(bw){var bz=[],bC=b(bw),bB=this.length===1&&this[0].parentNode;if(bB&&bB.nodeType===11&&bB.childNodes.length===1&&bC.length===1){bC[bv](this[0]);return this}else{for(var bA=0,bx=bC.length;bA<bx;bA++){var by=(bA>0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1></$2>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]==="<table>"&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB<bG;bB++){E(bz[bB])}}else{E(bz)}}if(bz.nodeType){bI.push(bz)}else{bI=b.merge(bI,bz)}}if(bH){bF=function(bL){return !bL.type||bm.test(bL.type)};for(bE=0;bI[bE];bE++){if(bA&&b.nodeName(bI[bE],"script")&&(!bI[bE].type||bI[bE].type.toLowerCase()==="text/javascript")){bA.push(bI[bE].parentNode?bI[bE].parentNode.removeChild(bI[bE]):bI[bE])}else{if(bI[bE].nodeType===1){var bJ=b.grep(bI[bE].getElementsByTagName("script"),bF);bI.splice.apply(bI,[bE+1,0].concat(bJ))}bH.appendChild(bI[bE])}}}return bI},cleanData:function(bv){var by,bw,e=b.cache,bB=b.event.special,bA=b.support.deleteExpando;for(var bz=0,bx;(bx=bv[bz])!=null;bz++){if(bx.nodeName&&b.noData[bx.nodeName.toLowerCase()]){continue}bw=bx[b.expando];if(bw){by=e[bw];if(by&&by.events){for(var bC in by.events){if(bB[bC]){b.event.remove(bx,bC)}else{b.removeEvent(bx,bC,by.handle)}}if(by.handle){by.handle.elem=null}}if(bA){delete bx[b.expando]}else{if(bx.removeAttribute){bx.removeAttribute(b.expando)}}delete e[bw]}}}});function bo(e,bv){if(bv.src){b.ajax({url:bv.src,async:false,dataType:"script"})}else{b.globalEval((bv.text||bv.textContent||bv.innerHTML||"").replace(aN,"/*$0*/"))}if(bv.parentNode){bv.parentNode.removeChild(bv)}}var ak=/alpha\([^)]*\)/i,au=/opacity=([^)]*)/,z=/([A-Z]|^ms)/g,bc=/^-?\d+(?:px)?$/i,bn=/^-?\d/,I=/^([\-+])=([\-+.\de]+)/,a7={position:"absolute",visibility:"hidden",display:"block"},an=["Left","Right"],a1=["Top","Bottom"],Z,aI,aX;b.fn.css=function(e,bv){if(arguments.length===2&&bv===L){return this}return b.access(this,e,bv,true,function(bx,bw,by){return by!==L?b.style(bx,bw,by):b.css(bx,bw)})};b.extend({cssHooks:{opacity:{get:function(bw,bv){if(bv){var e=Z(bw,"opacity","opacity");return e===""?"1":e}else{return bw.style.opacity}}}},cssNumber:{fillOpacity:true,fontWeight:true,lineHeight:true,opacity:true,orphans:true,widows:true,zIndex:true,zoom:true},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(bx,bw,bD,by){if(!bx||bx.nodeType===3||bx.nodeType===8||!bx.style){return}var bB,bC,bz=b.camelCase(bw),bv=bx.style,bE=b.cssHooks[bz];bw=b.cssProps[bz]||bz;if(bD!==L){bC=typeof bD;if(bC==="string"&&(bB=I.exec(bD))){bD=(+(bB[1]+1)*+bB[2])+parseFloat(b.css(bx,bw));bC="number"}if(bD==null||bC==="number"&&isNaN(bD)){return}if(bC==="number"&&!b.cssNumber[bz]){bD+="px"}if(!bE||!("set" in bE)||(bD=bE.set(bx,bD))!==L){try{bv[bw]=bD}catch(bA){}}}else{if(bE&&"get" in bE&&(bB=bE.get(bx,false,by))!==L){return bB}return bv[bw]}},css:function(by,bx,bv){var bw,e;bx=b.camelCase(bx);e=b.cssHooks[bx];bx=b.cssProps[bx]||bx;if(bx==="cssFloat"){bx="float"}if(e&&"get" in e&&(bw=e.get(by,true,bv))!==L){return bw}else{if(Z){return Z(by,bx)}}},swap:function(bx,bw,by){var e={};for(var bv in bw){e[bv]=bx.style[bv];bx.style[bv]=bw[bv]}by.call(bx);for(bv in bw){bx.style[bv]=e[bv]}}});b.curCSS=b.css;b.each(["height","width"],function(bv,e){b.cssHooks[e]={get:function(by,bx,bw){var bz;if(bx){if(by.offsetWidth!==0){return p(by,e,bw)}else{b.swap(by,a7,function(){bz=p(by,e,bw)})}return bz}},set:function(bw,bx){if(bc.test(bx)){bx=parseFloat(bx);if(bx>=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length;if(bA>0){if(bv!=="border"){for(;bx<e;bx++){if(!bv){bA-=parseFloat(b.css(by,"padding"+bz[bx]))||0}if(bv==="margin"){bA+=parseFloat(b.css(by,bv+bz[bx]))||0}else{bA-=parseFloat(b.css(by,"border"+bz[bx]+"Width"))||0}}}return bA+"px"}bA=Z(by,bw,bw);if(bA<0||bA==null){bA=by.style[bw]||0}bA=parseFloat(bA)||0;if(bv){for(;bx<e;bx++){bA+=parseFloat(b.css(by,"padding"+bz[bx]))||0;if(bv!=="padding"){bA+=parseFloat(b.css(by,"border"+bz[bx]+"Width"))||0}if(bv==="margin"){bA+=parseFloat(b.css(by,bv+bz[bx]))||0}}}return bA+"px"}if(b.expr&&b.expr.filters){b.expr.filters.hidden=function(bw){var bv=bw.offsetWidth,e=bw.offsetHeight;return(bv===0&&e===0)||(!b.support.reliableHiddenOffsets&&((bw.style&&bw.style.display)||b.css(bw,"display"))==="none")};b.expr.filters.visible=function(e){return !b.expr.filters.hidden(e)}}var k=/%20/g,ap=/\[\]$/,bs=/\r?\n/g,bq=/#.*$/,aD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,aZ=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,aM=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,aQ=/^(?:GET|HEAD)$/,c=/^\/\//,M=/\?/,a6=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw<bz;bw++){bv=bx[bw];bC=/^\+/.test(bv);if(bC){bv=bv.substr(1)||"*"}bB=e[bv]=e[bv]||[];bB[bC?"unshift":"push"](bA)}}}}function aW(bv,bE,bz,bD,bB,bx){bB=bB||bE.dataTypes[0];bx=bx||{};bx[bB]=true;var bA=bv[bB],bw=0,e=bA?bA.length:0,by=(bv===aa),bC;for(;bw<e&&(by||!bC);bw++){bC=bA[bw](bE,bz,bD);if(typeof bC==="string"){if(!by||bx[bC]){bC=L}else{bE.dataTypes.unshift(bC);bC=aW(bv,bE,bz,bD,bC,bx)}}}if((by||!bC)&&!bx["*"]){bC=aW(bv,bE,bz,bD,"*",bx)}return bC}function am(bw,bx){var bv,e,by=b.ajaxSettings.flatOptions||{};for(bv in bx){if(bx[bv]!==L){(by[bv]?bw:(e||(e={})))[bv]=bx[bv]}}if(e){b.extend(true,bw,e)}}b.fn.extend({load:function(bw,bz,bA){if(typeof bw!=="string"&&A){return A.apply(this,arguments)}else{if(!this.length){return this}}var by=bw.indexOf(" ");if(by>=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("<div>").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA<bw;bA++){if(bA===1){for(bE in bH.converters){if(typeof bE==="string"){bG[bE.toLowerCase()]=bH.converters[bE]}}}bx=bC;bC=bD[bA];if(bC==="*"){bC=bx}else{if(bx!=="*"&&bx!==bC){by=bx+" "+bC;bF=bG[by]||bG["* "+bC];if(!bF){e=L;for(bv in bG){bB=bv.split(" ");if(bB[0]===bx||bB[0]==="*"){e=bG[bB[1]+" "+bC];if(e){bv=bG[bv];if(bv===true){bF=e}else{if(e===true){bF=bv}}break}}}}if(!(bF||e)){b.error("No conversion from "+by.replace(" "," to "))}if(bF!==true){bz=bF?bF(bz):e(bv(bz))}}}}return bz}var aC=b.now(),u=/(\=)\?(&|$)|\?\?/i;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return b.expando+"_"+(aC++)}});b.ajaxPrefilter("json jsonp",function(bD,bA,bC){var bx=bD.contentType==="application/x-www-form-urlencoded"&&(typeof bD.data==="string");if(bD.dataTypes[0]==="jsonp"||bD.jsonp!==false&&(u.test(bD.url)||bx&&u.test(bD.data))){var bB,bw=bD.jsonpCallback=b.isFunction(bD.jsonpCallback)?bD.jsonpCallback():bD.jsonpCallback,bz=bb[bw],e=bD.url,by=bD.data,bv="$1"+bw+"$2";if(bD.jsonp!==false){e=e.replace(u,bv);if(bD.url===e){if(bx){by=by.replace(u,bv)}if(bD.data===by){e+=(/\?/.test(e)?"&":"?")+bD.jsonp+"="+bw}}}bD.url=e;bD.data=by;bb[bw]=function(bE){bB=[bE]};bC.always(function(){bb[bw]=bz;if(bB&&b.isFunction(bz)){bb[bw](bB[0])}});bD.converters["script json"]=function(){if(!bB){b.error(bw+" was not called")}return bB[0]};bD.dataTypes[0]="json";return"script"}});b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){b.globalEval(e);return e}}});b.ajaxPrefilter("script",function(e){if(e.cache===L){e.cache=false}if(e.crossDomain){e.type="GET";e.global=false}});b.ajaxTransport("script",function(bw){if(bw.crossDomain){var e,bv=av.head||av.getElementsByTagName("head")[0]||av.documentElement;return{send:function(bx,by){e=av.createElement("script");e.async="async";if(bw.scriptCharset){e.charset=bw.scriptCharset}e.src=bw.url;e.onload=e.onreadystatechange=function(bA,bz){if(bz||!e.readyState||/loaded|complete/.test(e.readyState)){e.onload=e.onreadystatechange=null;if(bv&&e.parentNode){bv.removeChild(e)}e=L;if(!bz){by(200,"success")}}};bv.insertBefore(e,bv.firstChild)},abort:function(){if(e){e.onload(0,1)}}}}});var B=bb.ActiveXObject?function(){for(var e in N){N[e](0,1)}}:false,y=0,N;function aL(){try{return new bb.XMLHttpRequest()}catch(bv){}}function aj(){try{return new bb.ActiveXObject("Microsoft.XMLHTTP")}catch(bv){}}b.ajaxSettings.xhr=bb.ActiveXObject?function(){return !this.isLocal&&aL()||aj()}:aL;(function(e){b.extend(b.support,{ajax:!!e,cors:!!e&&("withCredentials" in e)})})(b.ajaxSettings.xhr());if(b.support.ajax){b.ajaxTransport(function(e){if(!e.crossDomain||b.support.cors){var bv;return{send:function(bB,bw){var bA=e.xhr(),bz,by;if(e.username){bA.open(e.type,e.url,e.async,e.username,e.password)}else{bA.open(e.type,e.url,e.async)}if(e.xhrFields){for(by in e.xhrFields){bA[by]=e.xhrFields[by]}}if(e.mimeType&&bA.overrideMimeType){bA.overrideMimeType(e.mimeType)}if(!e.crossDomain&&!bB["X-Requested-With"]){bB["X-Requested-With"]="XMLHttpRequest"}try{for(by in bB){bA.setRequestHeader(by,bB[by])}}catch(bx){}bA.send((e.hasContent&&e.data)||null);bv=function(bK,bE){var bF,bD,bC,bI,bH;try{if(bv&&(bE||bA.readyState===4)){bv=L;if(bz){bA.onreadystatechange=b.noop;if(B){delete N[bz]}}if(bE){if(bA.readyState!==4){bA.abort()}}else{bF=bA.status;bC=bA.getAllResponseHeaders();bI={};bH=bA.responseXML;if(bH&&bH.documentElement){bI.xml=bH}bI.text=bA.responseText;try{bD=bA.statusText}catch(bJ){bD=""}if(!bF&&e.isLocal&&!e.crossDomain){bF=bI.text?200:404}else{if(bF===1223){bF=204}}}}}catch(bG){if(!bE){bw(-1,bG)}}if(bI){bw(bF,bD,bI,bC)}};if(!e.async||bA.readyState===4){bv()}else{bz=++y;if(B){if(!N){N={};b(bb).unload(B)}N[bz]=bv}bA.onreadystatechange=bv}},abort:function(){if(bv){bv(0,1)}}}}})}var Q={},a8,m,aB=/^(?:toggle|show|hide)$/,aT=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,a3,aH=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],a4;b.fn.extend({show:function(bx,bA,bz){var bw,by;if(bx||bx===0){return this.animate(a0("show",3),bx,bA,bz)}else{for(var bv=0,e=this.length;bv<e;bv++){bw=this[bv];if(bw.style){by=bw.style.display;if(!b._data(bw,"olddisplay")&&by==="none"){by=bw.style.display=""}if(by===""&&b.css(bw,"display")==="none"){b._data(bw,"olddisplay",x(bw.nodeName))}}}for(bv=0;bv<e;bv++){bw=this[bv];if(bw.style){by=bw.style.display;if(by===""||by==="none"){bw.style.display=b._data(bw,"olddisplay")||""}}}return this}},hide:function(bx,bA,bz){if(bx||bx===0){return this.animate(a0("hide",3),bx,bA,bz)}else{var bw,by,bv=0,e=this.length;for(;bv<e;bv++){bw=this[bv];if(bw.style){by=b.css(bw,"display");if(by!=="none"&&!b._data(bw,"olddisplay")){b._data(bw,"olddisplay",by)}}}for(bv=0;bv<e;bv++){if(this[bv].style){this[bv].style.display="none"}}return this}},_toggle:b.fn.toggle,toggle:function(bw,bv,bx){var e=typeof bw==="boolean";if(b.isFunction(bw)&&b.isFunction(bv)){this._toggle.apply(this,arguments)}else{if(bw==null||e){this.each(function(){var by=e?bw:b(this).is(":hidden");b(this)[by?"show":"hide"]()})}else{this.animate(a0("toggle",3),bw,bv,bx)}}return this},fadeTo:function(e,bx,bw,bv){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:bx},e,bw,bv)},animate:function(bz,bw,by,bx){var e=b.speed(bw,by,bx);if(b.isEmptyObject(bz)){return this.each(e.complete,[false])}bz=b.extend({},bz);function bv(){if(e.queue===false){b._mark(this)}var bE=b.extend({},e),bK=this.nodeType===1,bI=bK&&b(this).is(":hidden"),bB,bF,bD,bJ,bH,bC,bG,bL,bA;bE.animatedProperties={};for(bD in bz){bB=b.camelCase(bD);if(bD!==bB){bz[bB]=bz[bD];delete bz[bD]}bF=bz[bB];if(b.isArray(bF)){bE.animatedProperties[bB]=bF[1];bF=bz[bB]=bF[0]}else{bE.animatedProperties[bB]=bE.specialEasing&&bE.specialEasing[bB]||bE.easing||"swing"}if(bF==="hide"&&bI||bF==="show"&&!bI){return bE.complete.call(this)}if(bK&&(bB==="height"||bB==="width")){bE.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(b.css(this,"display")==="inline"&&b.css(this,"float")==="none"){if(!b.support.inlineBlockNeedsLayout||x(this.nodeName)==="inline"){this.style.display="inline-block"}else{this.style.zoom=1}}}}if(bE.overflow!=null){this.style.overflow="hidden"}for(bD in bz){bJ=new b.fx(this,bE,bD);bF=bz[bD];if(aB.test(bF)){bA=b._data(this,"toggle"+bD)||(bF==="toggle"?bI?"show":"hide":0);if(bA){b._data(this,"toggle"+bD,bA==="show"?"hide":"show");bJ[bA]()}else{bJ[bF]()}}else{bH=aT.exec(bF);bC=bJ.cur();if(bH){bG=parseFloat(bH[2]);bL=bH[3]||(b.cssNumber[bD]?"":"px");if(bL!=="px"){b.style(this,bD,(bG||1)+bL);bC=((bG||1)/bJ.cur())*bC;b.style(this,bD,bC+bL)}if(bH[1]){bG=((bH[1]==="-="?-1:1)*bG)+bC}bJ.custom(bC,bG,bL)}else{bJ.custom(bC,bF,"")}}}return true}return e.queue===false?this.each(bv):this.queue(e.queue,bv)},stop:function(bw,bv,e){if(typeof bw!=="string"){e=bv;bv=bw;bw=L}if(bv&&bw!==false){this.queue(bw||"fx",[])}return this.each(function(){var bx,by=false,bA=b.timers,bz=b._data(this);if(!e){b._unmark(true,this)}function bB(bE,bF,bD){var bC=bF[bD];b.removeData(bE,bD,true);bC.stop(e)}if(bw==null){for(bx in bz){if(bz[bx]&&bz[bx].stop&&bx.indexOf(".run")===bx.length-4){bB(this,bz,bx)}}}else{if(bz[bx=bw+".run"]&&bz[bx].stop){bB(this,bz,bx)}}for(bx=bA.length;bx--;){if(bA[bx].elem===this&&(bw==null||bA[bx].queue===bw)){if(e){bA[bx](true)}else{bA[bx].saveState()}by=true;bA.splice(bx,1)}}if(!(e&&by)){b.dequeue(this,bw)}})}});function bh(){setTimeout(at,0);return(a4=b.now())}function at(){a4=L}function a0(bv,e){var bw={};b.each(aH.concat.apply([],aH.slice(0,e)),function(){bw[this]=bv});return bw}b.each({slideDown:a0("show",1),slideUp:a0("hide",1),slideToggle:a0("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,bv){b.fn[e]=function(bw,by,bx){return this.animate(bv,bw,by,bx)}});b.extend({speed:function(bw,bx,bv){var e=bw&&typeof bw==="object"?b.extend({},bw):{complete:bv||!bv&&bx||b.isFunction(bw)&&bw,duration:bw,easing:bv&&bx||bx&&!b.isFunction(bx)&&bx};e.duration=b.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in b.fx.speeds?b.fx.speeds[e.duration]:b.fx.speeds._default;if(e.queue==null||e.queue===true){e.queue="fx"}e.old=e.complete;e.complete=function(by){if(b.isFunction(e.old)){e.old.call(this)}if(e.queue){b.dequeue(this,e.queue)}else{if(by!==false){b._unmark(this)}}};return e},easing:{linear:function(bw,bx,e,bv){return e+bv*bw},swing:function(bw,bx,e,bv){return((-Math.cos(bw*Math.PI)/2)+0.5)*bv+e}},timers:[],fx:function(bv,e,bw){this.options=e;this.elem=bv;this.prop=bw;e.orig=e.orig||{}}});b.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(b.fx.step[this.prop]||b.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var e,bv=b.css(this.elem,this.prop);return isNaN(e=parseFloat(bv))?!bv||bv==="auto"?0:bv:e},custom:function(bz,by,bx){var e=this,bw=b.fx;this.startTime=a4||bh();this.end=by;this.now=this.start=bz;this.pos=this.state=0;this.unit=bx||this.unit||(b.cssNumber[this.prop]?"":"px");function bv(bA){return e.step(bA)}bv.queue=this.options.queue;bv.elem=this.elem;bv.saveState=function(){if(e.options.hide&&b._data(e.elem,"fxshow"+e.prop)===L){b._data(e.elem,"fxshow"+e.prop,e.start)}};if(bv()&&b.timers.push(bv)&&!a3){a3=setInterval(bw.tick,bw.interval)}},show:function(){var e=b._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=e||b.style(this.elem,this.prop);this.options.show=true;if(e!==L){this.custom(this.cur(),e)}else{this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur())}b(this.elem).show()},hide:function(){this.options.orig[this.prop]=b._data(this.elem,"fxshow"+this.prop)||b.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(by){var bA,bB,bv,bx=a4||bh(),e=true,bz=this.elem,bw=this.options;if(by||bx>=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e<bv.length;e++){bw=bv[e];if(!bw()&&bv[e]===bw){bv.splice(e--,1)}}if(!bv.length){b.fx.stop()}},interval:13,stop:function(){clearInterval(a3);a3=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(e){b.style(e.elem,"opacity",e.now)},_default:function(e){if(e.elem.style&&e.elem.style[e.prop]!=null){e.elem.style[e.prop]=e.now+e.unit}else{e.elem[e.prop]=e.now}}}});b.each(["width","height"],function(e,bv){b.fx.step[bv]=function(bw){b.style(bw.elem,bv,Math.max(0,bw.now)+bw.unit)}});if(b.expr&&b.expr.filters){b.expr.filters.animated=function(e){return b.grep(b.timers,function(bv){return e===bv.elem}).length}}function x(bx){if(!Q[bx]){var e=av.body,bv=b("<"+bx+">").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b})}})(window);/*!
+ * jQuery UI 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI
+ */
+(function(a,d){a.ui=a.ui||{};if(a.ui.version){return}a.extend(a.ui,{version:"1.8.18",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(e,f){return typeof e==="number"?this.each(function(){var g=this;setTimeout(function(){a(g).focus();if(f){f.call(g)}},e)}):this._focus.apply(this,arguments)},scrollParent:function(){var e;if((a.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){e=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(a.curCSS(this,"position",1))&&(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}else{e=this.parents().filter(function(){return(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!e.length?a(document):e},zIndex:function(h){if(h!==d){return this.css("zIndex",h)}if(this.length){var f=a(this[0]),e,g;while(f.length&&f[0]!==document){e=f.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){g=parseInt(f.css("zIndex"),10);if(!isNaN(g)&&g!==0){return g}}f=f.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});a.each(["Width","Height"],function(g,e){var f=e==="Width"?["Left","Right"]:["Top","Bottom"],h=e.toLowerCase(),k={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};function j(m,l,i,n){a.each(f,function(){l-=parseFloat(a.curCSS(m,"padding"+this,true))||0;if(i){l-=parseFloat(a.curCSS(m,"border"+this+"Width",true))||0}if(n){l-=parseFloat(a.curCSS(m,"margin"+this,true))||0}});return l}a.fn["inner"+e]=function(i){if(i===d){return k["inner"+e].call(this)}return this.each(function(){a(this).css(h,j(this,i)+"px")})};a.fn["outer"+e]=function(i,l){if(typeof i!=="number"){return k["outer"+e].call(this,i)}return this.each(function(){a(this).css(h,j(this,i,true,l)+"px")})}});function c(g,e){var j=g.nodeName.toLowerCase();if("area"===j){var i=g.parentNode,h=i.name,f;if(!g.href||!h||i.nodeName.toLowerCase()!=="map"){return false}f=a("img[usemap=#"+h+"]")[0];return !!f&&b(f)}return(/input|select|textarea|button|object/.test(j)?!g.disabled:"a"==j?g.href||e:e)&&b(g)}function b(e){return !a(e).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.extend(a.expr[":"],{data:function(g,f,e){return !!a.data(g,e[3])},focusable:function(e){return c(e,!isNaN(a.attr(e,"tabindex")))},tabbable:function(g){var e=a.attr(g,"tabindex"),f=isNaN(e);return(f||e>=0)&&c(g,!f)}});a(function(){var e=document.body,f=e.appendChild(f=document.createElement("div"));f.offsetHeight;a.extend(f.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});a.support.minHeight=f.offsetHeight===100;a.support.selectstart="onselectstart" in f;e.removeChild(f).style.display="none"});a.extend(a.ui,{plugin:{add:function(f,g,j){var h=a.ui[f].prototype;for(var e in j){h.plugins[e]=h.plugins[e]||[];h.plugins[e].push([g,j[e]])}},call:function(e,g,f){var j=e.plugins[g];if(!j||!e.element[0].parentNode){return}for(var h=0;h<j.length;h++){if(e.options[j[h][0]]){j[h][1].apply(e.element,f)}}}},contains:function(f,e){return document.compareDocumentPosition?f.compareDocumentPosition(e)&16:f!==e&&f.contains(e)},hasScroll:function(h,f){if(a(h).css("overflow")==="hidden"){return false}var e=(f&&f==="left")?"scrollLeft":"scrollTop",g=false;if(h[e]>0){return true}h[e]=1;g=(h[e]>0);h[e]=0;return g},isOverAxis:function(f,e,g){return(f>e)&&(f<(e+g))},isOver:function(j,f,i,h,e,g){return a.ui.isOverAxis(j,i,e)&&a.ui.isOverAxis(f,h,g)}})})(jQuery);/*!
+ * jQuery UI Widget 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Widget
+ */
+(function(b,d){if(b.cleanData){var c=b.cleanData;b.cleanData=function(f){for(var g=0,h;(h=f[g])!=null;g++){try{b(h).triggerHandler("remove")}catch(j){}}c(f)}}else{var a=b.fn.remove;b.fn.remove=function(e,f){return this.each(function(){if(!f){if(!e||b.filter(e,[this]).length){b("*",this).add([this]).each(function(){try{b(this).triggerHandler("remove")}catch(g){}})}}return a.call(b(this),e,f)})}}b.widget=function(f,h,e){var g=f.split(".")[0],j;f=f.split(".")[1];j=g+"-"+f;if(!e){e=h;h=b.Widget}b.expr[":"][j]=function(k){return !!b.data(k,f)};b[g]=b[g]||{};b[g][f]=function(k,l){if(arguments.length){this._createWidget(k,l)}};var i=new h();i.options=b.extend(true,{},i.options);b[g][f].prototype=b.extend(true,i,{namespace:g,widgetName:f,widgetEventPrefix:b[g][f].prototype.widgetEventPrefix||f,widgetBaseClass:j},e);b.widget.bridge(f,b[g][f])};b.widget.bridge=function(f,e){b.fn[f]=function(i){var g=typeof i==="string",h=Array.prototype.slice.call(arguments,1),j=this;i=!g&&h.length?b.extend.apply(null,[true,i].concat(h)):i;if(g&&i.charAt(0)==="_"){return j}if(g){this.each(function(){var k=b.data(this,f),l=k&&b.isFunction(k[i])?k[i].apply(k,h):k;if(l!==k&&l!==d){j=l;return false}})}else{this.each(function(){var k=b.data(this,f);if(k){k.option(i||{})._init()}else{b.data(this,f,new e(i,this))}})}return j}};b.Widget=function(e,f){if(arguments.length){this._createWidget(e,f)}};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(f,g){b.data(g,this.widgetName,this);this.element=b(g);this.options=b.extend(true,{},this.options,this._getCreateOptions(),f);var e=this;this.element.bind("remove."+this.widgetName,function(){e.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(f,g){var e=f;if(arguments.length===0){return b.extend({},this.options)}if(typeof f==="string"){if(g===d){return this.options[f]}e={};e[f]=g}this._setOptions(e);return this},_setOptions:function(f){var e=this;b.each(f,function(g,h){e._setOption(g,h)});return this},_setOption:function(e,f){this.options[e]=f;if(e==="disabled"){this.widget()[f?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",f)}return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(e,f,g){var j,i,h=this.options[e];g=g||{};f=b.Event(f);f.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase();f.target=this.element[0];i=f.originalEvent;if(i){for(j in i){if(!(j in f)){f[j]=i[j]}}}this.element.trigger(f,g);return !(b.isFunction(h)&&h.call(this.element[0],f,g)===false||f.isDefaultPrevented())}}})(jQuery);/*!
+ * jQuery UI Mouse 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Mouse
+ *
+ * Depends:
+ * jquery.ui.widget.js
+ */
+(function(b,c){var a=false;b(document).mouseup(function(d){a=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var d=this;this.element.bind("mousedown."+this.widgetName,function(e){return d._mouseDown(e)}).bind("click."+this.widgetName,function(e){if(true===b.data(e.target,d.widgetName+".preventClickEvent")){b.removeData(e.target,d.widgetName+".preventClickEvent");e.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(f){if(a){return}(this._mouseStarted&&this._mouseUp(f));this._mouseDownEvent=f;var e=this,g=(f.which==1),d=(typeof this.options.cancel=="string"&&f.target.nodeName?b(f.target).closest(this.options.cancel).length:false);if(!g||d||!this._mouseCapture(f)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(f)&&this._mouseDelayMet(f)){this._mouseStarted=(this._mouseStart(f)!==false);if(!this._mouseStarted){f.preventDefault();return true}}if(true===b.data(f.target,this.widgetName+".preventClickEvent")){b.removeData(f.target,this.widgetName+".preventClickEvent")}this._mouseMoveDelegate=function(h){return e._mouseMove(h)};this._mouseUpDelegate=function(h){return e._mouseUp(h)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);f.preventDefault();a=true;return true},_mouseMove:function(d){if(b.browser.msie&&!(document.documentMode>=9)&&!d.button){return this._mouseUp(d)}if(this._mouseStarted){this._mouseDrag(d);return d.preventDefault()}if(this._mouseDistanceMet(d)&&this._mouseDelayMet(d)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,d)!==false);(this._mouseStarted?this._mouseDrag(d):this._mouseUp(d))}return !this._mouseStarted},_mouseUp:function(d){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;if(d.target==this._mouseDownEvent.target){b.data(d.target,this.widgetName+".preventClickEvent",true)}this._mouseStop(d)}return false},_mouseDistanceMet:function(d){return(Math.max(Math.abs(this._mouseDownEvent.pageX-d.pageX),Math.abs(this._mouseDownEvent.pageY-d.pageY))>=this.options.distance)},_mouseDelayMet:function(d){return this.mouseDelayMet},_mouseStart:function(d){},_mouseDrag:function(d){},_mouseStop:function(d){},_mouseCapture:function(d){return true}})})(jQuery);(function(c,d){c.widget("ui.resizable",c.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000},_create:function(){var f=this,k=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(k.aspectRatio),aspectRatio:k.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:k.helper||k.ghost||k.animate?k.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){this.element.wrap(c('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=k.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var l=this.handles.split(",");this.handles={};for(var g=0;g<l.length;g++){var j=c.trim(l[g]),e="ui-resizable-"+j;var h=c('<div class="ui-resizable-handle '+e+'"></div>');if(/sw|se|ne|nw/.test(j)){h.css({zIndex:++k.zIndex})}if("se"==j){h.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[j]=".ui-resizable-"+j;this.element.append(h)}}this._renderAxis=function(q){q=q||this.element;for(var n in this.handles){if(this.handles[n].constructor==String){this.handles[n]=c(this.handles[n],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var o=c(this.handles[n],this.element),p=0;p=/sw|ne|nw|se|n|s/.test(n)?o.outerHeight():o.outerWidth();var m=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");q.css(m,p);this._proportionallyResize()}if(!c(this.handles[n]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!f.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}f.axis=i&&i[1]?i[1]:"se"}});if(k.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){if(k.disabled){return}c(this).removeClass("ui-resizable-autohide");f._handles.show()},function(){if(k.disabled){return}if(!f.resizing){c(this).addClass("ui-resizable-autohide");f._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var e=function(g){c(g).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){e(this.element);var f=this.element;f.after(this.originalElement.css({position:f.css("position"),width:f.outerWidth(),height:f.outerHeight(),top:f.css("top"),left:f.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);e(this.originalElement);return this},_mouseCapture:function(f){var g=false;for(var e in this.handles){if(c(this.handles[e])[0]==f.target){g=true}}return !this.options.disabled&&g},_mouseStart:function(g){var j=this.options,f=this.element.position(),e=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(e.is(".ui-draggable")||(/absolute/).test(e.css("position"))){e.css({position:"absolute",top:f.top,left:f.left})}this._renderProxy();var k=b(this.helper.css("left")),h=b(this.helper.css("top"));if(j.containment){k+=c(j.containment).scrollLeft()||0;h+=c(j.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:k,top:h};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:k,top:h};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:g.pageX,top:g.pageY};this.aspectRatio=(typeof j.aspectRatio=="number")?j.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var i=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",i=="auto"?this.axis+"-resize":i);e.addClass("ui-resizable-resizing");this._propagate("start",g);return true},_mouseDrag:function(e){var h=this.helper,g=this.options,m={},q=this,j=this.originalMousePosition,n=this.axis;var r=(e.pageX-j.left)||0,p=(e.pageY-j.top)||0;var i=this._change[n];if(!i){return false}var l=i.apply(this,[e,r,p]),k=c.browser.msie&&c.browser.version<7,f=this.sizeDiff;this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey){l=this._updateRatio(l,e)}l=this._respectSize(l,e);this._propagate("resize",e);h.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(l);this._trigger("resize",e,this.ui());return false},_mouseStop:function(h){this.resizing=false;var i=this.options,m=this;if(this._helper){var g=this._proportionallyResizeElements,e=g.length&&(/textarea/i).test(g[0].nodeName),f=e&&c.ui.hasScroll(g[0],"left")?0:m.sizeDiff.height,k=e?0:m.sizeDiff.width;var n={width:(m.helper.width()-k),height:(m.helper.height()-f)},j=(parseInt(m.element.css("left"),10)+(m.position.left-m.originalPosition.left))||null,l=(parseInt(m.element.css("top"),10)+(m.position.top-m.originalPosition.top))||null;if(!i.animate){this.element.css(c.extend(n,{top:l,left:j}))}m.helper.height(m.size.height);m.helper.width(m.size.width);if(this._helper&&!i.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",h);if(this._helper){this.helper.remove()}return false},_updateVirtualBoundaries:function(g){var j=this.options,i,h,f,k,e;e={minWidth:a(j.minWidth)?j.minWidth:0,maxWidth:a(j.maxWidth)?j.maxWidth:Infinity,minHeight:a(j.minHeight)?j.minHeight:0,maxHeight:a(j.maxHeight)?j.maxHeight:Infinity};if(this._aspectRatio||g){i=e.minHeight*this.aspectRatio;f=e.minWidth/this.aspectRatio;h=e.maxHeight*this.aspectRatio;k=e.maxWidth/this.aspectRatio;if(i>e.minWidth){e.minWidth=i}if(f>e.minHeight){e.minHeight=f}if(h<e.maxWidth){e.maxWidth=h}if(k<e.maxHeight){e.maxHeight=k}}this._vBoundaries=e},_updateCache:function(e){var f=this.options;this.offset=this.helper.offset();if(a(e.left)){this.position.left=e.left}if(a(e.top)){this.position.top=e.top}if(a(e.height)){this.size.height=e.height}if(a(e.width)){this.size.width=e.width}},_updateRatio:function(h,g){var i=this.options,j=this.position,f=this.size,e=this.axis;if(a(h.height)){h.width=(h.height*this.aspectRatio)}else{if(a(h.width)){h.height=(h.width/this.aspectRatio)}}if(e=="sw"){h.left=j.left+(f.width-h.width);h.top=null}if(e=="nw"){h.top=j.top+(f.height-h.height);h.left=j.left+(f.width-h.width)}return h},_respectSize:function(l,g){var j=this.helper,i=this._vBoundaries,r=this._aspectRatio||g.shiftKey,q=this.axis,t=a(l.width)&&i.maxWidth&&(i.maxWidth<l.width),m=a(l.height)&&i.maxHeight&&(i.maxHeight<l.height),h=a(l.width)&&i.minWidth&&(i.minWidth>l.width),s=a(l.height)&&i.minHeight&&(i.minHeight>l.height);if(h){l.width=i.minWidth}if(s){l.height=i.minHeight}if(t){l.width=i.maxWidth}if(m){l.height=i.maxHeight}var f=this.originalPosition.left+this.originalSize.width,p=this.position.top+this.size.height;var k=/sw|nw|w/.test(q),e=/nw|ne|n/.test(q);if(h&&k){l.left=f-i.minWidth}if(t&&k){l.left=f-i.maxWidth}if(s&&e){l.top=p-i.minHeight}if(m&&e){l.top=p-i.maxHeight}var n=!l.width&&!l.height;if(n&&!l.left&&l.top){l.top=null}else{if(n&&!l.top&&l.left){l.left=null}}return l},_proportionallyResize:function(){var k=this.options;if(!this._proportionallyResizeElements.length){return}var g=this.helper||this.element;for(var f=0;f<this._proportionallyResizeElements.length;f++){var h=this._proportionallyResizeElements[f];if(!this.borderDif){var e=[h.css("borderTopWidth"),h.css("borderRightWidth"),h.css("borderBottomWidth"),h.css("borderLeftWidth")],j=[h.css("paddingTop"),h.css("paddingRight"),h.css("paddingBottom"),h.css("paddingLeft")];this.borderDif=c.map(e,function(l,n){var m=parseInt(l,10)||0,o=parseInt(j[n],10)||0;return m+o})}if(c.browser.msie&&!(!(c(g).is(":hidden")||c(g).parents(":hidden").length))){continue}h.css({height:(g.height()-this.borderDif[0]-this.borderDif[2])||0,width:(g.width()-this.borderDif[1]-this.borderDif[3])||0})}},_renderProxy:function(){var f=this.element,i=this.options;this.elementOffset=f.offset();if(this._helper){this.helper=this.helper||c('<div style="overflow:hidden;"></div>');var e=c.browser.msie&&c.browser.version<7,g=(e?1:0),h=(e?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+h,height:this.element.outerHeight()+h,position:"absolute",left:this.elementOffset.left-g+"px",top:this.elementOffset.top-g+"px",zIndex:++i.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(g,f,e){return{width:this.originalSize.width+f}},w:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{left:i.left+f,width:g.width-f}},n:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{top:i.top+e,height:g.height-e}},s:function(g,f,e){return{height:this.originalSize.height+e}},se:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},sw:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[g,f,e]))},ne:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},nw:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[g,f,e]))}},_propagate:function(f,e){c.ui.plugin.call(this,f,[e,this.ui()]);(f!="resize"&&this._trigger(f,e,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});c.extend(c.ui.resizable,{version:"1.8.18"});c.ui.plugin.add("resizable","alsoResize",{start:function(f,g){var e=c(this).data("resizable"),i=e.options;var h=function(j){c(j).each(function(){var k=c(this);k.data("resizable-alsoresize",{width:parseInt(k.width(),10),height:parseInt(k.height(),10),left:parseInt(k.css("left"),10),top:parseInt(k.css("top"),10)})})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.parentNode){if(i.alsoResize.length){i.alsoResize=i.alsoResize[0];h(i.alsoResize)}else{c.each(i.alsoResize,function(j){h(j)})}}else{h(i.alsoResize)}},resize:function(g,i){var f=c(this).data("resizable"),j=f.options,h=f.originalSize,l=f.originalPosition;var k={height:(f.size.height-h.height)||0,width:(f.size.width-h.width)||0,top:(f.position.top-l.top)||0,left:(f.position.left-l.left)||0},e=function(m,n){c(m).each(function(){var q=c(this),r=c(this).data("resizable-alsoresize"),p={},o=n&&n.length?n:q.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];c.each(o,function(s,u){var t=(r[u]||0)+(k[u]||0);if(t&&t>=0){p[u]=t||null}});q.css(p)})};if(typeof(j.alsoResize)=="object"&&!j.alsoResize.nodeType){c.each(j.alsoResize,function(m,n){e(m,n)})}else{e(j.alsoResize)}},stop:function(e,f){c(this).removeData("resizable-alsoresize")}});c.ui.plugin.add("resizable","animate",{stop:function(i,n){var p=c(this).data("resizable"),j=p.options;var h=p._proportionallyResizeElements,e=h.length&&(/textarea/i).test(h[0].nodeName),f=e&&c.ui.hasScroll(h[0],"left")?0:p.sizeDiff.height,l=e?0:p.sizeDiff.width;var g={width:(p.size.width-l),height:(p.size.height-f)},k=(parseInt(p.element.css("left"),10)+(p.position.left-p.originalPosition.left))||null,m=(parseInt(p.element.css("top"),10)+(p.position.top-p.originalPosition.top))||null;p.element.animate(c.extend(g,m&&k?{top:m,left:k}:{}),{duration:j.animateDuration,easing:j.animateEasing,step:function(){var o={width:parseInt(p.element.css("width"),10),height:parseInt(p.element.css("height"),10),top:parseInt(p.element.css("top"),10),left:parseInt(p.element.css("left"),10)};if(h&&h.length){c(h[0]).css({width:o.width,height:o.height})}p._updateCache(o);p._propagate("resize",i)}})}});c.ui.plugin.add("resizable","containment",{start:function(f,r){var t=c(this).data("resizable"),j=t.options,l=t.element;var g=j.containment,k=(g instanceof c)?g.get(0):(/parent/.test(g))?l.parent().get(0):g;if(!k){return}t.containerElement=c(k);if(/document/.test(g)||g==document){t.containerOffset={left:0,top:0};t.containerPosition={left:0,top:0};t.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var n=c(k),i=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){i[p]=b(n.css("padding"+o))});t.containerOffset=n.offset();t.containerPosition=n.position();t.containerSize={height:(n.innerHeight()-i[3]),width:(n.innerWidth()-i[1])};var q=t.containerOffset,e=t.containerSize.height,m=t.containerSize.width,h=(c.ui.hasScroll(k,"left")?k.scrollWidth:m),s=(c.ui.hasScroll(k)?k.scrollHeight:e);t.parentData={element:k,left:q.left,top:q.top,width:h,height:s}}},resize:function(g,q){var t=c(this).data("resizable"),i=t.options,f=t.containerSize,p=t.containerOffset,m=t.size,n=t.position,r=t._aspectRatio||g.shiftKey,e={top:0,left:0},h=t.containerElement;if(h[0]!=document&&(/static/).test(h.css("position"))){e=p}if(n.left<(t._helper?p.left:0)){t.size.width=t.size.width+(t._helper?(t.position.left-p.left):(t.position.left-e.left));if(r){t.size.height=t.size.width/i.aspectRatio}t.position.left=i.helper?p.left:0}if(n.top<(t._helper?p.top:0)){t.size.height=t.size.height+(t._helper?(t.position.top-p.top):t.position.top);if(r){t.size.width=t.size.height*i.aspectRatio}t.position.top=t._helper?p.top:0}t.offset.left=t.parentData.left+t.position.left;t.offset.top=t.parentData.top+t.position.top;var l=Math.abs((t._helper?t.offset.left-e.left:(t.offset.left-e.left))+t.sizeDiff.width),s=Math.abs((t._helper?t.offset.top-e.top:(t.offset.top-p.top))+t.sizeDiff.height);var k=t.containerElement.get(0)==t.element.parent().get(0),j=/relative|absolute/.test(t.containerElement.css("position"));if(k&&j){l-=t.parentData.left}if(l+t.size.width>=t.parentData.width){t.size.width=t.parentData.width-l;if(r){t.size.height=t.size.width/t.aspectRatio}}if(s+t.size.height>=t.parentData.height){t.size.height=t.parentData.height-s;if(r){t.size.width=t.size.height*t.aspectRatio}}},stop:function(f,n){var q=c(this).data("resizable"),g=q.options,l=q.position,m=q.containerOffset,e=q.containerPosition,i=q.containerElement;var j=c(q.helper),r=j.offset(),p=j.outerWidth()-q.sizeDiff.width,k=j.outerHeight()-q.sizeDiff.height;if(q._helper&&!g.animate&&(/relative/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}if(q._helper&&!g.animate&&(/static/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}}});c.ui.plugin.add("resizable","ghost",{start:function(g,h){var e=c(this).data("resizable"),i=e.options,f=e.size;e.ghost=e.originalElement.clone();e.ghost.css({opacity:0.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:"");e.ghost.appendTo(e.helper)},resize:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost){e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})}},stop:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost&&e.helper){e.helper.get(0).removeChild(e.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(e,m){var p=c(this).data("resizable"),h=p.options,k=p.size,i=p.originalSize,j=p.originalPosition,n=p.axis,l=h._aspectRatio||e.shiftKey;h.grid=typeof h.grid=="number"?[h.grid,h.grid]:h.grid;var g=Math.round((k.width-i.width)/(h.grid[0]||1))*(h.grid[0]||1),f=Math.round((k.height-i.height)/(h.grid[1]||1))*(h.grid[1]||1);if(/^(se|s|e)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f}else{if(/^(ne)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f}else{if(/^(sw)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.left=j.left-g}else{p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f;p.position.left=j.left-g}}}}});var b=function(e){return parseInt(e,10)||0};var a=function(e){return !isNaN(parseInt(e,10))}})(jQuery);/*!
+ * jQuery hashchange event - v1.3 - 7/21/2010
+ * http://benalman.com/projects/jquery-hashchange-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){r||l(a());n()}).attr("src",r||"javascript:0").insertAfter("body")[0].contentWindow;h.onpropertychange=function(){try{if(event.propertyName==="title"){q.document.title=h.title}}catch(s){}}}};j.stop=k;o=function(){return a(q.location.href)};l=function(v,s){var u=q.document,t=$.fn[c].domain;if(v!==s){u.title=h.title;u.open();t&&u.write('<script>document.domain="'+t+'"<\/script>');u.close();q.location.hash=v}}})();return j})()})(jQuery,this);(function(c){var a=c.scrollTo=function(f,e,d){c(window).scrollTo(f,e,d)};a.defaults={axis:"xy",duration:parseFloat(c.fn.jquery)>=1.3?0:1};a.window=function(d){return c(window)._scrollable()};c.fn._scrollable=function(){return this.map(function(){var e=this,d=!e.nodeName||c.inArray(e.nodeName.toLowerCase(),["iframe","#document","html","body"])!=-1;if(!d){return e}var f=(e.contentWindow||e).document||e.ownerDocument||e;return c.browser.safari||f.compatMode=="BackCompat"?f.body:f.documentElement})};c.fn.scrollTo=function(f,e,d){if(typeof e=="object"){d=e;e=0}if(typeof d=="function"){d={onAfter:d}}if(f=="max"){f=9000000000}d=c.extend({},a.defaults,d);e=e||d.speed||d.duration;d.queue=d.queue&&d.axis.length>1;if(d.queue){e/=2}d.offset=b(d.offset);d.over=b(d.over);return this._scrollable().each(function(){var l=this,j=c(l),k=f,i,g={},m=j.is("html,body");switch(typeof k){case"number":case"string":if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(k)){k=b(k);break}k=c(k,this);case"object":if(k.is||k.style){i=(k=c(k)).offset()}}c.each(d.axis.split(""),function(q,r){var s=r=="x"?"Left":"Top",u=s.toLowerCase(),p="scroll"+s,o=l[p],n=a.max(l,r);if(i){g[p]=i[u]+(m?0:o-j.offset()[u]);if(d.margin){g[p]-=parseInt(k.css("margin"+s))||0;g[p]-=parseInt(k.css("border"+s+"Width"))||0}g[p]+=d.offset[u]||0;if(d.over[u]){g[p]+=k[r=="x"?"width":"height"]()*d.over[u]}}else{var t=k[u];g[p]=t.slice&&t.slice(-1)=="%"?parseFloat(t)/100*n:t}if(/^\d+$/.test(g[p])){g[p]=g[p]<=0?0:Math.min(g[p],n)}if(!q&&d.queue){if(o!=g[p]){h(d.onAfterFirst)}delete g[p]}});h(d.onAfter);function h(n){j.animate(g,e,d.easing,n&&function(){n.call(this,f,d)})}}).end()};a.max=function(j,i){var h=i=="x"?"Width":"Height",e="scroll"+h;if(!c(j).is("html,body")){return j[e]-c(j)[h.toLowerCase()]()}var g="client"+h,f=j.ownerDocument.documentElement,d=j.ownerDocument.body;return Math.max(f[e],d[e])-Math.min(f[g],d[g])};function b(d){return typeof d=="object"?d:{top:d,left:d}}})(jQuery);/*!
+ PowerTip - v1.2.0 - 2013-04-03
+ http://stevenbenner.github.com/jquery-powertip/
+ Copyright (c) 2013 Steven Benner (http://stevenbenner.com/).
+ Released under MIT license.
+ https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt
+*/
+(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{a(jQuery)}}(function(k){var A=k(document),s=k(window),w=k("body");var n="displayController",e="hasActiveHover",d="forcedOpen",u="hasMouseMove",f="mouseOnToPopup",g="originalTitle",y="powertip",o="powertipjq",l="powertiptarget",E=180/Math.PI;var c={isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var p={none:0,top:1,bottom:2,left:4,right:8};k.fn.powerTip=function(F,N){if(!this.length){return this}if(k.type(F)==="string"&&k.powerTip[F]){return k.powerTip[F].call(this,this,N)}var O=k.extend({},k.fn.powerTip.defaults,F),G=new x(O);h();this.each(function M(){var R=k(this),Q=R.data(y),P=R.data(o),T=R.data(l),S;if(R.data(n)){k.powerTip.destroy(R)}S=R.attr("title");if(!Q&&!T&&!P&&S){R.data(y,S);R.data(g,S);R.removeAttr("title")}R.data(n,new t(R,O,G))});if(!O.manual){this.on({"mouseenter.powertip":function J(P){k.powerTip.show(this,P)},"mouseleave.powertip":function L(){k.powerTip.hide(this)},"focus.powertip":function K(){k.powerTip.show(this)},"blur.powertip":function H(){k.powerTip.hide(this,true)},"keydown.powertip":function I(P){if(P.keyCode===27){k.powerTip.hide(this,true)}}})}return this};k.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false};k.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};k.powerTip={show:function z(F,G){if(G){i(G);c.previousX=G.pageX;c.previousY=G.pageY;k(F).data(n).show()}else{k(F).first().data(n).show(true,true)}return F},reposition:function r(F){k(F).first().data(n).resetPosition();return F},hide:function D(G,F){if(G){k(G).first().data(n).hide(F)}else{if(c.activeHover){c.activeHover.data(n).hide(true)}}return G},destroy:function C(G){k(G).off(".powertip").each(function F(){var I=k(this),H=[g,n,e,d];if(I.data(g)){I.attr("title",I.data(g));H.push(y)}I.removeData(H)});return G}};k.powerTip.showTip=k.powerTip.show;k.powerTip.closeTip=k.powerTip.hide;function b(){var F=this;F.top="auto";F.left="auto";F.right="auto";F.bottom="auto";F.set=function(H,G){if(k.isNumeric(G)){F[H]=Math.round(G)}}}function t(K,N,F){var J=null;function L(P,Q){M();if(!K.data(e)){if(!P){c.tipOpenImminent=true;J=setTimeout(function O(){J=null;I()},N.intentPollInterval)}else{if(Q){K.data(d,true)}F.showTip(K)}}}function G(P){M();c.tipOpenImminent=false;if(K.data(e)){K.data(d,false);if(!P){c.delayInProgress=true;J=setTimeout(function O(){J=null;F.hideTip(K);c.delayInProgress=false},N.closeDelay)}else{F.hideTip(K)}}}function I(){var Q=Math.abs(c.previousX-c.currentX),O=Math.abs(c.previousY-c.currentY),P=Q+O;if(P<N.intentSensitivity){F.showTip(K)}else{c.previousX=c.currentX;c.previousY=c.currentY;L()}}function M(){J=clearTimeout(J);c.delayInProgress=false}function H(){F.resetPosition(K)}this.show=L;this.hide=G;this.cancel=M;this.resetPosition=H}function j(){function G(M,L,J,O,P){var K=L.split("-")[0],N=new b(),I;if(q(M)){I=H(M,K)}else{I=F(M,K)}switch(L){case"n":N.set("left",I.left-(J/2));N.set("bottom",c.windowHeight-I.top+P);break;case"e":N.set("left",I.left+P);N.set("top",I.top-(O/2));break;case"s":N.set("left",I.left-(J/2));N.set("top",I.top+P);break;case"w":N.set("top",I.top-(O/2));N.set("right",c.windowWidth-I.left+P);break;case"nw":N.set("bottom",c.windowHeight-I.top+P);N.set("right",c.windowWidth-I.left-20);break;case"nw-alt":N.set("left",I.left);N.set("bottom",c.windowHeight-I.top+P);break;case"ne":N.set("left",I.left-20);N.set("bottom",c.windowHeight-I.top+P);break;case"ne-alt":N.set("bottom",c.windowHeight-I.top+P);N.set("right",c.windowWidth-I.left);break;case"sw":N.set("top",I.top+P);N.set("right",c.windowWidth-I.left-20);break;case"sw-alt":N.set("left",I.left);N.set("top",I.top+P);break;case"se":N.set("left",I.left-20);N.set("top",I.top+P);break;case"se-alt":N.set("top",I.top+P);N.set("right",c.windowWidth-I.left);break}return N}function F(K,J){var O=K.offset(),N=K.outerWidth(),I=K.outerHeight(),M,L;switch(J){case"n":M=O.left+N/2;L=O.top;break;case"e":M=O.left+N;L=O.top+I/2;break;case"s":M=O.left+N/2;L=O.top+I;break;case"w":M=O.left;L=O.top+I/2;break;case"nw":M=O.left;L=O.top;break;case"ne":M=O.left+N;L=O.top;break;case"sw":M=O.left;L=O.top+I;break;case"se":M=O.left+N;L=O.top+I;break}return{top:L,left:M}}function H(O,K){var S=O.closest("svg")[0],N=O[0],W=S.createSVGPoint(),L=N.getBBox(),V=N.getScreenCTM(),M=L.width/2,Q=L.height/2,P=[],I=["nw","n","ne","e","se","s","sw","w"],U,X,R,T;function J(){P.push(W.matrixTransform(V))}W.x=L.x;W.y=L.y;J();W.x+=M;J();W.x+=M;J();W.y+=Q;J();W.y+=Q;J();W.x-=M;J();W.x-=M;J();W.y-=Q;J();if(P[0].y!==P[1].y||P[0].x!==P[7].x){X=Math.atan2(V.b,V.a)*E;R=Math.ceil(((X%360)-22.5)/45);if(R<1){R+=8}while(R--){I.push(I.shift())}}for(T=0;T<P.length;T++){if(I[T]===K){U=P[T];break}}return{top:U.y+c.scrollTop,left:U.x+c.scrollLeft}}this.compute=G}function x(Q){var P=new j(),O=k("#"+Q.popupId);if(O.length===0){O=k("<div/>",{id:Q.popupId});if(w.length===0){w=k("body")}w.append(O)}if(Q.followMouse){if(!O.data(u)){A.on("mousemove",M);s.on("scroll",M);O.data(u,true)}}if(Q.mouseOnToPopup){O.on({mouseenter:function L(){if(O.data(f)){if(c.activeHover){c.activeHover.data(n).cancel()}}},mouseleave:function N(){if(c.activeHover){c.activeHover.data(n).hide()}}})}function I(S){S.data(e,true);O.queue(function R(T){H(S);T()})}function H(S){var U;if(!S.data(e)){return}if(c.isTipOpen){if(!c.isClosing){K(c.activeHover)}O.delay(100).queue(function R(V){H(S);V()});return}S.trigger("powerTipPreRender");U=B(S);if(U){O.empty().append(U)}else{return}S.trigger("powerTipRender");c.activeHover=S;c.isTipOpen=true;O.data(f,Q.mouseOnToPopup);if(!Q.followMouse){G(S);c.isFixedTipOpen=true}else{M()}O.fadeIn(Q.fadeInTime,function T(){if(!c.desyncTimeout){c.desyncTimeout=setInterval(J,500)}S.trigger("powerTipOpen")})}function K(R){c.isClosing=true;c.activeHover=null;c.isTipOpen=false;c.desyncTimeout=clearInterval(c.desyncTimeout);R.data(e,false);R.data(d,false);O.fadeOut(Q.fadeOutTime,function S(){var T=new b();c.isClosing=false;c.isFixedTipOpen=false;O.removeClass();T.set("top",c.currentY+Q.offset);T.set("left",c.currentX+Q.offset);O.css(T);R.trigger("powerTipClose")})}function M(){if(!c.isFixedTipOpen&&(c.isTipOpen||(c.tipOpenImminent&&O.data(u)))){var R=O.outerWidth(),V=O.outerHeight(),U=new b(),S,T;U.set("top",c.currentY+Q.offset);U.set("left",c.currentX+Q.offset);S=m(U,R,V);if(S!==p.none){T=a(S);if(T===1){if(S===p.right){U.set("left",c.windowWidth-R)}else{if(S===p.bottom){U.set("top",c.scrollTop+c.windowHeight-V)}}}else{U.set("left",c.currentX-R-Q.offset);U.set("top",c.currentY-V-Q.offset)}}O.css(U)}}function G(S){var R,T;if(Q.smartPlacement){R=k.fn.powerTip.smartPlacementLists[Q.placement];k.each(R,function(U,W){var V=m(F(S,W),O.outerWidth(),O.outerHeight());T=W;if(V===p.none){return false}})}else{F(S,Q.placement);T=Q.placement}O.addClass(T)}function F(U,T){var R=0,S,W,V=new b();V.set("top",0);V.set("left",0);O.css(V);do{S=O.outerWidth();W=O.outerHeight();V=P.compute(U,T,S,W,Q.offset);O.css(V)}while(++R<=5&&(S!==O.outerWidth()||W!==O.outerHeight()));return V}function J(){var R=false;if(c.isTipOpen&&!c.isClosing&&!c.delayInProgress){if(c.activeHover.data(e)===false||c.activeHover.is(":disabled")){R=true}else{if(!v(c.activeHover)&&!c.activeHover.is(":focus")&&!c.activeHover.data(d)){if(O.data(f)){if(!v(O)){R=true}}else{R=true}}}if(R){K(c.activeHover)}}}this.showTip=I;this.hideTip=K;this.resetPosition=G}function q(F){return window.SVGElement&&F[0] instanceof SVGElement}function h(){if(!c.mouseTrackingActive){c.mouseTrackingActive=true;k(function H(){c.scrollLeft=s.scrollLeft();c.scrollTop=s.scrollTop();c.windowWidth=s.width();c.windowHeight=s.height()});A.on("mousemove",i);s.on({resize:function G(){c.windowWidth=s.width();c.windowHeight=s.height()},scroll:function F(){var I=s.scrollLeft(),J=s.scrollTop();if(I!==c.scrollLeft){c.currentX+=I-c.scrollLeft;c.scrollLeft=I}if(J!==c.scrollTop){c.currentY+=J-c.scrollTop;c.scrollTop=J}}})}}function i(F){c.currentX=F.pageX;c.currentY=F.pageY}function v(F){var H=F.offset(),J=F[0].getBoundingClientRect(),I=J.right-J.left,G=J.bottom-J.top;return c.currentX>=H.left&&c.currentX<=H.left+I&&c.currentY>=H.top&&c.currentY<=H.top+G}function B(I){var G=I.data(y),F=I.data(o),K=I.data(l),H,J;if(G){if(k.isFunction(G)){G=G.call(I[0])}J=G}else{if(F){if(k.isFunction(F)){F=F.call(I[0])}if(F.length>0){J=F.clone(true,true)}}else{if(K){H=k("#"+K);if(H.length>0){J=H.html()}}}}return J}function m(M,L,K){var G=c.scrollTop,J=c.scrollLeft,I=G+c.windowHeight,F=J+c.windowWidth,H=p.none;if(M.top<G||Math.abs(M.bottom-c.windowHeight)-K<G){H|=p.top}if(M.top+K>I||Math.abs(M.bottom-c.windowHeight)>I){H|=p.bottom}if(M.left<J||M.right+L>F){H|=p.left}if(M.left+L>F||M.right<J){H|=p.right}return H}function a(G){var F=0;while(G){G&=G-1;F++}return F}}));/*!
+ * jQuery UI Touch Punch 0.2.3
+ *
+ * Copyright 2011–2014, Dave Furfero
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ * Depends:
+ * jquery.ui.widget.js
+ * jquery.ui.mouse.js
+ */
+(function(b){b.support.touch="ontouchend" in document;if(!b.support.touch){return}var d=b.ui.mouse.prototype,f=d._mouseInit,c=d._mouseDestroy,a;function e(h,i){if(h.originalEvent.touches.length>1){return}h.preventDefault();var j=h.originalEvent.changedTouches[0],g=document.createEvent("MouseEvents");g.initMouseEvent(i,true,true,window,1,j.screenX,j.screenY,j.clientX,j.clientY,false,false,false,false,0,null);h.target.dispatchEvent(g)}d._touchStart=function(h){var g=this;if(a||!g._mouseCapture(h.originalEvent.changedTouches[0])){return}a=true;g._touchMoved=false;e(h,"mouseover");e(h,"mousemove");e(h,"mousedown")};d._touchMove=function(g){if(!a){return}this._touchMoved=true;e(g,"mousemove")};d._touchEnd=function(g){if(!a){return}e(g,"mouseup");e(g,"mouseout");if(!this._touchMoved){e(g,"click")}a=false};d._mouseInit=function(){var g=this;g.element.bind({touchstart:b.proxy(g,"_touchStart"),touchmove:b.proxy(g,"_touchMove"),touchend:b.proxy(g,"_touchEnd")});f.call(g)};d._mouseDestroy=function(){var g=this;g.element.unbind({touchstart:b.proxy(g,"_touchStart"),touchmove:b.proxy(g,"_touchMove"),touchend:b.proxy(g,"_touchEnd")});c.call(g)}})(jQuery);/*!
+ * SmartMenus jQuery Plugin - v1.0.0 - January 27, 2016
+ * http://www.smartmenus.org/
+ *
+ * Copyright Vasil Dinkov, Vadikom Web Ltd.
+ * http://vadikom.com
+ *
+ * Licensed MIT
+ */
+(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{if(typeof module==="object"&&typeof module.exports==="object"){module.exports=a(require("jquery"))}else{a(jQuery)}}}(function(a){var b=[],e=!!window.createPopup,f=false,d="ontouchstart" in window,h=false,g=window.requestAnimationFrame||function(l){return setTimeout(l,1000/60)},c=window.cancelAnimationFrame||function(l){clearTimeout(l)};function k(m){var n=".smartmenus_mouse";if(!h&&!m){var o=true,l=null;a(document).bind(i([["mousemove",function(s){var t={x:s.pageX,y:s.pageY,timeStamp:new Date().getTime()};if(l){var q=Math.abs(l.x-t.x),p=Math.abs(l.y-t.y);if((q>0||p>0)&&q<=2&&p<=2&&t.timeStamp-l.timeStamp<=300){f=true;if(o){var r=a(s.target).closest("a");if(r.is("a")){a.each(b,function(){if(a.contains(this.$root[0],r[0])){this.itemEnter({currentTarget:r[0]});return false}})}o=false}}}l=t}],[d?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut",function(p){if(j(p.originalEvent)){f=false}}]],n));h=true}else{if(h&&m){a(document).unbind(n);h=false}}}function j(l){return !/^(4|mouse)$/.test(l.pointerType)}function i(l,n){if(!n){n=""}var m={};a.each(l,function(o,p){m[p[0].split(" ").join(n+" ")+n]=p[1]});return m}a.SmartMenus=function(m,l){this.$root=a(m);this.opts=l;this.rootId="";this.accessIdPrefix="";this.$subArrow=null;this.activatedItems=[];this.visibleSubMenus=[];this.showTimeout=0;this.hideTimeout=0;this.scrollTimeout=0;this.clickActivated=false;this.focusActivated=false;this.zIndexInc=0;this.idInc=0;this.$firstLink=null;this.$firstSub=null;this.disabled=false;this.$disableOverlay=null;this.$touchScrollingSub=null;this.cssTransforms3d="perspective" in m.style||"webkitPerspective" in m.style;this.wasCollapsible=false;this.init()};a.extend(a.SmartMenus,{hideAll:function(){a.each(b,function(){this.menuHideAll()})},destroy:function(){while(b.length){b[0].destroy()}k(true)},prototype:{init:function(n){var l=this;if(!n){b.push(this);this.rootId=(new Date().getTime()+Math.random()+"").replace(/\D/g,"");this.accessIdPrefix="sm-"+this.rootId+"-";if(this.$root.hasClass("sm-rtl")){this.opts.rightToLeftSubMenus=true}var r=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).bind(i([["mouseover focusin",a.proxy(this.rootOver,this)],["mouseout focusout",a.proxy(this.rootOut,this)],["keydown",a.proxy(this.rootKeyDown,this)]],r)).delegate("a",i([["mouseenter",a.proxy(this.itemEnter,this)],["mouseleave",a.proxy(this.itemLeave,this)],["mousedown",a.proxy(this.itemDown,this)],["focus",a.proxy(this.itemFocus,this)],["blur",a.proxy(this.itemBlur,this)],["click",a.proxy(this.itemClick,this)]],r));r+=this.rootId;if(this.opts.hideOnClick){a(document).bind(i([["touchstart",a.proxy(this.docTouchStart,this)],["touchmove",a.proxy(this.docTouchMove,this)],["touchend",a.proxy(this.docTouchEnd,this)],["click",a.proxy(this.docClick,this)]],r))}a(window).bind(i([["resize orientationchange",a.proxy(this.winResize,this)]],r));if(this.opts.subIndicators){this.$subArrow=a("<span/>").addClass("sub-arrow");if(this.opts.subIndicatorsText){this.$subArrow.html(this.opts.subIndicatorsText)}}k()}this.$firstSub=this.$root.find("ul").each(function(){l.menuInit(a(this))}).eq(0);this.$firstLink=this.$root.find("a").eq(0);if(this.opts.markCurrentItem){var p=/(index|default)\.[^#\?\/]*/i,m=/#.*/,q=window.location.href.replace(p,""),o=q.replace(m,"");this.$root.find("a").each(function(){var s=this.href.replace(p,""),t=a(this);if(s==q||s==o){t.addClass("current");if(l.opts.markCurrentTree){t.parentsUntil("[data-smartmenus-id]","ul").each(function(){a(this).dataSM("parent-a").addClass("current")})}}})}this.wasCollapsible=this.isCollapsible()},destroy:function(m){if(!m){var n=".smartmenus";this.$root.removeData("smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").unbind(n).undelegate(n);n+=this.rootId;a(document).unbind(n);a(window).unbind(n);if(this.opts.subIndicators){this.$subArrow=null}}this.menuHideAll();var l=this;this.$root.find("ul").each(function(){var o=a(this);if(o.dataSM("scroll-arrows")){o.dataSM("scroll-arrows").remove()}if(o.dataSM("shown-before")){if(l.opts.subMenusMinWidth||l.opts.subMenusMaxWidth){o.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap")}if(o.dataSM("scroll-arrows")){o.dataSM("scroll-arrows").remove()}o.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})}if((o.attr("id")||"").indexOf(l.accessIdPrefix)==0){o.removeAttr("id")}}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("ie-shim").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded");this.$root.find("a.has-submenu").each(function(){var o=a(this);if(o.attr("id").indexOf(l.accessIdPrefix)==0){o.removeAttr("id")}}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub");if(this.opts.subIndicators){this.$root.find("span.sub-arrow").remove()}if(this.opts.markCurrentItem){this.$root.find("a.current").removeClass("current")}if(!m){this.$root=null;this.$firstLink=null;this.$firstSub=null;if(this.$disableOverlay){this.$disableOverlay.remove();this.$disableOverlay=null}b.splice(a.inArray(this,b),1)}},disable:function(l){if(!this.disabled){this.menuHideAll();if(!l&&!this.opts.isPopup&&this.$root.is(":visible")){var m=this.$root.offset();this.$disableOverlay=a('<div class="sm-jquery-disable-overlay"/>').css({position:"absolute",top:m.top,left:m.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(true),opacity:0}).appendTo(document.body)}this.disabled=true}},docClick:function(l){if(this.$touchScrollingSub){this.$touchScrollingSub=null;return}if(this.visibleSubMenus.length&&!a.contains(this.$root[0],l.target)||a(l.target).is("a")){this.menuHideAll()}},docTouchEnd:function(m){if(!this.lastTouch){return}if(this.visibleSubMenus.length&&(this.lastTouch.x2===undefined||this.lastTouch.x1==this.lastTouch.x2)&&(this.lastTouch.y2===undefined||this.lastTouch.y1==this.lastTouch.y2)&&(!this.lastTouch.target||!a.contains(this.$root[0],this.lastTouch.target))){if(this.hideTimeout){clearTimeout(this.hideTimeout);this.hideTimeout=0}var l=this;this.hideTimeout=setTimeout(function(){l.menuHideAll()},350)}this.lastTouch=null},docTouchMove:function(m){if(!this.lastTouch){return}var l=m.originalEvent.touches[0];this.lastTouch.x2=l.pageX;this.lastTouch.y2=l.pageY},docTouchStart:function(m){var l=m.originalEvent.touches[0];this.lastTouch={x1:l.pageX,y1:l.pageY,target:l.target}},enable:function(){if(this.disabled){if(this.$disableOverlay){this.$disableOverlay.remove();this.$disableOverlay=null}this.disabled=false}},getClosestMenu:function(m){var l=a(m).closest("ul");while(l.dataSM("in-mega")){l=l.parent().closest("ul")}return l[0]||null},getHeight:function(l){return this.getOffset(l,true)},getOffset:function(n,l){var m;if(n.css("display")=="none"){m={position:n[0].style.position,visibility:n[0].style.visibility};n.css({position:"absolute",visibility:"hidden"}).show()}var o=n[0].getBoundingClientRect&&n[0].getBoundingClientRect(),p=o&&(l?o.height||o.bottom-o.top:o.width||o.right-o.left);if(!p&&p!==0){p=l?n[0].offsetHeight:n[0].offsetWidth}if(m){n.hide().css(m)}return p},getStartZIndex:function(l){var m=parseInt(this[l?"$root":"$firstSub"].css("z-index"));if(!l&&isNaN(m)){m=parseInt(this.$root.css("z-index"))}return !isNaN(m)?m:1},getTouchPoint:function(l){return l.touches&&l.touches[0]||l.changedTouches&&l.changedTouches[0]||l},getViewport:function(l){var m=l?"Height":"Width",o=document.documentElement["client"+m],n=window["inner"+m];if(n){o=Math.min(o,n)}return o},getViewportHeight:function(){return this.getViewport(true)},getViewportWidth:function(){return this.getViewport()},getWidth:function(l){return this.getOffset(l)},handleEvents:function(){return !this.disabled&&this.isCSSOn()},handleItemEvents:function(l){return this.handleEvents()&&!this.isLinkInMegaMenu(l)},isCollapsible:function(){return this.$firstSub.css("position")=="static"},isCSSOn:function(){return this.$firstLink.css("display")=="block"},isFixed:function(){var l=this.$root.css("position")=="fixed";if(!l){this.$root.parentsUntil("body").each(function(){if(a(this).css("position")=="fixed"){l=true;return false}})}return l},isLinkInMegaMenu:function(l){return a(this.getClosestMenu(l[0])).hasClass("mega-menu")},isTouchMode:function(){return !f||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(p,l){var n=p.closest("ul"),q=n.dataSM("level");if(q>1&&(!this.activatedItems[q-2]||this.activatedItems[q-2][0]!=n.dataSM("parent-a")[0])){var m=this;a(n.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(n).each(function(){m.itemActivate(a(this).dataSM("parent-a"))})}if(!this.isCollapsible()||l){this.menuHideSubMenus(!this.activatedItems[q-1]||this.activatedItems[q-1][0]!=p[0]?q-1:q)}this.activatedItems[q-1]=p;if(this.$root.triggerHandler("activate.smapi",p[0])===false){return}var o=p.dataSM("sub");if(o&&(this.isTouchMode()||(!this.opts.showOnClick||this.clickActivated))){this.menuShow(o)}},itemBlur:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}this.$root.triggerHandler("blur.smapi",l[0])},itemClick:function(o){var n=a(o.currentTarget);if(!this.handleItemEvents(n)){return}if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==n.closest("ul")[0]){this.$touchScrollingSub=null;o.stopPropagation();return false}if(this.$root.triggerHandler("click.smapi",n[0])===false){return false}var p=a(o.target).is("span.sub-arrow"),m=n.dataSM("sub"),l=m?m.dataSM("level")==2:false;if(m&&!m.is(":visible")){if(this.opts.showOnClick&&l){this.clickActivated=true}this.itemActivate(n);if(m.is(":visible")){this.focusActivated=true;return false}}else{if(this.isCollapsible()&&p){this.itemActivate(n);this.menuHide(m);return false}}if(this.opts.showOnClick&&l||n.hasClass("disabled")||this.$root.triggerHandler("select.smapi",n[0])===false){return false}},itemDown:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}l.dataSM("mousedown",true)},itemEnter:function(n){var m=a(n.currentTarget);if(!this.handleItemEvents(m)){return}if(!this.isTouchMode()){if(this.showTimeout){clearTimeout(this.showTimeout);this.showTimeout=0}var l=this;this.showTimeout=setTimeout(function(){l.itemActivate(m)},this.opts.showOnClick&&m.closest("ul").dataSM("level")==1?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",m[0])},itemFocus:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}if(this.focusActivated&&(!this.isTouchMode()||!l.dataSM("mousedown"))&&(!this.activatedItems.length||this.activatedItems[this.activatedItems.length-1][0]!=l[0])){this.itemActivate(l,true)}this.$root.triggerHandler("focus.smapi",l[0])},itemLeave:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}if(!this.isTouchMode()){l[0].blur();if(this.showTimeout){clearTimeout(this.showTimeout);this.showTimeout=0}}l.removeDataSM("mousedown");this.$root.triggerHandler("mouseleave.smapi",l[0])},menuHide:function(m){if(this.$root.triggerHandler("beforehide.smapi",m[0])===false){return}m.stop(true,true);if(m.css("display")!="none"){var l=function(){m.css("z-index","")};if(this.isCollapsible()){if(this.opts.collapsibleHideFunction){this.opts.collapsibleHideFunction.call(this,m,l)}else{m.hide(this.opts.collapsibleHideDuration,l)}}else{if(this.opts.hideFunction){this.opts.hideFunction.call(this,m,l)}else{m.hide(this.opts.hideDuration,l)}}if(m.dataSM("ie-shim")){m.dataSM("ie-shim").remove().css({"-webkit-transform":"",transform:""})}if(m.dataSM("scroll")){this.menuScrollStop(m);m.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).unbind(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()}m.dataSM("parent-a").removeClass("highlighted").attr("aria-expanded","false");m.attr({"aria-expanded":"false","aria-hidden":"true"});var n=m.dataSM("level");this.activatedItems.splice(n-1,1);this.visibleSubMenus.splice(a.inArray(m,this.visibleSubMenus),1);this.$root.triggerHandler("hide.smapi",m[0])}},menuHideAll:function(){if(this.showTimeout){clearTimeout(this.showTimeout);this.showTimeout=0}var m=this.opts.isPopup?1:0;for(var l=this.visibleSubMenus.length-1;l>=m;l--){this.menuHide(this.visibleSubMenus[l])}if(this.opts.isPopup){this.$root.stop(true,true);if(this.$root.is(":visible")){if(this.opts.hideFunction){this.opts.hideFunction.call(this,this.$root)}else{this.$root.hide(this.opts.hideDuration)}if(this.$root.dataSM("ie-shim")){this.$root.dataSM("ie-shim").remove()}}}this.activatedItems=[];this.visibleSubMenus=[];this.clickActivated=false;this.focusActivated=false;this.zIndexInc=0;this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(n){for(var l=this.activatedItems.length-1;l>=n;l--){var m=this.activatedItems[l].dataSM("sub");if(m){this.menuHide(m)}}},menuIframeShim:function(l){if(e&&this.opts.overlapControlsInIE&&!l.dataSM("ie-shim")){l.dataSM("ie-shim",a("<iframe/>").attr({src:"javascript:0",tabindex:-9}).css({position:"absolute",top:"auto",left:"0",opacity:0,border:"0"}))}},menuInit:function(l){if(!l.dataSM("in-mega")){if(l.hasClass("mega-menu")){l.find("ul").dataSM("in-mega",true)}var q=2,m=l[0];while((m=m.parentNode.parentNode)!=this.$root[0]){q++}var n=l.prevAll("a").eq(-1);if(!n.length){n=l.prevAll().find("a").eq(-1)}n.addClass("has-submenu").dataSM("sub",l);l.dataSM("parent-a",n).dataSM("level",q).parent().dataSM("sub",l);var o=n.attr("id")||this.accessIdPrefix+(++this.idInc),p=l.attr("id")||this.accessIdPrefix+(++this.idInc);n.attr({id:o,"aria-haspopup":"true","aria-controls":p,"aria-expanded":"false"});l.attr({id:p,role:"group","aria-hidden":"true","aria-labelledby":o,"aria-expanded":"false"});if(this.opts.subIndicators){n[this.opts.subIndicatorsPos](this.$subArrow.clone())}}},menuPosition:function(K){var r=K.dataSM("parent-a"),D=r.closest("li"),E=D.parent(),l=K.dataSM("level"),t=this.getWidth(K),J=this.getHeight(K),u=r.offset(),o=u.left,m=u.top,q=this.getWidth(r),F=this.getHeight(r),H=a(window),v=H.scrollLeft(),s=H.scrollTop(),z=this.getViewportWidth(),L=this.getViewportHeight(),w=E.parent().is("[data-sm-horizontal-sub]")||l==2&&!E.hasClass("sm-vertical"),B=this.opts.rightToLeftSubMenus&&!D.is("[data-sm-reverse]")||!this.opts.rightToLeftSubMenus&&D.is("[data-sm-reverse]"),p=l==2?this.opts.mainMenuSubOffsetX:this.opts.subMenusSubOffsetX,n=l==2?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY,C,A;if(w){C=B?q-t-p:p;A=this.opts.bottomToTopSubMenus?-J-n:F+n}else{C=B?p-t:q-p;A=this.opts.bottomToTopSubMenus?F-n-J:n}if(this.opts.keepInViewport){var N=o+C,M=m+A;if(B&&N<v){C=w?v-N+C:q-p}else{if(!B&&N+t>v+z){C=w?v+z-t-N+C:p-t}}if(!w){if(J<L&&M+J>s+L){A+=s+L-J-M}else{if(J>=L||M<s){A+=s-M}}}if(w&&(M+J>s+L+0.49||M<s)||!w&&J>L+0.49){var G=this;if(!K.dataSM("scroll-arrows")){K.dataSM("scroll-arrows",a([a('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0],a('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]]).bind({mouseenter:function(){K.dataSM("scroll").up=a(this).hasClass("scroll-up");G.menuScroll(K)},mouseleave:function(x){G.menuScrollStop(K);G.menuScrollOut(K,x)},"mousewheel DOMMouseScroll":function(x){x.preventDefault()}}).insertAfter(K))}var I=".smartmenus_scroll";K.dataSM("scroll",{y:this.cssTransforms3d?0:A-F,step:1,itemH:F,subH:J,arrowDownH:this.getHeight(K.dataSM("scroll-arrows").eq(1))}).bind(i([["mouseover",function(x){G.menuScrollOver(K,x)}],["mouseout",function(x){G.menuScrollOut(K,x)}],["mousewheel DOMMouseScroll",function(x){G.menuScrollMousewheel(K,x)}]],I)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:C+(parseInt(K.css("border-left-width"))||0),width:t-(parseInt(K.css("border-left-width"))||0)-(parseInt(K.css("border-right-width"))||0),zIndex:K.css("z-index")}).eq(w&&this.opts.bottomToTopSubMenus?0:1).show();if(this.isFixed()){K.css({"touch-action":"none","-ms-touch-action":"none"}).bind(i([[d?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp",function(x){G.menuScrollTouch(K,x)}]],I))}}}K.css({top:"auto",left:"0",marginLeft:C,marginTop:A-F});this.menuIframeShim(K);if(K.dataSM("ie-shim")){K.dataSM("ie-shim").css({zIndex:K.css("z-index"),width:t,height:J,marginLeft:C,marginTop:A-F})}},menuScroll:function(r,m,n){var p=r.dataSM("scroll"),q=r.dataSM("scroll-arrows"),o=p.up?p.upEnd:p.downEnd,s;if(!m&&p.momentum){p.momentum*=0.92;s=p.momentum;if(s<0.5){this.menuScrollStop(r);return}}else{s=n||(m||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(p.step))}var l=r.dataSM("level");if(this.activatedItems[l-1]&&this.activatedItems[l-1].dataSM("sub")&&this.activatedItems[l-1].dataSM("sub").is(":visible")){this.menuHideSubMenus(l-1)}p.y=p.up&&o<=p.y||!p.up&&o>=p.y?p.y:(Math.abs(o-p.y)>s?p.y+(p.up?s:-s):o);r.add(r.dataSM("ie-shim")).css(this.cssTransforms3d?{"-webkit-transform":"translate3d(0, "+p.y+"px, 0)",transform:"translate3d(0, "+p.y+"px, 0)"}:{marginTop:p.y});if(f&&(p.up&&p.y>p.downEnd||!p.up&&p.y<p.upEnd)){q.eq(p.up?1:0).show()}if(p.y==o){if(f){q.eq(p.up?0:1).hide()}this.menuScrollStop(r)}else{if(!m){if(this.opts.scrollAccelerate&&p.step<this.opts.scrollStep){p.step+=0.2}var t=this;this.scrollTimeout=g(function(){t.menuScroll(r)})}}},menuScrollMousewheel:function(m,n){if(this.getClosestMenu(n.target)==m[0]){n=n.originalEvent;var l=(n.wheelDelta||-n.detail)>0;if(m.dataSM("scroll-arrows").eq(l?0:1).is(":visible")){m.dataSM("scroll").up=l;this.menuScroll(m,true)}}n.preventDefault()},menuScrollOut:function(l,m){if(f){if(!/^scroll-(up|down)/.test((m.relatedTarget||"").className)&&(l[0]!=m.relatedTarget&&!a.contains(l[0],m.relatedTarget)||this.getClosestMenu(m.relatedTarget)!=l[0])){l.dataSM("scroll-arrows").css("visibility","hidden")}}},menuScrollOver:function(n,o){if(f){if(!/^scroll-(up|down)/.test(o.target.className)&&this.getClosestMenu(o.target)==n[0]){this.menuScrollRefreshData(n);var m=n.dataSM("scroll"),l=a(window).scrollTop()-n.dataSM("parent-a").offset().top-m.itemH;n.dataSM("scroll-arrows").eq(0).css("margin-top",l).end().eq(1).css("margin-top",l+this.getViewportHeight()-m.arrowDownH).end().css("visibility","visible")}}},menuScrollRefreshData:function(n){var m=n.dataSM("scroll"),l=a(window).scrollTop()-n.dataSM("parent-a").offset().top-m.itemH;if(this.cssTransforms3d){l=-(parseFloat(n.css("margin-top"))-l)}a.extend(m,{upEnd:l,downEnd:l+this.getViewportHeight()-m.subH})},menuScrollStop:function(l){if(this.scrollTimeout){c(this.scrollTimeout);this.scrollTimeout=0;l.dataSM("scroll").step=1;return true}},menuScrollTouch:function(p,q){q=q.originalEvent;if(j(q)){var m=this.getTouchPoint(q);if(this.getClosestMenu(m.target)==p[0]){var o=p.dataSM("scroll");if(/(start|down)$/i.test(q.type)){if(this.menuScrollStop(p)){q.preventDefault();this.$touchScrollingSub=p}else{this.$touchScrollingSub=null}this.menuScrollRefreshData(p);a.extend(o,{touchStartY:m.pageY,touchStartTime:q.timeStamp})}else{if(/move$/i.test(q.type)){var n=o.touchY!==undefined?o.touchY:o.touchStartY;if(n!==undefined&&n!=m.pageY){this.$touchScrollingSub=p;var l=n<m.pageY;if(o.up!==undefined&&o.up!=l){a.extend(o,{touchStartY:m.pageY,touchStartTime:q.timeStamp})}a.extend(o,{up:l,touchY:m.pageY});this.menuScroll(p,true,Math.abs(m.pageY-n))}q.preventDefault()}else{if(o.touchY!==undefined){if(o.momentum=Math.pow(Math.abs(m.pageY-o.touchStartY)/(q.timeStamp-o.touchStartTime),2)*15){this.menuScrollStop(p);this.menuScroll(p);q.preventDefault()}delete o.touchY}}}}}},menuShow:function(n){if(!n.dataSM("beforefirstshowfired")){n.dataSM("beforefirstshowfired",true);if(this.$root.triggerHandler("beforefirstshow.smapi",n[0])===false){return}}if(this.$root.triggerHandler("beforeshow.smapi",n[0])===false){return}n.dataSM("shown-before",true).stop(true,true);if(!n.is(":visible")){var m=n.dataSM("parent-a");if(this.opts.keepHighlighted||this.isCollapsible()){m.addClass("highlighted")}if(this.isCollapsible()){n.removeClass("sm-nowrap").css({zIndex:"",width:"auto",minWidth:"",maxWidth:"",top:"",left:"",marginLeft:"",marginTop:""})}else{n.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1);if(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth){n.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap");if(this.opts.subMenusMinWidth){n.css("min-width",this.opts.subMenusMinWidth)}if(this.opts.subMenusMaxWidth){var o=this.getWidth(n);n.css("max-width",this.opts.subMenusMaxWidth);if(o>this.getWidth(n)){n.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}}}this.menuPosition(n);if(n.dataSM("ie-shim")){n.dataSM("ie-shim").insertBefore(n)}}var l=function(){n.css("overflow","")};if(this.isCollapsible()){if(this.opts.collapsibleShowFunction){this.opts.collapsibleShowFunction.call(this,n,l)}else{n.show(this.opts.collapsibleShowDuration,l)}}else{if(this.opts.showFunction){this.opts.showFunction.call(this,n,l)}else{n.show(this.opts.showDuration,l)}}m.attr("aria-expanded","true");n.attr({"aria-expanded":"true","aria-hidden":"false"});this.visibleSubMenus.push(n);this.$root.triggerHandler("show.smapi",n[0])}},popupHide:function(l){if(this.hideTimeout){clearTimeout(this.hideTimeout);this.hideTimeout=0}var m=this;this.hideTimeout=setTimeout(function(){m.menuHideAll()},l?1:this.opts.hideTimeout)},popupShow:function(o,n){if(!this.opts.isPopup){alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');return}if(this.hideTimeout){clearTimeout(this.hideTimeout);this.hideTimeout=0}this.$root.dataSM("shown-before",true).stop(true,true);if(!this.$root.is(":visible")){this.$root.css({left:o,top:n});this.menuIframeShim(this.$root);if(this.$root.dataSM("ie-shim")){this.$root.dataSM("ie-shim").css({zIndex:this.$root.css("z-index"),width:this.getWidth(this.$root),height:this.getHeight(this.$root),left:o,top:n}).insertBefore(this.$root)}var m=this,l=function(){m.$root.css("overflow","")};if(this.opts.showFunction){this.opts.showFunction.call(this,this.$root,l)}else{this.$root.show(this.opts.showDuration,l)}this.visibleSubMenus[0]=this.$root}},refresh:function(){this.destroy(true);this.init(true)},rootKeyDown:function(o){if(!this.handleEvents()){return}switch(o.keyCode){case 27:var m=this.activatedItems[0];if(m){this.menuHideAll();m[0].focus();var n=m.dataSM("sub");if(n){this.menuHide(n)}}break;case 32:var l=a(o.target);if(l.is("a")&&this.handleItemEvents(l)){var n=l.dataSM("sub");if(n&&!n.is(":visible")){this.itemClick({currentTarget:o.target});o.preventDefault()}}break}},rootOut:function(m){if(!this.handleEvents()||this.isTouchMode()||m.target==this.$root[0]){return}if(this.hideTimeout){clearTimeout(this.hideTimeout);this.hideTimeout=0}if(!this.opts.showOnClick||!this.opts.hideOnClick){var l=this;this.hideTimeout=setTimeout(function(){l.menuHideAll()},this.opts.hideTimeout)}},rootOver:function(l){if(!this.handleEvents()||this.isTouchMode()||l.target==this.$root[0]){return}if(this.hideTimeout){clearTimeout(this.hideTimeout);this.hideTimeout=0}},winResize:function(m){if(!this.handleEvents()){if(this.$disableOverlay){var n=this.$root.offset();this.$disableOverlay.css({top:n.top,left:n.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}return}if(!("onorientationchange" in window)||m.type=="orientationchange"){var l=this.isCollapsible();if(!(this.wasCollapsible&&l)){if(this.activatedItems.length){this.activatedItems[this.activatedItems.length-1][0].blur()}this.menuHideAll()}this.wasCollapsible=l}}}});a.fn.dataSM=function(l,m){if(m){return this.data(l+"_smartmenus",m)}return this.data(l+"_smartmenus")};a.fn.removeDataSM=function(l){return this.removeData(l+"_smartmenus")};a.fn.smartmenus=function(m){if(typeof m=="string"){var l=arguments,o=m;Array.prototype.shift.call(l);return this.each(function(){var p=a(this).data("smartmenus");if(p&&p[o]){p[o].apply(p,l)}})}var n=a.extend({},a.fn.smartmenus.defaults,m);return this.each(function(){new a.SmartMenus(this,n)})};a.fn.smartmenus.defaults={isPopup:false,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:true,subIndicatorsPos:"prepend",subIndicatorsText:"+",scrollStep:30,scrollAccelerate:true,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(m,l){m.fadeOut(200,l)},collapsibleShowDuration:0,collapsibleShowFunction:function(m,l){m.slideDown(200,l)},collapsibleHideDuration:0,collapsibleHideFunction:function(m,l){m.slideUp(200,l)},showOnClick:false,hideOnClick:true,noMouseOver:false,keepInViewport:true,keepHighlighted:true,markCurrentItem:false,markCurrentTree:true,rightToLeftSubMenus:false,bottomToTopSubMenus:false,overlapControlsInIE:true};return a})); \ No newline at end of file
diff --git a/docs/menu.js b/docs/menu.js
new file mode 100644
index 0000000..97db4c2
--- /dev/null
+++ b/docs/menu.js
@@ -0,0 +1,26 @@
+function initMenu(relPath,searchEnabled,serverSide,searchPage,search) {
+ function makeTree(data,relPath) {
+ var result='';
+ if ('children' in data) {
+ result+='<ul>';
+ for (var i in data.children) {
+ result+='<li><a href="'+relPath+data.children[i].url+'">'+
+ data.children[i].text+'</a>'+
+ makeTree(data.children[i],relPath)+'</li>';
+ }
+ result+='</ul>';
+ }
+ return result;
+ }
+
+ $('#main-nav').append(makeTree(menudata,relPath));
+ $('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu');
+ if (searchEnabled) {
+ if (serverSide) {
+ $('#main-menu').append('<li style="float:right"><div id="MSearchBox" class="MSearchBoxInactive"><div class="left"><form id="FSearchBox" action="'+searchPage+'" method="get"><img id="MSearchSelect" src="'+relPath+'search/mag.png" alt=""/><input type="text" id="MSearchField" name="query" value="'+search+'" size="20" accesskey="S" onfocus="searchBox.OnSearchFieldFocus(true)" onblur="searchBox.OnSearchFieldFocus(false)"></form></div><div class="right"></div></div></li>');
+ } else {
+ $('#main-menu').append('<li style="float:right"><div id="MSearchBox" class="MSearchBoxInactive"><span class="left"><img id="MSearchSelect" src="'+relPath+'search/mag_sel.png" onmouseover="return searchBox.OnSearchSelectShow()" onmouseout="return searchBox.OnSearchSelectHide()" alt=""/><input type="text" id="MSearchField" value="'+search+'" accesskey="S" onfocus="searchBox.OnSearchFieldFocus(true)" onblur="searchBox.OnSearchFieldFocus(false)" onkeyup="searchBox.OnSearchFieldChange(event)"/></span><span class="right"><a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="'+relPath+'search/close.png" alt=""/></a></span></div></li>');
+ }
+ }
+ $('#main-menu').smartmenus();
+}
diff --git a/docs/menudata.js b/docs/menudata.js
new file mode 100644
index 0000000..4398a4d
--- /dev/null
+++ b/docs/menudata.js
@@ -0,0 +1,19 @@
+var menudata={children:[
+{text:"Main Page",url:"index.html"},
+{text:"Related Pages",url:"pages.html"},
+{text:"Classes",url:"annotated.html",children:[
+{text:"Class List",url:"annotated.html"},
+{text:"Class Index",url:"classes.html"},
+{text:"Class Members",url:"functions.html",children:[
+{text:"All",url:"functions.html"},
+{text:"Variables",url:"functions_vars.html"}]}]},
+{text:"Files",url:"files.html",children:[
+{text:"File List",url:"files.html"},
+{text:"File Members",url:"globals.html",children:[
+{text:"All",url:"globals.html",children:[
+{text:"p",url:"globals.html#index_p"}]},
+{text:"Functions",url:"globals_func.html",children:[
+{text:"p",url:"globals_func.html#index_p"}]},
+{text:"Variables",url:"globals_vars.html"},
+{text:"Typedefs",url:"globals_type.html"},
+{text:"Macros",url:"globals_defs.html"}]}]}]}
diff --git a/docs/nav_f.png b/docs/nav_f.png
new file mode 100644
index 0000000..72a58a5
--- /dev/null
+++ b/docs/nav_f.png
Binary files differ
diff --git a/docs/nav_g.png b/docs/nav_g.png
new file mode 100644
index 0000000..2093a23
--- /dev/null
+++ b/docs/nav_g.png
Binary files differ
diff --git a/docs/nav_h.png b/docs/nav_h.png
new file mode 100644
index 0000000..33389b1
--- /dev/null
+++ b/docs/nav_h.png
Binary files differ
diff --git a/docs/open.png b/docs/open.png
new file mode 100644
index 0000000..30f75c7
--- /dev/null
+++ b/docs/open.png
Binary files differ
diff --git a/docs/pages.html b/docs/pages.html
new file mode 100644
index 0000000..364ac95
--- /dev/null
+++ b/docs/pages.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: Related Pages</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">Related Pages</div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here is a list of all related documentation pages:</div><div class="directory">
+<table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="todo.html" target="_self">Todo List</a></td><td class="desc"></td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom_8h.html b/docs/prom_8h.html
new file mode 100644
index 0000000..9400ab3
--- /dev/null
+++ b/docs/prom_8h.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Include <a class="el" href="prom_8h.html" title="Include prom.h to include the entire public API. ">prom.h</a> to include the entire public API.
+<a href="#details">More...</a></p>
+<div class="textblock"><code>#include &quot;<a class="el" href="prom__alloc_8h_source.html">prom_alloc.h</a>&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__collector_8h_source.html">prom_collector.h</a>&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__collector__registry_8h_source.html">prom_collector_registry.h</a>&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__counter_8h_source.html">prom_counter.h</a>&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__gauge_8h_source.html">prom_gauge.h</a>&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__histogram_8h_source.html">prom_histogram.h</a>&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__histogram__buckets_8h_source.html">prom_histogram_buckets.h</a>&quot;</code><br />
+<code>#include &quot;prom_linked_list.h&quot;</code><br />
+<code>#include &quot;prom_map.h&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__metric_8h_source.html">prom_metric.h</a>&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__metric__sample_8h_source.html">prom_metric_sample.h</a>&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__metric__sample__histogram_8h_source.html">prom_metric_sample_histogram.h</a>&quot;</code><br />
+</div><div class="textblock"><div class="dynheader">
+Include dependency graph for prom.h:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom_8h__incl.png" border="0" usemap="#prom_2include_2prom_8h" alt=""/></div>
+<map name="prom_2include_2prom_8h" id="prom_2include_2prom_8h">
+<area shape="rect" id="node2" href="prom__alloc_8h.html" title="memory management " alt="" coords="571,80,678,107"/>
+<area shape="rect" id="node5" href="prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="922,155,1052,181"/>
+<area shape="rect" id="node6" href="prom__map_8h_source.html" title="prom_map.h" alt="" coords="979,229,1083,256"/>
+<area shape="rect" id="node7" href="prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="498,229,615,256"/>
+<area shape="rect" id="node8" href="prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="310,311,482,338"/>
+<area shape="rect" id="node9" href="prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="636,304,796,345"/>
+<area shape="rect" id="node10" href="prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="840,80,1027,107"/>
+<area shape="rect" id="node11" href="prom__counter_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#counter " alt="" coords="256,80,379,107"/>
+<area shape="rect" id="node12" href="prom__gauge_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#gauge " alt="" coords="702,80,816,107"/>
+<area shape="rect" id="node13" href="prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="91,80,232,107"/>
+<area shape="rect" id="node14" href="prom__histogram__buckets_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="52,155,250,181"/>
+<area shape="rect" id="node15" href="prom__linked__list_8h_source.html" title="prom_linked_list.h" alt="" coords="404,80,546,107"/>
+</map>
+</div>
+</div>
+<p><a href="prom_8h_source.html">Go to the source code of this file.</a></p>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Include <a class="el" href="prom_8h.html" title="Include prom.h to include the entire public API. ">prom.h</a> to include the entire public API. </p>
+</div></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom_8h__dep__incl.dot b/docs/prom_8h__dep__incl.dot
new file mode 100644
index 0000000..e630766
--- /dev/null
+++ b/docs/prom_8h__dep__incl.dot
@@ -0,0 +1,8 @@
+digraph "prom/include/prom.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node14 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node14 -> Node15 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node15 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$promhttp_8h.html",tooltip="Provides a HTTP endpoint for metric exposition References: "];
+}
diff --git a/docs/prom_8h__dep__incl.map b/docs/prom_8h__dep__incl.map
new file mode 100644
index 0000000..2881d48
--- /dev/null
+++ b/docs/prom_8h__dep__incl.map
@@ -0,0 +1,3 @@
+<map id="prom/include/prom.h" name="prom/include/prom.h">
+<area shape="rect" id="node2" href="$promhttp_8h.html" title="Provides a HTTP endpoint for metric exposition References: " alt="" coords="5,80,215,107"/>
+</map>
diff --git a/docs/prom_8h__dep__incl.md5 b/docs/prom_8h__dep__incl.md5
new file mode 100644
index 0000000..4b9c5b7
--- /dev/null
+++ b/docs/prom_8h__dep__incl.md5
@@ -0,0 +1 @@
+f447616eb8315fa589f0311f234bb94a \ No newline at end of file
diff --git a/docs/prom_8h__dep__incl.png b/docs/prom_8h__dep__incl.png
new file mode 100644
index 0000000..8f25d62
--- /dev/null
+++ b/docs/prom_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom_8h__incl.dot b/docs/prom_8h__incl.dot
new file mode 100644
index 0000000..e23705b
--- /dev/null
+++ b/docs/prom_8h__incl.dot
@@ -0,0 +1,51 @@
+digraph "prom/include/prom.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node0 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node0 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 [label="prom_collector.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector_8h.html",tooltip="A Prometheus collector returns a collection of metrics. "];
+ Node1 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node2 [label="prom_errors.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__errors_8h.html",tooltip="Prometheus client errors. "];
+ Node1 -> Node3 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom_map.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__map_8h_source.html"];
+ Node1 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 [label="prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric_8h.html"];
+ Node4 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node5 [label="prom_metric_sample.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample_8h.html"];
+ Node5 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 -> Node6 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node6 [label="prom_metric_sample\l_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample__histogram_8h.html"];
+ Node6 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node7 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 [label="prom_collector_registry.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector__registry_8h.html",tooltip="The collector registry registers collectors for metric exposition. "];
+ Node7 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node8 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 [label="prom_counter.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__counter_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#counter "];
+ Node8 -> Node9 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node9 [label="stdlib.h",height=0.2,width=0.4,color="grey75", fillcolor="white", style="filled"];
+ Node8 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node10 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node10 [label="prom_gauge.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__gauge_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#gauge "];
+ Node10 -> Node9 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node10 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node10 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node11 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node11 [label="prom_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__histogram_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#histogram "];
+ Node11 -> Node9 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node11 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node11 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node11 -> Node12 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node12 [label="prom_histogram_buckets.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__histogram__buckets_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#histogram "];
+ Node0 -> Node12 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node13 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node13 [label="prom_linked_list.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__linked__list_8h_source.html"];
+ Node13 -> Node9 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node3 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom_8h__incl.map b/docs/prom_8h__incl.map
new file mode 100644
index 0000000..61509b9
--- /dev/null
+++ b/docs/prom_8h__incl.map
@@ -0,0 +1,14 @@
+<map id="prom/include/prom.h" name="prom/include/prom.h">
+<area shape="rect" id="node2" href="$prom__alloc_8h.html" title="memory management " alt="" coords="571,80,678,107"/>
+<area shape="rect" id="node5" href="$prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="922,155,1052,181"/>
+<area shape="rect" id="node6" href="$prom__map_8h_source.html" title="prom_map.h" alt="" coords="979,229,1083,256"/>
+<area shape="rect" id="node7" href="$prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="498,229,615,256"/>
+<area shape="rect" id="node8" href="$prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="310,311,482,338"/>
+<area shape="rect" id="node9" href="$prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="636,304,796,345"/>
+<area shape="rect" id="node10" href="$prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="840,80,1027,107"/>
+<area shape="rect" id="node11" href="$prom__counter_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#counter " alt="" coords="256,80,379,107"/>
+<area shape="rect" id="node12" href="$prom__gauge_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#gauge " alt="" coords="702,80,816,107"/>
+<area shape="rect" id="node13" href="$prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="91,80,232,107"/>
+<area shape="rect" id="node14" href="$prom__histogram__buckets_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="52,155,250,181"/>
+<area shape="rect" id="node15" href="$prom__linked__list_8h_source.html" title="prom_linked_list.h" alt="" coords="404,80,546,107"/>
+</map>
diff --git a/docs/prom_8h__incl.md5 b/docs/prom_8h__incl.md5
new file mode 100644
index 0000000..8863e60
--- /dev/null
+++ b/docs/prom_8h__incl.md5
@@ -0,0 +1 @@
+997d8c31651c98f51e83142372bbf5a3 \ No newline at end of file
diff --git a/docs/prom_8h__incl.png b/docs/prom_8h__incl.png
new file mode 100644
index 0000000..e260a66
--- /dev/null
+++ b/docs/prom_8h__incl.png
Binary files differ
diff --git a/docs/prom_8h_source.html b/docs/prom_8h_source.html
new file mode 100644
index 0000000..4d95e89
--- /dev/null
+++ b/docs/prom_8h_source.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00118"></a><span class="lineno"> 118</span>&#160;<span class="preprocessor">#ifndef PROM_INCLUDED</span></div><div class="line"><a name="l00119"></a><span class="lineno"> 119</span>&#160;<span class="preprocessor">#define PROM_INCLUDED</span></div><div class="line"><a name="l00120"></a><span class="lineno"> 120</span>&#160;</div><div class="line"><a name="l00121"></a><span class="lineno"> 121</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__alloc_8h.html">prom_alloc.h</a>&quot;</span></div><div class="line"><a name="l00122"></a><span class="lineno"> 122</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__collector_8h.html">prom_collector.h</a>&quot;</span></div><div class="line"><a name="l00123"></a><span class="lineno"> 123</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__collector__registry_8h.html">prom_collector_registry.h</a>&quot;</span></div><div class="line"><a name="l00124"></a><span class="lineno"> 124</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__counter_8h.html">prom_counter.h</a>&quot;</span></div><div class="line"><a name="l00125"></a><span class="lineno"> 125</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__gauge_8h.html">prom_gauge.h</a>&quot;</span></div><div class="line"><a name="l00126"></a><span class="lineno"> 126</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__histogram_8h.html">prom_histogram.h</a>&quot;</span></div><div class="line"><a name="l00127"></a><span class="lineno"> 127</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__histogram__buckets_8h.html">prom_histogram_buckets.h</a>&quot;</span></div><div class="line"><a name="l00128"></a><span class="lineno"> 128</span>&#160;<span class="preprocessor">#include &quot;prom_linked_list.h&quot;</span></div><div class="line"><a name="l00129"></a><span class="lineno"> 129</span>&#160;<span class="preprocessor">#include &quot;prom_map.h&quot;</span></div><div class="line"><a name="l00130"></a><span class="lineno"> 130</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__metric_8h.html">prom_metric.h</a>&quot;</span></div><div class="line"><a name="l00131"></a><span class="lineno"> 131</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__metric__sample_8h.html">prom_metric_sample.h</a>&quot;</span></div><div class="line"><a name="l00132"></a><span class="lineno"> 132</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__metric__sample__histogram_8h.html">prom_metric_sample_histogram.h</a>&quot;</span></div><div class="line"><a name="l00133"></a><span class="lineno"> 133</span>&#160;</div><div class="line"><a name="l00134"></a><span class="lineno"> 134</span>&#160;<span class="preprocessor">#endif // PROM_INCLUDED</span></div><div class="ttc" id="prom__gauge_8h_html"><div class="ttname"><a href="prom__gauge_8h.html">prom_gauge.h</a></div><div class="ttdoc">https://prometheus.io/docs/concepts/metric_types/#gauge </div></div>
+<div class="ttc" id="prom__collector_8h_html"><div class="ttname"><a href="prom__collector_8h.html">prom_collector.h</a></div><div class="ttdoc">A Prometheus collector returns a collection of metrics. </div></div>
+<div class="ttc" id="prom__histogram_8h_html"><div class="ttname"><a href="prom__histogram_8h.html">prom_histogram.h</a></div><div class="ttdoc">https://prometheus.io/docs/concepts/metric_types/#histogram </div></div>
+<div class="ttc" id="prom__metric__sample_8h_html"><div class="ttname"><a href="prom__metric__sample_8h.html">prom_metric_sample.h</a></div><div class="ttdoc">Functions for interfacting with metric samples directly. </div></div>
+<div class="ttc" id="prom__counter_8h_html"><div class="ttname"><a href="prom__counter_8h.html">prom_counter.h</a></div><div class="ttdoc">https://prometheus.io/docs/concepts/metric_types/#counter </div></div>
+<div class="ttc" id="prom__metric__sample__histogram_8h_html"><div class="ttname"><a href="prom__metric__sample__histogram_8h.html">prom_metric_sample_histogram.h</a></div><div class="ttdoc">Functions for interacting with histogram metric samples directly. </div></div>
+<div class="ttc" id="prom__alloc_8h_html"><div class="ttname"><a href="prom__alloc_8h.html">prom_alloc.h</a></div><div class="ttdoc">memory management </div></div>
+<div class="ttc" id="prom__metric_8h_html"><div class="ttname"><a href="prom__metric_8h.html">prom_metric.h</a></div><div class="ttdoc">Functions for retrieving metric samples from metrics given an ordered set of labels. </div></div>
+<div class="ttc" id="prom__collector__registry_8h_html"><div class="ttname"><a href="prom__collector__registry_8h.html">prom_collector_registry.h</a></div><div class="ttdoc">The collector registry registers collectors for metric exposition. </div></div>
+<div class="ttc" id="prom__histogram__buckets_8h_html"><div class="ttname"><a href="prom__histogram__buckets_8h.html">prom_histogram_buckets.h</a></div><div class="ttdoc">https://prometheus.io/docs/concepts/metric_types/#histogram </div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__alloc_8h.html b/docs/prom__alloc_8h.html
new file mode 100644
index 0000000..fb9c3e8
--- /dev/null
+++ b/docs/prom__alloc_8h.html
@@ -0,0 +1,190 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_alloc.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#define-members">Macros</a> </div>
+ <div class="headertitle">
+<div class="title">prom_alloc.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>memory management
+<a href="#details">More...</a></p>
+<div class="textblock"><code>#include &lt;stdlib.h&gt;</code><br />
+<code>#include &lt;string.h&gt;</code><br />
+</div><div class="textblock"><div class="dynheader">
+Include dependency graph for prom_alloc.h:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__alloc_8h__incl.png" border="0" usemap="#prom_2include_2prom__alloc_8h" alt=""/></div>
+<map name="prom_2include_2prom__alloc_8h" id="prom_2include_2prom__alloc_8h">
+</map>
+</div>
+</div><div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__alloc_8h__dep__incl.png" border="0" usemap="#prom_2include_2prom__alloc_8hdep" alt=""/></div>
+<map name="prom_2include_2prom__alloc_8hdep" id="prom_2include_2prom__alloc_8hdep">
+<area shape="rect" id="node2" href="prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="24,80,181,107"/>
+</map>
+</div>
+</div>
+<p><a href="prom__alloc_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:ae1613c091e07daa2bfa4303ef5628827"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__alloc_8h.html#ae1613c091e07daa2bfa4303ef5628827">prom_malloc</a>&#160;&#160;&#160;malloc</td></tr>
+<tr class="memdesc:ae1613c091e07daa2bfa4303ef5628827"><td class="mdescLeft">&#160;</td><td class="mdescRight">Redefine this macro if you wish to override it. <a href="#ae1613c091e07daa2bfa4303ef5628827">More...</a><br /></td></tr>
+<tr class="separator:ae1613c091e07daa2bfa4303ef5628827"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aab8dc4629c851a8c59cc721bd2f7c6f3"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__alloc_8h.html#aab8dc4629c851a8c59cc721bd2f7c6f3">prom_realloc</a>&#160;&#160;&#160;realloc</td></tr>
+<tr class="memdesc:aab8dc4629c851a8c59cc721bd2f7c6f3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Redefine this macro if you wish to override it. <a href="#aab8dc4629c851a8c59cc721bd2f7c6f3">More...</a><br /></td></tr>
+<tr class="separator:aab8dc4629c851a8c59cc721bd2f7c6f3"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a21faa2fafc84c8ca25467fe9cb0a55f3"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__alloc_8h.html#a21faa2fafc84c8ca25467fe9cb0a55f3">prom_strdup</a>&#160;&#160;&#160;strdup</td></tr>
+<tr class="memdesc:a21faa2fafc84c8ca25467fe9cb0a55f3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Redefine this macro if you wish to override it. <a href="#a21faa2fafc84c8ca25467fe9cb0a55f3">More...</a><br /></td></tr>
+<tr class="separator:a21faa2fafc84c8ca25467fe9cb0a55f3"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a19b2231f9b45a520bbbcf046ed5d81ef"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__alloc_8h.html#a19b2231f9b45a520bbbcf046ed5d81ef">prom_free</a>&#160;&#160;&#160;free</td></tr>
+<tr class="memdesc:a19b2231f9b45a520bbbcf046ed5d81ef"><td class="mdescLeft">&#160;</td><td class="mdescRight">Redefine this macro if you wish to override it. <a href="#a19b2231f9b45a520bbbcf046ed5d81ef">More...</a><br /></td></tr>
+<tr class="separator:a19b2231f9b45a520bbbcf046ed5d81ef"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>memory management </p>
+</div><h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="a19b2231f9b45a520bbbcf046ed5d81ef"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a19b2231f9b45a520bbbcf046ed5d81ef">&#9670;&nbsp;</a></span>prom_free</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define prom_free&#160;&#160;&#160;free</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Redefine this macro if you wish to override it. </p>
+<p>The default value is free. </p>
+
+</div>
+</div>
+<a id="ae1613c091e07daa2bfa4303ef5628827"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae1613c091e07daa2bfa4303ef5628827">&#9670;&nbsp;</a></span>prom_malloc</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define prom_malloc&#160;&#160;&#160;malloc</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Redefine this macro if you wish to override it. </p>
+<p>The default value is malloc. </p>
+
+</div>
+</div>
+<a id="aab8dc4629c851a8c59cc721bd2f7c6f3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aab8dc4629c851a8c59cc721bd2f7c6f3">&#9670;&nbsp;</a></span>prom_realloc</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define prom_realloc&#160;&#160;&#160;realloc</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Redefine this macro if you wish to override it. </p>
+<p>The default value is realloc. </p>
+
+</div>
+</div>
+<a id="a21faa2fafc84c8ca25467fe9cb0a55f3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a21faa2fafc84c8ca25467fe9cb0a55f3">&#9670;&nbsp;</a></span>prom_strdup</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define prom_strdup&#160;&#160;&#160;strdup</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Redefine this macro if you wish to override it. </p>
+<p>The default value is strdup. </p>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__alloc_8h__dep__incl.map b/docs/prom__alloc_8h__dep__incl.map
new file mode 100644
index 0000000..a737d21
--- /dev/null
+++ b/docs/prom__alloc_8h__dep__incl.map
@@ -0,0 +1,3 @@
+<map id="prom/include/prom_alloc.h" name="prom/include/prom_alloc.h">
+<area shape="rect" id="node2" href="$prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="24,80,181,107"/>
+</map>
diff --git a/docs/prom__alloc_8h__dep__incl.md5 b/docs/prom__alloc_8h__dep__incl.md5
new file mode 100644
index 0000000..bdb7be0
--- /dev/null
+++ b/docs/prom__alloc_8h__dep__incl.md5
@@ -0,0 +1 @@
+5b924c712bed7489a2830deb6f9f3c5c \ No newline at end of file
diff --git a/docs/prom__alloc_8h__dep__incl.png b/docs/prom__alloc_8h__dep__incl.png
new file mode 100644
index 0000000..cd70aa2
--- /dev/null
+++ b/docs/prom__alloc_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom__alloc_8h__incl.map b/docs/prom__alloc_8h__incl.map
new file mode 100644
index 0000000..2b2df31
--- /dev/null
+++ b/docs/prom__alloc_8h__incl.map
@@ -0,0 +1,2 @@
+<map id="prom/include/prom_alloc.h" name="prom/include/prom_alloc.h">
+</map>
diff --git a/docs/prom__alloc_8h__incl.md5 b/docs/prom__alloc_8h__incl.md5
new file mode 100644
index 0000000..726c631
--- /dev/null
+++ b/docs/prom__alloc_8h__incl.md5
@@ -0,0 +1 @@
+ca0ae2ac88b74acddef29bf677e42e80 \ No newline at end of file
diff --git a/docs/prom__alloc_8h__incl.png b/docs/prom__alloc_8h__incl.png
new file mode 100644
index 0000000..00f7f0a
--- /dev/null
+++ b/docs/prom__alloc_8h__incl.png
Binary files differ
diff --git a/docs/prom__alloc_8h_source.html b/docs/prom__alloc_8h_source.html
new file mode 100644
index 0000000..7f921e7
--- /dev/null
+++ b/docs/prom__alloc_8h_source.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_alloc.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_alloc.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom__alloc_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;<span class="preprocessor">#ifndef PROM_ALLOC_H</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="preprocessor">#define PROM_ALLOC_H</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;</div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160;<span class="preprocessor">#include &lt;stdlib.h&gt;</span></div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span>&#160;<span class="preprocessor">#include &lt;string.h&gt;</span></div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span>&#160;</div><div class="line"><a name="l00031"></a><span class="lineno"><a class="line" href="prom__alloc_8h.html#ae1613c091e07daa2bfa4303ef5628827"> 31</a></span>&#160;<span class="preprocessor">#define prom_malloc malloc</span></div><div class="line"><a name="l00032"></a><span class="lineno"> 32</span>&#160;</div><div class="line"><a name="l00036"></a><span class="lineno"><a class="line" href="prom__alloc_8h.html#aab8dc4629c851a8c59cc721bd2f7c6f3"> 36</a></span>&#160;<span class="preprocessor">#define prom_realloc realloc</span></div><div class="line"><a name="l00037"></a><span class="lineno"> 37</span>&#160;</div><div class="line"><a name="l00041"></a><span class="lineno"><a class="line" href="prom__alloc_8h.html#a21faa2fafc84c8ca25467fe9cb0a55f3"> 41</a></span>&#160;<span class="preprocessor">#define prom_strdup strdup</span></div><div class="line"><a name="l00042"></a><span class="lineno"> 42</span>&#160;</div><div class="line"><a name="l00046"></a><span class="lineno"><a class="line" href="prom__alloc_8h.html#a19b2231f9b45a520bbbcf046ed5d81ef"> 46</a></span>&#160;<span class="preprocessor">#define prom_free free</span></div><div class="line"><a name="l00047"></a><span class="lineno"> 47</span>&#160;</div><div class="line"><a name="l00048"></a><span class="lineno"> 48</span>&#160;<span class="preprocessor">#endif // PROM_ALLOC_H</span></div></div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__collector_8h.html b/docs/prom__collector_8h.html
new file mode 100644
index 0000000..8054c84
--- /dev/null
+++ b/docs/prom__collector_8h.html
@@ -0,0 +1,207 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_collector.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">prom_collector.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>A Prometheus collector returns a collection of metrics.
+<a href="#details">More...</a></p>
+<div class="textblock"><code>#include &quot;prom_map.h&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__metric_8h_source.html">prom_metric.h</a>&quot;</code><br />
+</div><div class="textblock"><div class="dynheader">
+Include dependency graph for prom_collector.h:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__collector_8h__incl.png" border="0" usemap="#prom_2include_2prom__collector_8h" alt=""/></div>
+<map name="prom_2include_2prom__collector_8h" id="prom_2include_2prom__collector_8h">
+<area shape="rect" id="node2" href="prom__map_8h_source.html" title="prom_map.h" alt="" coords="5,80,109,107"/>
+<area shape="rect" id="node3" href="prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="133,80,251,107"/>
+<area shape="rect" id="node4" href="prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="10,162,182,189"/>
+<area shape="rect" id="node5" href="prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="207,155,367,196"/>
+</map>
+</div>
+</div><div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__collector_8h__dep__incl.png" border="0" usemap="#prom_2include_2prom__collector_8hdep" alt=""/></div>
+<map name="prom_2include_2prom__collector_8hdep" id="prom_2include_2prom__collector_8hdep">
+<area shape="rect" id="node2" href="prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="36,169,193,196"/>
+<area shape="rect" id="node3" href="prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="81,80,289,121"/>
+</map>
+</div>
+</div>
+<p><a href="prom__collector_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:a28cf36f114f69a96508c044c44716f9c"><td class="memItemLeft" align="right" valign="top"><a id="a28cf36f114f69a96508c044c44716f9c"></a>
+typedef struct prom_collector&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a></td></tr>
+<tr class="memdesc:a28cf36f114f69a96508c044c44716f9c"><td class="mdescLeft">&#160;</td><td class="mdescRight">A prometheus collector calls collect to prepare metrics and return them to the registry to which it is registered. <br /></td></tr>
+<tr class="separator:a28cf36f114f69a96508c044c44716f9c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:af87330edd48cdb8e1074517e734b1e40"><td class="memItemLeft" align="right" valign="top">typedef prom_map_t *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector_8h.html#af87330edd48cdb8e1074517e734b1e40">prom_collect_fn</a>(<a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *self)</td></tr>
+<tr class="memdesc:af87330edd48cdb8e1074517e734b1e40"><td class="mdescLeft">&#160;</td><td class="mdescRight">The function responsible for preparing metric data and returning metrics for a given collector. <a href="#af87330edd48cdb8e1074517e734b1e40">More...</a><br /></td></tr>
+<tr class="separator:af87330edd48cdb8e1074517e734b1e40"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:a4300cf33b6f8e4457df385c3d2a51a4b"><td class="memItemLeft" align="right" valign="top"><a id="a4300cf33b6f8e4457df385c3d2a51a4b"></a>
+<a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector_8h.html#a4300cf33b6f8e4457df385c3d2a51a4b">prom_collector_new</a> (const char *name)</td></tr>
+<tr class="memdesc:a4300cf33b6f8e4457df385c3d2a51a4b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Create a collector. <br /></td></tr>
+<tr class="separator:a4300cf33b6f8e4457df385c3d2a51a4b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:af50746bb4af87eda617fa08237e3834e"><td class="memItemLeft" align="right" valign="top"><a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector_8h.html#af50746bb4af87eda617fa08237e3834e">prom_collector_process_new</a> (const char *limits_path, const char *stat_path)</td></tr>
+<tr class="memdesc:af50746bb4af87eda617fa08237e3834e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Return a collector including the default process metrics. <a href="#af50746bb4af87eda617fa08237e3834e">More...</a><br /></td></tr>
+<tr class="separator:af50746bb4af87eda617fa08237e3834e"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a037b72b2edb81a477999a7dfc08758c7"><td class="memItemLeft" align="right" valign="top"><a id="a037b72b2edb81a477999a7dfc08758c7"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector_8h.html#a037b72b2edb81a477999a7dfc08758c7">prom_collector_destroy</a> (<a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *self)</td></tr>
+<tr class="memdesc:a037b72b2edb81a477999a7dfc08758c7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroy a collector. <br /></td></tr>
+<tr class="separator:a037b72b2edb81a477999a7dfc08758c7"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a875b72940cd578ee76c71f1f4853f139"><td class="memItemLeft" align="right" valign="top"><a id="a875b72940cd578ee76c71f1f4853f139"></a>
+void&#160;</td><td class="memItemRight" valign="bottom"><b>prom_collector_free_generic</b> (void *gen)</td></tr>
+<tr class="separator:a875b72940cd578ee76c71f1f4853f139"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a12c297cce0a30ee4149f2b486d9f0337"><td class="memItemLeft" align="right" valign="top"><a id="a12c297cce0a30ee4149f2b486d9f0337"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector_8h.html#a12c297cce0a30ee4149f2b486d9f0337">prom_collector_destroy_generic</a> (void *gen)</td></tr>
+<tr class="memdesc:a12c297cce0a30ee4149f2b486d9f0337"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroy a collector. <br /></td></tr>
+<tr class="separator:a12c297cce0a30ee4149f2b486d9f0337"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:abd87021bd63f759d55642685a74874ee"><td class="memItemLeft" align="right" valign="top"><a id="abd87021bd63f759d55642685a74874ee"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector_8h.html#abd87021bd63f759d55642685a74874ee">prom_collector_add_metric</a> (<a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *self, <a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *metric)</td></tr>
+<tr class="memdesc:abd87021bd63f759d55642685a74874ee"><td class="mdescLeft">&#160;</td><td class="mdescRight">Add a metric to a collector. <br /></td></tr>
+<tr class="separator:abd87021bd63f759d55642685a74874ee"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a9929cb81f4fb49ffca8aa880a4699650"><td class="memItemLeft" align="right" valign="top"><a id="a9929cb81f4fb49ffca8aa880a4699650"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector_8h.html#a9929cb81f4fb49ffca8aa880a4699650">prom_collector_set_collect_fn</a> (<a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *self, <a class="el" href="prom__collector_8h.html#af87330edd48cdb8e1074517e734b1e40">prom_collect_fn</a> *fn)</td></tr>
+<tr class="memdesc:a9929cb81f4fb49ffca8aa880a4699650"><td class="mdescLeft">&#160;</td><td class="mdescRight">The collect function is responsible for doing any work involving a set of metrics and then returning them for metric exposition. <br /></td></tr>
+<tr class="separator:a9929cb81f4fb49ffca8aa880a4699650"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>A Prometheus collector returns a collection of metrics. </p>
+</div><h2 class="groupheader">Typedef Documentation</h2>
+<a id="af87330edd48cdb8e1074517e734b1e40"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#af87330edd48cdb8e1074517e734b1e40">&#9670;&nbsp;</a></span>prom_collect_fn</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef prom_map_t* prom_collect_fn(<a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *self)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>The function responsible for preparing metric data and returning metrics for a given collector. </p>
+<p>If you use the default collector registry, this should not concern you. If you are using a custom collector, you may which to set this function on your collector to do additional work before returning the contained metrics. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="af50746bb4af87eda617fa08237e3834e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#af50746bb4af87eda617fa08237e3834e">&#9670;&nbsp;</a></span>prom_collector_process_new()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a>* prom_collector_process_new </td>
+ <td>(</td>
+ <td class="paramtype">const char *&#160;</td>
+ <td class="paramname"><em>limits_path</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&#160;</td>
+ <td class="paramname"><em>stat_path</em>&#160;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Return a collector including the default process metrics. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">limits_path</td><td>Pass NULL to discover the path to the proc/[pid]/limits file associated with process ID assigned by the host environment. Otherwise, pass a string to said path. </td></tr>
+ <tr><td class="paramname">stat_path</td><td>Pass NULL to discover the path to the proc/[pid]/stat file associated with process ID assigned by the host environment. Otherwise, pass a string to said path. </td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__collector_8h__dep__incl.dot b/docs/prom__collector_8h__dep__incl.dot
new file mode 100644
index 0000000..3510f62
--- /dev/null
+++ b/docs/prom__collector_8h__dep__incl.dot
@@ -0,0 +1,13 @@
+digraph "prom/include/prom_collector.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node6 [label="prom/include/prom_collector.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node6 -> Node7 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom_8h.html",tooltip="Include prom.h to include the entire public API. "];
+ Node7 -> Node8 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$promhttp_8h.html",tooltip="Provides a HTTP endpoint for metric exposition References: "];
+ Node6 -> Node9 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node9 [label="prom/include/prom_collector\l_registry.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector__registry_8h.html",tooltip="The collector registry registers collectors for metric exposition. "];
+ Node9 -> Node7 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom__collector_8h__dep__incl.map b/docs/prom__collector_8h__dep__incl.map
new file mode 100644
index 0000000..9fa0427
--- /dev/null
+++ b/docs/prom__collector_8h__dep__incl.map
@@ -0,0 +1,4 @@
+<map id="prom/include/prom_collector.h" name="prom/include/prom_collector.h">
+<area shape="rect" id="node2" href="$prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="36,169,193,196"/>
+<area shape="rect" id="node3" href="$prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="81,80,289,121"/>
+</map>
diff --git a/docs/prom__collector_8h__dep__incl.md5 b/docs/prom__collector_8h__dep__incl.md5
new file mode 100644
index 0000000..82a4851
--- /dev/null
+++ b/docs/prom__collector_8h__dep__incl.md5
@@ -0,0 +1 @@
+07dc7165f11a707089d59b1682323dc4 \ No newline at end of file
diff --git a/docs/prom__collector_8h__dep__incl.png b/docs/prom__collector_8h__dep__incl.png
new file mode 100644
index 0000000..e39cd6f
--- /dev/null
+++ b/docs/prom__collector_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom__collector_8h__incl.dot b/docs/prom__collector_8h__incl.dot
new file mode 100644
index 0000000..4127250
--- /dev/null
+++ b/docs/prom__collector_8h__incl.dot
@@ -0,0 +1,18 @@
+digraph "prom/include/prom_collector.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node0 [label="prom/include/prom_collector.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node0 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 [label="prom_errors.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__errors_8h.html",tooltip="Prometheus client errors. "];
+ Node0 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node2 [label="prom_map.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__map_8h_source.html"];
+ Node0 -> Node3 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric_8h.html"];
+ Node3 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 [label="prom_metric_sample.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample_8h.html"];
+ Node4 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node5 [label="prom_metric_sample\l_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample__histogram_8h.html"];
+ Node5 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom__collector_8h__incl.map b/docs/prom__collector_8h__incl.map
new file mode 100644
index 0000000..a6586ce
--- /dev/null
+++ b/docs/prom__collector_8h__incl.map
@@ -0,0 +1,6 @@
+<map id="prom/include/prom_collector.h" name="prom/include/prom_collector.h">
+<area shape="rect" id="node2" href="$prom__map_8h_source.html" title="prom_map.h" alt="" coords="5,80,109,107"/>
+<area shape="rect" id="node3" href="$prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="133,80,251,107"/>
+<area shape="rect" id="node4" href="$prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="10,162,182,189"/>
+<area shape="rect" id="node5" href="$prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="207,155,367,196"/>
+</map>
diff --git a/docs/prom__collector_8h__incl.md5 b/docs/prom__collector_8h__incl.md5
new file mode 100644
index 0000000..bd63e6e
--- /dev/null
+++ b/docs/prom__collector_8h__incl.md5
@@ -0,0 +1 @@
+09d2f46fa501f75ec3e79295a53fe6a8 \ No newline at end of file
diff --git a/docs/prom__collector_8h__incl.png b/docs/prom__collector_8h__incl.png
new file mode 100644
index 0000000..0031d34
--- /dev/null
+++ b/docs/prom__collector_8h__incl.png
Binary files differ
diff --git a/docs/prom__collector_8h_source.html b/docs/prom__collector_8h_source.html
new file mode 100644
index 0000000..0f92e80
--- /dev/null
+++ b/docs/prom__collector_8h_source.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_collector.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_collector.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom__collector_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00017"></a><span class="lineno"> 17</span>&#160;<span class="preprocessor">#ifndef PROM_COLLECTOR_H</span></div><div class="line"><a name="l00018"></a><span class="lineno"> 18</span>&#160;<span class="preprocessor">#define PROM_COLLECTOR_H</span></div><div class="line"><a name="l00019"></a><span class="lineno"> 19</span>&#160;</div><div class="line"><a name="l00020"></a><span class="lineno"> 20</span>&#160;<span class="preprocessor">#include &quot;prom_map.h&quot;</span></div><div class="line"><a name="l00021"></a><span class="lineno"> 21</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__metric_8h.html">prom_metric.h</a>&quot;</span></div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;</div><div class="line"><a name="l00032"></a><span class="lineno"><a class="line" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c"> 32</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span>prom_collector <a class="code" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a>;</div><div class="line"><a name="l00033"></a><span class="lineno"> 33</span>&#160;</div><div class="line"><a name="l00040"></a><span class="lineno"><a class="line" href="prom__collector_8h.html#af87330edd48cdb8e1074517e734b1e40"> 40</a></span>&#160;<span class="keyword">typedef</span> prom_map_t* <a class="code" href="prom__collector_8h.html#af87330edd48cdb8e1074517e734b1e40">prom_collect_fn</a>(<a class="code" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a>* <span class="keyword">self</span>);</div><div class="line"><a name="l00041"></a><span class="lineno"> 41</span>&#160;</div><div class="line"><a name="l00045"></a><span class="lineno"> 45</span>&#160;<a class="code" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a>* <a class="code" href="prom__collector_8h.html#a4300cf33b6f8e4457df385c3d2a51a4b">prom_collector_new</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *name);</div><div class="line"><a name="l00046"></a><span class="lineno"> 46</span>&#160;</div><div class="line"><a name="l00054"></a><span class="lineno"> 54</span>&#160;<a class="code" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a>* <a class="code" href="prom__collector_8h.html#af50746bb4af87eda617fa08237e3834e">prom_collector_process_new</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *limits_path, <span class="keyword">const</span> <span class="keywordtype">char</span> *stat_path);</div><div class="line"><a name="l00055"></a><span class="lineno"> 55</span>&#160;</div><div class="line"><a name="l00059"></a><span class="lineno"> 59</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__collector_8h.html#a037b72b2edb81a477999a7dfc08758c7">prom_collector_destroy</a>(<a class="code" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *<span class="keyword">self</span>);</div><div class="line"><a name="l00060"></a><span class="lineno"> 60</span>&#160;</div><div class="line"><a name="l00061"></a><span class="lineno"> 61</span>&#160;<span class="keywordtype">void</span> prom_collector_free_generic(<span class="keywordtype">void</span> *gen);</div><div class="line"><a name="l00062"></a><span class="lineno"> 62</span>&#160;</div><div class="line"><a name="l00066"></a><span class="lineno"> 66</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__collector_8h.html#a12c297cce0a30ee4149f2b486d9f0337">prom_collector_destroy_generic</a>(<span class="keywordtype">void</span> *gen);</div><div class="line"><a name="l00067"></a><span class="lineno"> 67</span>&#160;</div><div class="line"><a name="l00071"></a><span class="lineno"> 71</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__collector_8h.html#abd87021bd63f759d55642685a74874ee">prom_collector_add_metric</a>(<a class="code" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *<span class="keyword">self</span>, <a class="code" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *metric);</div><div class="line"><a name="l00072"></a><span class="lineno"> 72</span>&#160;</div><div class="line"><a name="l00077"></a><span class="lineno"> 77</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__collector_8h.html#a9929cb81f4fb49ffca8aa880a4699650">prom_collector_set_collect_fn</a>(<a class="code" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *<span class="keyword">self</span>, <a class="code" href="prom__collector_8h.html#af87330edd48cdb8e1074517e734b1e40">prom_collect_fn</a> *fn);</div><div class="line"><a name="l00078"></a><span class="lineno"> 78</span>&#160;</div><div class="line"><a name="l00079"></a><span class="lineno"> 79</span>&#160;<span class="preprocessor">#endif // PROM_COLLECTOR_H</span></div><div class="ttc" id="prom__collector_8h_html_a28cf36f114f69a96508c044c44716f9c"><div class="ttname"><a href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a></div><div class="ttdeci">struct prom_collector prom_collector_t</div><div class="ttdoc">A prometheus collector calls collect to prepare metrics and return them to the registry to which it i...</div><div class="ttdef"><b>Definition:</b> prom_collector.h:32</div></div>
+<div class="ttc" id="prom__metric_8h_html_afd1bd014c48955d6c2c36aa8a8cbb889"><div class="ttname"><a href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a></div><div class="ttdeci">struct prom_metric prom_metric_t</div><div class="ttdoc">A prometheus metric. </div><div class="ttdef"><b>Definition:</b> prom_metric.h:34</div></div>
+<div class="ttc" id="prom__collector_8h_html_abd87021bd63f759d55642685a74874ee"><div class="ttname"><a href="prom__collector_8h.html#abd87021bd63f759d55642685a74874ee">prom_collector_add_metric</a></div><div class="ttdeci">int prom_collector_add_metric(prom_collector_t *self, prom_metric_t *metric)</div><div class="ttdoc">Add a metric to a collector. </div></div>
+<div class="ttc" id="prom__collector_8h_html_a037b72b2edb81a477999a7dfc08758c7"><div class="ttname"><a href="prom__collector_8h.html#a037b72b2edb81a477999a7dfc08758c7">prom_collector_destroy</a></div><div class="ttdeci">int prom_collector_destroy(prom_collector_t *self)</div><div class="ttdoc">Destroy a collector. </div></div>
+<div class="ttc" id="prom__collector_8h_html_a9929cb81f4fb49ffca8aa880a4699650"><div class="ttname"><a href="prom__collector_8h.html#a9929cb81f4fb49ffca8aa880a4699650">prom_collector_set_collect_fn</a></div><div class="ttdeci">int prom_collector_set_collect_fn(prom_collector_t *self, prom_collect_fn *fn)</div><div class="ttdoc">The collect function is responsible for doing any work involving a set of metrics and then returning ...</div></div>
+<div class="ttc" id="prom__collector_8h_html_a4300cf33b6f8e4457df385c3d2a51a4b"><div class="ttname"><a href="prom__collector_8h.html#a4300cf33b6f8e4457df385c3d2a51a4b">prom_collector_new</a></div><div class="ttdeci">prom_collector_t * prom_collector_new(const char *name)</div><div class="ttdoc">Create a collector. </div></div>
+<div class="ttc" id="prom__collector_8h_html_af50746bb4af87eda617fa08237e3834e"><div class="ttname"><a href="prom__collector_8h.html#af50746bb4af87eda617fa08237e3834e">prom_collector_process_new</a></div><div class="ttdeci">prom_collector_t * prom_collector_process_new(const char *limits_path, const char *stat_path)</div><div class="ttdoc">Return a collector including the default process metrics. </div></div>
+<div class="ttc" id="prom__metric_8h_html"><div class="ttname"><a href="prom__metric_8h.html">prom_metric.h</a></div><div class="ttdoc">Functions for retrieving metric samples from metrics given an ordered set of labels. </div></div>
+<div class="ttc" id="prom__collector_8h_html_a12c297cce0a30ee4149f2b486d9f0337"><div class="ttname"><a href="prom__collector_8h.html#a12c297cce0a30ee4149f2b486d9f0337">prom_collector_destroy_generic</a></div><div class="ttdeci">int prom_collector_destroy_generic(void *gen)</div><div class="ttdoc">Destroy a collector. </div></div>
+<div class="ttc" id="prom__collector_8h_html_af87330edd48cdb8e1074517e734b1e40"><div class="ttname"><a href="prom__collector_8h.html#af87330edd48cdb8e1074517e734b1e40">prom_collect_fn</a></div><div class="ttdeci">prom_map_t * prom_collect_fn(prom_collector_t *self)</div><div class="ttdoc">The function responsible for preparing metric data and returning metrics for a given collector...</div><div class="ttdef"><b>Definition:</b> prom_collector.h:40</div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__collector__registry_8h.html b/docs/prom__collector__registry_8h.html
new file mode 100644
index 0000000..8eb546a
--- /dev/null
+++ b/docs/prom__collector__registry_8h.html
@@ -0,0 +1,304 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_collector_registry.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a> &#124;
+<a href="#var-members">Variables</a> </div>
+ <div class="headertitle">
+<div class="title">prom_collector_registry.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>The collector registry registers collectors for metric exposition.
+<a href="#details">More...</a></p>
+<div class="textblock"><code>#include &quot;<a class="el" href="prom__collector_8h_source.html">prom_collector.h</a>&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__metric_8h_source.html">prom_metric.h</a>&quot;</code><br />
+</div><div class="textblock"><div class="dynheader">
+Include dependency graph for prom_collector_registry.h:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__collector__registry_8h__incl.png" border="0" usemap="#prom_2include_2prom__collector__registry_8h" alt=""/></div>
+<map name="prom_2include_2prom__collector__registry_8h" id="prom_2include_2prom__collector__registry_8h">
+<area shape="rect" id="node2" href="prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="24,95,155,121"/>
+<area shape="rect" id="node4" href="prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="133,169,251,196"/>
+<area shape="rect" id="node3" href="prom__map_8h_source.html" title="prom_map.h" alt="" coords="5,169,109,196"/>
+<area shape="rect" id="node5" href="prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="11,251,183,278"/>
+<area shape="rect" id="node6" href="prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="208,244,368,285"/>
+</map>
+</div>
+</div><div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__collector__registry_8h__dep__incl.png" border="0" usemap="#prom_2include_2prom__collector__registry_8hdep" alt=""/></div>
+<map name="prom_2include_2prom__collector__registry_8hdep" id="prom_2include_2prom__collector__registry_8hdep">
+<area shape="rect" id="node2" href="prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="31,95,188,121"/>
+</map>
+</div>
+</div>
+<p><a href="prom__collector__registry_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:a20f07748401fbbde9efc8a718f9bc202"><td class="memItemLeft" align="right" valign="top"><a id="a20f07748401fbbde9efc8a718f9bc202"></a>
+typedef struct prom_collector_registry&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a></td></tr>
+<tr class="memdesc:a20f07748401fbbde9efc8a718f9bc202"><td class="mdescLeft">&#160;</td><td class="mdescRight">A prom_registry_t is responsible for registering metrics and briding them to the string exposition format. <br /></td></tr>
+<tr class="separator:a20f07748401fbbde9efc8a718f9bc202"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:aaf1421bd744f0dbbdaba7e64cec11f54"><td class="memItemLeft" align="right" valign="top"><a id="aaf1421bd744f0dbbdaba7e64cec11f54"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html#aaf1421bd744f0dbbdaba7e64cec11f54">prom_collector_registry_default_init</a> (void)</td></tr>
+<tr class="memdesc:aaf1421bd744f0dbbdaba7e64cec11f54"><td class="mdescLeft">&#160;</td><td class="mdescRight">Initializes the default collector registry and enables metric collection on the executing process. <br /></td></tr>
+<tr class="separator:aaf1421bd744f0dbbdaba7e64cec11f54"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ab5d622258998978c528253f07e2903b8"><td class="memItemLeft" align="right" valign="top"><a id="ab5d622258998978c528253f07e2903b8"></a>
+<a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html#ab5d622258998978c528253f07e2903b8">prom_collector_registry_new</a> (const char *name)</td></tr>
+<tr class="memdesc:ab5d622258998978c528253f07e2903b8"><td class="mdescLeft">&#160;</td><td class="mdescRight">Return a new collector registry. <br /></td></tr>
+<tr class="separator:ab5d622258998978c528253f07e2903b8"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad3854e6e40b6f741fde53dc65f0ecd87"><td class="memItemLeft" align="right" valign="top"><a id="ad3854e6e40b6f741fde53dc65f0ecd87"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html#ad3854e6e40b6f741fde53dc65f0ecd87">prom_collector_registry_destroy</a> (<a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *self)</td></tr>
+<tr class="memdesc:ad3854e6e40b6f741fde53dc65f0ecd87"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroy a collector registry. <br /></td></tr>
+<tr class="separator:ad3854e6e40b6f741fde53dc65f0ecd87"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a0d59bf988de4ee29e076910fa7135071"><td class="memItemLeft" align="right" valign="top"><a id="a0d59bf988de4ee29e076910fa7135071"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html#a0d59bf988de4ee29e076910fa7135071">prom_collector_registry_enable_process_metrics</a> (<a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *self)</td></tr>
+<tr class="memdesc:a0d59bf988de4ee29e076910fa7135071"><td class="mdescLeft">&#160;</td><td class="mdescRight">Enable process metrics on the given collector registry. <br /></td></tr>
+<tr class="separator:a0d59bf988de4ee29e076910fa7135071"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a113683f4e15ad9240a37ed2139ddaea6"><td class="memItemLeft" align="right" valign="top"><a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html#a113683f4e15ad9240a37ed2139ddaea6">prom_collector_registry_must_register_metric</a> (<a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *metric)</td></tr>
+<tr class="memdesc:a113683f4e15ad9240a37ed2139ddaea6"><td class="mdescLeft">&#160;</td><td class="mdescRight">Registers a metric with the default collector on PROM_DEFAULT_COLLECTOR_REGISTRY. <a href="#a113683f4e15ad9240a37ed2139ddaea6">More...</a><br /></td></tr>
+<tr class="separator:a113683f4e15ad9240a37ed2139ddaea6"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aa735fa0fbe03d6d9a0d11eb4792ec761"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html#aa735fa0fbe03d6d9a0d11eb4792ec761">prom_collector_registry_register_metric</a> (<a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *metric)</td></tr>
+<tr class="memdesc:aa735fa0fbe03d6d9a0d11eb4792ec761"><td class="mdescLeft">&#160;</td><td class="mdescRight">Registers a metric with the default collector on PROM_DEFAULT_COLLECTOR_REGISTRY. <a href="#aa735fa0fbe03d6d9a0d11eb4792ec761">More...</a><br /></td></tr>
+<tr class="separator:aa735fa0fbe03d6d9a0d11eb4792ec761"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a42203da085c6c6f2bc3ba31501683882"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html#a42203da085c6c6f2bc3ba31501683882">prom_collector_registry_register_collector</a> (<a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *self, <a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *collector)</td></tr>
+<tr class="memdesc:a42203da085c6c6f2bc3ba31501683882"><td class="mdescLeft">&#160;</td><td class="mdescRight">Register a collector with the given registry. <a href="#a42203da085c6c6f2bc3ba31501683882">More...</a><br /></td></tr>
+<tr class="separator:a42203da085c6c6f2bc3ba31501683882"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a0149a2702ae0b3ff39d57904d613c14f"><td class="memItemLeft" align="right" valign="top">const char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html#a0149a2702ae0b3ff39d57904d613c14f">prom_collector_registry_bridge</a> (<a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *self)</td></tr>
+<tr class="memdesc:a0149a2702ae0b3ff39d57904d613c14f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a string in the default metric exposition format. <a href="#a0149a2702ae0b3ff39d57904d613c14f">More...</a><br /></td></tr>
+<tr class="separator:a0149a2702ae0b3ff39d57904d613c14f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:acf002221c3239584723f9fb15c53e15e"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html#acf002221c3239584723f9fb15c53e15e">prom_collector_registry_validate_metric_name</a> (<a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *self, const char *metric_name)</td></tr>
+<tr class="memdesc:acf002221c3239584723f9fb15c53e15e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Validates that the given metric name complies with the specification: <a href="#acf002221c3239584723f9fb15c53e15e">More...</a><br /></td></tr>
+<tr class="separator:acf002221c3239584723f9fb15c53e15e"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="var-members"></a>
+Variables</h2></td></tr>
+<tr class="memitem:a6092b48e150390c1927da5fe8914981b"><td class="memItemLeft" align="right" valign="top"><a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__collector__registry_8h.html#a6092b48e150390c1927da5fe8914981b">PROM_COLLECTOR_REGISTRY_DEFAULT</a></td></tr>
+<tr class="memdesc:a6092b48e150390c1927da5fe8914981b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Initialize the default registry by calling prom_collector_registry_init within your program. <a href="#a6092b48e150390c1927da5fe8914981b">More...</a><br /></td></tr>
+<tr class="separator:a6092b48e150390c1927da5fe8914981b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>The collector registry registers collectors for metric exposition. </p>
+</div><h2 class="groupheader">Function Documentation</h2>
+<a id="a0149a2702ae0b3ff39d57904d613c14f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a0149a2702ae0b3ff39d57904d613c14f">&#9670;&nbsp;</a></span>prom_collector_registry_bridge()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">const char* prom_collector_registry_bridge </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *&#160;</td>
+ <td class="paramname"><em>self</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Returns a string in the default metric exposition format. </p>
+<p>Reference: <a href="https://prometheus.io/docs/instrumenting/exposition_formats/">https://prometheus.io/docs/instrumenting/exposition_formats/</a> </p>
+
+</div>
+</div>
+<a id="a113683f4e15ad9240a37ed2139ddaea6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a113683f4e15ad9240a37ed2139ddaea6">&#9670;&nbsp;</a></span>prom_collector_registry_must_register_metric()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a>* prom_collector_registry_must_register_metric </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *&#160;</td>
+ <td class="paramname"><em>metric</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Registers a metric with the default collector on PROM_DEFAULT_COLLECTOR_REGISTRY. </p>
+<p>The metric to be registered MUST NOT already be registered with the given metric. If so, the program will halt. It returns a prom_metric_t* to simplify metric creation and registration. Furthermore, PROM_DEFAULT_COLLECTOR_REGISTRY must be registered via <a class="el" href="prom__collector__registry_8h.html#aaf1421bd744f0dbbdaba7e64cec11f54" title="Initializes the default collector registry and enables metric collection on the executing process...">prom_collector_registry_default_init()</a> prior to calling this function. The metric will be added to the default registry's default collector. </p>
+
+</div>
+</div>
+<a id="a42203da085c6c6f2bc3ba31501683882"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a42203da085c6c6f2bc3ba31501683882">&#9670;&nbsp;</a></span>prom_collector_registry_register_collector()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int prom_collector_registry_register_collector </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *&#160;</td>
+ <td class="paramname"><em>self</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *&#160;</td>
+ <td class="paramname"><em>collector</em>&#160;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Register a collector with the given registry. </p>
+<p>Returns an error on failure. </p>
+
+</div>
+</div>
+<a id="aa735fa0fbe03d6d9a0d11eb4792ec761"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aa735fa0fbe03d6d9a0d11eb4792ec761">&#9670;&nbsp;</a></span>prom_collector_registry_register_metric()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int prom_collector_registry_register_metric </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *&#160;</td>
+ <td class="paramname"><em>metric</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Registers a metric with the default collector on PROM_DEFAULT_COLLECTOR_REGISTRY. </p>
+<p>Returns an error on failure. See prom_collector_registry_must_register_metric. </p>
+
+</div>
+</div>
+<a id="acf002221c3239584723f9fb15c53e15e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#acf002221c3239584723f9fb15c53e15e">&#9670;&nbsp;</a></span>prom_collector_registry_validate_metric_name()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int prom_collector_registry_validate_metric_name </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *&#160;</td>
+ <td class="paramname"><em>self</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&#160;</td>
+ <td class="paramname"><em>metric_name</em>&#160;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Validates that the given metric name complies with the specification: </p>
+<p>Reference: <a href="https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels">https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels</a> </p>
+
+</div>
+</div>
+<h2 class="groupheader">Variable Documentation</h2>
+<a id="a6092b48e150390c1927da5fe8914981b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a6092b48e150390c1927da5fe8914981b">&#9670;&nbsp;</a></span>PROM_COLLECTOR_REGISTRY_DEFAULT</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a>* PROM_COLLECTOR_REGISTRY_DEFAULT</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Initialize the default registry by calling prom_collector_registry_init within your program. </p>
+<p>You MUST NOT modify this value. </p>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__collector__registry_8h__dep__incl.dot b/docs/prom__collector__registry_8h__dep__incl.dot
new file mode 100644
index 0000000..18cfa2e
--- /dev/null
+++ b/docs/prom__collector__registry_8h__dep__incl.dot
@@ -0,0 +1,10 @@
+digraph "prom/include/prom_collector_registry.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node7 [label="prom/include/prom_collector\l_registry.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node7 -> Node8 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom_8h.html",tooltip="Include prom.h to include the entire public API. "];
+ Node8 -> Node9 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node9 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$promhttp_8h.html",tooltip="Provides a HTTP endpoint for metric exposition References: "];
+}
diff --git a/docs/prom__collector__registry_8h__dep__incl.map b/docs/prom__collector__registry_8h__dep__incl.map
new file mode 100644
index 0000000..31fbe4c
--- /dev/null
+++ b/docs/prom__collector__registry_8h__dep__incl.map
@@ -0,0 +1,3 @@
+<map id="prom/include/prom_collector_registry.h" name="prom/include/prom_collector_registry.h">
+<area shape="rect" id="node2" href="$prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="31,95,188,121"/>
+</map>
diff --git a/docs/prom__collector__registry_8h__dep__incl.md5 b/docs/prom__collector__registry_8h__dep__incl.md5
new file mode 100644
index 0000000..fc16350
--- /dev/null
+++ b/docs/prom__collector__registry_8h__dep__incl.md5
@@ -0,0 +1 @@
+a87e40a3226cc69d3f7ff08cb008a187 \ No newline at end of file
diff --git a/docs/prom__collector__registry_8h__dep__incl.png b/docs/prom__collector__registry_8h__dep__incl.png
new file mode 100644
index 0000000..8091912
--- /dev/null
+++ b/docs/prom__collector__registry_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom__collector__registry_8h__incl.dot b/docs/prom__collector__registry_8h__incl.dot
new file mode 100644
index 0000000..57b5c64
--- /dev/null
+++ b/docs/prom__collector__registry_8h__incl.dot
@@ -0,0 +1,22 @@
+digraph "prom/include/prom_collector_registry.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node0 [label="prom/include/prom_collector\l_registry.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node0 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 [label="prom_collector.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector_8h.html",tooltip="A Prometheus collector returns a collection of metrics. "];
+ Node1 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node2 [label="prom_errors.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__errors_8h.html",tooltip="Prometheus client errors. "];
+ Node1 -> Node3 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom_map.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__map_8h_source.html"];
+ Node1 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 [label="prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric_8h.html"];
+ Node4 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node5 [label="prom_metric_sample.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample_8h.html"];
+ Node5 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 -> Node6 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node6 [label="prom_metric_sample\l_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample__histogram_8h.html"];
+ Node6 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom__collector__registry_8h__incl.map b/docs/prom__collector__registry_8h__incl.map
new file mode 100644
index 0000000..d1056b4
--- /dev/null
+++ b/docs/prom__collector__registry_8h__incl.map
@@ -0,0 +1,7 @@
+<map id="prom/include/prom_collector_registry.h" name="prom/include/prom_collector_registry.h">
+<area shape="rect" id="node2" href="$prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="24,95,155,121"/>
+<area shape="rect" id="node4" href="$prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="133,169,251,196"/>
+<area shape="rect" id="node3" href="$prom__map_8h_source.html" title="prom_map.h" alt="" coords="5,169,109,196"/>
+<area shape="rect" id="node5" href="$prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="11,251,183,278"/>
+<area shape="rect" id="node6" href="$prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="208,244,368,285"/>
+</map>
diff --git a/docs/prom__collector__registry_8h__incl.md5 b/docs/prom__collector__registry_8h__incl.md5
new file mode 100644
index 0000000..6fbc15c
--- /dev/null
+++ b/docs/prom__collector__registry_8h__incl.md5
@@ -0,0 +1 @@
+72a7bb4f70815b45c471e5067710d62d \ No newline at end of file
diff --git a/docs/prom__collector__registry_8h__incl.png b/docs/prom__collector__registry_8h__incl.png
new file mode 100644
index 0000000..8efbae6
--- /dev/null
+++ b/docs/prom__collector__registry_8h__incl.png
Binary files differ
diff --git a/docs/prom__collector__registry_8h_source.html b/docs/prom__collector__registry_8h_source.html
new file mode 100644
index 0000000..f9a8d19
--- /dev/null
+++ b/docs/prom__collector__registry_8h_source.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_collector_registry.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_collector_registry.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom__collector__registry_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;<span class="preprocessor">#ifndef PROM_REGISTRY_H</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="preprocessor">#define PROM_REGISTRY_H</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;</div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__collector_8h.html">prom_collector.h</a>&quot;</span></div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__metric_8h.html">prom_metric.h</a>&quot;</span></div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span>&#160;</div><div class="line"><a name="l00031"></a><span class="lineno"><a class="line" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202"> 31</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span>prom_collector_registry <a class="code" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a>;</div><div class="line"><a name="l00032"></a><span class="lineno"> 32</span>&#160;</div><div class="line"><a name="l00037"></a><span class="lineno"><a class="line" href="prom__collector__registry_8h.html#a6092b48e150390c1927da5fe8914981b"> 37</a></span>&#160;<a class="code" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *<a class="code" href="prom__collector__registry_8h.html#a6092b48e150390c1927da5fe8914981b">PROM_COLLECTOR_REGISTRY_DEFAULT</a>;</div><div class="line"><a name="l00038"></a><span class="lineno"> 38</span>&#160;</div><div class="line"><a name="l00042"></a><span class="lineno"> 42</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__collector__registry_8h.html#aaf1421bd744f0dbbdaba7e64cec11f54">prom_collector_registry_default_init</a>(<span class="keywordtype">void</span>);</div><div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160;</div><div class="line"><a name="l00047"></a><span class="lineno"> 47</span>&#160;<a class="code" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a>* <a class="code" href="prom__collector__registry_8h.html#ab5d622258998978c528253f07e2903b8">prom_collector_registry_new</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *name);</div><div class="line"><a name="l00048"></a><span class="lineno"> 48</span>&#160;</div><div class="line"><a name="l00052"></a><span class="lineno"> 52</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__collector__registry_8h.html#ad3854e6e40b6f741fde53dc65f0ecd87">prom_collector_registry_destroy</a>(<a class="code" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *<span class="keyword">self</span>);</div><div class="line"><a name="l00053"></a><span class="lineno"> 53</span>&#160;</div><div class="line"><a name="l00057"></a><span class="lineno"> 57</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__collector__registry_8h.html#a0d59bf988de4ee29e076910fa7135071">prom_collector_registry_enable_process_metrics</a>(<a class="code" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *<span class="keyword">self</span>);</div><div class="line"><a name="l00058"></a><span class="lineno"> 58</span>&#160;</div><div class="line"><a name="l00067"></a><span class="lineno"> 67</span>&#160;<a class="code" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a>* <a class="code" href="prom__collector__registry_8h.html#a113683f4e15ad9240a37ed2139ddaea6">prom_collector_registry_must_register_metric</a>(<a class="code" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *metric);</div><div class="line"><a name="l00068"></a><span class="lineno"> 68</span>&#160;</div><div class="line"><a name="l00073"></a><span class="lineno"> 73</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__collector__registry_8h.html#aa735fa0fbe03d6d9a0d11eb4792ec761">prom_collector_registry_register_metric</a>(<a class="code" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *metric);</div><div class="line"><a name="l00074"></a><span class="lineno"> 74</span>&#160;</div><div class="line"><a name="l00078"></a><span class="lineno"> 78</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__collector__registry_8h.html#a42203da085c6c6f2bc3ba31501683882">prom_collector_registry_register_collector</a>(<a class="code" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *<span class="keyword">self</span>, <a class="code" href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a> *collector);</div><div class="line"><a name="l00079"></a><span class="lineno"> 79</span>&#160;</div><div class="line"><a name="l00085"></a><span class="lineno"> 85</span>&#160;<span class="keyword">const</span> <span class="keywordtype">char</span>* <a class="code" href="prom__collector__registry_8h.html#a0149a2702ae0b3ff39d57904d613c14f">prom_collector_registry_bridge</a>(<a class="code" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *<span class="keyword">self</span>);</div><div class="line"><a name="l00086"></a><span class="lineno"> 86</span>&#160;</div><div class="line"><a name="l00092"></a><span class="lineno"> 92</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__collector__registry_8h.html#acf002221c3239584723f9fb15c53e15e">prom_collector_registry_validate_metric_name</a>(<a class="code" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *<span class="keyword">self</span>,</div><div class="line"><a name="l00093"></a><span class="lineno"> 93</span>&#160; <span class="keyword">const</span> <span class="keywordtype">char</span> *metric_name);</div><div class="line"><a name="l00094"></a><span class="lineno"> 94</span>&#160;</div><div class="line"><a name="l00095"></a><span class="lineno"> 95</span>&#160;<span class="preprocessor">#endif // PROM_H</span></div><div class="ttc" id="prom__collector_8h_html_a28cf36f114f69a96508c044c44716f9c"><div class="ttname"><a href="prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c">prom_collector_t</a></div><div class="ttdeci">struct prom_collector prom_collector_t</div><div class="ttdoc">A prometheus collector calls collect to prepare metrics and return them to the registry to which it i...</div><div class="ttdef"><b>Definition:</b> prom_collector.h:32</div></div>
+<div class="ttc" id="prom__collector__registry_8h_html_a0149a2702ae0b3ff39d57904d613c14f"><div class="ttname"><a href="prom__collector__registry_8h.html#a0149a2702ae0b3ff39d57904d613c14f">prom_collector_registry_bridge</a></div><div class="ttdeci">const char * prom_collector_registry_bridge(prom_collector_registry_t *self)</div><div class="ttdoc">Returns a string in the default metric exposition format. </div></div>
+<div class="ttc" id="prom__collector__registry_8h_html_ad3854e6e40b6f741fde53dc65f0ecd87"><div class="ttname"><a href="prom__collector__registry_8h.html#ad3854e6e40b6f741fde53dc65f0ecd87">prom_collector_registry_destroy</a></div><div class="ttdeci">int prom_collector_registry_destroy(prom_collector_registry_t *self)</div><div class="ttdoc">Destroy a collector registry. </div></div>
+<div class="ttc" id="prom__metric_8h_html_afd1bd014c48955d6c2c36aa8a8cbb889"><div class="ttname"><a href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a></div><div class="ttdeci">struct prom_metric prom_metric_t</div><div class="ttdoc">A prometheus metric. </div><div class="ttdef"><b>Definition:</b> prom_metric.h:34</div></div>
+<div class="ttc" id="prom__collector__registry_8h_html_aaf1421bd744f0dbbdaba7e64cec11f54"><div class="ttname"><a href="prom__collector__registry_8h.html#aaf1421bd744f0dbbdaba7e64cec11f54">prom_collector_registry_default_init</a></div><div class="ttdeci">int prom_collector_registry_default_init(void)</div><div class="ttdoc">Initializes the default collector registry and enables metric collection on the executing process...</div></div>
+<div class="ttc" id="prom__collector_8h_html"><div class="ttname"><a href="prom__collector_8h.html">prom_collector.h</a></div><div class="ttdoc">A Prometheus collector returns a collection of metrics. </div></div>
+<div class="ttc" id="prom__collector__registry_8h_html_ab5d622258998978c528253f07e2903b8"><div class="ttname"><a href="prom__collector__registry_8h.html#ab5d622258998978c528253f07e2903b8">prom_collector_registry_new</a></div><div class="ttdeci">prom_collector_registry_t * prom_collector_registry_new(const char *name)</div><div class="ttdoc">Return a new collector registry. </div></div>
+<div class="ttc" id="prom__collector__registry_8h_html_a0d59bf988de4ee29e076910fa7135071"><div class="ttname"><a href="prom__collector__registry_8h.html#a0d59bf988de4ee29e076910fa7135071">prom_collector_registry_enable_process_metrics</a></div><div class="ttdeci">int prom_collector_registry_enable_process_metrics(prom_collector_registry_t *self)</div><div class="ttdoc">Enable process metrics on the given collector registry. </div></div>
+<div class="ttc" id="prom__collector__registry_8h_html_a20f07748401fbbde9efc8a718f9bc202"><div class="ttname"><a href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a></div><div class="ttdeci">struct prom_collector_registry prom_collector_registry_t</div><div class="ttdoc">A prom_registry_t is responsible for registering metrics and briding them to the string exposition fo...</div><div class="ttdef"><b>Definition:</b> prom_collector_registry.h:31</div></div>
+<div class="ttc" id="prom__collector__registry_8h_html_a113683f4e15ad9240a37ed2139ddaea6"><div class="ttname"><a href="prom__collector__registry_8h.html#a113683f4e15ad9240a37ed2139ddaea6">prom_collector_registry_must_register_metric</a></div><div class="ttdeci">prom_metric_t * prom_collector_registry_must_register_metric(prom_metric_t *metric)</div><div class="ttdoc">Registers a metric with the default collector on PROM_DEFAULT_COLLECTOR_REGISTRY. ...</div></div>
+<div class="ttc" id="prom__collector__registry_8h_html_a6092b48e150390c1927da5fe8914981b"><div class="ttname"><a href="prom__collector__registry_8h.html#a6092b48e150390c1927da5fe8914981b">PROM_COLLECTOR_REGISTRY_DEFAULT</a></div><div class="ttdeci">prom_collector_registry_t * PROM_COLLECTOR_REGISTRY_DEFAULT</div><div class="ttdoc">Initialize the default registry by calling prom_collector_registry_init within your program...</div><div class="ttdef"><b>Definition:</b> prom_collector_registry.h:37</div></div>
+<div class="ttc" id="prom__metric_8h_html"><div class="ttname"><a href="prom__metric_8h.html">prom_metric.h</a></div><div class="ttdoc">Functions for retrieving metric samples from metrics given an ordered set of labels. </div></div>
+<div class="ttc" id="prom__collector__registry_8h_html_aa735fa0fbe03d6d9a0d11eb4792ec761"><div class="ttname"><a href="prom__collector__registry_8h.html#aa735fa0fbe03d6d9a0d11eb4792ec761">prom_collector_registry_register_metric</a></div><div class="ttdeci">int prom_collector_registry_register_metric(prom_metric_t *metric)</div><div class="ttdoc">Registers a metric with the default collector on PROM_DEFAULT_COLLECTOR_REGISTRY. ...</div></div>
+<div class="ttc" id="prom__collector__registry_8h_html_acf002221c3239584723f9fb15c53e15e"><div class="ttname"><a href="prom__collector__registry_8h.html#acf002221c3239584723f9fb15c53e15e">prom_collector_registry_validate_metric_name</a></div><div class="ttdeci">int prom_collector_registry_validate_metric_name(prom_collector_registry_t *self, const char *metric_name)</div><div class="ttdoc">Validates that the given metric name complies with the specification: </div></div>
+<div class="ttc" id="prom__collector__registry_8h_html_a42203da085c6c6f2bc3ba31501683882"><div class="ttname"><a href="prom__collector__registry_8h.html#a42203da085c6c6f2bc3ba31501683882">prom_collector_registry_register_collector</a></div><div class="ttdeci">int prom_collector_registry_register_collector(prom_collector_registry_t *self, prom_collector_t *collector)</div><div class="ttdoc">Register a collector with the given registry. </div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__counter_8h.html b/docs/prom__counter_8h.html
new file mode 100644
index 0000000..bb09195
--- /dev/null
+++ b/docs/prom__counter_8h.html
@@ -0,0 +1,155 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_counter.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">prom_counter.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p><a href="https://prometheus.io/docs/concepts/metric_types/#counter">https://prometheus.io/docs/concepts/metric_types/#counter</a>
+<a href="#details">More...</a></p>
+<div class="textblock"><code>#include &lt;stdlib.h&gt;</code><br />
+<code>#include &quot;<a class="el" href="prom__metric_8h_source.html">prom_metric.h</a>&quot;</code><br />
+</div><div class="textblock"><div class="dynheader">
+Include dependency graph for prom_counter.h:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__counter_8h__incl.png" border="0" usemap="#prom_2include_2prom__counter_8h" alt=""/></div>
+<map name="prom_2include_2prom__counter_8h" id="prom_2include_2prom__counter_8h">
+<area shape="rect" id="node3" href="prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="129,80,246,107"/>
+<area shape="rect" id="node4" href="prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="5,162,177,189"/>
+<area shape="rect" id="node5" href="prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="202,155,362,196"/>
+</map>
+</div>
+</div><div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__counter_8h__dep__incl.png" border="0" usemap="#prom_2include_2prom__counter_8hdep" alt=""/></div>
+<map name="prom_2include_2prom__counter_8hdep" id="prom_2include_2prom__counter_8hdep">
+<area shape="rect" id="node2" href="prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="33,80,190,107"/>
+</map>
+</div>
+</div>
+<p><a href="prom__counter_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:a814ceed99a1d618334e51f4d0e160606"><td class="memItemLeft" align="right" valign="top">typedef <a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a></td></tr>
+<tr class="memdesc:a814ceed99a1d618334e51f4d0e160606"><td class="mdescLeft">&#160;</td><td class="mdescRight">A prometheus counter. <a href="#a814ceed99a1d618334e51f4d0e160606">More...</a><br /></td></tr>
+<tr class="separator:a814ceed99a1d618334e51f4d0e160606"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:a3302a9f1a3556d17af9af29729be2651"><td class="memItemLeft" align="right" valign="top"><a id="a3302a9f1a3556d17af9af29729be2651"></a>
+<a class="el" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__counter_8h.html#a3302a9f1a3556d17af9af29729be2651">prom_counter_new</a> (const char *name, const char *help, size_t label_key_count, const char **label_keys)</td></tr>
+<tr class="memdesc:a3302a9f1a3556d17af9af29729be2651"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a pointer to a prom_counter. <br /></td></tr>
+<tr class="separator:a3302a9f1a3556d17af9af29729be2651"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ac36abc71c11df1e774c8c102b1fdb78d"><td class="memItemLeft" align="right" valign="top"><a id="ac36abc71c11df1e774c8c102b1fdb78d"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__counter_8h.html#ac36abc71c11df1e774c8c102b1fdb78d">prom_counter_destroy</a> (<a class="el" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a> *self)</td></tr>
+<tr class="memdesc:ac36abc71c11df1e774c8c102b1fdb78d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroys a pointer to a prom_counter. <br /></td></tr>
+<tr class="separator:ac36abc71c11df1e774c8c102b1fdb78d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a315695fdd8b9b6fa59904bb2e35bfa35"><td class="memItemLeft" align="right" valign="top"><a id="a315695fdd8b9b6fa59904bb2e35bfa35"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__counter_8h.html#a315695fdd8b9b6fa59904bb2e35bfa35">prom_counter_inc</a> (<a class="el" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a> *self, const char **label_values)</td></tr>
+<tr class="memdesc:a315695fdd8b9b6fa59904bb2e35bfa35"><td class="mdescLeft">&#160;</td><td class="mdescRight">Increment the prom_counter by 1. <br /></td></tr>
+<tr class="separator:a315695fdd8b9b6fa59904bb2e35bfa35"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:addd8a7efc39e17d30b2267e5a0a626db"><td class="memItemLeft" align="right" valign="top"><a id="addd8a7efc39e17d30b2267e5a0a626db"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__counter_8h.html#addd8a7efc39e17d30b2267e5a0a626db">prom_counter_add</a> (<a class="el" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a> *self, double r_value, const char **label_values)</td></tr>
+<tr class="memdesc:addd8a7efc39e17d30b2267e5a0a626db"><td class="mdescLeft">&#160;</td><td class="mdescRight">Add the value to the prom_counter. <br /></td></tr>
+<tr class="separator:addd8a7efc39e17d30b2267e5a0a626db"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p><a href="https://prometheus.io/docs/concepts/metric_types/#counter">https://prometheus.io/docs/concepts/metric_types/#counter</a> </p>
+</div><h2 class="groupheader">Typedef Documentation</h2>
+<a id="a814ceed99a1d618334e51f4d0e160606"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a814ceed99a1d618334e51f4d0e160606">&#9670;&nbsp;</a></span>prom_counter_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef <a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> <a class="el" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>A prometheus counter. </p>
+<p>References</p><ul>
+<li>See <a href="https://prometheus.io/docs/concepts/metric_types/#counter">https://prometheus.io/docs/concepts/metric_types/#counter</a> </li>
+</ul>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__counter_8h__dep__incl.dot b/docs/prom__counter_8h__dep__incl.dot
new file mode 100644
index 0000000..6edb93a
--- /dev/null
+++ b/docs/prom__counter_8h__dep__incl.dot
@@ -0,0 +1,10 @@
+digraph "prom/include/prom_counter.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node6 [label="prom/include/prom_counter.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node6 -> Node7 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom_8h.html",tooltip="Include prom.h to include the entire public API. "];
+ Node7 -> Node8 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$promhttp_8h.html",tooltip="Provides a HTTP endpoint for metric exposition References: "];
+}
diff --git a/docs/prom__counter_8h__dep__incl.map b/docs/prom__counter_8h__dep__incl.map
new file mode 100644
index 0000000..41bb7ee
--- /dev/null
+++ b/docs/prom__counter_8h__dep__incl.map
@@ -0,0 +1,3 @@
+<map id="prom/include/prom_counter.h" name="prom/include/prom_counter.h">
+<area shape="rect" id="node2" href="$prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="33,80,190,107"/>
+</map>
diff --git a/docs/prom__counter_8h__dep__incl.md5 b/docs/prom__counter_8h__dep__incl.md5
new file mode 100644
index 0000000..ed9ac7f
--- /dev/null
+++ b/docs/prom__counter_8h__dep__incl.md5
@@ -0,0 +1 @@
+9a9ee0d2f72c4aa1d328ca051d3fd824 \ No newline at end of file
diff --git a/docs/prom__counter_8h__dep__incl.png b/docs/prom__counter_8h__dep__incl.png
new file mode 100644
index 0000000..5e2a532
--- /dev/null
+++ b/docs/prom__counter_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom__counter_8h__incl.dot b/docs/prom__counter_8h__incl.dot
new file mode 100644
index 0000000..0ee6c85
--- /dev/null
+++ b/docs/prom__counter_8h__incl.dot
@@ -0,0 +1,18 @@
+digraph "prom/include/prom_counter.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node0 [label="prom/include/prom_counter.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node0 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 [label="stdlib.h",height=0.2,width=0.4,color="grey75", fillcolor="white", style="filled"];
+ Node0 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node2 [label="prom_errors.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__errors_8h.html",tooltip="Prometheus client errors. "];
+ Node0 -> Node3 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric_8h.html"];
+ Node3 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 [label="prom_metric_sample.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample_8h.html"];
+ Node4 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node5 [label="prom_metric_sample\l_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample__histogram_8h.html"];
+ Node5 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom__counter_8h__incl.map b/docs/prom__counter_8h__incl.map
new file mode 100644
index 0000000..131414f
--- /dev/null
+++ b/docs/prom__counter_8h__incl.map
@@ -0,0 +1,5 @@
+<map id="prom/include/prom_counter.h" name="prom/include/prom_counter.h">
+<area shape="rect" id="node3" href="$prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="129,80,246,107"/>
+<area shape="rect" id="node4" href="$prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="5,162,177,189"/>
+<area shape="rect" id="node5" href="$prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="202,155,362,196"/>
+</map>
diff --git a/docs/prom__counter_8h__incl.md5 b/docs/prom__counter_8h__incl.md5
new file mode 100644
index 0000000..719df5b
--- /dev/null
+++ b/docs/prom__counter_8h__incl.md5
@@ -0,0 +1 @@
+f79807ba83430dd8bb7c3aa0fdf691fd \ No newline at end of file
diff --git a/docs/prom__counter_8h__incl.png b/docs/prom__counter_8h__incl.png
new file mode 100644
index 0000000..ca92dd3
--- /dev/null
+++ b/docs/prom__counter_8h__incl.png
Binary files differ
diff --git a/docs/prom__counter_8h_source.html b/docs/prom__counter_8h_source.html
new file mode 100644
index 0000000..cf59fea
--- /dev/null
+++ b/docs/prom__counter_8h_source.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_counter.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_counter.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom__counter_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00017"></a><span class="lineno"> 17</span>&#160;</div><div class="line"><a name="l00018"></a><span class="lineno"> 18</span>&#160;<span class="preprocessor">#ifndef PROM_COUNTER_INCLUDED</span></div><div class="line"><a name="l00019"></a><span class="lineno"> 19</span>&#160;<span class="preprocessor">#define PROM_COUNTER_INCLUDED</span></div><div class="line"><a name="l00020"></a><span class="lineno"> 20</span>&#160;</div><div class="line"><a name="l00021"></a><span class="lineno"> 21</span>&#160;<span class="preprocessor">#include &lt;stdlib.h&gt;</span></div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;</div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__metric_8h.html">prom_metric.h</a>&quot;</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;</div><div class="line"><a name="l00036"></a><span class="lineno"><a class="line" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606"> 36</a></span>&#160;<span class="keyword">typedef</span> <a class="code" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> <a class="code" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a>;</div><div class="line"><a name="l00037"></a><span class="lineno"> 37</span>&#160;</div><div class="line"><a name="l00041"></a><span class="lineno"> 41</span>&#160;<a class="code" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a>* <a class="code" href="prom__counter_8h.html#a3302a9f1a3556d17af9af29729be2651">prom_counter_new</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *name,</div><div class="line"><a name="l00042"></a><span class="lineno"> 42</span>&#160; <span class="keyword">const</span> <span class="keywordtype">char</span> *help,</div><div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160; <span class="keywordtype">size_t</span> label_key_count,</div><div class="line"><a name="l00044"></a><span class="lineno"> 44</span>&#160; <span class="keyword">const</span> <span class="keywordtype">char</span> **label_keys);</div><div class="line"><a name="l00045"></a><span class="lineno"> 45</span>&#160;</div><div class="line"><a name="l00049"></a><span class="lineno"> 49</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__counter_8h.html#ac36abc71c11df1e774c8c102b1fdb78d">prom_counter_destroy</a>(<a class="code" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a> *<span class="keyword">self</span>);</div><div class="line"><a name="l00050"></a><span class="lineno"> 50</span>&#160;</div><div class="line"><a name="l00051"></a><span class="lineno"> 51</span>&#160;</div><div class="line"><a name="l00055"></a><span class="lineno"> 55</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__counter_8h.html#a315695fdd8b9b6fa59904bb2e35bfa35">prom_counter_inc</a>(<a class="code" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a> *<span class="keyword">self</span>, <span class="keyword">const</span> <span class="keywordtype">char</span> **label_values);</div><div class="line"><a name="l00056"></a><span class="lineno"> 56</span>&#160;</div><div class="line"><a name="l00057"></a><span class="lineno"> 57</span>&#160;</div><div class="line"><a name="l00061"></a><span class="lineno"> 61</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__counter_8h.html#addd8a7efc39e17d30b2267e5a0a626db">prom_counter_add</a>(<a class="code" href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a> *<span class="keyword">self</span>, <span class="keywordtype">double</span> r_value, <span class="keyword">const</span> <span class="keywordtype">char</span> **label_values);</div><div class="line"><a name="l00062"></a><span class="lineno"> 62</span>&#160;</div><div class="line"><a name="l00063"></a><span class="lineno"> 63</span>&#160;<span class="preprocessor">#endif // PROM_COUNTER_INCLUDED</span></div><div class="ttc" id="prom__counter_8h_html_addd8a7efc39e17d30b2267e5a0a626db"><div class="ttname"><a href="prom__counter_8h.html#addd8a7efc39e17d30b2267e5a0a626db">prom_counter_add</a></div><div class="ttdeci">int prom_counter_add(prom_counter_t *self, double r_value, const char **label_values)</div><div class="ttdoc">Add the value to the prom_counter. </div></div>
+<div class="ttc" id="prom__counter_8h_html_a315695fdd8b9b6fa59904bb2e35bfa35"><div class="ttname"><a href="prom__counter_8h.html#a315695fdd8b9b6fa59904bb2e35bfa35">prom_counter_inc</a></div><div class="ttdeci">int prom_counter_inc(prom_counter_t *self, const char **label_values)</div><div class="ttdoc">Increment the prom_counter by 1. </div></div>
+<div class="ttc" id="prom__metric_8h_html_afd1bd014c48955d6c2c36aa8a8cbb889"><div class="ttname"><a href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a></div><div class="ttdeci">struct prom_metric prom_metric_t</div><div class="ttdoc">A prometheus metric. </div><div class="ttdef"><b>Definition:</b> prom_metric.h:34</div></div>
+<div class="ttc" id="prom__counter_8h_html_a814ceed99a1d618334e51f4d0e160606"><div class="ttname"><a href="prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606">prom_counter_t</a></div><div class="ttdeci">prom_metric_t prom_counter_t</div><div class="ttdoc">A prometheus counter. </div><div class="ttdef"><b>Definition:</b> prom_counter.h:36</div></div>
+<div class="ttc" id="prom__counter_8h_html_ac36abc71c11df1e774c8c102b1fdb78d"><div class="ttname"><a href="prom__counter_8h.html#ac36abc71c11df1e774c8c102b1fdb78d">prom_counter_destroy</a></div><div class="ttdeci">int prom_counter_destroy(prom_counter_t *self)</div><div class="ttdoc">Destroys a pointer to a prom_counter. </div></div>
+<div class="ttc" id="prom__metric_8h_html"><div class="ttname"><a href="prom__metric_8h.html">prom_metric.h</a></div><div class="ttdoc">Functions for retrieving metric samples from metrics given an ordered set of labels. </div></div>
+<div class="ttc" id="prom__counter_8h_html_a3302a9f1a3556d17af9af29729be2651"><div class="ttname"><a href="prom__counter_8h.html#a3302a9f1a3556d17af9af29729be2651">prom_counter_new</a></div><div class="ttdeci">prom_counter_t * prom_counter_new(const char *name, const char *help, size_t label_key_count, const char **label_keys)</div><div class="ttdoc">Returns a pointer to a prom_counter. </div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__errors_8h.html b/docs/prom__errors_8h.html
new file mode 100644
index 0000000..af72f2a
--- /dev/null
+++ b/docs/prom__errors_8h.html
@@ -0,0 +1,136 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_errors.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#enum-members">Enumerations</a> &#124;
+<a href="#func-members">Functions</a> &#124;
+<a href="#var-members">Variables</a> </div>
+ <div class="headertitle">
+<div class="title">prom_errors.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Prometheus client errors.
+<a href="#details">More...</a></p>
+<div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__errors_8h__dep__incl.png" border="0" usemap="#prom_2include_2prom__errors_8hdep" alt=""/></div>
+<map name="prom_2include_2prom__errors_8hdep" id="prom_2include_2prom__errors_8hdep">
+<area shape="rect" id="node2" href="prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="93,244,312,271"/>
+<area shape="rect" id="node3" href="prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="389,408,547,435"/>
+<area shape="rect" id="node4" href="prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="223,319,431,360"/>
+<area shape="rect" id="node5" href="prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="67,80,261,121"/>
+<area shape="rect" id="node7" href="prom__counter_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#counter " alt="" coords="487,244,699,271"/>
+<area shape="rect" id="node8" href="prom__gauge_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#gauge " alt="" coords="723,244,927,271"/>
+<area shape="rect" id="node9" href="prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="1003,244,1234,271"/>
+<area shape="rect" id="node10" href="prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="393,80,588,121"/>
+<area shape="rect" id="node6" href="prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="387,169,594,196"/>
+</map>
+</div>
+</div>
+<p><a href="prom__errors_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:a8015021744851db1ed84f9602be7462f"><td class="memItemLeft" align="right" valign="top"><a id="a8015021744851db1ed84f9602be7462f"></a>
+typedef enum <a class="el" href="prom__errors_8h.html#ae9dcc70f3217ae6f5cd331dbdef06602">prom_return_code</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__errors_8h.html#a8015021744851db1ed84f9602be7462f">int</a></td></tr>
+<tr class="memdesc:a8015021744851db1ed84f9602be7462f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Contains returns codes for functions. <br /></td></tr>
+<tr class="separator:a8015021744851db1ed84f9602be7462f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="enum-members"></a>
+Enumerations</h2></td></tr>
+<tr class="memitem:ae9dcc70f3217ae6f5cd331dbdef06602"><td class="memItemLeft" align="right" valign="top"><a id="ae9dcc70f3217ae6f5cd331dbdef06602"></a>enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__errors_8h.html#ae9dcc70f3217ae6f5cd331dbdef06602">prom_return_code</a> { <b>PROM_SUCCESS</b>,
+<b>PROM_FAILURE</b>
+ }<tr class="memdesc:ae9dcc70f3217ae6f5cd331dbdef06602"><td class="mdescLeft">&#160;</td><td class="mdescRight">Contains returns codes for functions. <br /></td></tr>
+</td></tr>
+<tr class="separator:ae9dcc70f3217ae6f5cd331dbdef06602"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:abf8afd95318ab657b0a641477ff459a9"><td class="memItemLeft" align="right" valign="top"><a id="abf8afd95318ab657b0a641477ff459a9"></a>
+const char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__errors_8h.html#abf8afd95318ab657b0a641477ff459a9">prom_err_get</a> (<a class="el" href="prom__errors_8h.html#a8015021744851db1ed84f9602be7462f">int</a>)</td></tr>
+<tr class="memdesc:abf8afd95318ab657b0a641477ff459a9"><td class="mdescLeft">&#160;</td><td class="mdescRight">Retrieve the string value for the given int. <br /></td></tr>
+<tr class="separator:abf8afd95318ab657b0a641477ff459a9"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="var-members"></a>
+Variables</h2></td></tr>
+<tr class="memitem:a5c9aa17d6a3215d88d05d65a0f966973"><td class="memItemLeft" align="right" valign="top"><a id="a5c9aa17d6a3215d88d05d65a0f966973"></a>
+const char *&#160;</td><td class="memItemRight" valign="bottom"><b>prom_return_code_map</b> [2]</td></tr>
+<tr class="separator:a5c9aa17d6a3215d88d05d65a0f966973"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Prometheus client errors. </p>
+</div></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__errors_8h__dep__incl.dot b/docs/prom__errors_8h__dep__incl.dot
new file mode 100644
index 0000000..d95d597
--- /dev/null
+++ b/docs/prom__errors_8h__dep__incl.dot
@@ -0,0 +1,40 @@
+digraph "prom/include/prom_errors.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node1 [label="prom/include/prom_errors.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node1 -> Node2 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node2 [label="prom/include/prom_collector.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector_8h.html",tooltip="A Prometheus collector returns a collection of metrics. "];
+ Node2 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom_8h.html",tooltip="Include prom.h to include the entire public API. "];
+ Node3 -> Node4 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$promhttp_8h.html",tooltip="Provides a HTTP endpoint for metric exposition References: "];
+ Node2 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node5 [label="prom/include/prom_collector\l_registry.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector__registry_8h.html",tooltip="The collector registry registers collectors for metric exposition. "];
+ Node5 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 -> Node6 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node6 [label="prom/include/prom_metric\l_sample.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample_8h.html"];
+ Node6 -> Node7 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 [label="prom/include/prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric_8h.html"];
+ Node7 -> Node2 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 -> Node8 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 [label="prom/include/prom_counter.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__counter_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#counter "];
+ Node8 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 -> Node9 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node9 [label="prom/include/prom_gauge.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__gauge_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#gauge "];
+ Node9 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 -> Node10 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node10 [label="prom/include/prom_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__histogram_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#histogram "];
+ Node10 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node6 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 -> Node11 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node11 [label="prom/include/prom_metric\l_sample_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample__histogram_8h.html"];
+ Node11 -> Node7 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 -> Node8 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 -> Node9 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 -> Node10 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom__errors_8h__dep__incl.map b/docs/prom__errors_8h__dep__incl.map
new file mode 100644
index 0000000..40920fe
--- /dev/null
+++ b/docs/prom__errors_8h__dep__incl.map
@@ -0,0 +1,11 @@
+<map id="prom/include/prom_errors.h" name="prom/include/prom_errors.h">
+<area shape="rect" id="node2" href="$prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="93,244,312,271"/>
+<area shape="rect" id="node3" href="$prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="389,408,547,435"/>
+<area shape="rect" id="node4" href="$prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="223,319,431,360"/>
+<area shape="rect" id="node5" href="$prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="67,80,261,121"/>
+<area shape="rect" id="node7" href="$prom__counter_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#counter " alt="" coords="487,244,699,271"/>
+<area shape="rect" id="node8" href="$prom__gauge_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#gauge " alt="" coords="723,244,927,271"/>
+<area shape="rect" id="node9" href="$prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="1003,244,1234,271"/>
+<area shape="rect" id="node10" href="$prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="393,80,588,121"/>
+<area shape="rect" id="node6" href="$prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="387,169,594,196"/>
+</map>
diff --git a/docs/prom__errors_8h__dep__incl.md5 b/docs/prom__errors_8h__dep__incl.md5
new file mode 100644
index 0000000..903362e
--- /dev/null
+++ b/docs/prom__errors_8h__dep__incl.md5
@@ -0,0 +1 @@
+5ec144d3428dc6e5fd755b94a8cb2c0f \ No newline at end of file
diff --git a/docs/prom__errors_8h__dep__incl.png b/docs/prom__errors_8h__dep__incl.png
new file mode 100644
index 0000000..62bcc90
--- /dev/null
+++ b/docs/prom__errors_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom__errors_8h_source.html b/docs/prom__errors_8h_source.html
new file mode 100644
index 0000000..92adc59
--- /dev/null
+++ b/docs/prom__errors_8h_source.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_errors.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_errors.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom__errors_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span>&#160;<span class="preprocessor">#ifndef PROM_ERRORS_INCLUDED</span></div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span>&#160;<span class="preprocessor">#define PROM_ERRORS_INCLUDED</span></div><div class="line"><a name="l00028"></a><span class="lineno"> 28</span>&#160;</div><div class="line"><a name="l00032"></a><span class="lineno"><a class="line" href="prom__errors_8h.html#ae9dcc70f3217ae6f5cd331dbdef06602"> 32</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">enum</span> <a class="code" href="prom__errors_8h.html#ae9dcc70f3217ae6f5cd331dbdef06602">prom_return_code</a> {</div><div class="line"><a name="l00033"></a><span class="lineno"> 33</span>&#160; PROM_SUCCESS,</div><div class="line"><a name="l00034"></a><span class="lineno"> 34</span>&#160; PROM_FAILURE</div><div class="line"><a name="l00035"></a><span class="lineno"> 35</span>&#160;} <a class="code" href="prom__errors_8h.html#a8015021744851db1ed84f9602be7462f">int</a>;</div><div class="line"><a name="l00036"></a><span class="lineno"> 36</span>&#160;</div><div class="line"><a name="l00037"></a><span class="lineno"> 37</span>&#160;</div><div class="line"><a name="l00038"></a><span class="lineno"> 38</span>&#160;<span class="keyword">const</span> <span class="keywordtype">char</span>* prom_return_code_map[2];</div><div class="line"><a name="l00039"></a><span class="lineno"> 39</span>&#160;</div><div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160;<span class="keyword">const</span> <span class="keywordtype">char</span>* <a class="code" href="prom__errors_8h.html#abf8afd95318ab657b0a641477ff459a9">prom_err_get</a>(<a class="code" href="prom__errors_8h.html#a8015021744851db1ed84f9602be7462f">int</a>);</div><div class="line"><a name="l00044"></a><span class="lineno"> 44</span>&#160;</div><div class="line"><a name="l00045"></a><span class="lineno"> 45</span>&#160;<span class="preprocessor">#endif // PROM_ERRORS_INCLUDED</span></div><div class="ttc" id="prom__errors_8h_html_a8015021744851db1ed84f9602be7462f"><div class="ttname"><a href="prom__errors_8h.html#a8015021744851db1ed84f9602be7462f">int</a></div><div class="ttdeci">enum prom_return_code int</div><div class="ttdoc">Contains returns codes for functions. </div></div>
+<div class="ttc" id="prom__errors_8h_html_ae9dcc70f3217ae6f5cd331dbdef06602"><div class="ttname"><a href="prom__errors_8h.html#ae9dcc70f3217ae6f5cd331dbdef06602">prom_return_code</a></div><div class="ttdeci">prom_return_code</div><div class="ttdoc">Contains returns codes for functions. </div><div class="ttdef"><b>Definition:</b> prom_errors.h:32</div></div>
+<div class="ttc" id="prom__errors_8h_html_abf8afd95318ab657b0a641477ff459a9"><div class="ttname"><a href="prom__errors_8h.html#abf8afd95318ab657b0a641477ff459a9">prom_err_get</a></div><div class="ttdeci">const char * prom_err_get(int)</div><div class="ttdoc">Retrieve the string value for the given int. </div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__gauge_8h.html b/docs/prom__gauge_8h.html
new file mode 100644
index 0000000..ba0c18c
--- /dev/null
+++ b/docs/prom__gauge_8h.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_gauge.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">prom_gauge.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p><a href="https://prometheus.io/docs/concepts/metric_types/#gauge">https://prometheus.io/docs/concepts/metric_types/#gauge</a>
+<a href="#details">More...</a></p>
+<div class="textblock"><code>#include &lt;stdlib.h&gt;</code><br />
+<code>#include &quot;<a class="el" href="prom__metric_8h_source.html">prom_metric.h</a>&quot;</code><br />
+</div><div class="textblock"><div class="dynheader">
+Include dependency graph for prom_gauge.h:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__gauge_8h__incl.png" border="0" usemap="#prom_2include_2prom__gauge_8h" alt=""/></div>
+<map name="prom_2include_2prom__gauge_8h" id="prom_2include_2prom__gauge_8h">
+<area shape="rect" id="node3" href="prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="129,80,246,107"/>
+<area shape="rect" id="node4" href="prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="5,162,177,189"/>
+<area shape="rect" id="node5" href="prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="202,155,362,196"/>
+</map>
+</div>
+</div><div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__gauge_8h__dep__incl.png" border="0" usemap="#prom_2include_2prom__gauge_8hdep" alt=""/></div>
+<map name="prom_2include_2prom__gauge_8hdep" id="prom_2include_2prom__gauge_8hdep">
+<area shape="rect" id="node2" href="prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="29,80,186,107"/>
+</map>
+</div>
+</div>
+<p><a href="prom__gauge_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:a09417d7e7bab055a48f8e13181d136a5"><td class="memItemLeft" align="right" valign="top">typedef <a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a></td></tr>
+<tr class="memdesc:a09417d7e7bab055a48f8e13181d136a5"><td class="mdescLeft">&#160;</td><td class="mdescRight">A prometheus gauge. <a href="#a09417d7e7bab055a48f8e13181d136a5">More...</a><br /></td></tr>
+<tr class="separator:a09417d7e7bab055a48f8e13181d136a5"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:a5ecd07c83cf0981944a9256914571d70"><td class="memItemLeft" align="right" valign="top"><a id="a5ecd07c83cf0981944a9256914571d70"></a>
+<a class="el" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__gauge_8h.html#a5ecd07c83cf0981944a9256914571d70">prom_gauge_new</a> (const char *name, const char *help, size_t label_key_count, const char **label_keys)</td></tr>
+<tr class="memdesc:a5ecd07c83cf0981944a9256914571d70"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a pointer to a prom_gauge. <br /></td></tr>
+<tr class="separator:a5ecd07c83cf0981944a9256914571d70"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a2fc5dc11239cefdf59ae978be4bfd789"><td class="memItemLeft" align="right" valign="top"><a id="a2fc5dc11239cefdf59ae978be4bfd789"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__gauge_8h.html#a2fc5dc11239cefdf59ae978be4bfd789">prom_gauge_destroy</a> (<a class="el" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *self)</td></tr>
+<tr class="memdesc:a2fc5dc11239cefdf59ae978be4bfd789"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroys a pointer to a prom_gauge. <br /></td></tr>
+<tr class="separator:a2fc5dc11239cefdf59ae978be4bfd789"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad953b12ea1f8a3c3b7a39e6c260d07a2"><td class="memItemLeft" align="right" valign="top"><a id="ad953b12ea1f8a3c3b7a39e6c260d07a2"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__gauge_8h.html#ad953b12ea1f8a3c3b7a39e6c260d07a2">prom_gauge_inc</a> (<a class="el" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *self, const char **label_values)</td></tr>
+<tr class="memdesc:ad953b12ea1f8a3c3b7a39e6c260d07a2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Increment the prom_gauge by 1. <br /></td></tr>
+<tr class="separator:ad953b12ea1f8a3c3b7a39e6c260d07a2"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aa351ef4f2d917d7dae914df6d81c547b"><td class="memItemLeft" align="right" valign="top"><a id="aa351ef4f2d917d7dae914df6d81c547b"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__gauge_8h.html#aa351ef4f2d917d7dae914df6d81c547b">prom_gauge_dec</a> (<a class="el" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *self, const char **label_values)</td></tr>
+<tr class="memdesc:aa351ef4f2d917d7dae914df6d81c547b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Descrement the prom_gauge by 1. <br /></td></tr>
+<tr class="separator:aa351ef4f2d917d7dae914df6d81c547b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a96bc5b32abee5f99fbd4ae11bebd44c8"><td class="memItemLeft" align="right" valign="top"><a id="a96bc5b32abee5f99fbd4ae11bebd44c8"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__gauge_8h.html#a96bc5b32abee5f99fbd4ae11bebd44c8">prom_gauge_add</a> (<a class="el" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *self, double r_value, const char **label_values)</td></tr>
+<tr class="memdesc:a96bc5b32abee5f99fbd4ae11bebd44c8"><td class="mdescLeft">&#160;</td><td class="mdescRight">Add the value to the prom_gauge. <br /></td></tr>
+<tr class="separator:a96bc5b32abee5f99fbd4ae11bebd44c8"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a7ae193d586176bff82a39cd65e2bc999"><td class="memItemLeft" align="right" valign="top"><a id="a7ae193d586176bff82a39cd65e2bc999"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__gauge_8h.html#a7ae193d586176bff82a39cd65e2bc999">prom_gauge_sub</a> (<a class="el" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *self, double r_value, const char **label_values)</td></tr>
+<tr class="memdesc:a7ae193d586176bff82a39cd65e2bc999"><td class="mdescLeft">&#160;</td><td class="mdescRight">Subtract the value from the prom_gauge. <br /></td></tr>
+<tr class="separator:a7ae193d586176bff82a39cd65e2bc999"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a04210b18bfb89aa6f3ddc72d7851a528"><td class="memItemLeft" align="right" valign="top"><a id="a04210b18bfb89aa6f3ddc72d7851a528"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__gauge_8h.html#a04210b18bfb89aa6f3ddc72d7851a528">prom_gauge_set</a> (<a class="el" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *self, double r_value, const char **label_values)</td></tr>
+<tr class="memdesc:a04210b18bfb89aa6f3ddc72d7851a528"><td class="mdescLeft">&#160;</td><td class="mdescRight">Set the value for the prom_gauge. <br /></td></tr>
+<tr class="separator:a04210b18bfb89aa6f3ddc72d7851a528"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p><a href="https://prometheus.io/docs/concepts/metric_types/#gauge">https://prometheus.io/docs/concepts/metric_types/#gauge</a> </p>
+</div><h2 class="groupheader">Typedef Documentation</h2>
+<a id="a09417d7e7bab055a48f8e13181d136a5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a09417d7e7bab055a48f8e13181d136a5">&#9670;&nbsp;</a></span>prom_gauge_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef <a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> <a class="el" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>A prometheus gauge. </p>
+<p>References</p><ul>
+<li>See <a href="https://prometheus.io/docs/concepts/metric_types/#gauge">https://prometheus.io/docs/concepts/metric_types/#gauge</a> </li>
+</ul>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__gauge_8h__dep__incl.dot b/docs/prom__gauge_8h__dep__incl.dot
new file mode 100644
index 0000000..921a387
--- /dev/null
+++ b/docs/prom__gauge_8h__dep__incl.dot
@@ -0,0 +1,10 @@
+digraph "prom/include/prom_gauge.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node6 [label="prom/include/prom_gauge.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node6 -> Node7 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom_8h.html",tooltip="Include prom.h to include the entire public API. "];
+ Node7 -> Node8 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$promhttp_8h.html",tooltip="Provides a HTTP endpoint for metric exposition References: "];
+}
diff --git a/docs/prom__gauge_8h__dep__incl.map b/docs/prom__gauge_8h__dep__incl.map
new file mode 100644
index 0000000..39a4520
--- /dev/null
+++ b/docs/prom__gauge_8h__dep__incl.map
@@ -0,0 +1,3 @@
+<map id="prom/include/prom_gauge.h" name="prom/include/prom_gauge.h">
+<area shape="rect" id="node2" href="$prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="29,80,186,107"/>
+</map>
diff --git a/docs/prom__gauge_8h__dep__incl.md5 b/docs/prom__gauge_8h__dep__incl.md5
new file mode 100644
index 0000000..f378593
--- /dev/null
+++ b/docs/prom__gauge_8h__dep__incl.md5
@@ -0,0 +1 @@
+9c764603425f807c3f45ae990afbb05b \ No newline at end of file
diff --git a/docs/prom__gauge_8h__dep__incl.png b/docs/prom__gauge_8h__dep__incl.png
new file mode 100644
index 0000000..67347f7
--- /dev/null
+++ b/docs/prom__gauge_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom__gauge_8h__incl.dot b/docs/prom__gauge_8h__incl.dot
new file mode 100644
index 0000000..936200a
--- /dev/null
+++ b/docs/prom__gauge_8h__incl.dot
@@ -0,0 +1,18 @@
+digraph "prom/include/prom_gauge.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node0 [label="prom/include/prom_gauge.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node0 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 [label="stdlib.h",height=0.2,width=0.4,color="grey75", fillcolor="white", style="filled"];
+ Node0 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node2 [label="prom_errors.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__errors_8h.html",tooltip="Prometheus client errors. "];
+ Node0 -> Node3 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric_8h.html"];
+ Node3 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 [label="prom_metric_sample.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample_8h.html"];
+ Node4 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node5 [label="prom_metric_sample\l_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample__histogram_8h.html"];
+ Node5 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom__gauge_8h__incl.map b/docs/prom__gauge_8h__incl.map
new file mode 100644
index 0000000..c58f6c9
--- /dev/null
+++ b/docs/prom__gauge_8h__incl.map
@@ -0,0 +1,5 @@
+<map id="prom/include/prom_gauge.h" name="prom/include/prom_gauge.h">
+<area shape="rect" id="node3" href="$prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="129,80,246,107"/>
+<area shape="rect" id="node4" href="$prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="5,162,177,189"/>
+<area shape="rect" id="node5" href="$prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="202,155,362,196"/>
+</map>
diff --git a/docs/prom__gauge_8h__incl.md5 b/docs/prom__gauge_8h__incl.md5
new file mode 100644
index 0000000..d1576d3
--- /dev/null
+++ b/docs/prom__gauge_8h__incl.md5
@@ -0,0 +1 @@
+47f818bf60543a61a23ce02c8326abf9 \ No newline at end of file
diff --git a/docs/prom__gauge_8h__incl.png b/docs/prom__gauge_8h__incl.png
new file mode 100644
index 0000000..5db9e55
--- /dev/null
+++ b/docs/prom__gauge_8h__incl.png
Binary files differ
diff --git a/docs/prom__gauge_8h_source.html b/docs/prom__gauge_8h_source.html
new file mode 100644
index 0000000..8b0e466
--- /dev/null
+++ b/docs/prom__gauge_8h_source.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_gauge.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_gauge.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom__gauge_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;<span class="preprocessor">#ifndef PROM_GAUGE_INCLUDED</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="preprocessor">#define PROM_GAUGE_INCLUDED</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;</div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160;<span class="preprocessor">#include &lt;stdlib.h&gt;</span></div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span>&#160;</div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__metric_8h.html">prom_metric.h</a>&quot;</span></div><div class="line"><a name="l00028"></a><span class="lineno"> 28</span>&#160;</div><div class="line"><a name="l00035"></a><span class="lineno"><a class="line" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5"> 35</a></span>&#160;<span class="keyword">typedef</span> <a class="code" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> <a class="code" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a>;</div><div class="line"><a name="l00036"></a><span class="lineno"> 36</span>&#160;</div><div class="line"><a name="l00040"></a><span class="lineno"> 40</span>&#160;<a class="code" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a>* <a class="code" href="prom__gauge_8h.html#a5ecd07c83cf0981944a9256914571d70">prom_gauge_new</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *name,</div><div class="line"><a name="l00041"></a><span class="lineno"> 41</span>&#160; <span class="keyword">const</span> <span class="keywordtype">char</span> *help,</div><div class="line"><a name="l00042"></a><span class="lineno"> 42</span>&#160; <span class="keywordtype">size_t</span> label_key_count,</div><div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160; <span class="keyword">const</span> <span class="keywordtype">char</span> **label_keys);</div><div class="line"><a name="l00044"></a><span class="lineno"> 44</span>&#160;</div><div class="line"><a name="l00048"></a><span class="lineno"> 48</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__gauge_8h.html#a2fc5dc11239cefdf59ae978be4bfd789">prom_gauge_destroy</a>(<a class="code" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *<span class="keyword">self</span>);</div><div class="line"><a name="l00049"></a><span class="lineno"> 49</span>&#160;</div><div class="line"><a name="l00050"></a><span class="lineno"> 50</span>&#160;</div><div class="line"><a name="l00054"></a><span class="lineno"> 54</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__gauge_8h.html#ad953b12ea1f8a3c3b7a39e6c260d07a2">prom_gauge_inc</a>(<a class="code" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *<span class="keyword">self</span>, <span class="keyword">const</span> <span class="keywordtype">char</span> **label_values);</div><div class="line"><a name="l00055"></a><span class="lineno"> 55</span>&#160;</div><div class="line"><a name="l00056"></a><span class="lineno"> 56</span>&#160;</div><div class="line"><a name="l00060"></a><span class="lineno"> 60</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__gauge_8h.html#aa351ef4f2d917d7dae914df6d81c547b">prom_gauge_dec</a>(<a class="code" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *<span class="keyword">self</span>, <span class="keyword">const</span> <span class="keywordtype">char</span> **label_values);</div><div class="line"><a name="l00061"></a><span class="lineno"> 61</span>&#160;</div><div class="line"><a name="l00062"></a><span class="lineno"> 62</span>&#160;</div><div class="line"><a name="l00066"></a><span class="lineno"> 66</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__gauge_8h.html#a96bc5b32abee5f99fbd4ae11bebd44c8">prom_gauge_add</a>(<a class="code" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *<span class="keyword">self</span>, <span class="keywordtype">double</span> r_value, <span class="keyword">const</span> <span class="keywordtype">char</span> **label_values);</div><div class="line"><a name="l00067"></a><span class="lineno"> 67</span>&#160;</div><div class="line"><a name="l00068"></a><span class="lineno"> 68</span>&#160;</div><div class="line"><a name="l00072"></a><span class="lineno"> 72</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__gauge_8h.html#a7ae193d586176bff82a39cd65e2bc999">prom_gauge_sub</a>(<a class="code" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *<span class="keyword">self</span>, <span class="keywordtype">double</span> r_value, <span class="keyword">const</span> <span class="keywordtype">char</span> **label_values);</div><div class="line"><a name="l00073"></a><span class="lineno"> 73</span>&#160;</div><div class="line"><a name="l00074"></a><span class="lineno"> 74</span>&#160;</div><div class="line"><a name="l00078"></a><span class="lineno"> 78</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__gauge_8h.html#a04210b18bfb89aa6f3ddc72d7851a528">prom_gauge_set</a>(<a class="code" href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a> *<span class="keyword">self</span>, <span class="keywordtype">double</span> r_value, <span class="keyword">const</span> <span class="keywordtype">char</span> **label_values);</div><div class="line"><a name="l00079"></a><span class="lineno"> 79</span>&#160;</div><div class="line"><a name="l00080"></a><span class="lineno"> 80</span>&#160;<span class="preprocessor">#endif // PROM_GAUGE_INCLUDED</span></div><div class="ttc" id="prom__gauge_8h_html_a5ecd07c83cf0981944a9256914571d70"><div class="ttname"><a href="prom__gauge_8h.html#a5ecd07c83cf0981944a9256914571d70">prom_gauge_new</a></div><div class="ttdeci">prom_gauge_t * prom_gauge_new(const char *name, const char *help, size_t label_key_count, const char **label_keys)</div><div class="ttdoc">Returns a pointer to a prom_gauge. </div></div>
+<div class="ttc" id="prom__metric_8h_html_afd1bd014c48955d6c2c36aa8a8cbb889"><div class="ttname"><a href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a></div><div class="ttdeci">struct prom_metric prom_metric_t</div><div class="ttdoc">A prometheus metric. </div><div class="ttdef"><b>Definition:</b> prom_metric.h:34</div></div>
+<div class="ttc" id="prom__gauge_8h_html_a7ae193d586176bff82a39cd65e2bc999"><div class="ttname"><a href="prom__gauge_8h.html#a7ae193d586176bff82a39cd65e2bc999">prom_gauge_sub</a></div><div class="ttdeci">int prom_gauge_sub(prom_gauge_t *self, double r_value, const char **label_values)</div><div class="ttdoc">Subtract the value from the prom_gauge. </div></div>
+<div class="ttc" id="prom__gauge_8h_html_aa351ef4f2d917d7dae914df6d81c547b"><div class="ttname"><a href="prom__gauge_8h.html#aa351ef4f2d917d7dae914df6d81c547b">prom_gauge_dec</a></div><div class="ttdeci">int prom_gauge_dec(prom_gauge_t *self, const char **label_values)</div><div class="ttdoc">Descrement the prom_gauge by 1. </div></div>
+<div class="ttc" id="prom__gauge_8h_html_a09417d7e7bab055a48f8e13181d136a5"><div class="ttname"><a href="prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5">prom_gauge_t</a></div><div class="ttdeci">prom_metric_t prom_gauge_t</div><div class="ttdoc">A prometheus gauge. </div><div class="ttdef"><b>Definition:</b> prom_gauge.h:35</div></div>
+<div class="ttc" id="prom__gauge_8h_html_a96bc5b32abee5f99fbd4ae11bebd44c8"><div class="ttname"><a href="prom__gauge_8h.html#a96bc5b32abee5f99fbd4ae11bebd44c8">prom_gauge_add</a></div><div class="ttdeci">int prom_gauge_add(prom_gauge_t *self, double r_value, const char **label_values)</div><div class="ttdoc">Add the value to the prom_gauge. </div></div>
+<div class="ttc" id="prom__gauge_8h_html_ad953b12ea1f8a3c3b7a39e6c260d07a2"><div class="ttname"><a href="prom__gauge_8h.html#ad953b12ea1f8a3c3b7a39e6c260d07a2">prom_gauge_inc</a></div><div class="ttdeci">int prom_gauge_inc(prom_gauge_t *self, const char **label_values)</div><div class="ttdoc">Increment the prom_gauge by 1. </div></div>
+<div class="ttc" id="prom__gauge_8h_html_a04210b18bfb89aa6f3ddc72d7851a528"><div class="ttname"><a href="prom__gauge_8h.html#a04210b18bfb89aa6f3ddc72d7851a528">prom_gauge_set</a></div><div class="ttdeci">int prom_gauge_set(prom_gauge_t *self, double r_value, const char **label_values)</div><div class="ttdoc">Set the value for the prom_gauge. </div></div>
+<div class="ttc" id="prom__gauge_8h_html_a2fc5dc11239cefdf59ae978be4bfd789"><div class="ttname"><a href="prom__gauge_8h.html#a2fc5dc11239cefdf59ae978be4bfd789">prom_gauge_destroy</a></div><div class="ttdeci">int prom_gauge_destroy(prom_gauge_t *self)</div><div class="ttdoc">Destroys a pointer to a prom_gauge. </div></div>
+<div class="ttc" id="prom__metric_8h_html"><div class="ttname"><a href="prom__metric_8h.html">prom_metric.h</a></div><div class="ttdoc">Functions for retrieving metric samples from metrics given an ordered set of labels. </div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__histogram_8h.html b/docs/prom__histogram_8h.html
new file mode 100644
index 0000000..8c5e752
--- /dev/null
+++ b/docs/prom__histogram_8h.html
@@ -0,0 +1,153 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_histogram.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">prom_histogram.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p><a href="https://prometheus.io/docs/concepts/metric_types/#histogram">https://prometheus.io/docs/concepts/metric_types/#histogram</a>
+<a href="#details">More...</a></p>
+<div class="textblock"><code>#include &lt;stdlib.h&gt;</code><br />
+<code>#include &quot;<a class="el" href="prom__metric_8h_source.html">prom_metric.h</a>&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__histogram__buckets_8h_source.html">prom_histogram_buckets.h</a>&quot;</code><br />
+</div><div class="textblock"><div class="dynheader">
+Include dependency graph for prom_histogram.h:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__histogram_8h__incl.png" border="0" usemap="#prom_2include_2prom__histogram_8h" alt=""/></div>
+<map name="prom_2include_2prom__histogram_8h" id="prom_2include_2prom__histogram_8h">
+<area shape="rect" id="node3" href="prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="129,80,246,107"/>
+<area shape="rect" id="node6" href="prom__histogram__buckets_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="269,80,468,107"/>
+<area shape="rect" id="node4" href="prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="5,162,177,189"/>
+<area shape="rect" id="node5" href="prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="202,155,362,196"/>
+</map>
+</div>
+</div><div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__histogram_8h__dep__incl.png" border="0" usemap="#prom_2include_2prom__histogram_8hdep" alt=""/></div>
+<map name="prom_2include_2prom__histogram_8hdep" id="prom_2include_2prom__histogram_8hdep">
+<area shape="rect" id="node2" href="prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="42,80,199,107"/>
+</map>
+</div>
+</div>
+<p><a href="prom__histogram_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:a8c061924368d41c161025bf3d3cde9ae"><td class="memItemLeft" align="right" valign="top">typedef <a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram_t</a></td></tr>
+<tr class="memdesc:a8c061924368d41c161025bf3d3cde9ae"><td class="mdescLeft">&#160;</td><td class="mdescRight">A prometheus histogram. <a href="#a8c061924368d41c161025bf3d3cde9ae">More...</a><br /></td></tr>
+<tr class="separator:a8c061924368d41c161025bf3d3cde9ae"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ad42681e59e727f9e3d43bf0cdbba9a1b"><td class="memItemLeft" align="right" valign="top"><a id="ad42681e59e727f9e3d43bf0cdbba9a1b"></a>
+<a class="el" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__histogram_8h.html#ad42681e59e727f9e3d43bf0cdbba9a1b">prom_histogram_new</a> (const char *name, const char *help, <a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a> *buckets, size_t label_key_count, const char **label_keys)</td></tr>
+<tr class="memdesc:ad42681e59e727f9e3d43bf0cdbba9a1b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a pointer to a prom_histogram_t. <br /></td></tr>
+<tr class="separator:ad42681e59e727f9e3d43bf0cdbba9a1b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:af9067b27e7ab2abd815af0614bb35357"><td class="memItemLeft" align="right" valign="top"><a id="af9067b27e7ab2abd815af0614bb35357"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__histogram_8h.html#af9067b27e7ab2abd815af0614bb35357">prom_histogram_destroy</a> (<a class="el" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram_t</a> *self)</td></tr>
+<tr class="memdesc:af9067b27e7ab2abd815af0614bb35357"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroys a pointer to a prom_gauge. <br /></td></tr>
+<tr class="separator:af9067b27e7ab2abd815af0614bb35357"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a274e4b869c7d9239e9f47b3898210fbe"><td class="memItemLeft" align="right" valign="top"><a id="a274e4b869c7d9239e9f47b3898210fbe"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__histogram_8h.html#a274e4b869c7d9239e9f47b3898210fbe">prom_histogram_observe</a> (<a class="el" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram_t</a> *self, double value, const char **label_values)</td></tr>
+<tr class="memdesc:a274e4b869c7d9239e9f47b3898210fbe"><td class="mdescLeft">&#160;</td><td class="mdescRight">Observe the prom_histogram_t given the value and labells. <br /></td></tr>
+<tr class="separator:a274e4b869c7d9239e9f47b3898210fbe"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p><a href="https://prometheus.io/docs/concepts/metric_types/#histogram">https://prometheus.io/docs/concepts/metric_types/#histogram</a> </p>
+</div><h2 class="groupheader">Typedef Documentation</h2>
+<a id="a8c061924368d41c161025bf3d3cde9ae"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a8c061924368d41c161025bf3d3cde9ae">&#9670;&nbsp;</a></span>prom_histogram_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef <a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> <a class="el" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>A prometheus histogram. </p>
+<p>References</p><ul>
+<li>See <a href="https://prometheus.io/docs/concepts/metric_types/#histogram">https://prometheus.io/docs/concepts/metric_types/#histogram</a> </li>
+</ul>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__histogram_8h__dep__incl.dot b/docs/prom__histogram_8h__dep__incl.dot
new file mode 100644
index 0000000..1cc0139
--- /dev/null
+++ b/docs/prom__histogram_8h__dep__incl.dot
@@ -0,0 +1,10 @@
+digraph "prom/include/prom_histogram.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node7 [label="prom/include/prom_histogram.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node7 -> Node8 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom_8h.html",tooltip="Include prom.h to include the entire public API. "];
+ Node8 -> Node9 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node9 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$promhttp_8h.html",tooltip="Provides a HTTP endpoint for metric exposition References: "];
+}
diff --git a/docs/prom__histogram_8h__dep__incl.map b/docs/prom__histogram_8h__dep__incl.map
new file mode 100644
index 0000000..7796f29
--- /dev/null
+++ b/docs/prom__histogram_8h__dep__incl.map
@@ -0,0 +1,3 @@
+<map id="prom/include/prom_histogram.h" name="prom/include/prom_histogram.h">
+<area shape="rect" id="node2" href="$prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="42,80,199,107"/>
+</map>
diff --git a/docs/prom__histogram_8h__dep__incl.md5 b/docs/prom__histogram_8h__dep__incl.md5
new file mode 100644
index 0000000..26313c5
--- /dev/null
+++ b/docs/prom__histogram_8h__dep__incl.md5
@@ -0,0 +1 @@
+a62830da148452519c6a3f03ba5fddb6 \ No newline at end of file
diff --git a/docs/prom__histogram_8h__dep__incl.png b/docs/prom__histogram_8h__dep__incl.png
new file mode 100644
index 0000000..7415f6c
--- /dev/null
+++ b/docs/prom__histogram_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom__histogram_8h__incl.dot b/docs/prom__histogram_8h__incl.dot
new file mode 100644
index 0000000..2b0c2c0
--- /dev/null
+++ b/docs/prom__histogram_8h__incl.dot
@@ -0,0 +1,20 @@
+digraph "prom/include/prom_histogram.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node0 [label="prom/include/prom_histogram.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node0 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 [label="stdlib.h",height=0.2,width=0.4,color="grey75", fillcolor="white", style="filled"];
+ Node0 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node2 [label="prom_errors.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__errors_8h.html",tooltip="Prometheus client errors. "];
+ Node0 -> Node3 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric_8h.html"];
+ Node3 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 [label="prom_metric_sample.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample_8h.html"];
+ Node4 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node5 [label="prom_metric_sample\l_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample__histogram_8h.html"];
+ Node5 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node0 -> Node6 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node6 [label="prom_histogram_buckets.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__histogram__buckets_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#histogram "];
+}
diff --git a/docs/prom__histogram_8h__incl.map b/docs/prom__histogram_8h__incl.map
new file mode 100644
index 0000000..2545fab
--- /dev/null
+++ b/docs/prom__histogram_8h__incl.map
@@ -0,0 +1,6 @@
+<map id="prom/include/prom_histogram.h" name="prom/include/prom_histogram.h">
+<area shape="rect" id="node3" href="$prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="129,80,246,107"/>
+<area shape="rect" id="node6" href="$prom__histogram__buckets_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="269,80,468,107"/>
+<area shape="rect" id="node4" href="$prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="5,162,177,189"/>
+<area shape="rect" id="node5" href="$prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="202,155,362,196"/>
+</map>
diff --git a/docs/prom__histogram_8h__incl.md5 b/docs/prom__histogram_8h__incl.md5
new file mode 100644
index 0000000..1d78a11
--- /dev/null
+++ b/docs/prom__histogram_8h__incl.md5
@@ -0,0 +1 @@
+0893892567367d17547f313ae7f76866 \ No newline at end of file
diff --git a/docs/prom__histogram_8h__incl.png b/docs/prom__histogram_8h__incl.png
new file mode 100644
index 0000000..e0618ef
--- /dev/null
+++ b/docs/prom__histogram_8h__incl.png
Binary files differ
diff --git a/docs/prom__histogram_8h_source.html b/docs/prom__histogram_8h_source.html
new file mode 100644
index 0000000..7816971
--- /dev/null
+++ b/docs/prom__histogram_8h_source.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_histogram.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_histogram.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom__histogram_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;<span class="preprocessor">#ifndef PROM_HISTOGRAM_INCLUDED</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="preprocessor">#define PROM_HISTOGRAM_INCLUDED</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;</div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160;<span class="preprocessor">#include &lt;stdlib.h&gt;</span></div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span>&#160;</div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__metric_8h.html">prom_metric.h</a>&quot;</span></div><div class="line"><a name="l00028"></a><span class="lineno"> 28</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__histogram__buckets_8h.html">prom_histogram_buckets.h</a>&quot;</span></div><div class="line"><a name="l00029"></a><span class="lineno"> 29</span>&#160;</div><div class="line"><a name="l00036"></a><span class="lineno"><a class="line" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae"> 36</a></span>&#160;<span class="keyword">typedef</span> <a class="code" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> <a class="code" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram_t</a>;</div><div class="line"><a name="l00037"></a><span class="lineno"> 37</span>&#160;</div><div class="line"><a name="l00041"></a><span class="lineno"> 41</span>&#160;<a class="code" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram_t</a>* <a class="code" href="prom__histogram_8h.html#ad42681e59e727f9e3d43bf0cdbba9a1b">prom_histogram_new</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *name,</div><div class="line"><a name="l00042"></a><span class="lineno"> 42</span>&#160; <span class="keyword">const</span> <span class="keywordtype">char</span> *help,</div><div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160; <a class="code" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a> *buckets,</div><div class="line"><a name="l00044"></a><span class="lineno"> 44</span>&#160; <span class="keywordtype">size_t</span> label_key_count,</div><div class="line"><a name="l00045"></a><span class="lineno"> 45</span>&#160; <span class="keyword">const</span> <span class="keywordtype">char</span> **label_keys);</div><div class="line"><a name="l00046"></a><span class="lineno"> 46</span>&#160;</div><div class="line"><a name="l00050"></a><span class="lineno"> 50</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__histogram_8h.html#af9067b27e7ab2abd815af0614bb35357">prom_histogram_destroy</a>(<a class="code" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram_t</a> *<span class="keyword">self</span>);</div><div class="line"><a name="l00051"></a><span class="lineno"> 51</span>&#160;</div><div class="line"><a name="l00052"></a><span class="lineno"> 52</span>&#160;</div><div class="line"><a name="l00056"></a><span class="lineno"> 56</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__histogram_8h.html#a274e4b869c7d9239e9f47b3898210fbe">prom_histogram_observe</a>(<a class="code" href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram_t</a> *<span class="keyword">self</span>, <span class="keywordtype">double</span> value, <span class="keyword">const</span> <span class="keywordtype">char</span> **label_values);</div><div class="line"><a name="l00057"></a><span class="lineno"> 57</span>&#160;</div><div class="line"><a name="l00058"></a><span class="lineno"> 58</span>&#160;<span class="preprocessor">#endif // PROM_HISTOGRAM_INCLUDED</span></div><div class="ttc" id="prom__histogram_8h_html_af9067b27e7ab2abd815af0614bb35357"><div class="ttname"><a href="prom__histogram_8h.html#af9067b27e7ab2abd815af0614bb35357">prom_histogram_destroy</a></div><div class="ttdeci">int prom_histogram_destroy(prom_histogram_t *self)</div><div class="ttdoc">Destroys a pointer to a prom_gauge. </div></div>
+<div class="ttc" id="prom__metric_8h_html_afd1bd014c48955d6c2c36aa8a8cbb889"><div class="ttname"><a href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a></div><div class="ttdeci">struct prom_metric prom_metric_t</div><div class="ttdoc">A prometheus metric. </div><div class="ttdef"><b>Definition:</b> prom_metric.h:34</div></div>
+<div class="ttc" id="structprom__histogram__buckets_html"><div class="ttname"><a href="structprom__histogram__buckets.html">prom_histogram_buckets</a></div><div class="ttdef"><b>Definition:</b> prom_histogram_buckets.h:25</div></div>
+<div class="ttc" id="prom__histogram_8h_html_a8c061924368d41c161025bf3d3cde9ae"><div class="ttname"><a href="prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae">prom_histogram_t</a></div><div class="ttdeci">prom_metric_t prom_histogram_t</div><div class="ttdoc">A prometheus histogram. </div><div class="ttdef"><b>Definition:</b> prom_histogram.h:36</div></div>
+<div class="ttc" id="prom__histogram_8h_html_ad42681e59e727f9e3d43bf0cdbba9a1b"><div class="ttname"><a href="prom__histogram_8h.html#ad42681e59e727f9e3d43bf0cdbba9a1b">prom_histogram_new</a></div><div class="ttdeci">prom_histogram_t * prom_histogram_new(const char *name, const char *help, prom_histogram_buckets_t *buckets, size_t label_key_count, const char **label_keys)</div><div class="ttdoc">Returns a pointer to a prom_histogram_t. </div></div>
+<div class="ttc" id="prom__metric_8h_html"><div class="ttname"><a href="prom__metric_8h.html">prom_metric.h</a></div><div class="ttdoc">Functions for retrieving metric samples from metrics given an ordered set of labels. </div></div>
+<div class="ttc" id="prom__histogram_8h_html_a274e4b869c7d9239e9f47b3898210fbe"><div class="ttname"><a href="prom__histogram_8h.html#a274e4b869c7d9239e9f47b3898210fbe">prom_histogram_observe</a></div><div class="ttdeci">int prom_histogram_observe(prom_histogram_t *self, double value, const char **label_values)</div><div class="ttdoc">Observe the prom_histogram_t given the value and labells. </div></div>
+<div class="ttc" id="prom__histogram__buckets_8h_html"><div class="ttname"><a href="prom__histogram__buckets_8h.html">prom_histogram_buckets.h</a></div><div class="ttdoc">https://prometheus.io/docs/concepts/metric_types/#histogram </div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__histogram__buckets_8h.html b/docs/prom__histogram__buckets_8h.html
new file mode 100644
index 0000000..8d94bd3
--- /dev/null
+++ b/docs/prom__histogram__buckets_8h.html
@@ -0,0 +1,232 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_histogram_buckets.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#nested-classes">Classes</a> &#124;
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a> &#124;
+<a href="#var-members">Variables</a> </div>
+ <div class="headertitle">
+<div class="title">prom_histogram_buckets.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p><a href="https://prometheus.io/docs/concepts/metric_types/#histogram">https://prometheus.io/docs/concepts/metric_types/#histogram</a>
+<a href="#details">More...</a></p>
+<div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__histogram__buckets_8h__dep__incl.png" border="0" usemap="#prom_2include_2prom__histogram__buckets_8hdep" alt=""/></div>
+<map name="prom_2include_2prom__histogram__buckets_8hdep" id="prom_2include_2prom__histogram__buckets_8hdep">
+<area shape="rect" id="node2" href="prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="5,95,236,121"/>
+<area shape="rect" id="node3" href="prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="118,169,275,196"/>
+</map>
+</div>
+</div>
+<p><a href="prom__histogram__buckets_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="nested-classes"></a>
+Classes</h2></td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets</a></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:ac611328b4d7375ed913373025274090f"><td class="memItemLeft" align="right" valign="top"><a id="ac611328b4d7375ed913373025274090f"></a>
+typedef struct <a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets</a>&#160;</td><td class="memItemRight" valign="bottom"><b>prom_histogram_buckets_t</b></td></tr>
+<tr class="separator:ac611328b4d7375ed913373025274090f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:a03736e2fac21748bbfd80100bf9546c4"><td class="memItemLeft" align="right" valign="top"><a id="a03736e2fac21748bbfd80100bf9546c4"></a>
+<a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><b>prom_histogram_buckets_new</b> (size_t count, double bucket,...)</td></tr>
+<tr class="separator:a03736e2fac21748bbfd80100bf9546c4"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aa1adc550bf8999a27f6a26769d6bfc72"><td class="memItemLeft" align="right" valign="top"><a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__histogram__buckets_8h.html#aa1adc550bf8999a27f6a26769d6bfc72">prom_histogram_buckets_linear</a> (double start, double width, size_t count)</td></tr>
+<tr class="memdesc:aa1adc550bf8999a27f6a26769d6bfc72"><td class="mdescLeft">&#160;</td><td class="mdescRight">Create linear buckets. <a href="#aa1adc550bf8999a27f6a26769d6bfc72">More...</a><br /></td></tr>
+<tr class="separator:aa1adc550bf8999a27f6a26769d6bfc72"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a164da4101785b6fa2a292a964c232f12"><td class="memItemLeft" align="right" valign="top"><a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__histogram__buckets_8h.html#a164da4101785b6fa2a292a964c232f12">prom_histogram_buckets_exponential</a> (double start, double factor, size_t count)</td></tr>
+<tr class="memdesc:a164da4101785b6fa2a292a964c232f12"><td class="mdescLeft">&#160;</td><td class="mdescRight">Create linear buckets. <a href="#a164da4101785b6fa2a292a964c232f12">More...</a><br /></td></tr>
+<tr class="separator:a164da4101785b6fa2a292a964c232f12"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a36bc3312f8f479bbd6eb92fa3b1a5033"><td class="memItemLeft" align="right" valign="top"><a id="a36bc3312f8f479bbd6eb92fa3b1a5033"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__histogram__buckets_8h.html#a36bc3312f8f479bbd6eb92fa3b1a5033">prom_histogram_buckets_destroy</a> (<a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a> *self)</td></tr>
+<tr class="memdesc:a36bc3312f8f479bbd6eb92fa3b1a5033"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroy a prom_histogram_buckets_t. <br /></td></tr>
+<tr class="separator:a36bc3312f8f479bbd6eb92fa3b1a5033"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a92158192cfe9a71a98dbb1d9adc8508a"><td class="memItemLeft" align="right" valign="top"><a id="a92158192cfe9a71a98dbb1d9adc8508a"></a>
+size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__histogram__buckets_8h.html#a92158192cfe9a71a98dbb1d9adc8508a">prom_histogram_buckets_count</a> (<a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a> *self)</td></tr>
+<tr class="memdesc:a92158192cfe9a71a98dbb1d9adc8508a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Get the count of buckets. <br /></td></tr>
+<tr class="separator:a92158192cfe9a71a98dbb1d9adc8508a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="var-members"></a>
+Variables</h2></td></tr>
+<tr class="memitem:aa8d61c1abc355eb54173b27cb1b50a5d"><td class="memItemLeft" align="right" valign="top"><a id="aa8d61c1abc355eb54173b27cb1b50a5d"></a>
+<a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__histogram__buckets_8h.html#aa8d61c1abc355eb54173b27cb1b50a5d">prom_histogram_default_buckets</a></td></tr>
+<tr class="memdesc:aa8d61c1abc355eb54173b27cb1b50a5d"><td class="mdescLeft">&#160;</td><td class="mdescRight">the default histogram buckets: .005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10 <br /></td></tr>
+<tr class="separator:aa8d61c1abc355eb54173b27cb1b50a5d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p><a href="https://prometheus.io/docs/concepts/metric_types/#histogram">https://prometheus.io/docs/concepts/metric_types/#histogram</a> </p>
+</div><h2 class="groupheader">Function Documentation</h2>
+<a id="a164da4101785b6fa2a292a964c232f12"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a164da4101785b6fa2a292a964c232f12">&#9670;&nbsp;</a></span>prom_histogram_buckets_exponential()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a>* prom_histogram_buckets_exponential </td>
+ <td>(</td>
+ <td class="paramtype">double&#160;</td>
+ <td class="paramname"><em>start</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">double&#160;</td>
+ <td class="paramname"><em>factor</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t&#160;</td>
+ <td class="paramname"><em>count</em>&#160;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Create linear buckets. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">start</td><td>The first upper bound. The value MUST be greater than 0. </td></tr>
+ <tr><td class="paramname">factor</td><td>The factor to apply to the previous upper bound to produce the next upper bound. The value MUST be greater than 1. </td></tr>
+ <tr><td class="paramname">count</td><td>The total number of buckets. The final +Inf bucket is not counted and not included in the returned. The value MUST be greater than or equal to 1 array </td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The array of upper bounds represented as double values</dd></dl>
+<p>The array returned MUST be freed </p>
+
+</div>
+</div>
+<a id="aa1adc550bf8999a27f6a26769d6bfc72"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aa1adc550bf8999a27f6a26769d6bfc72">&#9670;&nbsp;</a></span>prom_histogram_buckets_linear()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a>* prom_histogram_buckets_linear </td>
+ <td>(</td>
+ <td class="paramtype">double&#160;</td>
+ <td class="paramname"><em>start</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">double&#160;</td>
+ <td class="paramname"><em>width</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t&#160;</td>
+ <td class="paramname"><em>count</em>&#160;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Create linear buckets. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">start</td><td>The first upper bound </td></tr>
+ <tr><td class="paramname">width</td><td>The distance between each upper bound in buckets </td></tr>
+ <tr><td class="paramname">count</td><td>The total number of buckets. The final +Inf bucket is not counted and not included in the returned array </td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The array of upper bounds represented as double values</dd></dl>
+<p>The Array returned MUST be freed </p>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__histogram__buckets_8h__dep__incl.dot b/docs/prom__histogram__buckets_8h__dep__incl.dot
new file mode 100644
index 0000000..f312d71
--- /dev/null
+++ b/docs/prom__histogram__buckets_8h__dep__incl.dot
@@ -0,0 +1,13 @@
+digraph "prom/include/prom_histogram_buckets.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node1 [label="prom/include/prom_histogram\l_buckets.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node1 -> Node2 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node2 [label="prom/include/prom_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__histogram_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#histogram "];
+ Node2 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom_8h.html",tooltip="Include prom.h to include the entire public API. "];
+ Node3 -> Node4 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$promhttp_8h.html",tooltip="Provides a HTTP endpoint for metric exposition References: "];
+ Node1 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom__histogram__buckets_8h__dep__incl.map b/docs/prom__histogram__buckets_8h__dep__incl.map
new file mode 100644
index 0000000..2a03229
--- /dev/null
+++ b/docs/prom__histogram__buckets_8h__dep__incl.map
@@ -0,0 +1,4 @@
+<map id="prom/include/prom_histogram_buckets.h" name="prom/include/prom_histogram_buckets.h">
+<area shape="rect" id="node2" href="$prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="5,95,236,121"/>
+<area shape="rect" id="node3" href="$prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="118,169,275,196"/>
+</map>
diff --git a/docs/prom__histogram__buckets_8h__dep__incl.md5 b/docs/prom__histogram__buckets_8h__dep__incl.md5
new file mode 100644
index 0000000..772a8f9
--- /dev/null
+++ b/docs/prom__histogram__buckets_8h__dep__incl.md5
@@ -0,0 +1 @@
+092e96abd0d6856400714b8a73b76ecc \ No newline at end of file
diff --git a/docs/prom__histogram__buckets_8h__dep__incl.png b/docs/prom__histogram__buckets_8h__dep__incl.png
new file mode 100644
index 0000000..97c4683
--- /dev/null
+++ b/docs/prom__histogram__buckets_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom__histogram__buckets_8h_source.html b/docs/prom__histogram__buckets_8h_source.html
new file mode 100644
index 0000000..68c13ef
--- /dev/null
+++ b/docs/prom__histogram__buckets_8h_source.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_histogram_buckets.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_histogram_buckets.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom__histogram__buckets_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;<span class="preprocessor">#ifndef PROM_HISTOGRAM_BUCKETS_INCLUDED</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="preprocessor">#define PROM_HISTOGRAM_BUCKETS_INCLUDED</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;</div><div class="line"><a name="l00025"></a><span class="lineno"><a class="line" href="structprom__histogram__buckets.html"> 25</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="structprom__histogram__buckets.html">prom_histogram_buckets</a> {</div><div class="line"><a name="l00026"></a><span class="lineno"><a class="line" href="structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621"> 26</a></span>&#160; <span class="keywordtype">int</span> <a class="code" href="structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621">count</a>; </div><div class="line"><a name="l00027"></a><span class="lineno"><a class="line" href="structprom__histogram__buckets.html#a8abda07c4930e15a3dff8a86e3164344"> 27</a></span>&#160; <span class="keyword">const</span> <span class="keywordtype">double</span> *<a class="code" href="structprom__histogram__buckets.html#a8abda07c4930e15a3dff8a86e3164344">upper_bounds</a>; </div><div class="line"><a name="l00028"></a><span class="lineno"> 28</span>&#160;} <a class="code" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a>;</div><div class="line"><a name="l00029"></a><span class="lineno"> 29</span>&#160;</div><div class="line"><a name="l00030"></a><span class="lineno"> 30</span>&#160;<a class="code" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a>* prom_histogram_buckets_new(<span class="keywordtype">size_t</span> <a class="code" href="structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621">count</a>, <span class="keywordtype">double</span> bucket, ...);</div><div class="line"><a name="l00031"></a><span class="lineno"> 31</span>&#160;</div><div class="line"><a name="l00035"></a><span class="lineno"><a class="line" href="prom__histogram__buckets_8h.html#aa8d61c1abc355eb54173b27cb1b50a5d"> 35</a></span>&#160;<a class="code" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a> *<a class="code" href="prom__histogram__buckets_8h.html#aa8d61c1abc355eb54173b27cb1b50a5d">prom_histogram_default_buckets</a>;</div><div class="line"><a name="l00036"></a><span class="lineno"> 36</span>&#160;</div><div class="line"><a name="l00047"></a><span class="lineno"> 47</span>&#160;<a class="code" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a>* <a class="code" href="prom__histogram__buckets_8h.html#aa1adc550bf8999a27f6a26769d6bfc72">prom_histogram_buckets_linear</a>(<span class="keywordtype">double</span> start, <span class="keywordtype">double</span> width, <span class="keywordtype">size_t</span> <a class="code" href="structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621">count</a>);</div><div class="line"><a name="l00048"></a><span class="lineno"> 48</span>&#160;</div><div class="line"><a name="l00061"></a><span class="lineno"> 61</span>&#160;<a class="code" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a>* <a class="code" href="prom__histogram__buckets_8h.html#a164da4101785b6fa2a292a964c232f12">prom_histogram_buckets_exponential</a>(<span class="keywordtype">double</span> start, <span class="keywordtype">double</span> factor, <span class="keywordtype">size_t</span> <a class="code" href="structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621">count</a>);</div><div class="line"><a name="l00062"></a><span class="lineno"> 62</span>&#160;</div><div class="line"><a name="l00063"></a><span class="lineno"> 63</span>&#160;</div><div class="line"><a name="l00067"></a><span class="lineno"> 67</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__histogram__buckets_8h.html#a36bc3312f8f479bbd6eb92fa3b1a5033">prom_histogram_buckets_destroy</a>(<a class="code" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a> *<span class="keyword">self</span>);</div><div class="line"><a name="l00068"></a><span class="lineno"> 68</span>&#160;</div><div class="line"><a name="l00072"></a><span class="lineno"> 72</span>&#160;<span class="keywordtype">size_t</span> <a class="code" href="prom__histogram__buckets_8h.html#a92158192cfe9a71a98dbb1d9adc8508a">prom_histogram_buckets_count</a>(<a class="code" href="structprom__histogram__buckets.html">prom_histogram_buckets_t</a> *<span class="keyword">self</span>);</div><div class="line"><a name="l00073"></a><span class="lineno"> 73</span>&#160;</div><div class="line"><a name="l00074"></a><span class="lineno"> 74</span>&#160;<span class="preprocessor">#endif // PROM_HISTOGRAM_BUCKETS_INCLUDED</span></div><div class="ttc" id="prom__histogram__buckets_8h_html_aa8d61c1abc355eb54173b27cb1b50a5d"><div class="ttname"><a href="prom__histogram__buckets_8h.html#aa8d61c1abc355eb54173b27cb1b50a5d">prom_histogram_default_buckets</a></div><div class="ttdeci">prom_histogram_buckets_t * prom_histogram_default_buckets</div><div class="ttdoc">the default histogram buckets: .005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10 </div><div class="ttdef"><b>Definition:</b> prom_histogram_buckets.h:35</div></div>
+<div class="ttc" id="structprom__histogram__buckets_html_a9da20001e02d992cee82a09372061621"><div class="ttname"><a href="structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621">prom_histogram_buckets::count</a></div><div class="ttdeci">int count</div><div class="ttdoc">Number of buckets. </div><div class="ttdef"><b>Definition:</b> prom_histogram_buckets.h:26</div></div>
+<div class="ttc" id="structprom__histogram__buckets_html_a8abda07c4930e15a3dff8a86e3164344"><div class="ttname"><a href="structprom__histogram__buckets.html#a8abda07c4930e15a3dff8a86e3164344">prom_histogram_buckets::upper_bounds</a></div><div class="ttdeci">const double * upper_bounds</div><div class="ttdoc">The bucket values. </div><div class="ttdef"><b>Definition:</b> prom_histogram_buckets.h:27</div></div>
+<div class="ttc" id="prom__histogram__buckets_8h_html_a92158192cfe9a71a98dbb1d9adc8508a"><div class="ttname"><a href="prom__histogram__buckets_8h.html#a92158192cfe9a71a98dbb1d9adc8508a">prom_histogram_buckets_count</a></div><div class="ttdeci">size_t prom_histogram_buckets_count(prom_histogram_buckets_t *self)</div><div class="ttdoc">Get the count of buckets. </div></div>
+<div class="ttc" id="structprom__histogram__buckets_html"><div class="ttname"><a href="structprom__histogram__buckets.html">prom_histogram_buckets</a></div><div class="ttdef"><b>Definition:</b> prom_histogram_buckets.h:25</div></div>
+<div class="ttc" id="prom__histogram__buckets_8h_html_a36bc3312f8f479bbd6eb92fa3b1a5033"><div class="ttname"><a href="prom__histogram__buckets_8h.html#a36bc3312f8f479bbd6eb92fa3b1a5033">prom_histogram_buckets_destroy</a></div><div class="ttdeci">int prom_histogram_buckets_destroy(prom_histogram_buckets_t *self)</div><div class="ttdoc">Destroy a prom_histogram_buckets_t. </div></div>
+<div class="ttc" id="prom__histogram__buckets_8h_html_aa1adc550bf8999a27f6a26769d6bfc72"><div class="ttname"><a href="prom__histogram__buckets_8h.html#aa1adc550bf8999a27f6a26769d6bfc72">prom_histogram_buckets_linear</a></div><div class="ttdeci">prom_histogram_buckets_t * prom_histogram_buckets_linear(double start, double width, size_t count)</div><div class="ttdoc">Create linear buckets. </div></div>
+<div class="ttc" id="prom__histogram__buckets_8h_html_a164da4101785b6fa2a292a964c232f12"><div class="ttname"><a href="prom__histogram__buckets_8h.html#a164da4101785b6fa2a292a964c232f12">prom_histogram_buckets_exponential</a></div><div class="ttdeci">prom_histogram_buckets_t * prom_histogram_buckets_exponential(double start, double factor, size_t count)</div><div class="ttdoc">Create linear buckets. </div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__linked__list_8h_source.html b/docs/prom__linked__list_8h_source.html
new file mode 100644
index 0000000..7fdaed9
--- /dev/null
+++ b/docs/prom__linked__list_8h_source.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_linked_list.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_linked_list.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00017"></a><span class="lineno"> 17</span>&#160;</div><div class="line"><a name="l00018"></a><span class="lineno"> 18</span>&#160;<span class="preprocessor">#ifndef PROM_LIST_H</span></div><div class="line"><a name="l00019"></a><span class="lineno"> 19</span>&#160;<span class="preprocessor">#define PROM_LIST_H</span></div><div class="line"><a name="l00020"></a><span class="lineno"> 20</span>&#160;</div><div class="line"><a name="l00021"></a><span class="lineno"> 21</span>&#160;<span class="preprocessor">#include &lt;stdlib.h&gt;</span></div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;</div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="keyword">struct </span>prom_linked_list;</div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span>prom_linked_list prom_linked_list_t;</div><div class="line"><a name="l00028"></a><span class="lineno"> 28</span>&#160;</div><div class="line"><a name="l00029"></a><span class="lineno"> 29</span>&#160;</div><div class="line"><a name="l00030"></a><span class="lineno"> 30</span>&#160;<span class="preprocessor">#endif // PROM_LIST_H</span></div></div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__map_8h_source.html b/docs/prom__map_8h_source.html
new file mode 100644
index 0000000..38e52c6
--- /dev/null
+++ b/docs/prom__map_8h_source.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_map.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_map.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00017"></a><span class="lineno"> 17</span>&#160;<span class="preprocessor">#ifndef PROM_MAP_H</span></div><div class="line"><a name="l00018"></a><span class="lineno"> 18</span>&#160;<span class="preprocessor">#define PROM_MAP_H</span></div><div class="line"><a name="l00019"></a><span class="lineno"> 19</span>&#160;</div><div class="line"><a name="l00020"></a><span class="lineno"> 20</span>&#160;<span class="keyword">struct </span>prom_map;</div><div class="line"><a name="l00021"></a><span class="lineno"> 21</span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span>prom_map prom_map_t;</div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;</div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="keyword">struct </span>prom_map_node;</div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span>prom_map_node prom_map_node_t;</div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160;</div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span>&#160;<span class="preprocessor">#endif // PROM_MAP_H</span></div></div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__metric_8h.html b/docs/prom__metric_8h.html
new file mode 100644
index 0000000..671569a
--- /dev/null
+++ b/docs/prom__metric_8h.html
@@ -0,0 +1,212 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_metric.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">prom_metric.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Functions for retrieving metric samples from metrics given an ordered set of labels.
+<a href="#details">More...</a></p>
+<div class="textblock"><code>#include &quot;<a class="el" href="prom__metric__sample_8h_source.html">prom_metric_sample.h</a>&quot;</code><br />
+<code>#include &quot;<a class="el" href="prom__metric__sample__histogram_8h_source.html">prom_metric_sample_histogram.h</a>&quot;</code><br />
+</div><div class="textblock"><div class="dynheader">
+Include dependency graph for prom_metric.h:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__metric_8h__incl.png" border="0" usemap="#prom_2include_2prom__metric_8h" alt=""/></div>
+<map name="prom_2include_2prom__metric_8h" id="prom_2include_2prom__metric_8h">
+<area shape="rect" id="node2" href="prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="5,87,177,114"/>
+<area shape="rect" id="node3" href="prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="202,80,362,121"/>
+</map>
+</div>
+</div><div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__metric_8h__dep__incl.png" border="0" usemap="#prom_2include_2prom__metric_8hdep" alt=""/></div>
+<map name="prom_2include_2prom__metric_8hdep" id="prom_2include_2prom__metric_8hdep">
+<area shape="rect" id="node2" href="prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="5,80,224,107"/>
+<area shape="rect" id="node3" href="prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="304,244,461,271"/>
+<area shape="rect" id="node4" href="prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="67,155,275,196"/>
+<area shape="rect" id="node5" href="prom__counter_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#counter " alt="" coords="349,162,561,189"/>
+<area shape="rect" id="node6" href="prom__gauge_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#gauge " alt="" coords="585,162,789,189"/>
+<area shape="rect" id="node7" href="prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="657,80,887,107"/>
+</map>
+</div>
+</div>
+<p><a href="prom__metric_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:afd1bd014c48955d6c2c36aa8a8cbb889"><td class="memItemLeft" align="right" valign="top">typedef struct prom_metric&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a></td></tr>
+<tr class="memdesc:afd1bd014c48955d6c2c36aa8a8cbb889"><td class="mdescLeft">&#160;</td><td class="mdescRight">A prometheus metric. <a href="#afd1bd014c48955d6c2c36aa8a8cbb889">More...</a><br /></td></tr>
+<tr class="separator:afd1bd014c48955d6c2c36aa8a8cbb889"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:a2c33d7e03b430a2903bf122fbeeb89de"><td class="memItemLeft" align="right" valign="top"><a class="el" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric_8h.html#a2c33d7e03b430a2903bf122fbeeb89de">prom_metric_sample_from_labels</a> (<a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *self, const char **label_values)</td></tr>
+<tr class="memdesc:a2c33d7e03b430a2903bf122fbeeb89de"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a prom_metric_sample_t*. <a href="#a2c33d7e03b430a2903bf122fbeeb89de">More...</a><br /></td></tr>
+<tr class="separator:a2c33d7e03b430a2903bf122fbeeb89de"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a3b76680b4a7177eebc864f3b3be1e935"><td class="memItemLeft" align="right" valign="top"><a class="el" href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f">prom_metric_sample_histogram_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric_8h.html#a3b76680b4a7177eebc864f3b3be1e935">prom_metric_sample_histogram_from_labels</a> (<a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *self, const char **label_values)</td></tr>
+<tr class="memdesc:a3b76680b4a7177eebc864f3b3be1e935"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a prom_metric_sample_histogram_t*. <a href="#a3b76680b4a7177eebc864f3b3be1e935">More...</a><br /></td></tr>
+<tr class="separator:a3b76680b4a7177eebc864f3b3be1e935"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Functions for retrieving metric samples from metrics given an ordered set of labels. </p>
+</div><h2 class="groupheader">Typedef Documentation</h2>
+<a id="afd1bd014c48955d6c2c36aa8a8cbb889"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#afd1bd014c48955d6c2c36aa8a8cbb889">&#9670;&nbsp;</a></span>prom_metric_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef struct prom_metric <a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>A prometheus metric. </p>
+<p>Reference: <a href="https://prometheus.io/docs/concepts/data_model">https://prometheus.io/docs/concepts/data_model</a> </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="a2c33d7e03b430a2903bf122fbeeb89de"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a2c33d7e03b430a2903bf122fbeeb89de">&#9670;&nbsp;</a></span>prom_metric_sample_from_labels()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a>* prom_metric_sample_from_labels </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *&#160;</td>
+ <td class="paramname"><em>self</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char **&#160;</td>
+ <td class="paramname"><em>label_values</em>&#160;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Returns a prom_metric_sample_t*. </p>
+<p>The order of label_values is significant.</p>
+<p>You may use this function to cache metric samples to avoid sample lookup. Metric samples are stored in a hash map with O(1) lookups in average case; nonethless, caching metric samples and updating them directly might be preferrable in performance-sensitive situations. </p>
+
+</div>
+</div>
+<a id="a3b76680b4a7177eebc864f3b3be1e935"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a3b76680b4a7177eebc864f3b3be1e935">&#9670;&nbsp;</a></span>prom_metric_sample_histogram_from_labels()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f">prom_metric_sample_histogram_t</a>* prom_metric_sample_histogram_from_labels </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *&#160;</td>
+ <td class="paramname"><em>self</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char **&#160;</td>
+ <td class="paramname"><em>label_values</em>&#160;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Returns a prom_metric_sample_histogram_t*. </p>
+<p>The order of label_values is significant.</p>
+<p>You may use this function to cache metric samples to avoid sample lookup. Metric samples are stored in a hash map with O(1) lookups in average case; nonethless, caching metric samples and updating them directly might be preferrable in performance-sensitive situations. </p>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__metric_8h__dep__incl.dot b/docs/prom__metric_8h__dep__incl.dot
new file mode 100644
index 0000000..494a0c6
--- /dev/null
+++ b/docs/prom__metric_8h__dep__incl.dot
@@ -0,0 +1,26 @@
+digraph "prom/include/prom_metric.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node4 [label="prom/include/prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node4 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node5 [label="prom/include/prom_collector.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector_8h.html",tooltip="A Prometheus collector returns a collection of metrics. "];
+ Node5 -> Node6 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node6 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom_8h.html",tooltip="Include prom.h to include the entire public API. "];
+ Node6 -> Node7 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$promhttp_8h.html",tooltip="Provides a HTTP endpoint for metric exposition References: "];
+ Node5 -> Node8 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 [label="prom/include/prom_collector\l_registry.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector__registry_8h.html",tooltip="The collector registry registers collectors for metric exposition. "];
+ Node8 -> Node6 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 -> Node8 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 -> Node9 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node9 [label="prom/include/prom_counter.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__counter_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#counter "];
+ Node9 -> Node6 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 -> Node10 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node10 [label="prom/include/prom_gauge.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__gauge_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#gauge "];
+ Node10 -> Node6 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 -> Node11 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node11 [label="prom/include/prom_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__histogram_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#histogram "];
+ Node11 -> Node6 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 -> Node6 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom__metric_8h__dep__incl.map b/docs/prom__metric_8h__dep__incl.map
new file mode 100644
index 0000000..9b9085e
--- /dev/null
+++ b/docs/prom__metric_8h__dep__incl.map
@@ -0,0 +1,8 @@
+<map id="prom/include/prom_metric.h" name="prom/include/prom_metric.h">
+<area shape="rect" id="node2" href="$prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="5,80,224,107"/>
+<area shape="rect" id="node3" href="$prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="304,244,461,271"/>
+<area shape="rect" id="node4" href="$prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="67,155,275,196"/>
+<area shape="rect" id="node5" href="$prom__counter_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#counter " alt="" coords="349,162,561,189"/>
+<area shape="rect" id="node6" href="$prom__gauge_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#gauge " alt="" coords="585,162,789,189"/>
+<area shape="rect" id="node7" href="$prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="657,80,887,107"/>
+</map>
diff --git a/docs/prom__metric_8h__dep__incl.md5 b/docs/prom__metric_8h__dep__incl.md5
new file mode 100644
index 0000000..6922bea
--- /dev/null
+++ b/docs/prom__metric_8h__dep__incl.md5
@@ -0,0 +1 @@
+1ddbf7dc5b59aeeb4e6354d79efcf459 \ No newline at end of file
diff --git a/docs/prom__metric_8h__dep__incl.png b/docs/prom__metric_8h__dep__incl.png
new file mode 100644
index 0000000..e7e18fb
--- /dev/null
+++ b/docs/prom__metric_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom__metric_8h__incl.dot b/docs/prom__metric_8h__incl.dot
new file mode 100644
index 0000000..0367445
--- /dev/null
+++ b/docs/prom__metric_8h__incl.dot
@@ -0,0 +1,13 @@
+digraph "prom/include/prom_metric.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node0 [label="prom/include/prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node0 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 [label="prom_metric_sample.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample_8h.html"];
+ Node1 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node2 [label="prom_errors.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__errors_8h.html",tooltip="Prometheus client errors. "];
+ Node0 -> Node3 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom_metric_sample\l_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample__histogram_8h.html"];
+ Node3 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom__metric_8h__incl.map b/docs/prom__metric_8h__incl.map
new file mode 100644
index 0000000..d023f5a
--- /dev/null
+++ b/docs/prom__metric_8h__incl.map
@@ -0,0 +1,4 @@
+<map id="prom/include/prom_metric.h" name="prom/include/prom_metric.h">
+<area shape="rect" id="node2" href="$prom__metric__sample_8h.html" title="Functions for interfacting with metric samples directly. " alt="" coords="5,87,177,114"/>
+<area shape="rect" id="node3" href="$prom__metric__sample__histogram_8h.html" title="Functions for interacting with histogram metric samples directly. " alt="" coords="202,80,362,121"/>
+</map>
diff --git a/docs/prom__metric_8h__incl.md5 b/docs/prom__metric_8h__incl.md5
new file mode 100644
index 0000000..755c7f5
--- /dev/null
+++ b/docs/prom__metric_8h__incl.md5
@@ -0,0 +1 @@
+d98b1c11d3c4b7656cc448699687339d \ No newline at end of file
diff --git a/docs/prom__metric_8h__incl.png b/docs/prom__metric_8h__incl.png
new file mode 100644
index 0000000..73003e7
--- /dev/null
+++ b/docs/prom__metric_8h__incl.png
Binary files differ
diff --git a/docs/prom__metric_8h_source.html b/docs/prom__metric_8h_source.html
new file mode 100644
index 0000000..15fec35
--- /dev/null
+++ b/docs/prom__metric_8h_source.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_metric.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_metric.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom__metric_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;<span class="preprocessor">#ifndef PROM_METRIC_H</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="preprocessor">#define PROM_METRIC_H</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;</div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__metric__sample_8h.html">prom_metric_sample.h</a>&quot;</span></div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span>&#160;<span class="preprocessor">#include &quot;<a class="code" href="prom__metric__sample__histogram_8h.html">prom_metric_sample_histogram.h</a>&quot;</span></div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span>&#160;</div><div class="line"><a name="l00028"></a><span class="lineno"> 28</span>&#160;<span class="keyword">struct </span>prom_metric;</div><div class="line"><a name="l00034"></a><span class="lineno"><a class="line" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889"> 34</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span>prom_metric <a class="code" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a>;</div><div class="line"><a name="l00035"></a><span class="lineno"> 35</span>&#160;</div><div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160;<a class="code" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a>* <a class="code" href="prom__metric_8h.html#a2c33d7e03b430a2903bf122fbeeb89de">prom_metric_sample_from_labels</a>(<a class="code" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *<span class="keyword">self</span>, <span class="keyword">const</span> <span class="keywordtype">char</span> **label_values);</div><div class="line"><a name="l00044"></a><span class="lineno"> 44</span>&#160;</div><div class="line"><a name="l00052"></a><span class="lineno"> 52</span>&#160;<a class="code" href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f">prom_metric_sample_histogram_t</a>* <a class="code" href="prom__metric_8h.html#a3b76680b4a7177eebc864f3b3be1e935">prom_metric_sample_histogram_from_labels</a>(<a class="code" href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a> *<span class="keyword">self</span>,</div><div class="line"><a name="l00053"></a><span class="lineno"> 53</span>&#160; <span class="keyword">const</span> <span class="keywordtype">char</span> **label_values);</div><div class="line"><a name="l00054"></a><span class="lineno"> 54</span>&#160;</div><div class="line"><a name="l00055"></a><span class="lineno"> 55</span>&#160;<span class="preprocessor">#endif // PROM_METRIC_H</span></div><div class="ttc" id="prom__metric_8h_html_afd1bd014c48955d6c2c36aa8a8cbb889"><div class="ttname"><a href="prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889">prom_metric_t</a></div><div class="ttdeci">struct prom_metric prom_metric_t</div><div class="ttdoc">A prometheus metric. </div><div class="ttdef"><b>Definition:</b> prom_metric.h:34</div></div>
+<div class="ttc" id="prom__metric__sample_8h_html"><div class="ttname"><a href="prom__metric__sample_8h.html">prom_metric_sample.h</a></div><div class="ttdoc">Functions for interfacting with metric samples directly. </div></div>
+<div class="ttc" id="prom__metric__sample__histogram_8h_html_aed3455bc4eec61a3d8f01e6c1af84f9f"><div class="ttname"><a href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f">prom_metric_sample_histogram_t</a></div><div class="ttdeci">struct prom_metric_sample_histogram prom_metric_sample_histogram_t</div><div class="ttdoc">A histogram metric sample. </div><div class="ttdef"><b>Definition:</b> prom_metric_sample_histogram.h:29</div></div>
+<div class="ttc" id="prom__metric_8h_html_a3b76680b4a7177eebc864f3b3be1e935"><div class="ttname"><a href="prom__metric_8h.html#a3b76680b4a7177eebc864f3b3be1e935">prom_metric_sample_histogram_from_labels</a></div><div class="ttdeci">prom_metric_sample_histogram_t * prom_metric_sample_histogram_from_labels(prom_metric_t *self, const char **label_values)</div><div class="ttdoc">Returns a prom_metric_sample_histogram_t*. </div></div>
+<div class="ttc" id="prom__metric__sample_8h_html_a0fb9ff851bf9ee126756ae826a2ce72a"><div class="ttname"><a href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a></div><div class="ttdeci">struct prom_metric_sample prom_metric_sample_t</div><div class="ttdoc">Contains the specific metric and value given the name and label set Reference: https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels. </div><div class="ttdef"><b>Definition:</b> prom_metric_sample.h:30</div></div>
+<div class="ttc" id="prom__metric__sample__histogram_8h_html"><div class="ttname"><a href="prom__metric__sample__histogram_8h.html">prom_metric_sample_histogram.h</a></div><div class="ttdoc">Functions for interacting with histogram metric samples directly. </div></div>
+<div class="ttc" id="prom__metric_8h_html_a2c33d7e03b430a2903bf122fbeeb89de"><div class="ttname"><a href="prom__metric_8h.html#a2c33d7e03b430a2903bf122fbeeb89de">prom_metric_sample_from_labels</a></div><div class="ttdeci">prom_metric_sample_t * prom_metric_sample_from_labels(prom_metric_t *self, const char **label_values)</div><div class="ttdoc">Returns a prom_metric_sample_t*. </div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__metric__sample_8h.html b/docs/prom__metric__sample_8h.html
new file mode 100644
index 0000000..ea3b0c2
--- /dev/null
+++ b/docs/prom__metric__sample_8h.html
@@ -0,0 +1,217 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_metric_sample.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">prom_metric_sample.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Functions for interfacting with metric samples directly.
+<a href="#details">More...</a></p>
+<div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__metric__sample_8h__dep__incl.png" border="0" usemap="#prom_2include_2prom__metric__sample_8hdep" alt=""/></div>
+<map name="prom_2include_2prom__metric__sample_8hdep" id="prom_2include_2prom__metric__sample_8hdep">
+<area shape="rect" id="node2" href="prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="351,95,558,121"/>
+<area shape="rect" id="node4" href="prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="376,333,533,360"/>
+<area shape="rect" id="node3" href="prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="5,169,224,196"/>
+<area shape="rect" id="node5" href="prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="67,244,275,285"/>
+<area shape="rect" id="node6" href="prom__counter_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#counter " alt="" coords="349,251,561,278"/>
+<area shape="rect" id="node7" href="prom__gauge_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#gauge " alt="" coords="585,251,789,278"/>
+<area shape="rect" id="node8" href="prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="593,169,823,196"/>
+</map>
+</div>
+</div>
+<p><a href="prom__metric__sample_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:a0fb9ff851bf9ee126756ae826a2ce72a"><td class="memItemLeft" align="right" valign="top"><a id="a0fb9ff851bf9ee126756ae826a2ce72a"></a>
+typedef struct prom_metric_sample&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a></td></tr>
+<tr class="memdesc:a0fb9ff851bf9ee126756ae826a2ce72a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Contains the specific metric and value given the name and label set Reference: <a href="https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels">https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels</a>. <br /></td></tr>
+<tr class="separator:a0fb9ff851bf9ee126756ae826a2ce72a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:a3f8674d6c8ee2c27eb7504d602110daa"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric__sample_8h.html#a3f8674d6c8ee2c27eb7504d602110daa">prom_metric_sample_add</a> (<a class="el" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a> *self, double r_value)</td></tr>
+<tr class="memdesc:a3f8674d6c8ee2c27eb7504d602110daa"><td class="mdescLeft">&#160;</td><td class="mdescRight">Add the r_value to the sample. <a href="#a3f8674d6c8ee2c27eb7504d602110daa">More...</a><br /></td></tr>
+<tr class="separator:a3f8674d6c8ee2c27eb7504d602110daa"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a1965caa1626c308bc1cb23995e90a0a7"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric__sample_8h.html#a1965caa1626c308bc1cb23995e90a0a7">prom_metric_sample_sub</a> (<a class="el" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a> *self, double r_value)</td></tr>
+<tr class="memdesc:a1965caa1626c308bc1cb23995e90a0a7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Subtract the r_value from the sample. <a href="#a1965caa1626c308bc1cb23995e90a0a7">More...</a><br /></td></tr>
+<tr class="separator:a1965caa1626c308bc1cb23995e90a0a7"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a0c5f0c66599282c2ee2c042ae4574db3"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric__sample_8h.html#a0c5f0c66599282c2ee2c042ae4574db3">prom_metric_sample_set</a> (<a class="el" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a> *self, double r_value)</td></tr>
+<tr class="memdesc:a0c5f0c66599282c2ee2c042ae4574db3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Set the r_value of the sample. <a href="#a0c5f0c66599282c2ee2c042ae4574db3">More...</a><br /></td></tr>
+<tr class="separator:a0c5f0c66599282c2ee2c042ae4574db3"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Functions for interfacting with metric samples directly. </p>
+</div><h2 class="groupheader">Function Documentation</h2>
+<a id="a3f8674d6c8ee2c27eb7504d602110daa"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a3f8674d6c8ee2c27eb7504d602110daa">&#9670;&nbsp;</a></span>prom_metric_sample_add()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int prom_metric_sample_add </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a> *&#160;</td>
+ <td class="paramname"><em>self</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">double&#160;</td>
+ <td class="paramname"><em>r_value</em>&#160;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Add the r_value to the sample. </p>
+<p>The value must be greater than or equal to zero. </p>
+
+</div>
+</div>
+<a id="a0c5f0c66599282c2ee2c042ae4574db3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a0c5f0c66599282c2ee2c042ae4574db3">&#9670;&nbsp;</a></span>prom_metric_sample_set()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int prom_metric_sample_set </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a> *&#160;</td>
+ <td class="paramname"><em>self</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">double&#160;</td>
+ <td class="paramname"><em>r_value</em>&#160;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Set the r_value of the sample. </p>
+<p>This operation MUST be called on a sample derived from a gauge metric. </p>
+
+</div>
+</div>
+<a id="a1965caa1626c308bc1cb23995e90a0a7"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a1965caa1626c308bc1cb23995e90a0a7">&#9670;&nbsp;</a></span>prom_metric_sample_sub()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int prom_metric_sample_sub </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a> *&#160;</td>
+ <td class="paramname"><em>self</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">double&#160;</td>
+ <td class="paramname"><em>r_value</em>&#160;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Subtract the r_value from the sample. </p>
+<p>This operation MUST be called a sample derived from a gauge metric. </p>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__metric__sample_8h__dep__incl.dot b/docs/prom__metric__sample_8h__dep__incl.dot
new file mode 100644
index 0000000..5a3288e
--- /dev/null
+++ b/docs/prom__metric__sample_8h__dep__incl.dot
@@ -0,0 +1,29 @@
+digraph "prom/include/prom_metric_sample.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node2 [label="prom/include/prom_metric\l_sample.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node2 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom/include/prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric_8h.html"];
+ Node3 -> Node4 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 [label="prom/include/prom_collector.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector_8h.html",tooltip="A Prometheus collector returns a collection of metrics. "];
+ Node4 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node5 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom_8h.html",tooltip="Include prom.h to include the entire public API. "];
+ Node5 -> Node6 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node6 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$promhttp_8h.html",tooltip="Provides a HTTP endpoint for metric exposition References: "];
+ Node4 -> Node7 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 [label="prom/include/prom_collector\l_registry.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector__registry_8h.html",tooltip="The collector registry registers collectors for metric exposition. "];
+ Node7 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node7 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node8 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 [label="prom/include/prom_counter.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__counter_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#counter "];
+ Node8 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node9 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node9 [label="prom/include/prom_gauge.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__gauge_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#gauge "];
+ Node9 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node10 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node10 [label="prom/include/prom_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__histogram_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#histogram "];
+ Node10 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node2 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom__metric__sample_8h__dep__incl.map b/docs/prom__metric__sample_8h__dep__incl.map
new file mode 100644
index 0000000..920a514
--- /dev/null
+++ b/docs/prom__metric__sample_8h__dep__incl.map
@@ -0,0 +1,9 @@
+<map id="prom/include/prom_metric_sample.h" name="prom/include/prom_metric_sample.h">
+<area shape="rect" id="node2" href="$prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="351,95,558,121"/>
+<area shape="rect" id="node4" href="$prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="376,333,533,360"/>
+<area shape="rect" id="node3" href="$prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="5,169,224,196"/>
+<area shape="rect" id="node5" href="$prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="67,244,275,285"/>
+<area shape="rect" id="node6" href="$prom__counter_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#counter " alt="" coords="349,251,561,278"/>
+<area shape="rect" id="node7" href="$prom__gauge_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#gauge " alt="" coords="585,251,789,278"/>
+<area shape="rect" id="node8" href="$prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="593,169,823,196"/>
+</map>
diff --git a/docs/prom__metric__sample_8h__dep__incl.md5 b/docs/prom__metric__sample_8h__dep__incl.md5
new file mode 100644
index 0000000..85d221a
--- /dev/null
+++ b/docs/prom__metric__sample_8h__dep__incl.md5
@@ -0,0 +1 @@
+58c240ed809da30c2febdf3cba575a28 \ No newline at end of file
diff --git a/docs/prom__metric__sample_8h__dep__incl.png b/docs/prom__metric__sample_8h__dep__incl.png
new file mode 100644
index 0000000..a008327
--- /dev/null
+++ b/docs/prom__metric__sample_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom__metric__sample_8h__incl.dot b/docs/prom__metric__sample_8h__incl.dot
new file mode 100644
index 0000000..f66323f
--- /dev/null
+++ b/docs/prom__metric__sample_8h__incl.dot
@@ -0,0 +1,8 @@
+digraph "prom/include/prom_metric_sample.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node0 [label="prom/include/prom_metric\l_sample.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node0 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 [label="prom_errors.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__errors_8h.html",tooltip="Prometheus client errors. "];
+}
diff --git a/docs/prom__metric__sample_8h__incl.map b/docs/prom__metric__sample_8h__incl.map
new file mode 100644
index 0000000..82210ff
--- /dev/null
+++ b/docs/prom__metric__sample_8h__incl.map
@@ -0,0 +1,3 @@
+<map id="prom/include/prom_metric_sample.h" name="prom/include/prom_metric_sample.h">
+<area shape="rect" id="node2" href="$prom__errors_8h.html" title="Prometheus client errors. " alt="" coords="46,95,159,121"/>
+</map>
diff --git a/docs/prom__metric__sample_8h__incl.md5 b/docs/prom__metric__sample_8h__incl.md5
new file mode 100644
index 0000000..24487c0
--- /dev/null
+++ b/docs/prom__metric__sample_8h__incl.md5
@@ -0,0 +1 @@
+6bae0b9a939e04235cee6cc7512e4eb3 \ No newline at end of file
diff --git a/docs/prom__metric__sample_8h__incl.png b/docs/prom__metric__sample_8h__incl.png
new file mode 100644
index 0000000..709c923
--- /dev/null
+++ b/docs/prom__metric__sample_8h__incl.png
Binary files differ
diff --git a/docs/prom__metric__sample_8h_source.html b/docs/prom__metric__sample_8h_source.html
new file mode 100644
index 0000000..572158a
--- /dev/null
+++ b/docs/prom__metric__sample_8h_source.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_metric_sample.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_metric_sample.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom__metric__sample_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;<span class="preprocessor">#ifndef PROM_METRIC_SAMPLE_H</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="preprocessor">#define PROM_METRIC_SAMPLE_H</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;</div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160;<span class="keyword">struct </span>prom_metric_sample;</div><div class="line"><a name="l00030"></a><span class="lineno"><a class="line" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a"> 30</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span>prom_metric_sample <a class="code" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a>;</div><div class="line"><a name="l00031"></a><span class="lineno"> 31</span>&#160;</div><div class="line"><a name="l00035"></a><span class="lineno"> 35</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__metric__sample_8h.html#a3f8674d6c8ee2c27eb7504d602110daa">prom_metric_sample_add</a>(<a class="code" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a> *<span class="keyword">self</span>, <span class="keywordtype">double</span> r_value);</div><div class="line"><a name="l00036"></a><span class="lineno"> 36</span>&#160;</div><div class="line"><a name="l00042"></a><span class="lineno"> 42</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__metric__sample_8h.html#a1965caa1626c308bc1cb23995e90a0a7">prom_metric_sample_sub</a>(<a class="code" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a> *<span class="keyword">self</span>, <span class="keywordtype">double</span> r_value);</div><div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160;</div><div class="line"><a name="l00049"></a><span class="lineno"> 49</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__metric__sample_8h.html#a0c5f0c66599282c2ee2c042ae4574db3">prom_metric_sample_set</a>(<a class="code" href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a> *<span class="keyword">self</span>, <span class="keywordtype">double</span> r_value);</div><div class="line"><a name="l00050"></a><span class="lineno"> 50</span>&#160;</div><div class="line"><a name="l00051"></a><span class="lineno"> 51</span>&#160;<span class="preprocessor">#endif // PROM_METRIC_SAMPLE_H</span></div><div class="ttc" id="prom__metric__sample_8h_html_a0fb9ff851bf9ee126756ae826a2ce72a"><div class="ttname"><a href="prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a">prom_metric_sample_t</a></div><div class="ttdeci">struct prom_metric_sample prom_metric_sample_t</div><div class="ttdoc">Contains the specific metric and value given the name and label set Reference: https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels. </div><div class="ttdef"><b>Definition:</b> prom_metric_sample.h:30</div></div>
+<div class="ttc" id="prom__metric__sample_8h_html_a3f8674d6c8ee2c27eb7504d602110daa"><div class="ttname"><a href="prom__metric__sample_8h.html#a3f8674d6c8ee2c27eb7504d602110daa">prom_metric_sample_add</a></div><div class="ttdeci">int prom_metric_sample_add(prom_metric_sample_t *self, double r_value)</div><div class="ttdoc">Add the r_value to the sample. </div></div>
+<div class="ttc" id="prom__metric__sample_8h_html_a1965caa1626c308bc1cb23995e90a0a7"><div class="ttname"><a href="prom__metric__sample_8h.html#a1965caa1626c308bc1cb23995e90a0a7">prom_metric_sample_sub</a></div><div class="ttdeci">int prom_metric_sample_sub(prom_metric_sample_t *self, double r_value)</div><div class="ttdoc">Subtract the r_value from the sample. </div></div>
+<div class="ttc" id="prom__metric__sample_8h_html_a0c5f0c66599282c2ee2c042ae4574db3"><div class="ttname"><a href="prom__metric__sample_8h.html#a0c5f0c66599282c2ee2c042ae4574db3">prom_metric_sample_set</a></div><div class="ttdeci">int prom_metric_sample_set(prom_metric_sample_t *self, double r_value)</div><div class="ttdoc">Set the r_value of the sample. </div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__metric__sample__histogram_8h.html b/docs/prom__metric__sample__histogram_8h.html
new file mode 100644
index 0000000..930c173
--- /dev/null
+++ b/docs/prom__metric__sample__histogram_8h.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_metric_sample_histogram.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">prom_metric_sample_histogram.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Functions for interacting with histogram metric samples directly.
+<a href="#details">More...</a></p>
+<div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="prom__metric__sample__histogram_8h__dep__incl.png" border="0" usemap="#prom_2include_2prom__metric__sample__histogram_8hdep" alt=""/></div>
+<map name="prom_2include_2prom__metric__sample__histogram_8hdep" id="prom_2include_2prom__metric__sample__histogram_8hdep">
+<area shape="rect" id="node2" href="prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="351,95,558,121"/>
+<area shape="rect" id="node4" href="prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="376,333,533,360"/>
+<area shape="rect" id="node3" href="prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="5,169,224,196"/>
+<area shape="rect" id="node5" href="prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="67,244,275,285"/>
+<area shape="rect" id="node6" href="prom__counter_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#counter " alt="" coords="349,251,561,278"/>
+<area shape="rect" id="node7" href="prom__gauge_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#gauge " alt="" coords="585,251,789,278"/>
+<area shape="rect" id="node8" href="prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="593,169,823,196"/>
+</map>
+</div>
+</div>
+<p><a href="prom__metric__sample__histogram_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:aed3455bc4eec61a3d8f01e6c1af84f9f"><td class="memItemLeft" align="right" valign="top"><a id="aed3455bc4eec61a3d8f01e6c1af84f9f"></a>
+typedef struct prom_metric_sample_histogram&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f">prom_metric_sample_histogram_t</a></td></tr>
+<tr class="memdesc:aed3455bc4eec61a3d8f01e6c1af84f9f"><td class="mdescLeft">&#160;</td><td class="mdescRight">A histogram metric sample. <br /></td></tr>
+<tr class="separator:aed3455bc4eec61a3d8f01e6c1af84f9f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:a20a030bf6be56211c87c9feb520a3761"><td class="memItemLeft" align="right" valign="top"><a id="a20a030bf6be56211c87c9feb520a3761"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="prom__metric__sample__histogram_8h.html#a20a030bf6be56211c87c9feb520a3761">prom_metric_sample_histogram_observe</a> (<a class="el" href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f">prom_metric_sample_histogram_t</a> *self, double value)</td></tr>
+<tr class="memdesc:a20a030bf6be56211c87c9feb520a3761"><td class="mdescLeft">&#160;</td><td class="mdescRight">Observe the double for the given prom_metric_sample_histogram_observe_t. <br /></td></tr>
+<tr class="separator:a20a030bf6be56211c87c9feb520a3761"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Functions for interacting with histogram metric samples directly. </p>
+</div></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/prom__metric__sample__histogram_8h__dep__incl.dot b/docs/prom__metric__sample__histogram_8h__dep__incl.dot
new file mode 100644
index 0000000..217f3ad
--- /dev/null
+++ b/docs/prom__metric__sample__histogram_8h__dep__incl.dot
@@ -0,0 +1,28 @@
+digraph "prom/include/prom_metric_sample_histogram.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node2 [label="prom/include/prom_metric\l_sample_histogram.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node2 -> Node3 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom/include/prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric_8h.html"];
+ Node3 -> Node4 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 [label="prom/include/prom_collector.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector_8h.html",tooltip="A Prometheus collector returns a collection of metrics. "];
+ Node4 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node5 [label="prom/include/prom.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom_8h.html",tooltip="Include prom.h to include the entire public API. "];
+ Node5 -> Node6 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node6 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$promhttp_8h.html",tooltip="Provides a HTTP endpoint for metric exposition References: "];
+ Node4 -> Node7 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 [label="prom/include/prom_collector\l_registry.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector__registry_8h.html",tooltip="The collector registry registers collectors for metric exposition. "];
+ Node7 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node7 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node8 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 [label="prom/include/prom_counter.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__counter_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#counter "];
+ Node8 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node9 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node9 [label="prom/include/prom_gauge.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__gauge_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#gauge "];
+ Node9 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node10 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node10 [label="prom/include/prom_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__histogram_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#histogram "];
+ Node10 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node5 [dir="back",color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/prom__metric__sample__histogram_8h__dep__incl.map b/docs/prom__metric__sample__histogram_8h__dep__incl.map
new file mode 100644
index 0000000..2364309
--- /dev/null
+++ b/docs/prom__metric__sample__histogram_8h__dep__incl.map
@@ -0,0 +1,9 @@
+<map id="prom/include/prom_metric_sample_histogram.h" name="prom/include/prom_metric_sample_histogram.h">
+<area shape="rect" id="node2" href="$prom__metric_8h.html" title="Functions for retrieving metric samples from metrics given an ordered set of labels. " alt="" coords="351,95,558,121"/>
+<area shape="rect" id="node4" href="$prom_8h.html" title="Include prom.h to include the entire public API. " alt="" coords="376,333,533,360"/>
+<area shape="rect" id="node3" href="$prom__collector_8h.html" title="A Prometheus collector returns a collection of metrics. " alt="" coords="5,169,224,196"/>
+<area shape="rect" id="node5" href="$prom__collector__registry_8h.html" title="The collector registry registers collectors for metric exposition. " alt="" coords="67,244,275,285"/>
+<area shape="rect" id="node6" href="$prom__counter_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#counter " alt="" coords="349,251,561,278"/>
+<area shape="rect" id="node7" href="$prom__gauge_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#gauge " alt="" coords="585,251,789,278"/>
+<area shape="rect" id="node8" href="$prom__histogram_8h.html" title="https://prometheus.io/docs/concepts/metric_types/#histogram " alt="" coords="593,169,823,196"/>
+</map>
diff --git a/docs/prom__metric__sample__histogram_8h__dep__incl.md5 b/docs/prom__metric__sample__histogram_8h__dep__incl.md5
new file mode 100644
index 0000000..380671c
--- /dev/null
+++ b/docs/prom__metric__sample__histogram_8h__dep__incl.md5
@@ -0,0 +1 @@
+e71a590ac9e5f5180968f7ebb44dc8b8 \ No newline at end of file
diff --git a/docs/prom__metric__sample__histogram_8h__dep__incl.png b/docs/prom__metric__sample__histogram_8h__dep__incl.png
new file mode 100644
index 0000000..b6f3a1d
--- /dev/null
+++ b/docs/prom__metric__sample__histogram_8h__dep__incl.png
Binary files differ
diff --git a/docs/prom__metric__sample__histogram_8h__incl.dot b/docs/prom__metric__sample__histogram_8h__incl.dot
new file mode 100644
index 0000000..8db67c1
--- /dev/null
+++ b/docs/prom__metric__sample__histogram_8h__incl.dot
@@ -0,0 +1,8 @@
+digraph "prom/include/prom_metric_sample_histogram.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node0 [label="prom/include/prom_metric\l_sample_histogram.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node0 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 [label="prom_errors.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__errors_8h.html",tooltip="Prometheus client errors. "];
+}
diff --git a/docs/prom__metric__sample__histogram_8h__incl.map b/docs/prom__metric__sample__histogram_8h__incl.map
new file mode 100644
index 0000000..28673a0
--- /dev/null
+++ b/docs/prom__metric__sample__histogram_8h__incl.map
@@ -0,0 +1,3 @@
+<map id="prom/include/prom_metric_sample_histogram.h" name="prom/include/prom_metric_sample_histogram.h">
+<area shape="rect" id="node2" href="$prom__errors_8h.html" title="Prometheus client errors. " alt="" coords="46,95,159,121"/>
+</map>
diff --git a/docs/prom__metric__sample__histogram_8h__incl.md5 b/docs/prom__metric__sample__histogram_8h__incl.md5
new file mode 100644
index 0000000..2665445
--- /dev/null
+++ b/docs/prom__metric__sample__histogram_8h__incl.md5
@@ -0,0 +1 @@
+4a0783f96405ffb6caf6e1c466414e7b \ No newline at end of file
diff --git a/docs/prom__metric__sample__histogram_8h__incl.png b/docs/prom__metric__sample__histogram_8h__incl.png
new file mode 100644
index 0000000..8d5dd2f
--- /dev/null
+++ b/docs/prom__metric__sample__histogram_8h__incl.png
Binary files differ
diff --git a/docs/prom__metric__sample__histogram_8h_source.html b/docs/prom__metric__sample__histogram_8h_source.html
new file mode 100644
index 0000000..6db0c21
--- /dev/null
+++ b/docs/prom__metric__sample__histogram_8h_source.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom/include/prom_metric_sample_histogram.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_2c63f04010e7ff462eba5e344f58cd21.html">prom</a></li><li class="navelem"><a class="el" href="dir_83821d63a26a6eb889c4977bd95ca990.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_metric_sample_histogram.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="prom__metric__sample__histogram_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment">You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment">Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment">See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment">limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment">*/</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;<span class="preprocessor">#ifndef PROM_METRIC_SAMPLE_HISOTGRAM_H</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="preprocessor">#define PROM_METRIC_SAMPLE_HISOTGRAM_H</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;</div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160;<span class="keyword">struct </span>prom_metric_sample_histogram;</div><div class="line"><a name="l00029"></a><span class="lineno"><a class="line" href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f"> 29</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span>prom_metric_sample_histogram <a class="code" href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f">prom_metric_sample_histogram_t</a>;</div><div class="line"><a name="l00030"></a><span class="lineno"> 30</span>&#160;</div><div class="line"><a name="l00034"></a><span class="lineno"> 34</span>&#160;<span class="keywordtype">int</span> <a class="code" href="prom__metric__sample__histogram_8h.html#a20a030bf6be56211c87c9feb520a3761">prom_metric_sample_histogram_observe</a>(<a class="code" href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f">prom_metric_sample_histogram_t</a> *<span class="keyword">self</span>, <span class="keywordtype">double</span> value);</div><div class="line"><a name="l00035"></a><span class="lineno"> 35</span>&#160;</div><div class="line"><a name="l00036"></a><span class="lineno"> 36</span>&#160;<span class="preprocessor">#endif // PROM_METRIC_SAMPLE_HISOTGRAM_H</span></div><div class="ttc" id="prom__metric__sample__histogram_8h_html_a20a030bf6be56211c87c9feb520a3761"><div class="ttname"><a href="prom__metric__sample__histogram_8h.html#a20a030bf6be56211c87c9feb520a3761">prom_metric_sample_histogram_observe</a></div><div class="ttdeci">int prom_metric_sample_histogram_observe(prom_metric_sample_histogram_t *self, double value)</div><div class="ttdoc">Observe the double for the given prom_metric_sample_histogram_observe_t. </div></div>
+<div class="ttc" id="prom__metric__sample__histogram_8h_html_aed3455bc4eec61a3d8f01e6c1af84f9f"><div class="ttname"><a href="prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f">prom_metric_sample_histogram_t</a></div><div class="ttdeci">struct prom_metric_sample_histogram prom_metric_sample_histogram_t</div><div class="ttdoc">A histogram metric sample. </div><div class="ttdef"><b>Definition:</b> prom_metric_sample_histogram.h:29</div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/promhttp_8h.html b/docs/promhttp_8h.html
new file mode 100644
index 0000000..1557e3a
--- /dev/null
+++ b/docs/promhttp_8h.html
@@ -0,0 +1,178 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: promhttp/include/promhttp.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_21619567660c3332e6a61228c76007f9.html">promhttp</a></li><li class="navelem"><a class="el" href="dir_8d140c3a8bac3cd45205c9ea74fd211f.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">promhttp.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Provides a HTTP endpoint for metric exposition References:
+<a href="#details">More...</a></p>
+<div class="textblock"><code>#include &lt;string.h&gt;</code><br />
+<code>#include &quot;microhttpd.h&quot;</code><br />
+</div><div class="textblock"><div class="dynheader">
+Include dependency graph for promhttp.h:</div>
+<div class="dyncontent">
+<div class="center"><img src="promhttp_8h__incl.png" border="0" usemap="#promhttp_2include_2promhttp_8h" alt=""/></div>
+<map name="promhttp_2include_2promhttp_8h" id="promhttp_2include_2promhttp_8h">
+</map>
+</div>
+</div>
+<p><a href="promhttp_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:a712a45634bc22724fef9bedcb2841e00"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="promhttp_8h.html#a712a45634bc22724fef9bedcb2841e00">promhttp_set_active_collector_registry</a> (<a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *active_registry)</td></tr>
+<tr class="memdesc:a712a45634bc22724fef9bedcb2841e00"><td class="mdescLeft">&#160;</td><td class="mdescRight">Sets the active registry for metric scraping. <a href="#a712a45634bc22724fef9bedcb2841e00">More...</a><br /></td></tr>
+<tr class="separator:a712a45634bc22724fef9bedcb2841e00"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a699ecc3aa11ed601269722f43da2823e"><td class="memItemLeft" align="right" valign="top">struct MHD_Daemon *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="promhttp_8h.html#a699ecc3aa11ed601269722f43da2823e">promhttp_start_daemon</a> (unsigned int flags, unsigned short port, MHD_AcceptPolicyCallback apc, void *apc_cls)</td></tr>
+<tr class="memdesc:a699ecc3aa11ed601269722f43da2823e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Starts a daemon in the background and returns a pointer to an HMD_Daemon. <a href="#a699ecc3aa11ed601269722f43da2823e">More...</a><br /></td></tr>
+<tr class="separator:a699ecc3aa11ed601269722f43da2823e"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Provides a HTTP endpoint for metric exposition References: </p>
+<ul>
+<li>MHD_FLAG: <a href="https://www.gnu.org/software/libmicrohttpd/manual/libmicrohttpd.html#microhttpd_002dconst">https://www.gnu.org/software/libmicrohttpd/manual/libmicrohttpd.html#microhttpd_002dconst</a></li>
+<li>MHD_AcceptPolicyCallback: <a href="https://www.gnu.org/software/libmicrohttpd/manual/libmicrohttpd.html#index-_002aMHD_005fAcceptPolicyCallback">https://www.gnu.org/software/libmicrohttpd/manual/libmicrohttpd.html#index-_002aMHD_005fAcceptPolicyCallback</a> </li>
+</ul>
+</div><h2 class="groupheader">Function Documentation</h2>
+<a id="a712a45634bc22724fef9bedcb2841e00"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a712a45634bc22724fef9bedcb2841e00">&#9670;&nbsp;</a></span>promhttp_set_active_collector_registry()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void promhttp_set_active_collector_registry </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *&#160;</td>
+ <td class="paramname"><em>active_registry</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Sets the active registry for metric scraping. </p>
+<p>If null is passed, the default registry is used. The registry MUST be initialized. </p>
+
+</div>
+</div>
+<a id="a699ecc3aa11ed601269722f43da2823e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a699ecc3aa11ed601269722f43da2823e">&#9670;&nbsp;</a></span>promhttp_start_daemon()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct MHD_Daemon* promhttp_start_daemon </td>
+ <td>(</td>
+ <td class="paramtype">unsigned int&#160;</td>
+ <td class="paramname"><em>flags</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">unsigned short&#160;</td>
+ <td class="paramname"><em>port</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">MHD_AcceptPolicyCallback&#160;</td>
+ <td class="paramname"><em>apc</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">void *&#160;</td>
+ <td class="paramname"><em>apc_cls</em>&#160;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Starts a daemon in the background and returns a pointer to an HMD_Daemon. </p>
+<p>References:</p><ul>
+<li><a href="https://www.gnu.org/software/libmicrohttpd/manual/libmicrohttpd.html#microhttpd_002dinit">https://www.gnu.org/software/libmicrohttpd/manual/libmicrohttpd.html#microhttpd_002dinit</a> </li>
+</ul>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/promhttp_8h__incl.dot b/docs/promhttp_8h__incl.dot
new file mode 100644
index 0000000..d5d937d
--- /dev/null
+++ b/docs/promhttp_8h__incl.dot
@@ -0,0 +1,57 @@
+digraph "promhttp/include/promhttp.h"
+{
+ edge [fontname="Helvetica",fontsize="10",labelfontname="Helvetica",labelfontsize="10"];
+ node [fontname="Helvetica",fontsize="10",shape=record];
+ Node0 [label="promhttp/include/promhttp.h",height=0.2,width=0.4,color="black", fillcolor="grey75", style="filled", fontcolor="black"];
+ Node0 -> Node1 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node1 [label="string.h",height=0.2,width=0.4,color="grey75", fillcolor="white", style="filled"];
+ Node0 -> Node2 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node2 [label="microhttpd.h",height=0.2,width=0.4,color="grey75", fillcolor="white", style="filled"];
+ Node0 -> Node3 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 [label="prom.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom_8h.html",tooltip="Include prom.h to include the entire public API. "];
+ Node3 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node4 [label="prom_collector.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector_8h.html",tooltip="A Prometheus collector returns a collection of metrics. "];
+ Node4 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node5 [label="prom_errors.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__errors_8h.html",tooltip="Prometheus client errors. "];
+ Node4 -> Node6 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node6 [label="prom_map.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__map_8h_source.html"];
+ Node4 -> Node7 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 [label="prom_metric.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric_8h.html"];
+ Node7 -> Node8 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node8 [label="prom_metric_sample.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample_8h.html"];
+ Node8 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node7 -> Node9 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node9 [label="prom_metric_sample\l_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__metric__sample__histogram_8h.html"];
+ Node9 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node10 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node10 [label="prom_collector_registry.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__collector__registry_8h.html",tooltip="The collector registry registers collectors for metric exposition. "];
+ Node10 -> Node4 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node10 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node10 -> Node7 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node11 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node11 [label="prom_counter.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__counter_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#counter "];
+ Node11 -> Node12 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node12 [label="stdlib.h",height=0.2,width=0.4,color="grey75", fillcolor="white", style="filled"];
+ Node11 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node11 -> Node7 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node13 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node13 [label="prom_gauge.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__gauge_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#gauge "];
+ Node13 -> Node12 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node13 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node13 -> Node7 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node14 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node14 [label="prom_histogram.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__histogram_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#histogram "];
+ Node14 -> Node12 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node14 -> Node5 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node14 -> Node7 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node14 -> Node15 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node15 [label="prom_histogram_buckets.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__histogram__buckets_8h.html",tooltip="https://prometheus.io/docs/concepts/metric_types/#histogram "];
+ Node3 -> Node15 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node16 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node16 [label="prom_linked_list.h",height=0.2,width=0.4,color="black", fillcolor="white", style="filled",URL="$prom__linked__list_8h_source.html"];
+ Node16 -> Node12 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node6 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node7 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+ Node3 -> Node8 [color="midnightblue",fontsize="10",style="solid",fontname="Helvetica"];
+}
diff --git a/docs/promhttp_8h__incl.map b/docs/promhttp_8h__incl.map
new file mode 100644
index 0000000..3b1713f
--- /dev/null
+++ b/docs/promhttp_8h__incl.map
@@ -0,0 +1,2 @@
+<map id="promhttp/include/promhttp.h" name="promhttp/include/promhttp.h">
+</map>
diff --git a/docs/promhttp_8h__incl.md5 b/docs/promhttp_8h__incl.md5
new file mode 100644
index 0000000..0413787
--- /dev/null
+++ b/docs/promhttp_8h__incl.md5
@@ -0,0 +1 @@
+5a38f59371d33bb776e7c896334016d4 \ No newline at end of file
diff --git a/docs/promhttp_8h__incl.png b/docs/promhttp_8h__incl.png
new file mode 100644
index 0000000..fb575c5
--- /dev/null
+++ b/docs/promhttp_8h__incl.png
Binary files differ
diff --git a/docs/promhttp_8h_source.html b/docs/promhttp_8h_source.html
new file mode 100644
index 0000000..0dfab52
--- /dev/null
+++ b/docs/promhttp_8h_source.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: promhttp/include/promhttp.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_21619567660c3332e6a61228c76007f9.html">promhttp</a></li><li class="navelem"><a class="el" href="dir_8d140c3a8bac3cd45205c9ea74fd211f.html">include</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">promhttp.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="promhttp_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment"> Copyright 2019 DigitalOcean Inc.</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment"> Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment"> you may not use this file except in compliance with the License.</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;<span class="comment"> You may obtain a copy of the License at</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;<span class="comment"> http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="comment"> Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="comment"> distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="comment"> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="comment"> See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="comment"> limitations under the License.</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="comment"> */</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;</div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160;<span class="preprocessor">#include &lt;string.h&gt;</span></div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span>&#160;</div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span>&#160;<span class="preprocessor">#include &quot;microhttpd.h&quot;</span></div><div class="line"><a name="l00028"></a><span class="lineno"> 28</span>&#160;</div><div class="line"><a name="l00029"></a><span class="lineno"> 29</span>&#160;</div><div class="line"><a name="l00035"></a><span class="lineno"> 35</span>&#160;<span class="keywordtype">void</span> <a class="code" href="promhttp_8h.html#a712a45634bc22724fef9bedcb2841e00">promhttp_set_active_collector_registry</a>(<a class="code" href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a> *active_registry);</div><div class="line"><a name="l00036"></a><span class="lineno"> 36</span>&#160;</div><div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160;<span class="keyword">struct </span>MHD_Daemon* <a class="code" href="promhttp_8h.html#a699ecc3aa11ed601269722f43da2823e">promhttp_start_daemon</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> flags,</div><div class="line"><a name="l00044"></a><span class="lineno"> 44</span>&#160; <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> port,</div><div class="line"><a name="l00045"></a><span class="lineno"> 45</span>&#160; MHD_AcceptPolicyCallback apc,</div><div class="line"><a name="l00046"></a><span class="lineno"> 46</span>&#160; <span class="keywordtype">void</span> *apc_cls);</div><div class="ttc" id="prom__collector__registry_8h_html_a20f07748401fbbde9efc8a718f9bc202"><div class="ttname"><a href="prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202">prom_collector_registry_t</a></div><div class="ttdeci">struct prom_collector_registry prom_collector_registry_t</div><div class="ttdoc">A prom_registry_t is responsible for registering metrics and briding them to the string exposition fo...</div><div class="ttdef"><b>Definition:</b> prom_collector_registry.h:31</div></div>
+<div class="ttc" id="promhttp_8h_html_a712a45634bc22724fef9bedcb2841e00"><div class="ttname"><a href="promhttp_8h.html#a712a45634bc22724fef9bedcb2841e00">promhttp_set_active_collector_registry</a></div><div class="ttdeci">void promhttp_set_active_collector_registry(prom_collector_registry_t *active_registry)</div><div class="ttdoc">Sets the active registry for metric scraping. </div></div>
+<div class="ttc" id="promhttp_8h_html_a699ecc3aa11ed601269722f43da2823e"><div class="ttname"><a href="promhttp_8h.html#a699ecc3aa11ed601269722f43da2823e">promhttp_start_daemon</a></div><div class="ttdeci">struct MHD_Daemon * promhttp_start_daemon(unsigned int flags, unsigned short port, MHD_AcceptPolicyCallback apc, void *apc_cls)</div><div class="ttdoc">Starts a daemon in the background and returns a pointer to an HMD_Daemon. </div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/search/all_0.html b/docs/search/all_0.html
new file mode 100644
index 0000000..f25360b
--- /dev/null
+++ b/docs/search/all_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/all_0.js b/docs/search/all_0.js
new file mode 100644
index 0000000..bbd3bf0
--- /dev/null
+++ b/docs/search/all_0.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['count',['count',['../structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621',1,'prom_histogram_buckets']]]
+];
diff --git a/docs/search/all_1.html b/docs/search/all_1.html
new file mode 100644
index 0000000..b13f0f7
--- /dev/null
+++ b/docs/search/all_1.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/all_1.js b/docs/search/all_1.js
new file mode 100644
index 0000000..e2dd56c
--- /dev/null
+++ b/docs/search/all_1.js
@@ -0,0 +1,72 @@
+var searchData=
+[
+ ['prom_2eh',['prom.h',['../prom_8h.html',1,'']]],
+ ['prom_5falloc_2eh',['prom_alloc.h',['../prom__alloc_8h.html',1,'']]],
+ ['prom_5fcollect_5ffn',['prom_collect_fn',['../prom__collector_8h.html#af87330edd48cdb8e1074517e734b1e40',1,'prom_collector.h']]],
+ ['prom_5fcollector_2eh',['prom_collector.h',['../prom__collector_8h.html',1,'']]],
+ ['prom_5fcollector_5fadd_5fmetric',['prom_collector_add_metric',['../prom__collector_8h.html#abd87021bd63f759d55642685a74874ee',1,'prom_collector.h']]],
+ ['prom_5fcollector_5fdestroy',['prom_collector_destroy',['../prom__collector_8h.html#a037b72b2edb81a477999a7dfc08758c7',1,'prom_collector.h']]],
+ ['prom_5fcollector_5fdestroy_5fgeneric',['prom_collector_destroy_generic',['../prom__collector_8h.html#a12c297cce0a30ee4149f2b486d9f0337',1,'prom_collector.h']]],
+ ['prom_5fcollector_5fnew',['prom_collector_new',['../prom__collector_8h.html#a4300cf33b6f8e4457df385c3d2a51a4b',1,'prom_collector.h']]],
+ ['prom_5fcollector_5fprocess_5fnew',['prom_collector_process_new',['../prom__collector_8h.html#af50746bb4af87eda617fa08237e3834e',1,'prom_collector.h']]],
+ ['prom_5fcollector_5fregistry_2eh',['prom_collector_registry.h',['../prom__collector__registry_8h.html',1,'']]],
+ ['prom_5fcollector_5fregistry_5fbridge',['prom_collector_registry_bridge',['../prom__collector__registry_8h.html#a0149a2702ae0b3ff39d57904d613c14f',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fdefault',['PROM_COLLECTOR_REGISTRY_DEFAULT',['../prom__collector__registry_8h.html#a6092b48e150390c1927da5fe8914981b',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fdefault_5finit',['prom_collector_registry_default_init',['../prom__collector__registry_8h.html#aaf1421bd744f0dbbdaba7e64cec11f54',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fdestroy',['prom_collector_registry_destroy',['../prom__collector__registry_8h.html#ad3854e6e40b6f741fde53dc65f0ecd87',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fenable_5fprocess_5fmetrics',['prom_collector_registry_enable_process_metrics',['../prom__collector__registry_8h.html#a0d59bf988de4ee29e076910fa7135071',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fmust_5fregister_5fmetric',['prom_collector_registry_must_register_metric',['../prom__collector__registry_8h.html#a113683f4e15ad9240a37ed2139ddaea6',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fnew',['prom_collector_registry_new',['../prom__collector__registry_8h.html#ab5d622258998978c528253f07e2903b8',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fregister_5fcollector',['prom_collector_registry_register_collector',['../prom__collector__registry_8h.html#a42203da085c6c6f2bc3ba31501683882',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fregister_5fmetric',['prom_collector_registry_register_metric',['../prom__collector__registry_8h.html#aa735fa0fbe03d6d9a0d11eb4792ec761',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5ft',['prom_collector_registry_t',['../prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fvalidate_5fmetric_5fname',['prom_collector_registry_validate_metric_name',['../prom__collector__registry_8h.html#acf002221c3239584723f9fb15c53e15e',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fset_5fcollect_5ffn',['prom_collector_set_collect_fn',['../prom__collector_8h.html#a9929cb81f4fb49ffca8aa880a4699650',1,'prom_collector.h']]],
+ ['prom_5fcollector_5ft',['prom_collector_t',['../prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c',1,'prom_collector.h']]],
+ ['prom_5fcounter_2eh',['prom_counter.h',['../prom__counter_8h.html',1,'']]],
+ ['prom_5fcounter_5fadd',['prom_counter_add',['../prom__counter_8h.html#addd8a7efc39e17d30b2267e5a0a626db',1,'prom_counter.h']]],
+ ['prom_5fcounter_5fdestroy',['prom_counter_destroy',['../prom__counter_8h.html#ac36abc71c11df1e774c8c102b1fdb78d',1,'prom_counter.h']]],
+ ['prom_5fcounter_5finc',['prom_counter_inc',['../prom__counter_8h.html#a315695fdd8b9b6fa59904bb2e35bfa35',1,'prom_counter.h']]],
+ ['prom_5fcounter_5fnew',['prom_counter_new',['../prom__counter_8h.html#a3302a9f1a3556d17af9af29729be2651',1,'prom_counter.h']]],
+ ['prom_5fcounter_5ft',['prom_counter_t',['../prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606',1,'prom_counter.h']]],
+ ['prom_5ffree',['prom_free',['../prom__alloc_8h.html#a19b2231f9b45a520bbbcf046ed5d81ef',1,'prom_alloc.h']]],
+ ['prom_5fgauge_2eh',['prom_gauge.h',['../prom__gauge_8h.html',1,'']]],
+ ['prom_5fgauge_5fadd',['prom_gauge_add',['../prom__gauge_8h.html#a96bc5b32abee5f99fbd4ae11bebd44c8',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5fdec',['prom_gauge_dec',['../prom__gauge_8h.html#aa351ef4f2d917d7dae914df6d81c547b',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5fdestroy',['prom_gauge_destroy',['../prom__gauge_8h.html#a2fc5dc11239cefdf59ae978be4bfd789',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5finc',['prom_gauge_inc',['../prom__gauge_8h.html#ad953b12ea1f8a3c3b7a39e6c260d07a2',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5fnew',['prom_gauge_new',['../prom__gauge_8h.html#a5ecd07c83cf0981944a9256914571d70',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5fset',['prom_gauge_set',['../prom__gauge_8h.html#a04210b18bfb89aa6f3ddc72d7851a528',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5fsub',['prom_gauge_sub',['../prom__gauge_8h.html#a7ae193d586176bff82a39cd65e2bc999',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5ft',['prom_gauge_t',['../prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5',1,'prom_gauge.h']]],
+ ['prom_5fhistogram_2eh',['prom_histogram.h',['../prom__histogram_8h.html',1,'']]],
+ ['prom_5fhistogram_5fbuckets',['prom_histogram_buckets',['../structprom__histogram__buckets.html',1,'']]],
+ ['prom_5fhistogram_5fbuckets_2eh',['prom_histogram_buckets.h',['../prom__histogram__buckets_8h.html',1,'']]],
+ ['prom_5fhistogram_5fbuckets_5fcount',['prom_histogram_buckets_count',['../prom__histogram__buckets_8h.html#a92158192cfe9a71a98dbb1d9adc8508a',1,'prom_histogram_buckets.h']]],
+ ['prom_5fhistogram_5fbuckets_5fdestroy',['prom_histogram_buckets_destroy',['../prom__histogram__buckets_8h.html#a36bc3312f8f479bbd6eb92fa3b1a5033',1,'prom_histogram_buckets.h']]],
+ ['prom_5fhistogram_5fbuckets_5fexponential',['prom_histogram_buckets_exponential',['../prom__histogram__buckets_8h.html#a164da4101785b6fa2a292a964c232f12',1,'prom_histogram_buckets.h']]],
+ ['prom_5fhistogram_5fbuckets_5flinear',['prom_histogram_buckets_linear',['../prom__histogram__buckets_8h.html#aa1adc550bf8999a27f6a26769d6bfc72',1,'prom_histogram_buckets.h']]],
+ ['prom_5fhistogram_5fdefault_5fbuckets',['prom_histogram_default_buckets',['../prom__histogram__buckets_8h.html#aa8d61c1abc355eb54173b27cb1b50a5d',1,'prom_histogram_buckets.h']]],
+ ['prom_5fhistogram_5fdestroy',['prom_histogram_destroy',['../prom__histogram_8h.html#af9067b27e7ab2abd815af0614bb35357',1,'prom_histogram.h']]],
+ ['prom_5fhistogram_5fnew',['prom_histogram_new',['../prom__histogram_8h.html#ad42681e59e727f9e3d43bf0cdbba9a1b',1,'prom_histogram.h']]],
+ ['prom_5fhistogram_5fobserve',['prom_histogram_observe',['../prom__histogram_8h.html#a274e4b869c7d9239e9f47b3898210fbe',1,'prom_histogram.h']]],
+ ['prom_5fhistogram_5ft',['prom_histogram_t',['../prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae',1,'prom_histogram.h']]],
+ ['prom_5fmalloc',['prom_malloc',['../prom__alloc_8h.html#ae1613c091e07daa2bfa4303ef5628827',1,'prom_alloc.h']]],
+ ['prom_5fmetric_2eh',['prom_metric.h',['../prom__metric_8h.html',1,'']]],
+ ['prom_5fmetric_5fsample_2eh',['prom_metric_sample.h',['../prom__metric__sample_8h.html',1,'']]],
+ ['prom_5fmetric_5fsample_5fadd',['prom_metric_sample_add',['../prom__metric__sample_8h.html#a3f8674d6c8ee2c27eb7504d602110daa',1,'prom_metric_sample.h']]],
+ ['prom_5fmetric_5fsample_5ffrom_5flabels',['prom_metric_sample_from_labels',['../prom__metric_8h.html#a2c33d7e03b430a2903bf122fbeeb89de',1,'prom_metric.h']]],
+ ['prom_5fmetric_5fsample_5fhistogram_2eh',['prom_metric_sample_histogram.h',['../prom__metric__sample__histogram_8h.html',1,'']]],
+ ['prom_5fmetric_5fsample_5fhistogram_5ffrom_5flabels',['prom_metric_sample_histogram_from_labels',['../prom__metric_8h.html#a3b76680b4a7177eebc864f3b3be1e935',1,'prom_metric.h']]],
+ ['prom_5fmetric_5fsample_5fhistogram_5fobserve',['prom_metric_sample_histogram_observe',['../prom__metric__sample__histogram_8h.html#a20a030bf6be56211c87c9feb520a3761',1,'prom_metric_sample_histogram.h']]],
+ ['prom_5fmetric_5fsample_5fhistogram_5ft',['prom_metric_sample_histogram_t',['../prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f',1,'prom_metric_sample_histogram.h']]],
+ ['prom_5fmetric_5fsample_5fset',['prom_metric_sample_set',['../prom__metric__sample_8h.html#a0c5f0c66599282c2ee2c042ae4574db3',1,'prom_metric_sample.h']]],
+ ['prom_5fmetric_5fsample_5fsub',['prom_metric_sample_sub',['../prom__metric__sample_8h.html#a1965caa1626c308bc1cb23995e90a0a7',1,'prom_metric_sample.h']]],
+ ['prom_5fmetric_5fsample_5ft',['prom_metric_sample_t',['../prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a',1,'prom_metric_sample.h']]],
+ ['prom_5fmetric_5ft',['prom_metric_t',['../prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889',1,'prom_metric.h']]],
+ ['prom_5frealloc',['prom_realloc',['../prom__alloc_8h.html#aab8dc4629c851a8c59cc721bd2f7c6f3',1,'prom_alloc.h']]],
+ ['prom_5fstrdup',['prom_strdup',['../prom__alloc_8h.html#a21faa2fafc84c8ca25467fe9cb0a55f3',1,'prom_alloc.h']]],
+ ['promhttp_2eh',['promhttp.h',['../promhttp_8h.html',1,'']]],
+ ['promhttp_5fset_5factive_5fcollector_5fregistry',['promhttp_set_active_collector_registry',['../promhttp_8h.html#a712a45634bc22724fef9bedcb2841e00',1,'promhttp.h']]],
+ ['promhttp_5fstart_5fdaemon',['promhttp_start_daemon',['../promhttp_8h.html#a699ecc3aa11ed601269722f43da2823e',1,'promhttp.h']]]
+];
diff --git a/docs/search/all_2.html b/docs/search/all_2.html
new file mode 100644
index 0000000..9543c57
--- /dev/null
+++ b/docs/search/all_2.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/all_2.js b/docs/search/all_2.js
new file mode 100644
index 0000000..441b2de
--- /dev/null
+++ b/docs/search/all_2.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['todo_20list',['Todo List',['../todo.html',1,'']]]
+];
diff --git a/docs/search/all_3.html b/docs/search/all_3.html
new file mode 100644
index 0000000..03405c0
--- /dev/null
+++ b/docs/search/all_3.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_3.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/all_3.js b/docs/search/all_3.js
new file mode 100644
index 0000000..f8121ac
--- /dev/null
+++ b/docs/search/all_3.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['upper_5fbounds',['upper_bounds',['../structprom__histogram__buckets.html#a8abda07c4930e15a3dff8a86e3164344',1,'prom_histogram_buckets']]]
+];
diff --git a/docs/search/all_4.html b/docs/search/all_4.html
new file mode 100644
index 0000000..8e1f4b9
--- /dev/null
+++ b/docs/search/all_4.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_4.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/all_4.js b/docs/search/all_4.js
new file mode 100644
index 0000000..5459b5b
--- /dev/null
+++ b/docs/search/all_4.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['welcome_20to_20the_20documentation_20site_20for_20prometheus_2dclient_2dc_21',['Welcome to the documentation site for prometheus-client-c!',['../index.html',1,'']]]
+];
diff --git a/docs/search/classes_0.html b/docs/search/classes_0.html
new file mode 100644
index 0000000..1c3e406
--- /dev/null
+++ b/docs/search/classes_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="classes_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/classes_0.js b/docs/search/classes_0.js
new file mode 100644
index 0000000..6a612bc
--- /dev/null
+++ b/docs/search/classes_0.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['prom_5fhistogram_5fbuckets',['prom_histogram_buckets',['../structprom__histogram__buckets.html',1,'']]]
+];
diff --git a/docs/search/close.png b/docs/search/close.png
new file mode 100644
index 0000000..9342d3d
--- /dev/null
+++ b/docs/search/close.png
Binary files differ
diff --git a/docs/search/defines_0.html b/docs/search/defines_0.html
new file mode 100644
index 0000000..5b25204
--- /dev/null
+++ b/docs/search/defines_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="defines_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/defines_0.js b/docs/search/defines_0.js
new file mode 100644
index 0000000..e7ffca3
--- /dev/null
+++ b/docs/search/defines_0.js
@@ -0,0 +1,7 @@
+var searchData=
+[
+ ['prom_5ffree',['prom_free',['../prom__alloc_8h.html#a19b2231f9b45a520bbbcf046ed5d81ef',1,'prom_alloc.h']]],
+ ['prom_5fmalloc',['prom_malloc',['../prom__alloc_8h.html#ae1613c091e07daa2bfa4303ef5628827',1,'prom_alloc.h']]],
+ ['prom_5frealloc',['prom_realloc',['../prom__alloc_8h.html#aab8dc4629c851a8c59cc721bd2f7c6f3',1,'prom_alloc.h']]],
+ ['prom_5fstrdup',['prom_strdup',['../prom__alloc_8h.html#a21faa2fafc84c8ca25467fe9cb0a55f3',1,'prom_alloc.h']]]
+];
diff --git a/docs/search/enums_0.html b/docs/search/enums_0.html
new file mode 100644
index 0000000..ee343ac
--- /dev/null
+++ b/docs/search/enums_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="enums_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/enums_0.js b/docs/search/enums_0.js
new file mode 100644
index 0000000..558c2bd
--- /dev/null
+++ b/docs/search/enums_0.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['prom_5freturn_5fcode',['prom_return_code',['../prom__errors_8h.html#ae9dcc70f3217ae6f5cd331dbdef06602',1,'prom_errors.h']]]
+];
diff --git a/docs/search/enumvalues_0.html b/docs/search/enumvalues_0.html
new file mode 100644
index 0000000..9387b6a
--- /dev/null
+++ b/docs/search/enumvalues_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="enumvalues_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/enumvalues_0.js b/docs/search/enumvalues_0.js
new file mode 100644
index 0000000..7796db7
--- /dev/null
+++ b/docs/search/enumvalues_0.js
@@ -0,0 +1,8 @@
+var searchData=
+[
+ ['prom_5fcollector_5fregistration_5ffailure',['PROM_COLLECTOR_REGISTRATION_FAILURE',['../prom__errors_8h.html#a3b3873fa7ceb3c9e4a8d714771fb4830a23269fa188cfe85113887765ae300781',1,'prom_errors.h']]],
+ ['prom_5ffailure',['PROM_FAILURE',['../prom__errors_8h.html#a3b3873fa7ceb3c9e4a8d714771fb4830a20d1dda215f590d375c018ecabb065cc',1,'prom_errors.h']]],
+ ['prom_5finvalid_5fmetric_5ftype',['PROM_INVALID_METRIC_TYPE',['../prom__errors_8h.html#a3b3873fa7ceb3c9e4a8d714771fb4830a11a15b66987a9d455f369a94101205fc',1,'prom_errors.h']]],
+ ['prom_5fmetric_5fregistration_5ffailure',['PROM_METRIC_REGISTRATION_FAILURE',['../prom__errors_8h.html#a3b3873fa7ceb3c9e4a8d714771fb4830ae3ad35c6d86de06362db4735e0805416',1,'prom_errors.h']]],
+ ['prom_5fsuccess',['PROM_SUCCESS',['../prom__errors_8h.html#a3b3873fa7ceb3c9e4a8d714771fb4830a4860821c9dc1ba212354b29a48b8c59c',1,'prom_errors.h']]]
+];
diff --git a/docs/search/files_0.html b/docs/search/files_0.html
new file mode 100644
index 0000000..4f272b8
--- /dev/null
+++ b/docs/search/files_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="files_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/files_0.js b/docs/search/files_0.js
new file mode 100644
index 0000000..6afd224
--- /dev/null
+++ b/docs/search/files_0.js
@@ -0,0 +1,15 @@
+var searchData=
+[
+ ['prom_2eh',['prom.h',['../prom_8h.html',1,'']]],
+ ['prom_5falloc_2eh',['prom_alloc.h',['../prom__alloc_8h.html',1,'']]],
+ ['prom_5fcollector_2eh',['prom_collector.h',['../prom__collector_8h.html',1,'']]],
+ ['prom_5fcollector_5fregistry_2eh',['prom_collector_registry.h',['../prom__collector__registry_8h.html',1,'']]],
+ ['prom_5fcounter_2eh',['prom_counter.h',['../prom__counter_8h.html',1,'']]],
+ ['prom_5fgauge_2eh',['prom_gauge.h',['../prom__gauge_8h.html',1,'']]],
+ ['prom_5fhistogram_2eh',['prom_histogram.h',['../prom__histogram_8h.html',1,'']]],
+ ['prom_5fhistogram_5fbuckets_2eh',['prom_histogram_buckets.h',['../prom__histogram__buckets_8h.html',1,'']]],
+ ['prom_5fmetric_2eh',['prom_metric.h',['../prom__metric_8h.html',1,'']]],
+ ['prom_5fmetric_5fsample_2eh',['prom_metric_sample.h',['../prom__metric__sample_8h.html',1,'']]],
+ ['prom_5fmetric_5fsample_5fhistogram_2eh',['prom_metric_sample_histogram.h',['../prom__metric__sample__histogram_8h.html',1,'']]],
+ ['promhttp_2eh',['promhttp.h',['../promhttp_8h.html',1,'']]]
+];
diff --git a/docs/search/functions_0.html b/docs/search/functions_0.html
new file mode 100644
index 0000000..4e6d87d
--- /dev/null
+++ b/docs/search/functions_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="functions_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/functions_0.js b/docs/search/functions_0.js
new file mode 100644
index 0000000..4844d35
--- /dev/null
+++ b/docs/search/functions_0.js
@@ -0,0 +1,44 @@
+var searchData=
+[
+ ['prom_5fcollector_5fadd_5fmetric',['prom_collector_add_metric',['../prom__collector_8h.html#abd87021bd63f759d55642685a74874ee',1,'prom_collector.h']]],
+ ['prom_5fcollector_5fdestroy',['prom_collector_destroy',['../prom__collector_8h.html#a037b72b2edb81a477999a7dfc08758c7',1,'prom_collector.h']]],
+ ['prom_5fcollector_5fdestroy_5fgeneric',['prom_collector_destroy_generic',['../prom__collector_8h.html#a12c297cce0a30ee4149f2b486d9f0337',1,'prom_collector.h']]],
+ ['prom_5fcollector_5fnew',['prom_collector_new',['../prom__collector_8h.html#a4300cf33b6f8e4457df385c3d2a51a4b',1,'prom_collector.h']]],
+ ['prom_5fcollector_5fprocess_5fnew',['prom_collector_process_new',['../prom__collector_8h.html#af50746bb4af87eda617fa08237e3834e',1,'prom_collector.h']]],
+ ['prom_5fcollector_5fregistry_5fbridge',['prom_collector_registry_bridge',['../prom__collector__registry_8h.html#a0149a2702ae0b3ff39d57904d613c14f',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fdefault_5finit',['prom_collector_registry_default_init',['../prom__collector__registry_8h.html#aaf1421bd744f0dbbdaba7e64cec11f54',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fdestroy',['prom_collector_registry_destroy',['../prom__collector__registry_8h.html#ad3854e6e40b6f741fde53dc65f0ecd87',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fenable_5fprocess_5fmetrics',['prom_collector_registry_enable_process_metrics',['../prom__collector__registry_8h.html#a0d59bf988de4ee29e076910fa7135071',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fmust_5fregister_5fmetric',['prom_collector_registry_must_register_metric',['../prom__collector__registry_8h.html#a113683f4e15ad9240a37ed2139ddaea6',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fnew',['prom_collector_registry_new',['../prom__collector__registry_8h.html#ab5d622258998978c528253f07e2903b8',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fregister_5fcollector',['prom_collector_registry_register_collector',['../prom__collector__registry_8h.html#a42203da085c6c6f2bc3ba31501683882',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fregister_5fmetric',['prom_collector_registry_register_metric',['../prom__collector__registry_8h.html#aa735fa0fbe03d6d9a0d11eb4792ec761',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fregistry_5fvalidate_5fmetric_5fname',['prom_collector_registry_validate_metric_name',['../prom__collector__registry_8h.html#acf002221c3239584723f9fb15c53e15e',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5fset_5fcollect_5ffn',['prom_collector_set_collect_fn',['../prom__collector_8h.html#a9929cb81f4fb49ffca8aa880a4699650',1,'prom_collector.h']]],
+ ['prom_5fcounter_5fadd',['prom_counter_add',['../prom__counter_8h.html#addd8a7efc39e17d30b2267e5a0a626db',1,'prom_counter.h']]],
+ ['prom_5fcounter_5fdestroy',['prom_counter_destroy',['../prom__counter_8h.html#ac36abc71c11df1e774c8c102b1fdb78d',1,'prom_counter.h']]],
+ ['prom_5fcounter_5finc',['prom_counter_inc',['../prom__counter_8h.html#a315695fdd8b9b6fa59904bb2e35bfa35',1,'prom_counter.h']]],
+ ['prom_5fcounter_5fnew',['prom_counter_new',['../prom__counter_8h.html#a3302a9f1a3556d17af9af29729be2651',1,'prom_counter.h']]],
+ ['prom_5fgauge_5fadd',['prom_gauge_add',['../prom__gauge_8h.html#a96bc5b32abee5f99fbd4ae11bebd44c8',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5fdec',['prom_gauge_dec',['../prom__gauge_8h.html#aa351ef4f2d917d7dae914df6d81c547b',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5fdestroy',['prom_gauge_destroy',['../prom__gauge_8h.html#a2fc5dc11239cefdf59ae978be4bfd789',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5finc',['prom_gauge_inc',['../prom__gauge_8h.html#ad953b12ea1f8a3c3b7a39e6c260d07a2',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5fnew',['prom_gauge_new',['../prom__gauge_8h.html#a5ecd07c83cf0981944a9256914571d70',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5fset',['prom_gauge_set',['../prom__gauge_8h.html#a04210b18bfb89aa6f3ddc72d7851a528',1,'prom_gauge.h']]],
+ ['prom_5fgauge_5fsub',['prom_gauge_sub',['../prom__gauge_8h.html#a7ae193d586176bff82a39cd65e2bc999',1,'prom_gauge.h']]],
+ ['prom_5fhistogram_5fbuckets_5fcount',['prom_histogram_buckets_count',['../prom__histogram__buckets_8h.html#a92158192cfe9a71a98dbb1d9adc8508a',1,'prom_histogram_buckets.h']]],
+ ['prom_5fhistogram_5fbuckets_5fdestroy',['prom_histogram_buckets_destroy',['../prom__histogram__buckets_8h.html#a36bc3312f8f479bbd6eb92fa3b1a5033',1,'prom_histogram_buckets.h']]],
+ ['prom_5fhistogram_5fbuckets_5fexponential',['prom_histogram_buckets_exponential',['../prom__histogram__buckets_8h.html#a164da4101785b6fa2a292a964c232f12',1,'prom_histogram_buckets.h']]],
+ ['prom_5fhistogram_5fbuckets_5flinear',['prom_histogram_buckets_linear',['../prom__histogram__buckets_8h.html#aa1adc550bf8999a27f6a26769d6bfc72',1,'prom_histogram_buckets.h']]],
+ ['prom_5fhistogram_5fdestroy',['prom_histogram_destroy',['../prom__histogram_8h.html#af9067b27e7ab2abd815af0614bb35357',1,'prom_histogram.h']]],
+ ['prom_5fhistogram_5fnew',['prom_histogram_new',['../prom__histogram_8h.html#ad42681e59e727f9e3d43bf0cdbba9a1b',1,'prom_histogram.h']]],
+ ['prom_5fhistogram_5fobserve',['prom_histogram_observe',['../prom__histogram_8h.html#a274e4b869c7d9239e9f47b3898210fbe',1,'prom_histogram.h']]],
+ ['prom_5fmetric_5fsample_5fadd',['prom_metric_sample_add',['../prom__metric__sample_8h.html#a3f8674d6c8ee2c27eb7504d602110daa',1,'prom_metric_sample.h']]],
+ ['prom_5fmetric_5fsample_5ffrom_5flabels',['prom_metric_sample_from_labels',['../prom__metric_8h.html#a2c33d7e03b430a2903bf122fbeeb89de',1,'prom_metric.h']]],
+ ['prom_5fmetric_5fsample_5fhistogram_5ffrom_5flabels',['prom_metric_sample_histogram_from_labels',['../prom__metric_8h.html#a3b76680b4a7177eebc864f3b3be1e935',1,'prom_metric.h']]],
+ ['prom_5fmetric_5fsample_5fhistogram_5fobserve',['prom_metric_sample_histogram_observe',['../prom__metric__sample__histogram_8h.html#a20a030bf6be56211c87c9feb520a3761',1,'prom_metric_sample_histogram.h']]],
+ ['prom_5fmetric_5fsample_5fset',['prom_metric_sample_set',['../prom__metric__sample_8h.html#a0c5f0c66599282c2ee2c042ae4574db3',1,'prom_metric_sample.h']]],
+ ['prom_5fmetric_5fsample_5fsub',['prom_metric_sample_sub',['../prom__metric__sample_8h.html#a1965caa1626c308bc1cb23995e90a0a7',1,'prom_metric_sample.h']]],
+ ['promhttp_5fset_5factive_5fcollector_5fregistry',['promhttp_set_active_collector_registry',['../promhttp_8h.html#a712a45634bc22724fef9bedcb2841e00',1,'promhttp.h']]],
+ ['promhttp_5fstart_5fdaemon',['promhttp_start_daemon',['../promhttp_8h.html#a699ecc3aa11ed601269722f43da2823e',1,'promhttp.h']]]
+];
diff --git a/docs/search/mag_sel.png b/docs/search/mag_sel.png
new file mode 100644
index 0000000..81f6040
--- /dev/null
+++ b/docs/search/mag_sel.png
Binary files differ
diff --git a/docs/search/nomatches.html b/docs/search/nomatches.html
new file mode 100644
index 0000000..b1ded27
--- /dev/null
+++ b/docs/search/nomatches.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="NoMatches">No Matches</div>
+</div>
+</body>
+</html>
diff --git a/docs/search/pages_0.html b/docs/search/pages_0.html
new file mode 100644
index 0000000..4955b9e
--- /dev/null
+++ b/docs/search/pages_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/pages_0.js b/docs/search/pages_0.js
new file mode 100644
index 0000000..441b2de
--- /dev/null
+++ b/docs/search/pages_0.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['todo_20list',['Todo List',['../todo.html',1,'']]]
+];
diff --git a/docs/search/pages_1.html b/docs/search/pages_1.html
new file mode 100644
index 0000000..aedb14e
--- /dev/null
+++ b/docs/search/pages_1.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/pages_1.js b/docs/search/pages_1.js
new file mode 100644
index 0000000..5459b5b
--- /dev/null
+++ b/docs/search/pages_1.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['welcome_20to_20the_20documentation_20site_20for_20prometheus_2dclient_2dc_21',['Welcome to the documentation site for prometheus-client-c!',['../index.html',1,'']]]
+];
diff --git a/docs/search/search.css b/docs/search/search.css
new file mode 100644
index 0000000..3cf9df9
--- /dev/null
+++ b/docs/search/search.css
@@ -0,0 +1,271 @@
+/*---------------- Search Box */
+
+#FSearchBox {
+ float: left;
+}
+
+#MSearchBox {
+ white-space : nowrap;
+ float: none;
+ margin-top: 8px;
+ right: 0px;
+ width: 170px;
+ height: 24px;
+ z-index: 102;
+}
+
+#MSearchBox .left
+{
+ display:block;
+ position:absolute;
+ left:10px;
+ width:20px;
+ height:19px;
+ background:url('search_l.png') no-repeat;
+ background-position:right;
+}
+
+#MSearchSelect {
+ display:block;
+ position:absolute;
+ width:20px;
+ height:19px;
+}
+
+.left #MSearchSelect {
+ left:4px;
+}
+
+.right #MSearchSelect {
+ right:5px;
+}
+
+#MSearchField {
+ display:block;
+ position:absolute;
+ height:19px;
+ background:url('search_m.png') repeat-x;
+ border:none;
+ width:115px;
+ margin-left:20px;
+ padding-left:4px;
+ color: #909090;
+ outline: none;
+ font: 9pt Arial, Verdana, sans-serif;
+ -webkit-border-radius: 0px;
+}
+
+#FSearchBox #MSearchField {
+ margin-left:15px;
+}
+
+#MSearchBox .right {
+ display:block;
+ position:absolute;
+ right:10px;
+ top:8px;
+ width:20px;
+ height:19px;
+ background:url('search_r.png') no-repeat;
+ background-position:left;
+}
+
+#MSearchClose {
+ display: none;
+ position: absolute;
+ top: 4px;
+ background : none;
+ border: none;
+ margin: 0px 4px 0px 0px;
+ padding: 0px 0px;
+ outline: none;
+}
+
+.left #MSearchClose {
+ left: 6px;
+}
+
+.right #MSearchClose {
+ right: 2px;
+}
+
+.MSearchBoxActive #MSearchField {
+ color: #000000;
+}
+
+/*---------------- Search filter selection */
+
+#MSearchSelectWindow {
+ display: none;
+ position: absolute;
+ left: 0; top: 0;
+ border: 1px solid #90A5CE;
+ background-color: #F9FAFC;
+ z-index: 10001;
+ padding-top: 4px;
+ padding-bottom: 4px;
+ -moz-border-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+ -webkit-border-top-right-radius: 4px;
+ -webkit-border-bottom-left-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+.SelectItem {
+ font: 8pt Arial, Verdana, sans-serif;
+ padding-left: 2px;
+ padding-right: 12px;
+ border: 0px;
+}
+
+span.SelectionMark {
+ margin-right: 4px;
+ font-family: monospace;
+ outline-style: none;
+ text-decoration: none;
+}
+
+a.SelectItem {
+ display: block;
+ outline-style: none;
+ color: #000000;
+ text-decoration: none;
+ padding-left: 6px;
+ padding-right: 12px;
+}
+
+a.SelectItem:focus,
+a.SelectItem:active {
+ color: #000000;
+ outline-style: none;
+ text-decoration: none;
+}
+
+a.SelectItem:hover {
+ color: #FFFFFF;
+ background-color: #3D578C;
+ outline-style: none;
+ text-decoration: none;
+ cursor: pointer;
+ display: block;
+}
+
+/*---------------- Search results window */
+
+iframe#MSearchResults {
+ width: 60ex;
+ height: 15em;
+}
+
+#MSearchResultsWindow {
+ display: none;
+ position: absolute;
+ left: 0; top: 0;
+ border: 1px solid #000;
+ background-color: #EEF1F7;
+ z-index:10000;
+}
+
+/* ----------------------------------- */
+
+
+#SRIndex {
+ clear:both;
+ padding-bottom: 15px;
+}
+
+.SREntry {
+ font-size: 10pt;
+ padding-left: 1ex;
+}
+
+.SRPage .SREntry {
+ font-size: 8pt;
+ padding: 1px 5px;
+}
+
+body.SRPage {
+ margin: 5px 2px;
+}
+
+.SRChildren {
+ padding-left: 3ex; padding-bottom: .5em
+}
+
+.SRPage .SRChildren {
+ display: none;
+}
+
+.SRSymbol {
+ font-weight: bold;
+ color: #425E97;
+ font-family: Arial, Verdana, sans-serif;
+ text-decoration: none;
+ outline: none;
+}
+
+a.SRScope {
+ display: block;
+ color: #425E97;
+ font-family: Arial, Verdana, sans-serif;
+ text-decoration: none;
+ outline: none;
+}
+
+a.SRSymbol:focus, a.SRSymbol:active,
+a.SRScope:focus, a.SRScope:active {
+ text-decoration: underline;
+}
+
+span.SRScope {
+ padding-left: 4px;
+}
+
+.SRPage .SRStatus {
+ padding: 2px 5px;
+ font-size: 8pt;
+ font-style: italic;
+}
+
+.SRResult {
+ display: none;
+}
+
+DIV.searchresults {
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+/*---------------- External search page results */
+
+.searchresult {
+ background-color: #F0F3F8;
+}
+
+.pages b {
+ color: white;
+ padding: 5px 5px 3px 5px;
+ background-image: url("../tab_a.png");
+ background-repeat: repeat-x;
+ text-shadow: 0 1px 1px #000000;
+}
+
+.pages {
+ line-height: 17px;
+ margin-left: 4px;
+ text-decoration: none;
+}
+
+.hl {
+ font-weight: bold;
+}
+
+#searchresults {
+ margin-bottom: 20px;
+}
+
+.searchpages {
+ margin-top: 10px;
+}
+
diff --git a/docs/search/search.js b/docs/search/search.js
new file mode 100644
index 0000000..dedce3b
--- /dev/null
+++ b/docs/search/search.js
@@ -0,0 +1,791 @@
+function convertToId(search)
+{
+ var result = '';
+ for (i=0;i<search.length;i++)
+ {
+ var c = search.charAt(i);
+ var cn = c.charCodeAt(0);
+ if (c.match(/[a-z0-9\u0080-\uFFFF]/))
+ {
+ result+=c;
+ }
+ else if (cn<16)
+ {
+ result+="_0"+cn.toString(16);
+ }
+ else
+ {
+ result+="_"+cn.toString(16);
+ }
+ }
+ return result;
+}
+
+function getXPos(item)
+{
+ var x = 0;
+ if (item.offsetWidth)
+ {
+ while (item && item!=document.body)
+ {
+ x += item.offsetLeft;
+ item = item.offsetParent;
+ }
+ }
+ return x;
+}
+
+function getYPos(item)
+{
+ var y = 0;
+ if (item.offsetWidth)
+ {
+ while (item && item!=document.body)
+ {
+ y += item.offsetTop;
+ item = item.offsetParent;
+ }
+ }
+ return y;
+}
+
+/* A class handling everything associated with the search panel.
+
+ Parameters:
+ name - The name of the global variable that will be
+ storing this instance. Is needed to be able to set timeouts.
+ resultPath - path to use for external files
+*/
+function SearchBox(name, resultsPath, inFrame, label)
+{
+ if (!name || !resultsPath) { alert("Missing parameters to SearchBox."); }
+
+ // ---------- Instance variables
+ this.name = name;
+ this.resultsPath = resultsPath;
+ this.keyTimeout = 0;
+ this.keyTimeoutLength = 500;
+ this.closeSelectionTimeout = 300;
+ this.lastSearchValue = "";
+ this.lastResultsPage = "";
+ this.hideTimeout = 0;
+ this.searchIndex = 0;
+ this.searchActive = false;
+ this.insideFrame = inFrame;
+ this.searchLabel = label;
+
+ // ----------- DOM Elements
+
+ this.DOMSearchField = function()
+ { return document.getElementById("MSearchField"); }
+
+ this.DOMSearchSelect = function()
+ { return document.getElementById("MSearchSelect"); }
+
+ this.DOMSearchSelectWindow = function()
+ { return document.getElementById("MSearchSelectWindow"); }
+
+ this.DOMPopupSearchResults = function()
+ { return document.getElementById("MSearchResults"); }
+
+ this.DOMPopupSearchResultsWindow = function()
+ { return document.getElementById("MSearchResultsWindow"); }
+
+ this.DOMSearchClose = function()
+ { return document.getElementById("MSearchClose"); }
+
+ this.DOMSearchBox = function()
+ { return document.getElementById("MSearchBox"); }
+
+ // ------------ Event Handlers
+
+ // Called when focus is added or removed from the search field.
+ this.OnSearchFieldFocus = function(isActive)
+ {
+ this.Activate(isActive);
+ }
+
+ this.OnSearchSelectShow = function()
+ {
+ var searchSelectWindow = this.DOMSearchSelectWindow();
+ var searchField = this.DOMSearchSelect();
+
+ if (this.insideFrame)
+ {
+ var left = getXPos(searchField);
+ var top = getYPos(searchField);
+ left += searchField.offsetWidth + 6;
+ top += searchField.offsetHeight;
+
+ // show search selection popup
+ searchSelectWindow.style.display='block';
+ left -= searchSelectWindow.offsetWidth;
+ searchSelectWindow.style.left = left + 'px';
+ searchSelectWindow.style.top = top + 'px';
+ }
+ else
+ {
+ var left = getXPos(searchField);
+ var top = getYPos(searchField);
+ top += searchField.offsetHeight;
+
+ // show search selection popup
+ searchSelectWindow.style.display='block';
+ searchSelectWindow.style.left = left + 'px';
+ searchSelectWindow.style.top = top + 'px';
+ }
+
+ // stop selection hide timer
+ if (this.hideTimeout)
+ {
+ clearTimeout(this.hideTimeout);
+ this.hideTimeout=0;
+ }
+ return false; // to avoid "image drag" default event
+ }
+
+ this.OnSearchSelectHide = function()
+ {
+ this.hideTimeout = setTimeout(this.name +".CloseSelectionWindow()",
+ this.closeSelectionTimeout);
+ }
+
+ // Called when the content of the search field is changed.
+ this.OnSearchFieldChange = function(evt)
+ {
+ if (this.keyTimeout) // kill running timer
+ {
+ clearTimeout(this.keyTimeout);
+ this.keyTimeout = 0;
+ }
+
+ var e = (evt) ? evt : window.event; // for IE
+ if (e.keyCode==40 || e.keyCode==13)
+ {
+ if (e.shiftKey==1)
+ {
+ this.OnSearchSelectShow();
+ var win=this.DOMSearchSelectWindow();
+ for (i=0;i<win.childNodes.length;i++)
+ {
+ var child = win.childNodes[i]; // get span within a
+ if (child.className=='SelectItem')
+ {
+ child.focus();
+ return;
+ }
+ }
+ return;
+ }
+ else if (window.frames.MSearchResults.searchResults)
+ {
+ var elem = window.frames.MSearchResults.searchResults.NavNext(0);
+ if (elem) elem.focus();
+ }
+ }
+ else if (e.keyCode==27) // Escape out of the search field
+ {
+ this.DOMSearchField().blur();
+ this.DOMPopupSearchResultsWindow().style.display = 'none';
+ this.DOMSearchClose().style.display = 'none';
+ this.lastSearchValue = '';
+ this.Activate(false);
+ return;
+ }
+
+ // strip whitespaces
+ var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
+
+ if (searchValue != this.lastSearchValue) // search value has changed
+ {
+ if (searchValue != "") // non-empty search
+ {
+ // set timer for search update
+ this.keyTimeout = setTimeout(this.name + '.Search()',
+ this.keyTimeoutLength);
+ }
+ else // empty search field
+ {
+ this.DOMPopupSearchResultsWindow().style.display = 'none';
+ this.DOMSearchClose().style.display = 'none';
+ this.lastSearchValue = '';
+ }
+ }
+ }
+
+ this.SelectItemCount = function(id)
+ {
+ var count=0;
+ var win=this.DOMSearchSelectWindow();
+ for (i=0;i<win.childNodes.length;i++)
+ {
+ var child = win.childNodes[i]; // get span within a
+ if (child.className=='SelectItem')
+ {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ this.SelectItemSet = function(id)
+ {
+ var i,j=0;
+ var win=this.DOMSearchSelectWindow();
+ for (i=0;i<win.childNodes.length;i++)
+ {
+ var child = win.childNodes[i]; // get span within a
+ if (child.className=='SelectItem')
+ {
+ var node = child.firstChild;
+ if (j==id)
+ {
+ node.innerHTML='&#8226;';
+ }
+ else
+ {
+ node.innerHTML='&#160;';
+ }
+ j++;
+ }
+ }
+ }
+
+ // Called when an search filter selection is made.
+ // set item with index id as the active item
+ this.OnSelectItem = function(id)
+ {
+ this.searchIndex = id;
+ this.SelectItemSet(id);
+ var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
+ if (searchValue!="" && this.searchActive) // something was found -> do a search
+ {
+ this.Search();
+ }
+ }
+
+ this.OnSearchSelectKey = function(evt)
+ {
+ var e = (evt) ? evt : window.event; // for IE
+ if (e.keyCode==40 && this.searchIndex<this.SelectItemCount()) // Down
+ {
+ this.searchIndex++;
+ this.OnSelectItem(this.searchIndex);
+ }
+ else if (e.keyCode==38 && this.searchIndex>0) // Up
+ {
+ this.searchIndex--;
+ this.OnSelectItem(this.searchIndex);
+ }
+ else if (e.keyCode==13 || e.keyCode==27)
+ {
+ this.OnSelectItem(this.searchIndex);
+ this.CloseSelectionWindow();
+ this.DOMSearchField().focus();
+ }
+ return false;
+ }
+
+ // --------- Actions
+
+ // Closes the results window.
+ this.CloseResultsWindow = function()
+ {
+ this.DOMPopupSearchResultsWindow().style.display = 'none';
+ this.DOMSearchClose().style.display = 'none';
+ this.Activate(false);
+ }
+
+ this.CloseSelectionWindow = function()
+ {
+ this.DOMSearchSelectWindow().style.display = 'none';
+ }
+
+ // Performs a search.
+ this.Search = function()
+ {
+ this.keyTimeout = 0;
+
+ // strip leading whitespace
+ var searchValue = this.DOMSearchField().value.replace(/^ +/, "");
+
+ var code = searchValue.toLowerCase().charCodeAt(0);
+ var idxChar = searchValue.substr(0, 1).toLowerCase();
+ if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) // surrogate pair
+ {
+ idxChar = searchValue.substr(0, 2);
+ }
+
+ var resultsPage;
+ var resultsPageWithSearch;
+ var hasResultsPage;
+
+ var idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar);
+ if (idx!=-1)
+ {
+ var hexCode=idx.toString(16);
+ resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html';
+ resultsPageWithSearch = resultsPage+'?'+escape(searchValue);
+ hasResultsPage = true;
+ }
+ else // nothing available for this search term
+ {
+ resultsPage = this.resultsPath + '/nomatches.html';
+ resultsPageWithSearch = resultsPage;
+ hasResultsPage = false;
+ }
+
+ window.frames.MSearchResults.location = resultsPageWithSearch;
+ var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow();
+
+ if (domPopupSearchResultsWindow.style.display!='block')
+ {
+ var domSearchBox = this.DOMSearchBox();
+ this.DOMSearchClose().style.display = 'inline';
+ if (this.insideFrame)
+ {
+ var domPopupSearchResults = this.DOMPopupSearchResults();
+ domPopupSearchResultsWindow.style.position = 'relative';
+ domPopupSearchResultsWindow.style.display = 'block';
+ var width = document.body.clientWidth - 8; // the -8 is for IE :-(
+ domPopupSearchResultsWindow.style.width = width + 'px';
+ domPopupSearchResults.style.width = width + 'px';
+ }
+ else
+ {
+ var domPopupSearchResults = this.DOMPopupSearchResults();
+ var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth;
+ var top = getYPos(domSearchBox) + 20; // domSearchBox.offsetHeight + 1;
+ domPopupSearchResultsWindow.style.display = 'block';
+ left -= domPopupSearchResults.offsetWidth;
+ domPopupSearchResultsWindow.style.top = top + 'px';
+ domPopupSearchResultsWindow.style.left = left + 'px';
+ }
+ }
+
+ this.lastSearchValue = searchValue;
+ this.lastResultsPage = resultsPage;
+ }
+
+ // -------- Activation Functions
+
+ // Activates or deactivates the search panel, resetting things to
+ // their default values if necessary.
+ this.Activate = function(isActive)
+ {
+ if (isActive || // open it
+ this.DOMPopupSearchResultsWindow().style.display == 'block'
+ )
+ {
+ this.DOMSearchBox().className = 'MSearchBoxActive';
+
+ var searchField = this.DOMSearchField();
+
+ if (searchField.value == this.searchLabel) // clear "Search" term upon entry
+ {
+ searchField.value = '';
+ this.searchActive = true;
+ }
+ }
+ else if (!isActive) // directly remove the panel
+ {
+ this.DOMSearchBox().className = 'MSearchBoxInactive';
+ this.DOMSearchField().value = this.searchLabel;
+ this.searchActive = false;
+ this.lastSearchValue = ''
+ this.lastResultsPage = '';
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+// The class that handles everything on the search results page.
+function SearchResults(name)
+{
+ // The number of matches from the last run of <Search()>.
+ this.lastMatchCount = 0;
+ this.lastKey = 0;
+ this.repeatOn = false;
+
+ // Toggles the visibility of the passed element ID.
+ this.FindChildElement = function(id)
+ {
+ var parentElement = document.getElementById(id);
+ var element = parentElement.firstChild;
+
+ while (element && element!=parentElement)
+ {
+ if (element.nodeName == 'DIV' && element.className == 'SRChildren')
+ {
+ return element;
+ }
+
+ if (element.nodeName == 'DIV' && element.hasChildNodes())
+ {
+ element = element.firstChild;
+ }
+ else if (element.nextSibling)
+ {
+ element = element.nextSibling;
+ }
+ else
+ {
+ do
+ {
+ element = element.parentNode;
+ }
+ while (element && element!=parentElement && !element.nextSibling);
+
+ if (element && element!=parentElement)
+ {
+ element = element.nextSibling;
+ }
+ }
+ }
+ }
+
+ this.Toggle = function(id)
+ {
+ var element = this.FindChildElement(id);
+ if (element)
+ {
+ if (element.style.display == 'block')
+ {
+ element.style.display = 'none';
+ }
+ else
+ {
+ element.style.display = 'block';
+ }
+ }
+ }
+
+ // Searches for the passed string. If there is no parameter,
+ // it takes it from the URL query.
+ //
+ // Always returns true, since other documents may try to call it
+ // and that may or may not be possible.
+ this.Search = function(search)
+ {
+ if (!search) // get search word from URL
+ {
+ search = window.location.search;
+ search = search.substring(1); // Remove the leading '?'
+ search = unescape(search);
+ }
+
+ search = search.replace(/^ +/, ""); // strip leading spaces
+ search = search.replace(/ +$/, ""); // strip trailing spaces
+ search = search.toLowerCase();
+ search = convertToId(search);
+
+ var resultRows = document.getElementsByTagName("div");
+ var matches = 0;
+
+ var i = 0;
+ while (i < resultRows.length)
+ {
+ var row = resultRows.item(i);
+ if (row.className == "SRResult")
+ {
+ var rowMatchName = row.id.toLowerCase();
+ rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_'
+
+ if (search.length<=rowMatchName.length &&
+ rowMatchName.substr(0, search.length)==search)
+ {
+ row.style.display = 'block';
+ matches++;
+ }
+ else
+ {
+ row.style.display = 'none';
+ }
+ }
+ i++;
+ }
+ document.getElementById("Searching").style.display='none';
+ if (matches == 0) // no results
+ {
+ document.getElementById("NoMatches").style.display='block';
+ }
+ else // at least one result
+ {
+ document.getElementById("NoMatches").style.display='none';
+ }
+ this.lastMatchCount = matches;
+ return true;
+ }
+
+ // return the first item with index index or higher that is visible
+ this.NavNext = function(index)
+ {
+ var focusItem;
+ while (1)
+ {
+ var focusName = 'Item'+index;
+ focusItem = document.getElementById(focusName);
+ if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
+ {
+ break;
+ }
+ else if (!focusItem) // last element
+ {
+ break;
+ }
+ focusItem=null;
+ index++;
+ }
+ return focusItem;
+ }
+
+ this.NavPrev = function(index)
+ {
+ var focusItem;
+ while (1)
+ {
+ var focusName = 'Item'+index;
+ focusItem = document.getElementById(focusName);
+ if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
+ {
+ break;
+ }
+ else if (!focusItem) // last element
+ {
+ break;
+ }
+ focusItem=null;
+ index--;
+ }
+ return focusItem;
+ }
+
+ this.ProcessKeys = function(e)
+ {
+ if (e.type == "keydown")
+ {
+ this.repeatOn = false;
+ this.lastKey = e.keyCode;
+ }
+ else if (e.type == "keypress")
+ {
+ if (!this.repeatOn)
+ {
+ if (this.lastKey) this.repeatOn = true;
+ return false; // ignore first keypress after keydown
+ }
+ }
+ else if (e.type == "keyup")
+ {
+ this.lastKey = 0;
+ this.repeatOn = false;
+ }
+ return this.lastKey!=0;
+ }
+
+ this.Nav = function(evt,itemIndex)
+ {
+ var e = (evt) ? evt : window.event; // for IE
+ if (e.keyCode==13) return true;
+ if (!this.ProcessKeys(e)) return false;
+
+ if (this.lastKey==38) // Up
+ {
+ var newIndex = itemIndex-1;
+ var focusItem = this.NavPrev(newIndex);
+ if (focusItem)
+ {
+ var child = this.FindChildElement(focusItem.parentNode.parentNode.id);
+ if (child && child.style.display == 'block') // children visible
+ {
+ var n=0;
+ var tmpElem;
+ while (1) // search for last child
+ {
+ tmpElem = document.getElementById('Item'+newIndex+'_c'+n);
+ if (tmpElem)
+ {
+ focusItem = tmpElem;
+ }
+ else // found it!
+ {
+ break;
+ }
+ n++;
+ }
+ }
+ }
+ if (focusItem)
+ {
+ focusItem.focus();
+ }
+ else // return focus to search field
+ {
+ parent.document.getElementById("MSearchField").focus();
+ }
+ }
+ else if (this.lastKey==40) // Down
+ {
+ var newIndex = itemIndex+1;
+ var focusItem;
+ var item = document.getElementById('Item'+itemIndex);
+ var elem = this.FindChildElement(item.parentNode.parentNode.id);
+ if (elem && elem.style.display == 'block') // children visible
+ {
+ focusItem = document.getElementById('Item'+itemIndex+'_c0');
+ }
+ if (!focusItem) focusItem = this.NavNext(newIndex);
+ if (focusItem) focusItem.focus();
+ }
+ else if (this.lastKey==39) // Right
+ {
+ var item = document.getElementById('Item'+itemIndex);
+ var elem = this.FindChildElement(item.parentNode.parentNode.id);
+ if (elem) elem.style.display = 'block';
+ }
+ else if (this.lastKey==37) // Left
+ {
+ var item = document.getElementById('Item'+itemIndex);
+ var elem = this.FindChildElement(item.parentNode.parentNode.id);
+ if (elem) elem.style.display = 'none';
+ }
+ else if (this.lastKey==27) // Escape
+ {
+ parent.searchBox.CloseResultsWindow();
+ parent.document.getElementById("MSearchField").focus();
+ }
+ else if (this.lastKey==13) // Enter
+ {
+ return true;
+ }
+ return false;
+ }
+
+ this.NavChild = function(evt,itemIndex,childIndex)
+ {
+ var e = (evt) ? evt : window.event; // for IE
+ if (e.keyCode==13) return true;
+ if (!this.ProcessKeys(e)) return false;
+
+ if (this.lastKey==38) // Up
+ {
+ if (childIndex>0)
+ {
+ var newIndex = childIndex-1;
+ document.getElementById('Item'+itemIndex+'_c'+newIndex).focus();
+ }
+ else // already at first child, jump to parent
+ {
+ document.getElementById('Item'+itemIndex).focus();
+ }
+ }
+ else if (this.lastKey==40) // Down
+ {
+ var newIndex = childIndex+1;
+ var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex);
+ if (!elem) // last child, jump to parent next parent
+ {
+ elem = this.NavNext(itemIndex+1);
+ }
+ if (elem)
+ {
+ elem.focus();
+ }
+ }
+ else if (this.lastKey==27) // Escape
+ {
+ parent.searchBox.CloseResultsWindow();
+ parent.document.getElementById("MSearchField").focus();
+ }
+ else if (this.lastKey==13) // Enter
+ {
+ return true;
+ }
+ return false;
+ }
+}
+
+function setKeyActions(elem,action)
+{
+ elem.setAttribute('onkeydown',action);
+ elem.setAttribute('onkeypress',action);
+ elem.setAttribute('onkeyup',action);
+}
+
+function setClassAttr(elem,attr)
+{
+ elem.setAttribute('class',attr);
+ elem.setAttribute('className',attr);
+}
+
+function createResults()
+{
+ var results = document.getElementById("SRResults");
+ for (var e=0; e<searchData.length; e++)
+ {
+ var id = searchData[e][0];
+ var srResult = document.createElement('div');
+ srResult.setAttribute('id','SR_'+id);
+ setClassAttr(srResult,'SRResult');
+ var srEntry = document.createElement('div');
+ setClassAttr(srEntry,'SREntry');
+ var srLink = document.createElement('a');
+ srLink.setAttribute('id','Item'+e);
+ setKeyActions(srLink,'return searchResults.Nav(event,'+e+')');
+ setClassAttr(srLink,'SRSymbol');
+ srLink.innerHTML = searchData[e][1][0];
+ srEntry.appendChild(srLink);
+ if (searchData[e][1].length==2) // single result
+ {
+ srLink.setAttribute('href',searchData[e][1][1][0]);
+ if (searchData[e][1][1][1])
+ {
+ srLink.setAttribute('target','_parent');
+ }
+ var srScope = document.createElement('span');
+ setClassAttr(srScope,'SRScope');
+ srScope.innerHTML = searchData[e][1][1][2];
+ srEntry.appendChild(srScope);
+ }
+ else // multiple results
+ {
+ srLink.setAttribute('href','javascript:searchResults.Toggle("SR_'+id+'")');
+ var srChildren = document.createElement('div');
+ setClassAttr(srChildren,'SRChildren');
+ for (var c=0; c<searchData[e][1].length-1; c++)
+ {
+ var srChild = document.createElement('a');
+ srChild.setAttribute('id','Item'+e+'_c'+c);
+ setKeyActions(srChild,'return searchResults.NavChild(event,'+e+','+c+')');
+ setClassAttr(srChild,'SRScope');
+ srChild.setAttribute('href',searchData[e][1][c+1][0]);
+ if (searchData[e][1][c+1][1])
+ {
+ srChild.setAttribute('target','_parent');
+ }
+ srChild.innerHTML = searchData[e][1][c+1][2];
+ srChildren.appendChild(srChild);
+ }
+ srEntry.appendChild(srChildren);
+ }
+ srResult.appendChild(srEntry);
+ results.appendChild(srResult);
+ }
+}
+
+function init_search()
+{
+ var results = document.getElementById("MSearchSelectWindow");
+ for (var key in indexSectionLabels)
+ {
+ var link = document.createElement('a');
+ link.setAttribute('class','SelectItem');
+ link.setAttribute('onclick','searchBox.OnSelectItem('+key+')');
+ link.href='javascript:void(0)';
+ link.innerHTML='<span class="SelectionMark">&#160;</span>'+indexSectionLabels[key];
+ results.appendChild(link);
+ }
+ searchBox.OnSelectItem(0);
+}
+
diff --git a/docs/search/search_l.png b/docs/search/search_l.png
new file mode 100644
index 0000000..c872f4d
--- /dev/null
+++ b/docs/search/search_l.png
Binary files differ
diff --git a/docs/search/search_m.png b/docs/search/search_m.png
new file mode 100644
index 0000000..b429a16
--- /dev/null
+++ b/docs/search/search_m.png
Binary files differ
diff --git a/docs/search/search_r.png b/docs/search/search_r.png
new file mode 100644
index 0000000..97ee8b4
--- /dev/null
+++ b/docs/search/search_r.png
Binary files differ
diff --git a/docs/search/searchdata.js b/docs/search/searchdata.js
new file mode 100644
index 0000000..f138f14
--- /dev/null
+++ b/docs/search/searchdata.js
@@ -0,0 +1,36 @@
+var indexSectionsWithContent =
+{
+ 0: "cptuw",
+ 1: "p",
+ 2: "p",
+ 3: "p",
+ 4: "cpu",
+ 5: "p",
+ 6: "p",
+ 7: "tw"
+};
+
+var indexSectionNames =
+{
+ 0: "all",
+ 1: "classes",
+ 2: "files",
+ 3: "functions",
+ 4: "variables",
+ 5: "typedefs",
+ 6: "defines",
+ 7: "pages"
+};
+
+var indexSectionLabels =
+{
+ 0: "All",
+ 1: "Classes",
+ 2: "Files",
+ 3: "Functions",
+ 4: "Variables",
+ 5: "Typedefs",
+ 6: "Macros",
+ 7: "Pages"
+};
+
diff --git a/docs/search/typedefs_0.html b/docs/search/typedefs_0.html
new file mode 100644
index 0000000..05722e1
--- /dev/null
+++ b/docs/search/typedefs_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="typedefs_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/typedefs_0.js b/docs/search/typedefs_0.js
new file mode 100644
index 0000000..2ec58a4
--- /dev/null
+++ b/docs/search/typedefs_0.js
@@ -0,0 +1,12 @@
+var searchData=
+[
+ ['prom_5fcollect_5ffn',['prom_collect_fn',['../prom__collector_8h.html#af87330edd48cdb8e1074517e734b1e40',1,'prom_collector.h']]],
+ ['prom_5fcollector_5fregistry_5ft',['prom_collector_registry_t',['../prom__collector__registry_8h.html#a20f07748401fbbde9efc8a718f9bc202',1,'prom_collector_registry.h']]],
+ ['prom_5fcollector_5ft',['prom_collector_t',['../prom__collector_8h.html#a28cf36f114f69a96508c044c44716f9c',1,'prom_collector.h']]],
+ ['prom_5fcounter_5ft',['prom_counter_t',['../prom__counter_8h.html#a814ceed99a1d618334e51f4d0e160606',1,'prom_counter.h']]],
+ ['prom_5fgauge_5ft',['prom_gauge_t',['../prom__gauge_8h.html#a09417d7e7bab055a48f8e13181d136a5',1,'prom_gauge.h']]],
+ ['prom_5fhistogram_5ft',['prom_histogram_t',['../prom__histogram_8h.html#a8c061924368d41c161025bf3d3cde9ae',1,'prom_histogram.h']]],
+ ['prom_5fmetric_5fsample_5fhistogram_5ft',['prom_metric_sample_histogram_t',['../prom__metric__sample__histogram_8h.html#aed3455bc4eec61a3d8f01e6c1af84f9f',1,'prom_metric_sample_histogram.h']]],
+ ['prom_5fmetric_5fsample_5ft',['prom_metric_sample_t',['../prom__metric__sample_8h.html#a0fb9ff851bf9ee126756ae826a2ce72a',1,'prom_metric_sample.h']]],
+ ['prom_5fmetric_5ft',['prom_metric_t',['../prom__metric_8h.html#afd1bd014c48955d6c2c36aa8a8cbb889',1,'prom_metric.h']]]
+];
diff --git a/docs/search/variables_0.html b/docs/search/variables_0.html
new file mode 100644
index 0000000..74ce807
--- /dev/null
+++ b/docs/search/variables_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/variables_0.js b/docs/search/variables_0.js
new file mode 100644
index 0000000..bbd3bf0
--- /dev/null
+++ b/docs/search/variables_0.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['count',['count',['../structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621',1,'prom_histogram_buckets']]]
+];
diff --git a/docs/search/variables_1.html b/docs/search/variables_1.html
new file mode 100644
index 0000000..84237b6
--- /dev/null
+++ b/docs/search/variables_1.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/variables_1.js b/docs/search/variables_1.js
new file mode 100644
index 0000000..ffdcbf3
--- /dev/null
+++ b/docs/search/variables_1.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+ ['prom_5fcollector_5fregistry_5fdefault',['PROM_COLLECTOR_REGISTRY_DEFAULT',['../prom__collector__registry_8h.html#a6092b48e150390c1927da5fe8914981b',1,'prom_collector_registry.h']]],
+ ['prom_5fhistogram_5fdefault_5fbuckets',['prom_histogram_default_buckets',['../prom__histogram__buckets_8h.html#aa8d61c1abc355eb54173b27cb1b50a5d',1,'prom_histogram_buckets.h']]]
+];
diff --git a/docs/search/variables_2.html b/docs/search/variables_2.html
new file mode 100644
index 0000000..5c9de1a
--- /dev/null
+++ b/docs/search/variables_2.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/search/variables_2.js b/docs/search/variables_2.js
new file mode 100644
index 0000000..f8121ac
--- /dev/null
+++ b/docs/search/variables_2.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['upper_5fbounds',['upper_bounds',['../structprom__histogram__buckets.html#a8abda07c4930e15a3dff8a86e3164344',1,'prom_histogram_buckets']]]
+];
diff --git a/docs/splitbar.png b/docs/splitbar.png
new file mode 100644
index 0000000..fe895f2
--- /dev/null
+++ b/docs/splitbar.png
Binary files differ
diff --git a/docs/structprom__histogram__buckets-members.html b/docs/structprom__histogram__buckets-members.html
new file mode 100644
index 0000000..cdbee1f
--- /dev/null
+++ b/docs/structprom__histogram__buckets-members.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">prom_histogram_buckets Member List</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets</a>, including all inherited members.</p>
+<table class="directory">
+ <tr class="even"><td class="entry"><a class="el" href="structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621">count</a></td><td class="entry"><a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets</a></td><td class="entry"></td></tr>
+ <tr><td class="entry"><a class="el" href="structprom__histogram__buckets.html#a8abda07c4930e15a3dff8a86e3164344">upper_bounds</a></td><td class="entry"><a class="el" href="structprom__histogram__buckets.html">prom_histogram_buckets</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/structprom__histogram__buckets.html b/docs/structprom__histogram__buckets.html
new file mode 100644
index 0000000..ebfadc0
--- /dev/null
+++ b/docs/structprom__histogram__buckets.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: prom_histogram_buckets Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="structprom__histogram__buckets-members.html">List of all members</a> </div>
+ <div class="headertitle">
+<div class="title">prom_histogram_buckets Struct Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a9da20001e02d992cee82a09372061621"><td class="memItemLeft" align="right" valign="top"><a id="a9da20001e02d992cee82a09372061621"></a>
+int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="structprom__histogram__buckets.html#a9da20001e02d992cee82a09372061621">count</a></td></tr>
+<tr class="memdesc:a9da20001e02d992cee82a09372061621"><td class="mdescLeft">&#160;</td><td class="mdescRight">Number of buckets. <br /></td></tr>
+<tr class="separator:a9da20001e02d992cee82a09372061621"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a8abda07c4930e15a3dff8a86e3164344"><td class="memItemLeft" align="right" valign="top"><a id="a8abda07c4930e15a3dff8a86e3164344"></a>
+const double *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="structprom__histogram__buckets.html#a8abda07c4930e15a3dff8a86e3164344">upper_bounds</a></td></tr>
+<tr class="memdesc:a8abda07c4930e15a3dff8a86e3164344"><td class="mdescLeft">&#160;</td><td class="mdescRight">The bucket values. <br /></td></tr>
+<tr class="separator:a8abda07c4930e15a3dff8a86e3164344"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li>prom/include/<a class="el" href="prom__histogram__buckets_8h_source.html">prom_histogram_buckets.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/sync_off.png b/docs/sync_off.png
new file mode 100644
index 0000000..3b443fc
--- /dev/null
+++ b/docs/sync_off.png
Binary files differ
diff --git a/docs/sync_on.png b/docs/sync_on.png
new file mode 100644
index 0000000..e08320f
--- /dev/null
+++ b/docs/sync_on.png
Binary files differ
diff --git a/docs/tab_a.png b/docs/tab_a.png
new file mode 100644
index 0000000..3b725c4
--- /dev/null
+++ b/docs/tab_a.png
Binary files differ
diff --git a/docs/tab_b.png b/docs/tab_b.png
new file mode 100644
index 0000000..e2b4a86
--- /dev/null
+++ b/docs/tab_b.png
Binary files differ
diff --git a/docs/tab_h.png b/docs/tab_h.png
new file mode 100644
index 0000000..fd5cb70
--- /dev/null
+++ b/docs/tab_h.png
Binary files differ
diff --git a/docs/tab_s.png b/docs/tab_s.png
new file mode 100644
index 0000000..ab478c9
--- /dev/null
+++ b/docs/tab_s.png
Binary files differ
diff --git a/docs/tabs.css b/docs/tabs.css
new file mode 100644
index 0000000..bbde11e
--- /dev/null
+++ b/docs/tabs.css
@@ -0,0 +1 @@
+.sm{position:relative;z-index:9999}.sm,.sm ul,.sm li{display:block;list-style:none;margin:0;padding:0;line-height:normal;direction:ltr;text-align:left;-webkit-tap-highlight-color:transparent}.sm-rtl,.sm-rtl ul,.sm-rtl li{direction:rtl;text-align:right}.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6{margin:0;padding:0}.sm ul{display:none}.sm li,.sm a{position:relative}.sm a{display:block}.sm a.disabled{cursor:not-allowed}.sm:after{content:"\00a0";display:block;height:0;font:0px/0 serif;clear:both;visibility:hidden;overflow:hidden}.sm,.sm *,.sm *:before,.sm *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sm-dox{background-image:url("tab_b.png")}.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active{padding:0px 12px;padding-right:43px;font-family:"Lucida Grande","Geneva","Helvetica",Arial,sans-serif;font-size:13px;font-weight:bold;line-height:36px;text-decoration:none;text-shadow:0px 1px 1px rgba(255,255,255,0.9);color:#283A5D;outline:none}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox a.current{color:#D23600}.sm-dox a.disabled{color:#bbb}.sm-dox a span.sub-arrow{position:absolute;top:50%;margin-top:-14px;left:auto;right:3px;width:28px;height:28px;overflow:hidden;font:bold 12px/28px monospace !important;text-align:center;text-shadow:none;background:rgba(255,255,255,0.5);border-radius:5px}.sm-dox a.highlighted span.sub-arrow:before{display:block;content:'-'}.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a{border-radius:5px 5px 0 0}.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul{border-radius:0 0 5px 5px}.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted{border-radius:0}.sm-dox ul{background:rgba(162,162,162,0.1)}.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active{font-size:12px;border-left:8px solid transparent;line-height:36px;text-shadow:none;background-color:white;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active{border-left:16px solid transparent}.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active{border-left:24px solid transparent}.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active{border-left:32px solid transparent}.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active{border-left:40px solid transparent}@media (min-width: 768px){.sm-dox ul{position:absolute;width:12em}.sm-dox li{float:left}.sm-dox.sm-rtl li{float:right}.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none}.sm-dox a{white-space:nowrap}.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal}.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a{white-space:nowrap}.sm-dox{padding:0 10px;background-image:url("tab_b.png");line-height:36px}.sm-dox a span.sub-arrow{top:50%;margin-top:-2px;right:12px;width:0;height:0;border-width:4px;border-style:solid dashed dashed dashed;border-color:#283A5D transparent transparent transparent;background:transparent;border-radius:0}.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted{padding:0px 12px;background-image:url("tab_s.png");background-repeat:no-repeat;background-position:right;border-radius:0 !important}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox a:hover span.sub-arrow{border-color:#fff transparent transparent transparent}.sm-dox a.has-submenu{padding-right:24px}.sm-dox li{border-top:0}.sm-dox>li>ul:before,.sm-dox>li>ul:after{content:'';position:absolute;top:-18px;left:30px;width:0;height:0;overflow:hidden;border-width:9px;border-style:dashed dashed solid dashed;border-color:transparent transparent #bbb transparent}.sm-dox>li>ul:after{top:-16px;left:31px;border-width:8px;border-color:transparent transparent #fff transparent}.sm-dox ul{border:1px solid #bbb;padding:5px 0;background:#fff;border-radius:5px !important;box-shadow:0 5px 9px rgba(0,0,0,0.2)}.sm-dox ul a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-color:transparent transparent transparent #555;border-style:dashed dashed dashed solid}.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted{color:#555;background-image:none;border:0 !important;color:#555;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent #fff}.sm-dox span.scroll-up,.sm-dox span.scroll-down{position:absolute;display:none;visibility:hidden;overflow:hidden;background:#fff;height:36px}.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover{background:#eee}.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow{border-color:transparent transparent #D23600 transparent}.sm-dox span.scroll-down:hover span.scroll-down-arrow{border-color:#D23600 transparent transparent transparent}.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow{position:absolute;top:0;left:50%;margin-left:-6px;width:0;height:0;overflow:hidden;border-width:6px;border-style:dashed dashed solid dashed;border-color:transparent transparent #555 transparent}.sm-dox span.scroll-down-arrow{top:8px;border-style:solid dashed dashed dashed;border-color:#555 transparent transparent transparent}.sm-dox.sm-rtl a.has-submenu{padding-right:12px;padding-left:24px}.sm-dox.sm-rtl a span.sub-arrow{right:auto;left:12px}.sm-dox.sm-rtl.sm-vertical a.has-submenu{padding:10px 20px}.sm-dox.sm-rtl.sm-vertical a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-rtl>li>ul:before{left:auto;right:30px}.sm-dox.sm-rtl>li>ul:after{left:auto;right:31px}.sm-dox.sm-rtl ul a.has-submenu{padding:10px 20px !important}.sm-dox.sm-rtl ul a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-vertical{padding:10px 0;border-radius:5px}.sm-dox.sm-vertical a{padding:10px 20px}.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted{background:#fff}.sm-dox.sm-vertical a.disabled{background-image:url("tab_b.png")}.sm-dox.sm-vertical a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-style:dashed dashed dashed solid;border-color:transparent transparent transparent #555}.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after{display:none}.sm-dox.sm-vertical ul a{padding:10px 20px}.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted{background:#eee}.sm-dox.sm-vertical ul a.disabled{background:#fff}}
diff --git a/docs/todo.html b/docs/todo.html
new file mode 100644
index 0000000..c677b66
--- /dev/null
+++ b/docs/todo.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>prometheus-client-c: Todo List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">prometheus-client-c
+ &#160;<span id="projectnumber">0.1.0</span>
+ </div>
+ <div id="projectbrief">Prometheus client for the C programming language</div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">Todo List </div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><dl class="reflist">
+<dt><a class="anchor" id="_todo000001"></a>page <a class="el" href="index.html">Welcome to the documentation site for prometheus-client-c!</a> </dt>
+<dd>Describe how to use libpromhttp to expose metrics over HTTP</dd>
+</dl>
+</div></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/example/Makefile b/example/Makefile
new file mode 100644
index 0000000..55778df
--- /dev/null
+++ b/example/Makefile
@@ -0,0 +1,39 @@
+.PHONY: clean
+
+VERSION = $(shell cat ../VERSION)
+
+
+GCC = /usr/bin/gcc
+FLAGS = -g -Wall
+DEPS = foo.h bar.h
+OBJ = foo.o bar.o main.o
+LIBS = /usr/lib/libprom.so /usr/lib/libpromhttp.so
+
+PROM_DEB_PACKAGE = ../prom/libprom-dev-${VERSION}-Linux.deb
+PROM_TGZ_PACKAGE = ../prom/libprom-dev-${VERSION}-Linux.tar.gz
+
+PROMHTTP_DEB_PACKAGE = ../promhttp/libpromhttp-dev-${VERSION}-Linux.deb
+PROMHTTP_TGZ_PACKAGE = ../promhttp/libpromhttp-dev-${VERSION}-Linux.tar.gz
+
+example: ${OBJ} ${LIBS}
+ gcc -g -o $@ ${FLAGS} -O1 -pthread ${OBJ} -lprom -lpromhttp -lmicrohttpd
+
+${PROM_DEB_PACKAGE}:
+ cd .. && ./auto build && ./auto package
+
+${PROMHTTP_DEB_PACKAGE}:
+ cd .. && ./auto build && ./auto package
+
+/usr/lib/libprom.so: ${PROM_DEB_PACKAGE}
+ dpkg -i ${PROM_DEB_PACKAGE}
+
+/usr/lib/libpromhttp.so: ${PROMHTTP_DEB_PACKAGE}
+ dpkg -i ${PROMHTTP_DEB_PACKAGE}
+
+%.o: %.c ${PROM_DEB_PACKAGE} ${PROMHTTP_DEB_PACKAGE} ${LIBS} ${DEPS}
+ ${GCC} ${FLAGS} -c $< -o $@
+
+clean:
+ -rm ${OBJ} example ${PROM_DEB_PACKAGE} ${PROM_TGZ_PACKAGE} ${PROMHTTP_DEB_PACKAGE} ${PROMHTTP_TGZ_PACKAGE}
+ -dpkg -r libprom-dev
+ -dpkg -r libpromhttp-dev
diff --git a/example/bar.c b/example/bar.c
new file mode 100644
index 0000000..2dd2393
--- /dev/null
+++ b/example/bar.c
@@ -0,0 +1,32 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "prom.h"
+
+prom_counter_t *bar_counter;
+prom_gauge_t *bar_gauge;
+
+int bar(int v, const char *label) {
+ int r = 0;
+ r = prom_counter_inc(bar_counter, NULL);
+ if (r) return r;
+ return prom_gauge_add(bar_gauge, v, (const char *[]) { label });
+}
+
+void bar_init(void) {
+ bar_counter = prom_collector_registry_must_register_metric(prom_counter_new("bar_counter", "counter for bar", 0, NULL));
+ bar_gauge = prom_collector_registry_must_register_metric(prom_gauge_new("bar_gauge", "gauge for bar", 1, (const char *[]) { "label" }));
+} \ No newline at end of file
diff --git a/example/bar.h b/example/bar.h
new file mode 100644
index 0000000..47bb7d1
--- /dev/null
+++ b/example/bar.h
@@ -0,0 +1,18 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+int bar(int v, const char *label);
+void bar_init(void); \ No newline at end of file
diff --git a/example/foo.c b/example/foo.c
new file mode 100644
index 0000000..ca0c759
--- /dev/null
+++ b/example/foo.c
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include "prom.h"
+
+prom_counter_t *foo_counter;
+prom_gauge_t *foo_gauge;
+
+int foo(int v, const char *label) {
+ int r = 0;
+ r = prom_counter_inc(foo_counter, NULL);
+ if (r) return r;
+ return prom_gauge_add(foo_gauge, v, (const char *[]) { label });
+}
+
+void foo_init(void) {
+ foo_counter = prom_collector_registry_must_register_metric(prom_counter_new("foo_counter", "counter for foo", 0, NULL));
+ foo_gauge = prom_collector_registry_must_register_metric(prom_gauge_new("foo_gauge", "gauge for foo", 1, (const char *[]) { "label" }));
+} \ No newline at end of file
diff --git a/example/foo.h b/example/foo.h
new file mode 100644
index 0000000..66d4b54
--- /dev/null
+++ b/example/foo.h
@@ -0,0 +1,19 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+int foo(int v, const char *label);
+void foo_init(void); \ No newline at end of file
diff --git a/example/main.c b/example/main.c
new file mode 100644
index 0000000..c93e149
--- /dev/null
+++ b/example/main.c
@@ -0,0 +1,104 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "microhttpd.h"
+#include "prom.h"
+#include "promhttp.h"
+#include "foo.h"
+#include "bar.h"
+
+
+prom_histogram_t *test_histogram;
+
+static void init(void) {
+ // Initialize the Default registry
+ prom_collector_registry_default_init();
+
+ // Register file-based metrics for each file
+ foo_init();
+ bar_init();
+
+ test_histogram = prom_collector_registry_must_register_metric(
+ prom_histogram_new(
+ "test_histogram",
+ "histogram under test",
+ prom_histogram_buckets_linear(5.0, 5.0, 2),
+ 0,
+ NULL
+ )
+ );
+
+ // Set the active registry for the HTTP handler
+ promhttp_set_active_collector_registry(NULL);
+}
+
+int main(int argc, const char **argv) {
+ init();
+ int r = 0;
+ const char *labels[] = { "one", "two", "three", "four", "five" };
+ for (int i = 1; i <= 100; i++) {
+ double hist_value;
+ if (i % 2 == 0) {
+ hist_value = 3.0;
+ } else {
+ hist_value = 7.0;
+ }
+
+ r = prom_histogram_observe(test_histogram, hist_value, NULL);
+ if (r) exit(1);
+
+ for (int x = 0; x < 5; x++) {
+ r = foo(i, labels[x]);
+ if (r) exit(r);
+ r = bar(i+x, labels[x]);
+ if (r) exit(r);
+ }
+ }
+
+
+ struct MHD_Daemon *daemon = promhttp_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD, 8000, NULL, NULL);
+ if (daemon == NULL) {
+ return 1;
+ }
+
+ int done = 0;
+
+ auto void intHandler(int signal);
+ void intHandler(int signal) {
+ printf("\nshutting down...\n");
+ fflush(stdout);
+ prom_collector_registry_destroy(PROM_COLLECTOR_REGISTRY_DEFAULT);
+ MHD_stop_daemon(daemon);
+ done = 1;
+ }
+
+ if (argc == 2) {
+ unsigned int timeout = atoi(argv[1]);
+ sleep(timeout);
+ intHandler(0);
+ return 0;
+ }
+
+ signal(SIGINT, intHandler);
+ while(done == 0) {}
+
+ return 0;
+} \ No newline at end of file
diff --git a/prom/CMakeLists.txt b/prom/CMakeLists.txt
new file mode 100644
index 0000000..e82beb9
--- /dev/null
+++ b/prom/CMakeLists.txt
@@ -0,0 +1,138 @@
+cmake_minimum_required(VERSION 3.14.5)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ OUTPUT_VARIABLE Version
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ COMMAND sed --regexp-extended "s/([0-9]+)\.([0-9])+\.([0-9]+)/\\1/g"
+ OUTPUT_VARIABLE MajorVersion
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ COMMAND sed --regexp-extended "s/([0-9]+)\.([0-9])+\.([0-9]+)/\\2/"
+ OUTPUT_VARIABLE MinorVersion
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ COMMAND sed --regexp-extended "s/([0-9]+)\.([0-9])+\.([0-9]+)/\\3/"
+ OUTPUT_VARIABLE PatchVersion
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+project(libprom VERSION ${Version} LANGUAGES C)
+
+set(build_dir ${CMAKE_CURRENT_SOURCE_DIR}/build)
+set(public_dir ${CMAKE_CURRENT_SOURCE_DIR}/include)
+set(private_dir ${CMAKE_CURRENT_SOURCE_DIR}/src)
+set(test_dir ${CMAKE_CURRENT_SOURCE_DIR}/test)
+
+set(
+ public_files
+ ${public_dir}/prom_alloc.h
+ ${public_dir}/prom_collector.h
+ ${public_dir}/prom_collector_registry.h
+ ${public_dir}/prom_counter.h
+ ${public_dir}/prom_gauge.h
+ ${public_dir}/prom_histogram.h
+ ${public_dir}/prom_histogram_buckets.h
+ ${public_dir}/prom_linked_list.h
+ ${public_dir}/prom_map.h
+ ${public_dir}/prom_metric.h
+ ${public_dir}/prom_metric_sample.h
+ ${public_dir}/prom_metric_sample_histogram.h
+ ${public_dir}/prom.h
+)
+
+set(
+ private_files
+ ${private_dir}/prom_assert.h
+ ${private_dir}/prom_collector.c
+ ${private_dir}/prom_collector_registry.c
+ ${private_dir}/prom_collector_registry_i.h
+ ${private_dir}/prom_collector_registry_t.h
+ ${private_dir}/prom_collector_t.h
+ ${private_dir}/prom_counter.c
+ ${private_dir}/prom_gauge.c
+ ${private_dir}/prom_histogram.c
+ ${private_dir}/prom_histogram_buckets.c
+ ${private_dir}/prom_linked_list.c
+ ${private_dir}/prom_linked_list_i.h
+ ${private_dir}/prom_linked_list_t.h
+ ${private_dir}/prom_log.h
+ ${private_dir}/prom_map.c
+ ${private_dir}/prom_map_i.h
+ ${private_dir}/prom_map_t.h
+ ${private_dir}/prom_metric.c
+ ${private_dir}/prom_metric_formatter.c
+ ${private_dir}/prom_metric_formatter_i.h
+ ${private_dir}/prom_metric_formatter_t.h
+ ${private_dir}/prom_metric_i.h
+ ${private_dir}/prom_metric_sample.c
+ ${private_dir}/prom_metric_sample_histogram.c
+ ${private_dir}/prom_metric_sample_histogram_i.h
+ ${private_dir}/prom_metric_sample_histogram_t.h
+ ${private_dir}/prom_metric_sample_i.h
+ ${private_dir}/prom_metric_sample_t.h
+ ${private_dir}/prom_metric_t.h
+ ${private_dir}/prom_process_fds.c
+ ${private_dir}/prom_process_fds_i.h
+ ${private_dir}/prom_process_fds_t.h
+ ${private_dir}/prom_process_limits.c
+ ${private_dir}/prom_process_limits_i.h
+ ${private_dir}/prom_process_limits_t.h
+ ${private_dir}/prom_process_stat.c
+ ${private_dir}/prom_process_stat_i.h
+ ${private_dir}/prom_process_stat_t.h
+ ${private_dir}/prom_procfs_i.h
+ ${private_dir}/prom_procfs_t.h
+ ${private_dir}/prom_procfs.c
+ ${private_dir}/prom_string_builder.c
+ ${private_dir}/prom_string_builder_i.h
+ ${private_dir}/prom_string_builder_t.h
+)
+
+include(FindThreads)
+
+add_library(prom SHARED)
+
+target_compile_options(prom PRIVATE "-Werror" "-Wuninitialized" "-Wall" "-Wno-unused-label" "-std=gnu11")
+
+target_include_directories(
+ prom
+ PUBLIC ${public_dir}
+ PRIVATE ${private_dir}
+)
+
+target_sources(
+ prom
+ PUBLIC ${public_files}
+ PRIVATE ${private_files}
+)
+
+target_link_libraries(prom PUBLIC Threads::Threads)
+
+if ($ENV{TEST} EQUAL "1")
+ include(test/CMakeLists.txt)
+endif()
+
+set(CPACK_PACKAGE_NAME libprom-dev)
+set(CPACK_GENERATOR TGZ;DEB)
+set(CPACK_PACKAGE_VENDOR DigitalOcean)
+set(CPACK_PACKAGE_VERSION_MAJOR ${MajorVersion})
+set(CPACK_PACKAGE_VERSION_MINOR ${MinorVersion})
+set(CPACK_PACKAGE_VERSION_PATCH ${PatchVersion})
+set(CPACK_PACKAGE_DESCRIPTION_FILE /code/README.md)
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A prometheus client library")
+set(CPACK_PACKAGE_HOMEPAGE_URL https://github.internal.digitalocean.com/timeseries/prometheus-client-c)
+
+include(CPack)
+install(TARGETS prom ARCHIVE)
+install(DIRECTORY include/ DESTINATION /usr/include/) \ No newline at end of file
diff --git a/prom/include/prom.h b/prom/include/prom.h
new file mode 100644
index 0000000..bb77736
--- /dev/null
+++ b/prom/include/prom.h
@@ -0,0 +1,134 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/**
+ * @file prom.h
+ * @brief Include prom.h to include the entire public API
+ * @mainpage Welcome to the documentation site for prometheus-client-c!
+ * @tableofcontents
+ * @section Introduction
+ *
+ * prometheus-client-c is a small suite of Prometheus client libraries targeted for the C programming language.
+ * In this brief tutorial you will learn how to create and register metrics, update metric samples, and expose metrics
+ * over HTTP.
+ *
+ * @section Creating-and-Registering-Metrics Creating and Registering Metrics
+ *
+ * prometheus-client-c supports the following metric types:
+ *
+ * * [Counter](https://prometheus.io/docs/concepts/metric_types/#counter)
+ * * [Gauge](https://prometheus.io/docs/concepts/metric_types/#gauge)
+ * * [Histogram](https://prometheus.io/docs/concepts/metric_types/#histogram)
+ *
+ * To get started using one of the metric types, declare the metric at file scope. For example:
+ *
+ * @code{.c}
+ *
+ * #incldue "prom.h"
+ *
+ * prom_counter_t *my_counter;
+ *
+ * @endcode
+ *
+ * Next, create a metric initialization function. You can create the metric and register it with the default metric
+ * collector registry in one chain of functions. A metric collector is responsible for collecting metrics and returning
+ * them. A metric collector registry is declared in global scope and contains metric collectors. More on this later...
+ *
+ * To create a metric and register it with the default metric collector registry in one shot, you may chain the metric
+ * constructor into the prom_collector_registry_must_register_metric function. For example:
+ *
+ * @code{.c}
+ *
+ * void foo_metric_init(void) {
+ * my_counter = prom_collector_registry_must_register_metric(prom_counter_new("my_counter", "counts things", 0, NULL));
+ * }
+ *
+ * @endcode
+ *
+ * The first argument to prom_counter_new is the counter name. The second argument is the counter description. The third
+ * argument is the number of metric labels. In this case, we will only have one metric sample for this metric so we pass
+ * 0 to specify that no labels will be used. The 4th argument is an array of strings storing the metric labels. Since we
+ * have none, we pass NULL. A call to foo_metric_init within the program's main function will initialize the metrics
+ * for the file we just created to the default prometheus metric collector registery called
+ * PROM_COLLECTOR_REGISTRY_DEFAULT
+ *
+ * @section Updating-Metric-Sample-Values Updating Metric Sample Values
+ *
+ * Now that we have a metric configured for creation and registration, we can update our metric within any of the
+ * functions of the file in which it was declared. For example:
+ *
+ * @code{.c}
+ *
+ * void my_lib_do_something(void) {
+ * printf("I did a really important thing!\n");
+ * prom_counter_inc(my_counter, NULL);
+ * }
+ * @endcode
+ *
+ * This function will increment the default metric sample for my_counter. Since we are not using metric labels, we pass
+ * NULL as the second argument.
+ *
+ * @section Program-Initialization Program Initialization
+ *
+ * At the start of the program's main function you need to do two things:
+ *
+ * * Initialize the default metric collector registry:
+ *
+ * @code{.c}
+ *
+ * prom_collector_registry_default_init();
+ *
+ * @endcode
+ *
+ * * For each file containing prometheus metrics, call its corresponding metric initialization function
+ *
+ * @code{.c}
+ *
+ * foo_metric_init()
+ *
+ * @endcode
+ *
+ * After initialization is complete, you may proceed to do work and update your metrics.
+ *
+ * @section Metric-Exposition-Over-HTTP Metric Exposition Over HTTP
+ *
+ * @todo Describe how to use libpromhttp to expose metrics over HTTP
+ *
+ * @section Where-To-Go-From-Here Where to Go From Here?
+ *
+ * Take a look at the [Files](https://github.internal.digitalocean.com/pages/timeseries/prometheus-client-c/files.html)
+ * tab in this documentation site for more information about the public API available to you. Also, you can take a look
+ * at the examples directory at the
+ * [Github repository](https://github.internal.digitalocean.com/timeseries/prometheus-client-c) for inspiration.
+ */
+
+#ifndef PROM_INCLUDED
+#define PROM_INCLUDED
+
+#include "prom_alloc.h"
+#include "prom_collector.h"
+#include "prom_collector_registry.h"
+#include "prom_counter.h"
+#include "prom_gauge.h"
+#include "prom_histogram.h"
+#include "prom_histogram_buckets.h"
+#include "prom_linked_list.h"
+#include "prom_map.h"
+#include "prom_metric.h"
+#include "prom_metric_sample.h"
+#include "prom_metric_sample_histogram.h"
+
+#endif // PROM_INCLUDED \ No newline at end of file
diff --git a/prom/include/prom_alloc.h b/prom/include/prom_alloc.h
new file mode 100644
index 0000000..0f00d0d
--- /dev/null
+++ b/prom/include/prom_alloc.h
@@ -0,0 +1,48 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/**
+ * @file prom_alloc.h
+ * @brief memory management
+ */
+
+#ifndef PROM_ALLOC_H
+#define PROM_ALLOC_H
+
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * @brief Redefine this macro if you wish to override it. The default value is malloc.
+ */
+#define prom_malloc malloc
+
+/**
+ * @brief Redefine this macro if you wish to override it. The default value is realloc.
+ */
+#define prom_realloc realloc
+
+/**
+ * @brief Redefine this macro if you wish to override it. The default value is strdup.
+ */
+#define prom_strdup strdup
+
+/**
+ * @brief Redefine this macro if you wish to override it. The default value is free.
+ */
+#define prom_free free
+
+#endif // PROM_ALLOC_H \ No newline at end of file
diff --git a/prom/include/prom_collector.h b/prom/include/prom_collector.h
new file mode 100644
index 0000000..0fc2a27
--- /dev/null
+++ b/prom/include/prom_collector.h
@@ -0,0 +1,79 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#ifndef PROM_COLLECTOR_H
+#define PROM_COLLECTOR_H
+
+#include "prom_map.h"
+#include "prom_metric.h"
+
+/**
+ * @file prom_collector.h
+ * @brief A Prometheus collector returns a collection of metrics
+ */
+
+/**
+ * @brief A prometheus collector calls collect to prepare metrics and return them to the registry to which it is
+ * registered.
+ */
+typedef struct prom_collector prom_collector_t;
+
+/**
+ * @brief The function responsible for preparing metric data and returning metrics for a given collector.
+ *
+ * If you use the default collector registry, this should not concern you. If you are using a custom collector, you may
+ * which to set this function on your collector to do additional work before returning the contained metrics.
+ */
+typedef prom_map_t* prom_collect_fn(prom_collector_t* self);
+
+/**
+ * @brief Create a collector
+ */
+prom_collector_t* prom_collector_new(const char *name);
+
+/**
+ * @brief Return a collector including the default process metrics
+ * @param limits_path Pass NULL to discover the path to the proc/[pid]/limits file associated with process ID assigned
+ * by the host environment. Otherwise, pass a string to said path.
+ * @param stat_path Pass NULL to discover the path to the proc/[pid]/stat file associated with process ID assigned
+ * by the host environment. Otherwise, pass a string to said path.
+ */
+prom_collector_t* prom_collector_process_new(const char *limits_path, const char *stat_path);
+
+/**
+ * @brief Destroy a collector
+ */
+int prom_collector_destroy(prom_collector_t *self);
+
+void prom_collector_free_generic(void *gen);
+
+/**
+ * @brief Destroy a collector
+ */
+int prom_collector_destroy_generic(void *gen);
+
+/**
+ * @brief Add a metric to a collector
+ */
+int prom_collector_add_metric(prom_collector_t *self, prom_metric_t *metric);
+
+/**
+ * @brief The collect function is responsible for doing any work involving a set of metrics and then returning them
+ * for metric exposition
+ */
+int prom_collector_set_collect_fn(prom_collector_t *self, prom_collect_fn *fn);
+
+#endif // PROM_COLLECTOR_H \ No newline at end of file
diff --git a/prom/include/prom_collector_registry.h b/prom/include/prom_collector_registry.h
new file mode 100644
index 0000000..3952cd7
--- /dev/null
+++ b/prom/include/prom_collector_registry.h
@@ -0,0 +1,95 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/**
+ * @file prom_collector_registry.h
+ * @brief The collector registry registers collectors for metric exposition.
+ */
+
+#ifndef PROM_REGISTRY_H
+#define PROM_REGISTRY_H
+
+#include "prom_collector.h"
+#include "prom_metric.h"
+
+/**
+ * @brief A prom_registry_t is responsible for registering metrics and briding them to the string exposition format
+ */
+typedef struct prom_collector_registry prom_collector_registry_t;
+
+/**
+ * @brief Initialize the default registry by calling prom_collector_registry_init within your program. You MUST NOT
+ * modify this value.
+ */
+prom_collector_registry_t *PROM_COLLECTOR_REGISTRY_DEFAULT;
+
+/**
+ * @brief Initializes the default collector registry and enables metric collection on the executing process
+ */
+int prom_collector_registry_default_init(void);
+
+/**
+ * @brief Return a new collector registry
+ */
+prom_collector_registry_t* prom_collector_registry_new(const char *name);
+
+/**
+ * @brief Destroy a collector registry
+ */
+int prom_collector_registry_destroy(prom_collector_registry_t *self);
+
+/**
+ * @brief Enable process metrics on the given collector registry.
+ */
+int prom_collector_registry_enable_process_metrics(prom_collector_registry_t *self);
+
+/**
+ * @brief Registers a metric with the default collector on PROM_DEFAULT_COLLECTOR_REGISTRY
+ *
+ * The metric to be registered MUST NOT already be registered with the given metric. If so, the program will
+ * halt. It returns a prom_metric_t* to simplify metric creation and registration. Furthermore,
+ * PROM_DEFAULT_COLLECTOR_REGISTRY must be registered via prom_collector_registry_default_init() prior to calling this
+ * function. The metric will be added to the default registry's default collector.
+ */
+prom_metric_t* prom_collector_registry_must_register_metric(prom_metric_t *metric);
+
+/**
+ * @brief Registers a metric with the default collector on PROM_DEFAULT_COLLECTOR_REGISTRY. Returns an error on failure.
+ * See prom_collector_registry_must_register_metric.
+ */
+int prom_collector_registry_register_metric(prom_metric_t *metric);
+
+/**
+ * @brief Register a collector with the given registry. Returns an error on failure.
+ */
+int prom_collector_registry_register_collector(prom_collector_registry_t *self, prom_collector_t *collector);
+
+/**
+ * @brief Returns a string in the default metric exposition format
+ *
+ * Reference: https://prometheus.io/docs/instrumenting/exposition_formats/
+ */
+const char* prom_collector_registry_bridge(prom_collector_registry_t *self);
+
+/**
+ * @brief Validates that the given metric name complies with the specification:
+ *
+ * Reference: https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels
+ */
+int prom_collector_registry_validate_metric_name(prom_collector_registry_t *self,
+ const char *metric_name);
+
+#endif // PROM_H \ No newline at end of file
diff --git a/prom/include/prom_counter.h b/prom/include/prom_counter.h
new file mode 100644
index 0000000..0728780
--- /dev/null
+++ b/prom/include/prom_counter.h
@@ -0,0 +1,63 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+#ifndef PROM_COUNTER_INCLUDED
+#define PROM_COUNTER_INCLUDED
+
+#include <stdlib.h>
+
+#include "prom_metric.h"
+
+/**
+ * @file prom_counter.h
+ * @brief https://prometheus.io/docs/concepts/metric_types/#counter
+ */
+
+/**
+ * @brief A prometheus counter.
+ *
+ * References
+ * * See https://prometheus.io/docs/concepts/metric_types/#counter
+ */
+typedef prom_metric_t prom_counter_t;
+
+/**
+ * @brief Returns a pointer to a prom_counter
+ */
+prom_counter_t* prom_counter_new(const char *name,
+ const char *help,
+ size_t label_key_count,
+ const char **label_keys);
+
+/**
+ * @brief Destroys a pointer to a prom_counter
+ */
+int prom_counter_destroy(prom_counter_t *self);
+
+
+/**
+ * @brief Increment the prom_counter by 1
+ */
+int prom_counter_inc(prom_counter_t *self, const char **label_values);
+
+
+/**
+ * @brief Add the value to the prom_counter
+ */
+int prom_counter_add(prom_counter_t *self, double r_value, const char **label_values);
+
+#endif // PROM_COUNTER_INCLUDED \ No newline at end of file
diff --git a/prom/include/prom_gauge.h b/prom/include/prom_gauge.h
new file mode 100644
index 0000000..8ff1b74
--- /dev/null
+++ b/prom/include/prom_gauge.h
@@ -0,0 +1,80 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/**
+ * @file prom_gauge.h
+ * @brief https://prometheus.io/docs/concepts/metric_types/#gauge
+ */
+
+#ifndef PROM_GAUGE_INCLUDED
+#define PROM_GAUGE_INCLUDED
+
+#include <stdlib.h>
+
+#include "prom_metric.h"
+
+/**
+ * @brief A prometheus gauge.
+ *
+ * References
+ * * See https://prometheus.io/docs/concepts/metric_types/#gauge
+ */
+typedef prom_metric_t prom_gauge_t;
+
+/**
+ * @brief Returns a pointer to a prom_gauge
+ */
+prom_gauge_t* prom_gauge_new(const char *name,
+ const char *help,
+ size_t label_key_count,
+ const char **label_keys);
+
+/**
+ * @brief Destroys a pointer to a prom_gauge
+ */
+int prom_gauge_destroy(prom_gauge_t *self);
+
+
+/**
+ * @brief Increment the prom_gauge by 1
+ */
+int prom_gauge_inc(prom_gauge_t *self, const char **label_values);
+
+
+/**
+ * @brief Descrement the prom_gauge by 1
+ */
+int prom_gauge_dec(prom_gauge_t *self, const char **label_values);
+
+
+/**
+ * @brief Add the value to the prom_gauge
+ */
+int prom_gauge_add(prom_gauge_t *self, double r_value, const char **label_values);
+
+
+/**
+ * @brief Subtract the value from the prom_gauge
+ */
+int prom_gauge_sub(prom_gauge_t *self, double r_value, const char **label_values);
+
+
+/**
+ * @brief Set the value for the prom_gauge
+ */
+int prom_gauge_set(prom_gauge_t *self, double r_value, const char **label_values);
+
+#endif // PROM_GAUGE_INCLUDED
diff --git a/prom/include/prom_histogram.h b/prom/include/prom_histogram.h
new file mode 100644
index 0000000..0436048
--- /dev/null
+++ b/prom/include/prom_histogram.h
@@ -0,0 +1,58 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/**
+ * @file prom_histogram.h
+ * @brief https://prometheus.io/docs/concepts/metric_types/#histogram
+ */
+
+#ifndef PROM_HISTOGRAM_INCLUDED
+#define PROM_HISTOGRAM_INCLUDED
+
+#include <stdlib.h>
+
+#include "prom_metric.h"
+#include "prom_histogram_buckets.h"
+
+/**
+ * @brief A prometheus histogram.
+ *
+ * References
+ * * See https://prometheus.io/docs/concepts/metric_types/#histogram
+ */
+typedef prom_metric_t prom_histogram_t;
+
+/**
+ * @brief Returns a pointer to a prom_histogram_t
+ */
+prom_histogram_t* prom_histogram_new(const char *name,
+ const char *help,
+ prom_histogram_buckets_t *buckets,
+ size_t label_key_count,
+ const char **label_keys);
+
+/**
+ * @brief Destroys a pointer to a prom_gauge
+ */
+int prom_histogram_destroy(prom_histogram_t *self);
+
+
+/**
+ * @brief Observe the prom_histogram_t given the value and labells
+ */
+int prom_histogram_observe(prom_histogram_t *self, double value, const char **label_values);
+
+#endif // PROM_HISTOGRAM_INCLUDED
diff --git a/prom/include/prom_histogram_buckets.h b/prom/include/prom_histogram_buckets.h
new file mode 100644
index 0000000..19a8824
--- /dev/null
+++ b/prom/include/prom_histogram_buckets.h
@@ -0,0 +1,74 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/**
+ * @file prom_histogram_buckets.h
+ * @brief https://prometheus.io/docs/concepts/metric_types/#histogram
+ */
+
+#ifndef PROM_HISTOGRAM_BUCKETS_INCLUDED
+#define PROM_HISTOGRAM_BUCKETS_INCLUDED
+
+typedef struct prom_histogram_buckets {
+ int count; /**< Number of buckets */
+ const double *upper_bounds; /**< The bucket values */
+} prom_histogram_buckets_t;
+
+prom_histogram_buckets_t* prom_histogram_buckets_new(size_t count, double bucket, ...);
+
+/**
+ * @brief the default histogram buckets: .005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10
+ */
+prom_histogram_buckets_t *prom_histogram_default_buckets;
+
+/**
+ * @brief Create linear buckets
+ * @param start The first upper bound
+ * @param width The distance between each upper bound in buckets
+ * @param count The total number of buckets. The final +Inf bucket is not counted and not included in the returned
+ * array
+ * @return The array of upper bounds represented as double values
+ *
+ * The Array returned MUST be freed
+ */
+prom_histogram_buckets_t* prom_histogram_buckets_linear(double start, double width, size_t count);
+
+/**
+ * @brief Create linear buckets.
+ * @param start The first upper bound. The value MUST be greater than 0.
+ * @param factor The factor to apply to the previous upper bound to produce the next upper bound. The value MUST be
+ * greater than 1.
+ * @param count The total number of buckets. The final +Inf bucket is not counted and not included in the returned. The
+ * value MUST be greater than or equal to 1
+ * array
+ * @return The array of upper bounds represented as double values
+ *
+ * The array returned MUST be freed
+ */
+prom_histogram_buckets_t* prom_histogram_buckets_exponential(double start, double factor, size_t count);
+
+
+/**
+ * @brief Destroy a prom_histogram_buckets_t
+ */
+int prom_histogram_buckets_destroy(prom_histogram_buckets_t *self);
+
+/**
+ * @brief Get the count of buckets
+ */
+size_t prom_histogram_buckets_count(prom_histogram_buckets_t *self);
+
+#endif // PROM_HISTOGRAM_BUCKETS_INCLUDED
diff --git a/prom/include/prom_linked_list.h b/prom/include/prom_linked_list.h
new file mode 100644
index 0000000..35a0701
--- /dev/null
+++ b/prom/include/prom_linked_list.h
@@ -0,0 +1,30 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+#ifndef PROM_LIST_H
+#define PROM_LIST_H
+
+#include <stdlib.h>
+
+struct prom_linked_list;
+/**
+* @brief Provides a generic linked list
+*/
+typedef struct prom_linked_list prom_linked_list_t;
+
+
+#endif // PROM_LIST_H
diff --git a/prom/include/prom_map.h b/prom/include/prom_map.h
new file mode 100644
index 0000000..73930b4
--- /dev/null
+++ b/prom/include/prom_map.h
@@ -0,0 +1,26 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#ifndef PROM_MAP_H
+#define PROM_MAP_H
+
+struct prom_map;
+typedef struct prom_map prom_map_t;
+
+struct prom_map_node;
+typedef struct prom_map_node prom_map_node_t;
+
+#endif // PROM_MAP_H
diff --git a/prom/include/prom_metric.h b/prom/include/prom_metric.h
new file mode 100644
index 0000000..c8a213c
--- /dev/null
+++ b/prom/include/prom_metric.h
@@ -0,0 +1,55 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/**
+ * @file prom_metric.h
+ * @brief Functions for retrieving metric samples from metrics given an ordered set of labels
+ */
+
+#ifndef PROM_METRIC_H
+#define PROM_METRIC_H
+
+#include "prom_metric_sample.h"
+#include "prom_metric_sample_histogram.h"
+
+struct prom_metric;
+/**
+ * @brief A prometheus metric.
+ *
+ * Reference: https://prometheus.io/docs/concepts/data_model
+ */
+typedef struct prom_metric prom_metric_t;
+
+/**
+ * @brief Returns a prom_metric_sample_t*. The order of label_values is significant.
+ *
+ * You may use this function to cache metric samples to avoid sample lookup. Metric samples are stored in a hash map
+ * with O(1) lookups in average case; nonethless, caching metric samples and updating them directly might be
+ * preferrable in performance-sensitive situations.
+ */
+prom_metric_sample_t* prom_metric_sample_from_labels(prom_metric_t *self, const char **label_values);
+
+/**
+ * @brief Returns a prom_metric_sample_histogram_t*. The order of label_values is significant.
+ *
+ * You may use this function to cache metric samples to avoid sample lookup. Metric samples are stored in a hash map
+ * with O(1) lookups in average case; nonethless, caching metric samples and updating them directly might be
+ * preferrable in performance-sensitive situations.
+ */
+prom_metric_sample_histogram_t* prom_metric_sample_histogram_from_labels(prom_metric_t *self,
+ const char **label_values);
+
+#endif // PROM_METRIC_H
diff --git a/prom/include/prom_metric_sample.h b/prom/include/prom_metric_sample.h
new file mode 100644
index 0000000..05e27fb
--- /dev/null
+++ b/prom/include/prom_metric_sample.h
@@ -0,0 +1,51 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/**
+ * @file prom_metric_sample.h
+ * @brief Functions for interfacting with metric samples directly
+ */
+
+#ifndef PROM_METRIC_SAMPLE_H
+#define PROM_METRIC_SAMPLE_H
+
+struct prom_metric_sample;
+/**
+ * @brief Contains the specific metric and value given the name and label set
+ * Reference: https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels
+ */
+typedef struct prom_metric_sample prom_metric_sample_t;
+
+/**
+ * @brief Add the r_value to the sample. The value must be greater than or equal to zero.
+ */
+int prom_metric_sample_add(prom_metric_sample_t *self, double r_value);
+
+/**
+ * @brief Subtract the r_value from the sample.
+ *
+ * This operation MUST be called a sample derived from a gauge metric.
+ */
+int prom_metric_sample_sub(prom_metric_sample_t *self, double r_value);
+
+/**
+ * @brief Set the r_value of the sample.
+ *
+ * This operation MUST be called on a sample derived from a gauge metric.
+ */
+int prom_metric_sample_set(prom_metric_sample_t *self, double r_value);
+
+#endif // PROM_METRIC_SAMPLE_H
diff --git a/prom/include/prom_metric_sample_histogram.h b/prom/include/prom_metric_sample_histogram.h
new file mode 100644
index 0000000..b96ef22
--- /dev/null
+++ b/prom/include/prom_metric_sample_histogram.h
@@ -0,0 +1,36 @@
+/*
+Copyright 2019 DigitalOcean Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/**
+ * @file prom_metric_sample_histogram.h
+ * @brief Functions for interacting with histogram metric samples directly
+ */
+
+#ifndef PROM_METRIC_SAMPLE_HISOTGRAM_H
+#define PROM_METRIC_SAMPLE_HISOTGRAM_H
+
+struct prom_metric_sample_histogram;
+/**
+ * @brief A histogram metric sample
+ */
+typedef struct prom_metric_sample_histogram prom_metric_sample_histogram_t;
+
+/**
+ * @brief Observe the double for the given prom_metric_sample_histogram_observe_t
+ */
+int prom_metric_sample_histogram_observe(prom_metric_sample_histogram_t *self, double value);
+
+#endif // PROM_METRIC_SAMPLE_HISOTGRAM_H \ No newline at end of file
diff --git a/prom/src/prom_assert.h b/prom/src/prom_assert.h
new file mode 100644
index 0000000..6ca2e13
--- /dev/null
+++ b/prom/src/prom_assert.h
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+
+#ifndef PROM_ASSERT_H
+#define PROM_ASSERT_H
+
+#ifdef PROM_ASSERT_ENABLE
+ #define PROM_ASSERT(i) assert(i);
+#else
+ #define PROM_ASSERT(i)
+#endif // PROM_TEST
+
+#endif // PROM_ASSERT_H \ No newline at end of file
diff --git a/prom/src/prom_collector.c b/prom/src/prom_collector.c
new file mode 100644
index 0000000..8e8e5ff
--- /dev/null
+++ b/prom/src/prom_collector.c
@@ -0,0 +1,275 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+// Public
+#include "prom_alloc.h"
+#include "prom_collector.h"
+#include "prom_collector_registry.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_collector_t.h"
+#include "prom_log.h"
+#include "prom_map_i.h"
+#include "prom_metric_i.h"
+#include "prom_process_fds_i.h"
+#include "prom_process_fds_t.h"
+#include "prom_process_limits_i.h"
+#include "prom_process_limits_t.h"
+#include "prom_process_stat_t.h"
+#include "prom_process_stat_i.h"
+#include "prom_string_builder_i.h"
+
+
+prom_map_t* prom_collector_default_collect(prom_collector_t *self) {
+ return self->metrics;
+}
+
+prom_collector_t* prom_collector_new(const char *name) {
+ int r = 0;
+ prom_collector_t *self = (prom_collector_t*) prom_malloc(sizeof(prom_collector_t));
+ self->name = prom_strdup(name);
+ self->metrics = prom_map_new();
+ if (self->metrics == NULL) {
+ prom_collector_destroy(self);
+ return NULL;
+ }
+ r = prom_map_set_free_value_fn(self->metrics, &prom_metric_free_generic);
+ if (r) {
+ prom_collector_destroy(self);
+ return NULL;
+ }
+ self->collect_fn = &prom_collector_default_collect;
+ self->string_builder = prom_string_builder_new();
+ if (self->string_builder == NULL) {
+ prom_collector_destroy(self);
+ return NULL;
+ }
+ self->proc_limits_file_path = NULL;
+ self->proc_stat_file_path = NULL;
+ return self;
+}
+
+int prom_collector_destroy(prom_collector_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+
+ int r = 0;
+ int ret = 0;
+
+ r = prom_map_destroy(self->metrics);
+ if (r) ret = r;
+ self->metrics = NULL;
+
+ r = prom_string_builder_destroy(self->string_builder);
+ if (r) ret = r;
+ self->string_builder = NULL;
+
+ prom_free((char *) self->name);
+ self->name = NULL;
+ prom_free(self);
+ self = NULL;
+
+ return ret;
+}
+
+int prom_collector_destroy_generic(void *gen) {
+ int r = 0;
+ prom_collector_t *self = (prom_collector_t *) gen;
+ r = prom_collector_destroy(self);
+ self = NULL;
+ return r;
+ }
+
+void prom_collector_free_generic(void *gen) {
+ prom_collector_t *self = (prom_collector_t *) gen;
+ prom_collector_destroy(self);
+}
+
+int prom_collector_set_collect_fn(prom_collector_t *self, prom_collect_fn *fn) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ self->collect_fn = fn;
+ return 0;
+}
+
+int prom_collector_add_metric(prom_collector_t *self, prom_metric_t *metric) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (prom_map_get(self->metrics, metric->name ) != NULL) {
+ PROM_LOG("metric already found in collector");
+ return 1;
+ }
+ return prom_map_set(self->metrics, metric->name, metric);
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Process Collector
+
+prom_map_t* prom_collector_process_collect(prom_collector_t *self);
+
+prom_collector_t* prom_collector_process_new(const char *limits_path, const char *stat_path) {
+ prom_collector_t *self = prom_collector_new("process");
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return NULL;
+
+ int r = 0;
+
+ self->proc_limits_file_path = limits_path;
+ self->proc_stat_file_path = stat_path;
+ self->collect_fn = &prom_collector_process_collect;
+
+ r = prom_process_limits_init();
+ if (r) return NULL;
+
+ r = prom_process_stats_init();
+ if (r) return NULL;
+
+ r = prom_process_fds_init();
+ if (r) return NULL;
+
+ r = prom_collector_add_metric(self, prom_process_max_fds);
+ if (r) return NULL;
+
+ r = prom_collector_add_metric(self, prom_process_virtual_memory_max_bytes);
+ if (r) return NULL;
+
+ r = prom_collector_add_metric(self, prom_process_cpu_seconds_total);
+ if (r) return NULL;
+
+ r = prom_collector_add_metric(self, prom_process_virtual_memory_bytes);
+ if (r) return NULL;
+
+ r = prom_collector_add_metric(self, prom_process_start_time_seconds);
+ if (r) return NULL;
+
+ r = prom_collector_add_metric(self, prom_process_open_fds);
+ if (r) return NULL;
+
+ return self;
+}
+
+prom_map_t* prom_collector_process_collect(prom_collector_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return NULL;
+
+ int r = 0;
+
+ // Allocate and create a *prom_process_limits_file_t
+ prom_process_limits_file_t *limits_f = prom_process_limits_file_new(self->proc_limits_file_path);
+ if (limits_f == NULL) {
+ prom_process_limits_file_destroy(limits_f);
+ return NULL;
+ }
+
+ // Allocate and create a *prom_map_t from prom_process_limits_file_t. This is the main storage container for the
+ // limits metric data
+ prom_map_t *limits_map = prom_process_limits(limits_f);
+ if (limits_map == NULL) {
+ prom_process_limits_file_destroy(limits_f);
+ prom_map_destroy(limits_map);
+ return NULL;
+ }
+
+ // Retrieve the *prom_process_limits_row_t for Max open files
+ prom_process_limits_row_t *max_fds = (prom_process_limits_row_t *) prom_map_get(limits_map, "Max open files");
+ if (max_fds == NULL) {
+ prom_process_limits_file_destroy(limits_f);
+ prom_map_destroy(limits_map);
+ return NULL;
+ }
+
+ // Retrieve the *prom_process_limits_row_t for Max address space
+ prom_process_limits_row_t *virtual_memory_max_bytes = (prom_process_limits_row_t *) prom_map_get(
+ limits_map, "Max address space"
+ );
+ if (virtual_memory_max_bytes == NULL) {
+ prom_process_limits_file_destroy(limits_f);
+ prom_map_destroy(limits_map);
+ return NULL;
+ }
+
+ // Set the metric values for max_fds and virtual_memory_max_bytes
+ r = prom_gauge_set(prom_process_max_fds, max_fds->soft, NULL);
+ if (r) return NULL;
+ r = prom_gauge_set(prom_process_virtual_memory_max_bytes, virtual_memory_max_bytes->soft, NULL);
+ if (r) return NULL;
+
+ // Aloocate and create a *prom_process_stat_file_t
+ prom_process_stat_file_t *stat_f = prom_process_stat_file_new(self->proc_stat_file_path);
+ if (stat_f == NULL) {
+ prom_process_limits_file_destroy(limits_f);
+ prom_map_destroy(limits_map);
+ return self->metrics;
+ }
+
+ // Allocate and create a *prom_process_stat_t from *prom_process_stat_file_t
+ prom_process_stat_t *stat = prom_process_stat_new(stat_f);
+
+ // Set the metrics related to the stat file
+ r = prom_gauge_set(prom_process_cpu_seconds_total, ((stat->cutime + stat->cstime) / 100), NULL);
+ if (r) {
+ prom_process_limits_file_destroy(limits_f);
+ prom_map_destroy(limits_map);
+ prom_process_stat_file_destroy(stat_f);
+ prom_process_stat_destroy(stat);
+ return NULL;
+ }
+ r = prom_gauge_set(prom_process_virtual_memory_bytes, stat->vsize, NULL);
+ if (r) {
+ prom_process_limits_file_destroy(limits_f);
+ prom_map_destroy(limits_map);
+ prom_process_stat_file_destroy(stat_f);
+ prom_process_stat_destroy(stat);
+ return NULL;
+ }
+ r = prom_gauge_set(prom_process_start_time_seconds, stat->starttime, NULL);
+ if (r) {
+ prom_process_limits_file_destroy(limits_f);
+ prom_map_destroy(limits_map);
+ prom_process_stat_file_destroy(stat_f);
+ prom_process_stat_destroy(stat);
+ return NULL;
+ }
+ r = prom_gauge_set(prom_process_open_fds, prom_process_fds_count(NULL), NULL);
+ if (r) {
+ prom_process_limits_file_destroy(limits_f);
+ prom_map_destroy(limits_map);
+ prom_process_stat_file_destroy(stat_f);
+ prom_process_stat_destroy(stat);
+ return NULL;
+ }
+
+ // If there is any issue deallocating the following structures, return NULL to indicate failure
+ r = prom_process_limits_file_destroy(limits_f);
+ if (r) return NULL;
+ r = prom_map_destroy(limits_map);
+ if (r) return NULL;
+ r = prom_process_stat_file_destroy(stat_f);
+ if (r) return NULL;
+ r = prom_process_stat_destroy(stat);
+ if (r) return NULL;
+
+ return self->metrics;
+}
+
+
+
diff --git a/prom/src/prom_collector_registry.c b/prom/src/prom_collector_registry.c
new file mode 100644
index 0000000..166c239
--- /dev/null
+++ b/prom/src/prom_collector_registry.c
@@ -0,0 +1,226 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <pthread.h>
+#include <regex.h>
+#include <stdio.h>
+
+// Public
+#include "prom_alloc.h"
+#include "prom_collector.h"
+#include "prom_collector_registry.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_collector_t.h"
+#include "prom_collector_registry_t.h"
+#include "prom_errors.h"
+#include "prom_log.h"
+#include "prom_map_i.h"
+#include "prom_metric_formatter_i.h"
+#include "prom_metric_i.h"
+#include "prom_metric_t.h"
+#include "prom_process_limits_i.h"
+#include "prom_string_builder_i.h"
+
+
+prom_collector_registry_t* prom_collector_registry_new(const char *name)
+{
+ int r = 0;
+
+ prom_collector_registry_t* self = (prom_collector_registry_t*) prom_malloc(sizeof(prom_collector_registry_t));
+
+ self->disable_process_metrics = false;
+
+ self->name = prom_strdup(name);
+ self->collectors = prom_map_new();
+ prom_map_set_free_value_fn(self->collectors, &prom_collector_free_generic);
+ prom_map_set(self->collectors, "default", prom_collector_new("default"));
+
+ self->metric_formatter = prom_metric_formatter_new();
+ self->string_builder = prom_string_builder_new();
+ self->lock = (pthread_rwlock_t*) prom_malloc(sizeof(pthread_rwlock_t));
+ r = pthread_rwlock_init(self->lock, NULL);
+ if (r) {
+ PROM_LOG("failed to initialize rwlock");
+ return NULL;
+ }
+ return self;
+}
+
+int prom_collector_registry_enable_process_metrics(prom_collector_registry_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ prom_collector_t *process_collector = prom_collector_process_new(NULL, NULL);
+ if (process_collector) {
+ prom_map_set(self->collectors, "process", process_collector);
+ return 0;
+ }
+ return 1;
+}
+
+
+int prom_collector_registry_enable_custom_process_metrics(prom_collector_registry_t *self,
+ const char *process_limits_path,
+ const char *process_stats_path)
+{
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) {
+ PROM_LOG("prom_collector_registry_t is NULL");
+ return 1;
+ }
+ prom_collector_t *process_collector = prom_collector_process_new(process_limits_path, process_stats_path);
+ if (process_collector) {
+ prom_map_set(self->collectors, "process", process_collector);
+ return 0;
+ }
+ return 1;
+}
+
+
+int prom_collector_registry_default_init(void) {
+ if (PROM_COLLECTOR_REGISTRY_DEFAULT != NULL) return 0;
+
+ int r = 0;
+
+ PROM_COLLECTOR_REGISTRY_DEFAULT = prom_collector_registry_new("default");
+ if (PROM_COLLECTOR_REGISTRY_DEFAULT) {
+ r = prom_collector_registry_enable_process_metrics(PROM_COLLECTOR_REGISTRY_DEFAULT);
+ if (r) return r;
+ }
+ return 1;
+}
+
+int prom_collector_registry_destroy(prom_collector_registry_t *self) {
+ if (self == NULL) return 0;
+
+ int r = 0;
+ int ret = 0;
+
+ r = prom_map_destroy(self->collectors);
+ self->collectors = NULL;
+ if (r) ret = r;
+
+ r = prom_metric_formatter_destroy(self->metric_formatter);
+ self->metric_formatter = NULL;
+ if (r) ret = r;
+
+ r = prom_string_builder_destroy(self->string_builder);
+ self->string_builder = NULL;
+ if (r) ret = r;
+
+ r = pthread_rwlock_destroy(self->lock);
+ prom_free(self->lock);
+ self->lock = NULL;
+ if (r) ret = r;
+
+ prom_free((char *) self->name);
+ self->name = NULL;
+
+ prom_free(self);
+ self = NULL;
+
+ return ret;
+}
+
+int prom_collector_registry_register_metric(prom_metric_t *metric) {
+ PROM_ASSERT(metric != NULL);
+
+ prom_collector_t *default_collector = (prom_collector_t *) prom_map_get(
+ PROM_COLLECTOR_REGISTRY_DEFAULT->collectors, "default"
+ );
+
+ if (default_collector == NULL) {
+ return 1;
+ }
+
+ return prom_collector_add_metric(default_collector, metric);
+}
+
+prom_metric_t* prom_collector_registry_must_register_metric(prom_metric_t *metric) {
+ int err = prom_collector_registry_register_metric(metric);
+ if (err != 0) {
+ exit(err);
+ }
+ return metric;
+}
+
+int prom_collector_registry_register_collector(prom_collector_registry_t *self, prom_collector_t *collector) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+
+ int r = 0;
+
+ r = pthread_rwlock_wrlock(self->lock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_LOCK_ERROR);
+ return 1;
+ }
+ if (prom_map_get(self->collectors, collector->name) != NULL){
+ PROM_LOG("the given prom_collector_t* is already registered");
+ int rr = pthread_rwlock_unlock(self->lock);
+ if (rr) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR);
+ return rr;
+ } else {
+ return 1;
+ }
+ }
+ r = prom_map_set(self->collectors, collector->name, collector);
+ if (r) {
+ int rr = pthread_rwlock_unlock(self->lock);
+ if (rr) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR);
+ return rr;
+ } else {
+ return r;
+ }
+ }
+ r = pthread_rwlock_unlock(self->lock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR);
+ return 1;
+ }
+ return 0;
+}
+
+int prom_collector_registry_validate_metric_name(prom_collector_registry_t *self, const char *metric_name) {
+ regex_t r;
+ int ret = 0;
+ ret = regcomp(&r, "^[a-zA-Z_:][a-zA-Z0-9_:]*$", REG_EXTENDED);
+ if (ret){
+ PROM_LOG(PROM_REGEX_REGCOMP_ERROR);
+ regfree(&r);
+ return ret;
+ }
+
+ ret = regexec(&r, metric_name, 0, NULL, 0);
+ if (ret){
+ PROM_LOG(PROM_REGEX_REGEXEC_ERROR);
+ regfree(&r);
+ return ret;
+ }
+ regfree(&r);
+ return 0;
+}
+
+const char* prom_collector_registry_bridge(prom_collector_registry_t *self) {
+ prom_metric_formatter_clear(self->metric_formatter);
+ prom_metric_formatter_load_metrics(self->metric_formatter, self->collectors);
+ return (const char*) prom_metric_formatter_dump(self->metric_formatter);
+}
+
diff --git a/prom/src/prom_collector_registry_i.h b/prom/src/prom_collector_registry_i.h
new file mode 100644
index 0000000..d1eb1ef
--- /dev/null
+++ b/prom/src/prom_collector_registry_i.h
@@ -0,0 +1,26 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "prom_collector_registry_t.h"
+
+#ifndef PROM_COLLECTOR_REGISTRY_I_INCLUDED
+#define PROM_COLLECTOR_REGISTRY_I_INCLUDED
+
+int prom_collector_registry_enable_custom_process_metrics(prom_collector_registry_t *self,
+ const char *process_limits_path,
+ const char *process_stats_path);
+
+#endif // PROM_COLLECTOR_REGISTRY_I_INCLUDED \ No newline at end of file
diff --git a/prom/src/prom_collector_registry_t.h b/prom/src/prom_collector_registry_t.h
new file mode 100644
index 0000000..c7d876e
--- /dev/null
+++ b/prom/src/prom_collector_registry_t.h
@@ -0,0 +1,41 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PROM_REGISTRY_T_H
+#define PROM_REGISTRY_T_H
+
+#include <pthread.h>
+#include <stdbool.h>
+
+// Public
+#include "prom_collector_registry.h"
+
+// Private
+#include "prom_map_t.h"
+#include "prom_metric_formatter_t.h"
+#include "prom_string_builder_t.h"
+
+
+struct prom_collector_registry {
+ const char *name;
+ bool disable_process_metrics; /**< Disables the collection of process metrics */
+ prom_map_t *collectors; /**< Map of collectors keyed by name */
+ prom_string_builder_t *string_builder; /**< Enables string building */
+ prom_metric_formatter_t *metric_formatter; /**< metric formatter for metric exposition on bridge call */
+ pthread_rwlock_t *lock; /**< mutex for safety against concurrent registration */
+};
+
+#endif // PROM_REGISTRY_T_H
diff --git a/prom/src/prom_collector_t.h b/prom/src/prom_collector_t.h
new file mode 100644
index 0000000..37cc649
--- /dev/null
+++ b/prom/src/prom_collector_t.h
@@ -0,0 +1,34 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef PROM_COLLECTOR_T_H
+#define PROM_COLLECTOR_T_H
+
+#include "prom_collector.h"
+#include "prom_map_t.h"
+#include "prom_string_builder_t.h"
+
+struct prom_collector {
+ const char *name;
+ prom_map_t *metrics;
+ prom_collect_fn *collect_fn;
+ prom_string_builder_t *string_builder;
+ const char *proc_limits_file_path;
+ const char *proc_stat_file_path;
+};
+
+#endif // PROM_COLLECTOR_T_H \ No newline at end of file
diff --git a/prom/src/prom_counter.c b/prom/src/prom_counter.c
new file mode 100644
index 0000000..c3d45c1
--- /dev/null
+++ b/prom/src/prom_counter.c
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Public
+#include "prom_alloc.h"
+#include "prom_counter.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_errors.h"
+#include "prom_log.h"
+#include "prom_metric_i.h"
+#include "prom_metric_t.h"
+#include "prom_metric_sample_i.h"
+#include "prom_metric_sample_t.h"
+
+
+prom_counter_t* prom_counter_new(const char *name,
+ const char *help,
+ size_t label_key_count,
+ const char **label_keys)
+{
+ return (prom_counter_t*) prom_metric_new(PROM_COUNTER, name, help, label_key_count, label_keys);
+}
+
+int prom_counter_destroy(prom_counter_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+ int r = 0;
+ r = prom_metric_destroy(self);
+ self = NULL;
+ return r;
+}
+
+int prom_counter_inc(prom_counter_t *self, const char **label_values) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (self->type != PROM_COUNTER) {
+ PROM_LOG(PROM_METRIC_INCORRECT_TYPE);
+ return 1;
+ }
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(self, label_values);
+ if (sample == NULL) return 1;
+ return prom_metric_sample_add(sample, 1.0);
+}
+
+int prom_counter_add(prom_counter_t *self, double r_value, const char **label_values) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (self->type != PROM_COUNTER) {
+ PROM_LOG(PROM_METRIC_INCORRECT_TYPE);
+ return 1;
+ }
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(self, label_values);
+ if (sample == NULL) return 1;
+ return prom_metric_sample_add(sample, r_value);
+} \ No newline at end of file
diff --git a/prom/src/prom_errors.h b/prom/src/prom_errors.h
new file mode 100644
index 0000000..2bb7c11
--- /dev/null
+++ b/prom/src/prom_errors.h
@@ -0,0 +1,26 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define PROM_STDIO_CLOSE_DIR_ERROR "failed to close dir"
+#define PROM_STDIO_OPEN_DIR_ERROR "failed to open dir"
+#define PROM_METRIC_INCORRECT_TYPE "incorrect metric type"
+#define PROM_METRIC_INVALID_LABEL_NAME "invalid label name"
+#define PROM_PTHREAD_RWLOCK_DESTROY_ERROR "failed to destroy the pthread_rwlock_t*"
+#define PROM_PTHREAD_RWLOCK_INIT_ERROR "failed to initialize the pthread_rwlock_t*"
+#define PROM_PTHREAD_RWLOCK_LOCK_ERROR "failed to lock the pthread_rwlock_t*"
+#define PROM_PTHREAD_RWLOCK_UNLOCK_ERROR "failed to unlock the pthread_rwlock_t*"
+#define PROM_REGEX_REGCOMP_ERROR "failed to compile the regular expression"
+#define PROM_REGEX_REGEXEC_ERROR "failed to execute the regular expression"
diff --git a/prom/src/prom_gauge.c b/prom/src/prom_gauge.c
new file mode 100644
index 0000000..9235e58
--- /dev/null
+++ b/prom/src/prom_gauge.c
@@ -0,0 +1,106 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+// Public
+#include "prom_alloc.h"
+#include "prom_gauge.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_errors.h"
+#include "prom_log.h"
+#include "prom_metric_i.h"
+#include "prom_metric_t.h"
+#include "prom_metric_sample_i.h"
+#include "prom_metric_sample_t.h"
+
+
+prom_gauge_t* prom_gauge_new(const char *name,
+ const char *help,
+ size_t label_key_count,
+ const char **label_keys)
+{
+ return (prom_gauge_t*) prom_metric_new(PROM_GAUGE, name, help, label_key_count, label_keys);
+}
+
+int prom_gauge_destroy(prom_gauge_t *self) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+ r = prom_metric_destroy(self);
+ self = NULL;
+ return r;
+}
+
+int prom_gauge_inc(prom_gauge_t *self, const char **label_values) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (self->type != PROM_GAUGE) {
+ PROM_LOG(PROM_METRIC_INCORRECT_TYPE);
+ return 1;
+ }
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(self, label_values);
+ if (sample == NULL) return 1;
+ return prom_metric_sample_add(sample, 1.0);
+}
+
+int prom_gauge_dec(prom_gauge_t *self, const char **label_values) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (self->type != PROM_GAUGE) {
+ PROM_LOG(PROM_METRIC_INCORRECT_TYPE);
+ return 1;
+ }
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(self, label_values);
+ if (sample == NULL) return 1;
+ return prom_metric_sample_sub(sample, 1.0);
+}
+
+int prom_gauge_add(prom_gauge_t *self, double r_value, const char **label_values) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (self->type != PROM_GAUGE) {
+ PROM_LOG(PROM_METRIC_INCORRECT_TYPE);
+ return 1;
+ }
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(self, label_values);
+ if (sample == NULL) return 1;
+ return prom_metric_sample_add(sample, r_value);
+}
+
+int prom_gauge_sub(prom_gauge_t *self, double r_value, const char **label_values) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (self->type != PROM_GAUGE) {
+ PROM_LOG(PROM_METRIC_INCORRECT_TYPE);
+ return 1;
+ }
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(self, label_values);
+ if (sample == NULL) return 1;
+ return prom_metric_sample_sub(sample, r_value);
+}
+
+int prom_gauge_set(prom_gauge_t *self, double r_value, const char **label_values) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (self->type != PROM_GAUGE) {
+ PROM_LOG(PROM_METRIC_INCORRECT_TYPE);
+ return 1;
+ }
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(self, label_values);
+ if (sample == NULL) return 1;
+ return prom_metric_sample_set(sample, r_value);
+}
diff --git a/prom/src/prom_histogram.c b/prom/src/prom_histogram.c
new file mode 100644
index 0000000..8744738
--- /dev/null
+++ b/prom/src/prom_histogram.c
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+// Public
+#include "prom_alloc.h"
+#include "prom_histogram.h"
+#include "prom_histogram_buckets.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_errors.h"
+#include "prom_log.h"
+#include "prom_map_i.h"
+#include "prom_metric_i.h"
+#include "prom_metric_t.h"
+#include "prom_metric_sample_histogram_i.h"
+#include "prom_metric_sample_histogram_t.h"
+
+
+
+prom_histogram_t* prom_histogram_new(const char *name,
+ const char *help,
+ prom_histogram_buckets_t *buckets,
+ size_t label_key_count,
+ const char **label_keys)
+{
+ prom_histogram_t *self = (prom_histogram_t*) prom_metric_new(PROM_HISTOGRAM, name, help, label_key_count, label_keys);
+ if (buckets == NULL) {
+ self->buckets = prom_histogram_default_buckets;
+ } else {
+ // Ensure the bucket values are increasing
+ for (int i = 0; i < buckets->count; i++) {
+ if (i == 0) {
+ continue;
+ }
+ if (buckets->upper_bounds[i-1] > buckets->upper_bounds[i]) {
+ return NULL;
+ }
+ }
+ self->buckets = buckets;
+ }
+ return self;
+}
+
+int prom_histogram_destroy(prom_histogram_t *self) {
+ PROM_ASSERT(self != NULL);
+
+ int r = 0;
+
+ if (self == NULL) return r;
+ r = prom_metric_destroy(self);
+ if (r) return r;
+ self = NULL;
+ return r;
+}
+
+int prom_histogram_observe(prom_histogram_t *self, double value, const char **label_values) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (self->type != PROM_HISTOGRAM) {
+ PROM_LOG(PROM_METRIC_INCORRECT_TYPE);
+ return 1;
+ }
+ prom_metric_sample_histogram_t *h_sample = prom_metric_sample_histogram_from_labels(self, label_values);
+ if (h_sample == NULL) return 1;
+ return prom_metric_sample_histogram_observe(h_sample, value);
+}
diff --git a/prom/src/prom_histogram_buckets.c b/prom/src/prom_histogram_buckets.c
new file mode 100644
index 0000000..ecfd00c
--- /dev/null
+++ b/prom/src/prom_histogram_buckets.c
@@ -0,0 +1,101 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+// Public
+#include "prom_alloc.h"
+#include "prom_histogram_buckets.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_log.h"
+
+prom_histogram_buckets_t* prom_histogram_buckets_new(size_t count, double bucket, ...) {
+ prom_histogram_buckets_t *self = (prom_histogram_buckets_t*) prom_malloc(sizeof(prom_histogram_buckets_t));
+ double *upper_bounds = (double*) prom_malloc(sizeof(double)*count);
+ upper_bounds[0] = bucket;
+ if (count == 1) {
+ self->upper_bounds = upper_bounds;
+ return self;
+ }
+ va_list arg_list;
+ va_start(arg_list, bucket);
+ for (int i = 1; i < count; i++) {
+ upper_bounds[i] = va_arg(arg_list, double);
+ }
+ va_end(arg_list);
+ self->upper_bounds = upper_bounds;
+ return self;
+}
+
+
+prom_histogram_buckets_t* prom_histogram_buckets_linear(double start, double width, size_t count) {
+ if (count <= 1) return NULL;
+
+ prom_histogram_buckets_t *self = (prom_histogram_buckets_t*) prom_malloc(sizeof(prom_histogram_buckets_t));
+
+ double *upper_bounds = (double*) prom_malloc(sizeof(double) * count);
+ upper_bounds[0] = start;
+ for (size_t i = 1; i < count; i++) {
+ upper_bounds[i] = upper_bounds[i-1] + width;
+ }
+ self->upper_bounds = upper_bounds;
+ self->count = count;
+ return self;
+}
+
+prom_histogram_buckets_t* prom_histogram_buckets_exponential(double start, double factor, size_t count) {
+ if (count < 1) {
+ PROM_LOG("count must be less than 1");
+ return NULL;
+ }
+ if (start <= 0) {
+ PROM_LOG("start must be less than or equal to 0");
+ return NULL;
+ }
+ if (factor <= 1) {
+ PROM_LOG("factor must be less than or equal to 1");
+ return NULL;
+ }
+
+ prom_histogram_buckets_t *self = (prom_histogram_buckets_t*) prom_malloc(sizeof(prom_histogram_buckets_t));
+
+ double *upper_bounds = (double*) prom_malloc(sizeof(double) * count);
+ upper_bounds[0] = start;
+ for (size_t i = 1; i < count; i++) {
+ upper_bounds[i] = upper_bounds[i-1] * factor;
+ }
+ self->upper_bounds = upper_bounds;
+ self->count = count;
+ return self;
+}
+
+int prom_histogram_buckets_destroy(prom_histogram_buckets_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+ prom_free((double *) self->upper_bounds);
+ self->upper_bounds = NULL;
+ prom_free(self);
+ self = NULL;
+ return 0;
+}
+
+size_t prom_histogram_buckets_count(prom_histogram_buckets_t *self) {
+ PROM_ASSERT(self != NULL);
+ return self->count;
+} \ No newline at end of file
diff --git a/prom/src/prom_linked_list.c b/prom/src/prom_linked_list.c
new file mode 100644
index 0000000..1dc3cbe
--- /dev/null
+++ b/prom/src/prom_linked_list.c
@@ -0,0 +1,222 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Public
+#include "prom_alloc.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_linked_list_i.h"
+#include "prom_linked_list_t.h"
+#include "prom_log.h"
+
+
+prom_linked_list_t* prom_linked_list_new(void) {
+ prom_linked_list_t *self = (prom_linked_list_t*) prom_malloc(sizeof(prom_linked_list_t));
+ self->head = NULL;
+ self->tail = NULL;
+ self->free_fn = NULL;
+ self->compare_fn = NULL;
+ self->size = 0;
+ return self;
+}
+
+int prom_linked_list_purge(prom_linked_list_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ prom_linked_list_node_t *node = self->head;
+ while (node != NULL) {
+ prom_linked_list_node_t *next = node->next;
+ if (node->item != NULL) {
+ if (self->free_fn) {
+ (*self->free_fn)(node->item);
+ } else {
+ prom_free(node->item);
+ }
+ }
+ prom_free(node);
+ node = NULL;
+ node = next;
+ }
+ self->head = NULL;
+ self->tail = NULL;
+ self->size = 0;
+ return 0;
+}
+
+int prom_linked_list_destroy(prom_linked_list_t *self) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+ int ret = 0;
+
+ r = prom_linked_list_purge(self);
+ if (r) ret = r;
+ prom_free(self);
+ self = NULL;
+ return ret;
+}
+
+void *prom_linked_list_first(prom_linked_list_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self->head) {
+ return self->head->item;
+ } else {
+ return NULL;
+ }
+}
+
+void *prom_linked_list_last(prom_linked_list_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self->tail) {
+ return self->tail->item;
+ } else {
+ return NULL;
+ }
+}
+
+int prom_linked_list_append(prom_linked_list_t *self, void *item){
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ prom_linked_list_node_t *node = (prom_linked_list_node_t *) prom_malloc(sizeof(prom_linked_list_node_t));
+
+ node->item = item;
+ if (self->tail) {
+ self->tail->next = node;
+ } else {
+ self->head = node;
+ }
+ self->tail = node;
+ node->next = NULL;
+ self->size++;
+ return 0;
+}
+
+int prom_linked_list_push(prom_linked_list_t *self, void *item){
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ prom_linked_list_node_t *node = (prom_linked_list_node_t *) prom_malloc(sizeof(prom_linked_list_node_t));
+
+ node->item = item;
+ node->next = self->head;
+ self->head = node;
+ if (self->tail == NULL) {
+ self->tail = node;
+ }
+ self->size++;
+ return 0;
+}
+
+void *prom_linked_list_pop(prom_linked_list_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return NULL;
+ prom_linked_list_node_t *node = self->head;
+ void* item = NULL;
+ if (node != NULL){
+ item = node->item;
+ self->head = node->next;
+ if (self->tail == node) {
+ self->tail = NULL;
+ }
+ if (node->item != NULL){
+ if (self->free_fn){
+ (*self->free_fn)(node->item);
+ } else {
+ prom_free(node->item);
+ }
+ }
+ node->item = NULL;
+ node = NULL;
+ self->size--;
+ }
+ return item;
+}
+
+int prom_linked_list_remove(prom_linked_list_t *self, void* item) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ prom_linked_list_node_t *node;
+ prom_linked_list_node_t *prev_node = NULL;
+
+ // Locate the node
+ for (node = self->head; node != NULL; node = node->next) {
+ if (self->compare_fn) {
+ if ((*self->compare_fn)(node->item, item) == PROM_EQUAL) {
+ break;
+ }
+ } else {
+ if (node->item == item) {
+ break;
+ }
+ }
+ prev_node = node;
+ }
+
+ if (node == NULL) return 0;
+
+ if (prev_node) {
+ prev_node->next = node->next;
+ } else {
+ self->head = node->next;
+ }
+ if (node->next == NULL) {
+ self->tail = prev_node;
+ }
+
+ if (node->item != NULL) {
+ if (self->free_fn) {
+ (*self->free_fn)(node->item);
+ } else {
+ prom_free(node->item);
+ }
+ }
+
+ node->item = NULL;
+ prom_free(node);
+ node = NULL;
+ self->size--;
+ return 0;
+}
+
+prom_linked_list_compare_t prom_linked_list_compare(prom_linked_list_t *self, void *item_a, void *item_b) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (self->compare_fn) {
+ return (*self->compare_fn)(item_a, item_b);
+ } else {
+ return strcmp(item_a, item_b);
+ }
+}
+
+size_t prom_linked_list_size(prom_linked_list_t *self) {
+ PROM_ASSERT(self != NULL);
+ return self->size;
+}
+
+int prom_linked_list_set_free_fn(prom_linked_list_t *self, prom_linked_list_free_item_fn free_fn) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ self->free_fn = free_fn;
+ return 0;
+}
+
+int prom_linked_list_set_compare_fn(prom_linked_list_t *self, prom_linked_list_compare_item_fn compare_fn) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ self->compare_fn = compare_fn;
+ return 0;
+}
+
+void prom_linked_list_no_op_free(void *item) { }
diff --git a/prom/src/prom_linked_list_i.h b/prom/src/prom_linked_list_i.h
new file mode 100644
index 0000000..fc73f70
--- /dev/null
+++ b/prom/src/prom_linked_list_i.h
@@ -0,0 +1,96 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef PROM_LIST_I_INCLUDED
+#define PROM_LIST_I_INCLUDED
+
+// Private
+#include "prom_linked_list_t.h"
+
+
+/**
+ * @brief API PRIVATE Returns a pointer to a prom_linked_list
+ */
+prom_linked_list_t *prom_linked_list_new(void);
+
+/**
+ * @brief API PRIVATE removes all nodes from the given prom_linked_list *
+ */
+int prom_linked_list_purge(prom_linked_list_t *self);
+
+/**
+ * @brief API PRIVATE Destroys a prom_linked_list
+ */
+int prom_linked_list_destroy(prom_linked_list_t *self);
+
+/**
+ * @brief API PRIVATE Append an item to the back of the list
+ */
+int prom_linked_list_append(prom_linked_list_t *self, void* item);
+
+/**
+ * @brief API PRIVATE Push an item onto the front of the list
+ */
+int prom_linked_list_push(prom_linked_list_t *self, void* item);
+
+/**
+ * @brief API PRIVATE Pop the first item off of the list
+ */
+void *prom_linked_list_pop(prom_linked_list_t *self);
+
+/**
+ * @brief API PRIVATE Returns the item at the head of the list or NULL if not present
+ */
+void *prom_linked_list_first(prom_linked_list_t *self);
+
+/**
+ * @brief API PRIVATE Returns the item at the tail of the list or NULL if not present
+ */
+void *prom_linked_list_last(prom_linked_list_t *self);
+
+/**
+ * @brief API PRIVATE Removes an item from the linked list
+ */
+int prom_linked_list_remove(prom_linked_list_t *self, void *item);
+
+/**
+ * @brief API PRIVATE Compares two items within a linked list
+ */
+prom_linked_list_compare_t prom_linked_list_compare(prom_linked_list_t *self, void *item_a, void *node_b);
+
+/**
+ * @brief API PRIVATE Get the size
+ */
+size_t prom_linked_list_size(prom_linked_list_t *self);
+
+/**
+ * @brief API PRIVATE Set the free_fn member on prom_linked_list
+ */
+int prom_linked_list_set_free_fn(prom_linked_list_t *self, prom_linked_list_free_item_fn free_fn);
+
+/**
+ * @brief API PRIVATE Set the compare_fn member on the prom_linked_list
+ */
+int prom_linked_list_set_compare_fn(prom_linked_list_t *self, prom_linked_list_compare_item_fn compare_fn);
+
+/**
+ * API PRIVATE
+ * @brief does nothing
+ */
+void prom_linked_list_no_op_free(void *item);
+
+#endif // PROM_LIST_I_INCLUDED
diff --git a/prom/src/prom_linked_list_t.h b/prom/src/prom_linked_list_t.h
new file mode 100644
index 0000000..b8851f4
--- /dev/null
+++ b/prom/src/prom_linked_list_t.h
@@ -0,0 +1,60 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef PROM_LIST_T_H
+#define PROM_LIST_T_H
+
+#include "prom_linked_list.h"
+
+typedef enum {
+ PROM_LESS = -1,
+ PROM_EQUAL = 0,
+ PROM_GREATER = 1
+} prom_linked_list_compare_t;
+
+/**
+ * @brief API PRIVATE Frees an item in a prom_linked_list_node
+ */
+typedef void (*prom_linked_list_free_item_fn)(void*);
+
+/**
+ * @brief API PRIVATE Compares two items within a prom_linked_list
+ */
+typedef prom_linked_list_compare_t (*prom_linked_list_compare_item_fn)(void *item_a, void *item_b);
+
+/**
+ * @brief API PRIVATE A struct containing a generic item, represented as a void pointer, and next, a pointer to the
+ * next prom_linked_list_node*
+ */
+typedef struct prom_linked_list_node {
+ struct prom_linked_list_node* next;
+ void *item;
+} prom_linked_list_node_t;
+
+/**
+ * @brief API PRIVATE A linked list comprised of prom_linked_list_node* instances
+ */
+struct prom_linked_list {
+ prom_linked_list_node_t *head;
+ prom_linked_list_node_t *tail;
+ size_t size;
+ prom_linked_list_free_item_fn free_fn;
+ prom_linked_list_compare_item_fn compare_fn;
+};
+
+#endif // PROM_LIST_T_H
+
diff --git a/prom/src/prom_log.h b/prom/src/prom_log.h
new file mode 100644
index 0000000..5077e89
--- /dev/null
+++ b/prom/src/prom_log.h
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#ifndef PROM_LOG_H
+#define PROM_LOG_H
+
+#ifdef PROM_LOG_ENABLE
+ #define PROM_LOG(msg) printf("%s %s %s %s %d %s\n", __DATE__, __TIME__, __FILE__, __FUNCTION__, __LINE__, msg);
+#else
+ #define PROM_LOG(msg)
+#endif // PROM_LOG_ENABLE
+
+#endif // PROM_LOG_H
diff --git a/prom/src/prom_map.c b/prom/src/prom_map.c
new file mode 100644
index 0000000..a36cad7
--- /dev/null
+++ b/prom/src/prom_map.c
@@ -0,0 +1,473 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pthread.h>
+#include <stdbool.h>
+
+// Public
+#include "prom_alloc.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_errors.h"
+#include "prom_log.h"
+#include "prom_map_i.h"
+#include "prom_map_t.h"
+#include "prom_linked_list_i.h"
+#include "prom_linked_list_t.h"
+
+#define PROM_MAP_INITIAL_SIZE 32
+
+static void destroy_map_node_value_no_op(void* value) {}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// prom_map_node
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+prom_map_node_t* prom_map_node_new(const char *key, void *value, prom_map_node_free_value_fn free_value_fn) {
+ prom_map_node_t *self = prom_malloc(sizeof(prom_map_node_t));
+ self->key = prom_strdup(key);
+ self->value = value;
+ self->free_value_fn = free_value_fn;
+ return self;
+}
+
+int prom_map_node_destroy(prom_map_node_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+ prom_free((void*) self->key);
+ self->key = NULL;
+ if (self->value != NULL) (*self->free_value_fn)(self->value);
+ self->value = NULL;
+ prom_free(self);
+ self = NULL;
+ return 0;
+}
+
+void prom_map_node_free(void *item) {
+ prom_map_node_t *map_node = (prom_map_node_t*) item;
+ prom_map_node_destroy(map_node);
+}
+
+prom_linked_list_compare_t prom_map_node_compare(void *item_a, void *item_b) {
+ prom_map_node_t *map_node_a = (prom_map_node_t *) item_a;
+ prom_map_node_t *map_node_b = (prom_map_node_t *) item_b;
+
+ return strcmp(map_node_a->key, map_node_b->key);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// prom_map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+prom_map_t* prom_map_new() {
+ int r = 0;
+
+ prom_map_t *self = (prom_map_t*) prom_malloc(sizeof(prom_map_t));
+ self->size = 0;
+ self->max_size = PROM_MAP_INITIAL_SIZE;
+
+ self->keys = prom_linked_list_new();
+ if (self->keys == NULL) return NULL;
+
+ // These each key will be allocated once by prom_map_node_new and used here as well to save memory. With that said
+ // we will only have to deallocate each key once. That will happen on prom_map_node_destroy.
+ r = prom_linked_list_set_free_fn(self->keys, prom_linked_list_no_op_free);
+ if (r) {
+ prom_map_destroy(self);
+ return NULL;
+ }
+
+ self->addrs = prom_malloc(sizeof(prom_linked_list_t) * self->max_size);
+ self->free_value_fn = destroy_map_node_value_no_op;
+
+ for (int i = 0; i < self->max_size; i++) {
+ self->addrs[i] = prom_linked_list_new();
+ r = prom_linked_list_set_free_fn(self->addrs[i], prom_map_node_free);
+ if (r) {
+ prom_map_destroy(self);
+ return NULL;
+ }
+ r = prom_linked_list_set_compare_fn(self->addrs[i], prom_map_node_compare);
+ if (r) {
+ prom_map_destroy(self);
+ return NULL;
+ }
+ }
+
+ self->rwlock = (pthread_rwlock_t *) prom_malloc(sizeof(pthread_rwlock_t));
+ r = pthread_rwlock_init(self->rwlock, NULL);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_INIT_ERROR);
+ prom_map_destroy(self);
+ return NULL;
+ }
+
+ return self;
+}
+
+int prom_map_destroy(prom_map_t *self) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+ int ret = 0;
+
+ r = prom_linked_list_destroy(self->keys);
+ if (r) ret = r;
+ self->keys = NULL;
+
+ for (size_t i = 0; i < self->max_size; i++) {
+ r = prom_linked_list_destroy(self->addrs[i]);
+ if (r) ret = r;
+ self->addrs[i] = NULL;
+ }
+ prom_free(self->addrs);
+ self->addrs = NULL;
+
+ r = pthread_rwlock_unlock(self->rwlock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR);
+ ret = r;
+ }
+
+ r = pthread_rwlock_destroy(self->rwlock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_DESTROY_ERROR)
+ ret = r;
+ }
+
+ prom_free(self->rwlock);
+ self->rwlock = NULL;
+ prom_free(self);
+ self = NULL;
+
+ return ret;
+}
+
+static size_t prom_map_get_index_internal(const char *key, size_t *size, size_t *max_size) {
+ size_t index;
+ size_t a = 31415, b = 27183;
+ for (index = 0; *key != '\0'; key++, a = a*b % (*max_size - 1)) {
+ index = (a * index + *key) % *max_size;
+ }
+ return index;
+}
+
+/**
+ * @brief API PRIVATE hash function that returns an array index from the given key and prom_map.
+ *
+ * The algorithm is based off of Horner's method. In a simpler version, you set the return value to 0. Next, for each
+ * character in the string, you add the integer value of the current character to the product of the prime number and
+ * the current return value, set the result to the return value, then finally return the return value.
+ *
+ * In this version of the algorithm, we attempt to achieve a probabily of key to index conversion collisions to
+ * 1/M (with M being the max_size of the map). This optimizes dispersion and consequently, evens out the performance
+ * for gets and sets for each item. Instead of using a fixed prime number, we generate a coefficient for each iteration
+ * through the loop.
+ *
+ * Reference:
+ * * Algorithms in C: Third Edition by Robert Sedgewick, p579
+ */
+size_t prom_map_get_index(prom_map_t *self, const char *key) {
+ return prom_map_get_index_internal(key, &self->size, &self->max_size);
+}
+
+
+static void* prom_map_get_internal(const char *key,
+ size_t *size,
+ size_t *max_size,
+ prom_linked_list_t *keys,
+ prom_linked_list_t **addrs,
+ prom_map_node_free_value_fn free_value_fn)
+{
+ size_t index = prom_map_get_index_internal(key, size, max_size);
+ prom_linked_list_t *list = addrs[index];
+ prom_map_node_t *temp_map_node = prom_map_node_new(key, NULL, free_value_fn);
+
+ for (
+ prom_linked_list_node_t *current_node = list->head;
+ current_node != NULL;
+ current_node = current_node->next
+ ) {
+ prom_map_node_t *current_map_node = (prom_map_node_t*) current_node->item;
+ prom_linked_list_compare_t result = prom_linked_list_compare(list, current_map_node, temp_map_node);
+ if (result == PROM_EQUAL) {
+ prom_map_node_destroy(temp_map_node);
+ temp_map_node = NULL;
+ return current_map_node->value;
+ }
+ }
+ prom_map_node_destroy(temp_map_node);
+ temp_map_node = NULL;
+ return NULL;
+}
+
+void* prom_map_get(prom_map_t *self, const char *key) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+ r = pthread_rwlock_wrlock(self->rwlock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_LOCK_ERROR);
+ NULL;
+ }
+ void *payload = prom_map_get_internal(
+ key,
+ &self->size,
+ &self->max_size,
+ self->keys,
+ self->addrs,
+ self->free_value_fn
+ );
+ r = pthread_rwlock_unlock(self->rwlock);
+ if (r){
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR);
+ return NULL;
+ }
+ return payload;
+}
+
+static int prom_map_set_internal(const char *key,
+ void *value,
+ size_t *size,
+ size_t *max_size,
+ prom_linked_list_t *keys,
+ prom_linked_list_t **addrs,
+ prom_map_node_free_value_fn free_value_fn,
+ bool destroy_current_value)
+{
+ prom_map_node_t *map_node = prom_map_node_new(key, value, free_value_fn);
+ if (map_node == NULL) return 1;
+
+ size_t index = prom_map_get_index_internal(key, size, max_size);
+ prom_linked_list_t *list = addrs[index];
+ for (
+ prom_linked_list_node_t *current_node = list->head;
+ current_node != NULL;
+ current_node = current_node->next
+ ) {
+ prom_map_node_t *current_map_node = (prom_map_node_t*) current_node->item;
+ prom_linked_list_compare_t result = prom_linked_list_compare(list, current_map_node, map_node);
+ if (result == PROM_EQUAL) {
+ if (destroy_current_value) {
+ free_value_fn(current_map_node->value);
+ current_map_node->value = NULL;
+ }
+ prom_free((char *) current_map_node->key);
+ current_map_node->key = NULL;
+ prom_free(current_map_node);
+ current_map_node = NULL;
+ current_node->item = map_node;
+ return 0;
+ }
+ }
+ prom_linked_list_append(list, map_node);
+ prom_linked_list_append(keys, (char *) map_node->key);
+ (*size)++;
+ return 0;
+}
+
+int prom_map_ensure_space(prom_map_t *self) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+
+ if (self->size <= self->max_size / 2) {
+ return 0;
+ }
+
+ // Increase the max size
+ size_t new_max = self->max_size * 2;
+ size_t new_size = 0;
+
+ // Create a new list of keys
+ prom_linked_list_t *new_keys = prom_linked_list_new();
+ if (new_keys == NULL) return 1;
+
+ r = prom_linked_list_set_free_fn(new_keys, prom_linked_list_no_op_free);
+ if (r) return r;
+
+ // Create a new array of addrs
+ prom_linked_list_t **new_addrs = prom_malloc(sizeof(prom_linked_list_t) * new_max);
+
+ // Initialize the new array
+ for (int i = 0; i < new_max; i++) {
+ new_addrs[i] = prom_linked_list_new();
+ r = prom_linked_list_set_free_fn(new_addrs[i], prom_map_node_free);
+ if (r) return r;
+ r = prom_linked_list_set_compare_fn(new_addrs[i], prom_map_node_compare);
+ if (r) return r;
+ }
+
+ // Iterate through each linked-list at each memory region in the map's backbone
+ for (int i = 0; i < self->max_size; i++) {
+ // Create a new map node for each node in the linked list and insert it into the new map. Afterwards, deallocate
+ // the old map node
+ prom_linked_list_t *list = self->addrs[i];
+ prom_linked_list_node_t *current_node = list->head;
+ while (current_node != NULL) {
+ prom_map_node_t *map_node = (prom_map_node_t*) current_node->item;
+ r = prom_map_set_internal(
+ map_node->key,
+ map_node->value,
+ &new_size,
+ &new_max,
+ new_keys,
+ new_addrs,
+ self->free_value_fn,
+ false
+ );
+ if (r) return r;
+
+ prom_linked_list_node_t *next = current_node->next;
+ prom_free(current_node);
+ current_node = NULL;
+ prom_free((void *) map_node->key);
+ map_node->key = NULL;
+ prom_free(map_node);
+ map_node = NULL;
+ current_node = next;
+ }
+ // We're done deallocating each map node in the linked list, so deallocate the linked-list object
+ prom_free(self->addrs[i]);
+ self->addrs[i] = NULL;
+ }
+ // Destroy the collection of keys in the map
+ prom_linked_list_destroy(self->keys);
+ self->keys = NULL;
+
+ // Deallocate the backbone of the map
+ prom_free(self->addrs);
+ self->addrs = NULL;
+
+ // Update the members of the current map
+ self->size = new_size;
+ self->max_size = new_max;
+ self->keys = new_keys;
+ self->addrs = new_addrs;
+
+ return 0;
+}
+
+int prom_map_set(prom_map_t *self, const char *key, void *value) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+ r = pthread_rwlock_wrlock(self->rwlock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_LOCK_ERROR);
+ return r;
+ }
+
+ r = prom_map_ensure_space(self);
+ if (r) {
+ int rr = 0;
+ rr = pthread_rwlock_unlock(self->rwlock);
+ if (rr) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR);
+ return rr;
+ } else {
+ return r;
+ }
+ }
+ r = prom_map_set_internal(
+ key,
+ value,
+ &self->size,
+ &self->max_size,
+ self->keys,
+ self->addrs,
+ self->free_value_fn,
+ true
+ );
+ if (r) {
+ int rr = 0;
+ rr = pthread_rwlock_unlock(self->rwlock);
+ if (rr) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR);
+ return rr;
+ } else {
+ return r;
+ }
+ }
+ r = pthread_rwlock_unlock(self->rwlock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR);
+ }
+ return r;
+}
+
+static int prom_map_delete_internal(const char *key,
+ size_t *size,
+ size_t *max_size,
+ prom_linked_list_t *keys,
+ prom_linked_list_t **addrs,
+ prom_map_node_free_value_fn free_value_fn)
+{
+ int r = 0;
+ size_t index = prom_map_get_index_internal(key, size, max_size);
+ prom_linked_list_t *list = addrs[index];
+ prom_map_node_t *temp_map_node = prom_map_node_new(key, NULL, free_value_fn);
+
+ for (
+ prom_linked_list_node_t *current_node = list->head;
+ current_node != NULL;
+ current_node = current_node->next
+ ) {
+ prom_map_node_t *current_map_node = (prom_map_node_t*) current_node->item;
+ prom_linked_list_compare_t result = prom_linked_list_compare(list, current_map_node, temp_map_node);
+ if (result == PROM_EQUAL) {
+ r = prom_linked_list_remove(list, current_node);
+ if (r) return r;
+
+ r = prom_linked_list_remove(keys, (char *) current_map_node->key);
+ if (r) return r;
+
+ (*size)--;
+ break;
+ }
+ }
+ r = prom_map_node_destroy(temp_map_node);
+ temp_map_node = NULL;
+ return r;
+}
+
+int prom_map_delete(prom_map_t *self, const char *key) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+ int ret = 0;
+ r = pthread_rwlock_wrlock(self->rwlock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_LOCK_ERROR);
+ ret = r;
+ }
+ r = prom_map_delete_internal(key, &self->size, &self->max_size, self->keys, self->addrs, self->free_value_fn);
+ if (r) ret = r;
+ r = pthread_rwlock_unlock(self->rwlock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR);
+ ret = r;
+ }
+ return ret;
+}
+
+int prom_map_set_free_value_fn(prom_map_t *self, prom_map_node_free_value_fn free_value_fn) {
+ PROM_ASSERT(self != NULL);
+ self->free_value_fn = free_value_fn;
+ return 0;
+}
+
+size_t prom_map_size(prom_map_t *self) {
+ PROM_ASSERT(self != NULL);
+ return self->size;
+}
+
diff --git a/prom/src/prom_map_i.h b/prom/src/prom_map_i.h
new file mode 100644
index 0000000..09c26dc
--- /dev/null
+++ b/prom/src/prom_map_i.h
@@ -0,0 +1,40 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+#ifndef PROM_MAP_I_INCLUDED
+#define PROM_MAP_I_INCLUDED
+
+#include "prom_map_t.h"
+
+prom_map_t* prom_map_new(void);
+
+int prom_map_set_free_value_fn(prom_map_t *self, prom_map_node_free_value_fn free_value_fn);
+
+void* prom_map_get(prom_map_t *self, const char *key);
+
+int prom_map_set(prom_map_t *self, const char *key, void *value);
+
+int prom_map_delete(prom_map_t *self, const char *key);
+
+int prom_map_destroy(prom_map_t *self);
+
+size_t prom_map_size(prom_map_t *self);
+
+prom_map_node_t* prom_map_node_new(const char *key, void *value, prom_map_node_free_value_fn free_value_fn);
+
+#endif // PROM_MAP_I_INCLUDED \ No newline at end of file
diff --git a/prom/src/prom_map_t.h b/prom/src/prom_map_t.h
new file mode 100644
index 0000000..544bc13
--- /dev/null
+++ b/prom/src/prom_map_t.h
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+#ifndef PROM_MAP_T_H
+#define PROM_MAP_T_H
+
+#include <pthread.h>
+
+// Public
+#include "prom_map.h"
+
+// Private
+#include "prom_linked_list_t.h"
+
+typedef void (*prom_map_node_free_value_fn)(void*);
+
+struct prom_map_node {
+ const char *key;
+ void *value;
+ prom_map_node_free_value_fn free_value_fn;
+};
+
+struct prom_map {
+ size_t size; /**< contains the size of the map */
+ size_t max_size; /**< stores the current max_size */
+ prom_linked_list_t *keys; /**< linked list containing containing all keys present */
+ prom_linked_list_t **addrs; /**< Sequence of linked lists. Each list contains nodes with the same index */
+ pthread_rwlock_t *rwlock;
+ prom_map_node_free_value_fn free_value_fn;
+};
+
+
+#endif // PROM_MAP_T_H \ No newline at end of file
diff --git a/prom/src/prom_metric.c b/prom/src/prom_metric.c
new file mode 100644
index 0000000..cbfab34
--- /dev/null
+++ b/prom/src/prom_metric.c
@@ -0,0 +1,268 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pthread.h>
+
+// Public
+#include "prom_alloc.h"
+#include "prom_histogram_buckets.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_errors.h"
+#include "prom_log.h"
+#include "prom_map_i.h"
+#include "prom_metric_i.h"
+#include "prom_metric_formatter_i.h"
+#include "prom_metric_sample_i.h"
+#include "prom_metric_sample_histogram_i.h"
+
+char *prom_metric_type_map[4] = {
+ "counter",
+ "gauge",
+ "histogram",
+ "summary"
+};
+
+prom_metric_t* prom_metric_new(prom_metric_type_t metric_type,
+ const char *name,
+ const char *help,
+ size_t label_key_count,
+ const char **label_keys)
+{
+ int r = 0;
+ prom_metric_t *self = (prom_metric_t *) prom_malloc(sizeof(prom_metric_t));
+ self->type = metric_type;
+ self->name = name;
+ self->help = help;
+ self->buckets = NULL;
+
+ const char **k = (const char **) prom_malloc(sizeof(const char *) * label_key_count);
+
+ for (int i = 0; i < label_key_count; i++) {
+ if (strcmp(label_keys[i], "le") == 0) {
+ PROM_LOG(PROM_METRIC_INVALID_LABEL_NAME);
+ prom_metric_destroy(self);
+ return NULL;
+ }
+ if (strcmp(label_keys[i], "quantile") == 0) {
+ PROM_LOG(PROM_METRIC_INVALID_LABEL_NAME);
+ prom_metric_destroy(self);
+ return NULL;
+ }
+ k[i] = prom_strdup(label_keys[i]);
+ }
+ self->label_keys = k;
+ self->label_key_count = label_key_count;
+ self->samples = prom_map_new();
+
+ if (metric_type == PROM_HISTOGRAM) {
+ r = prom_map_set_free_value_fn(self->samples, &prom_metric_sample_histogram_free_generic);
+ if (r) {
+ prom_metric_destroy(self);
+ return NULL;
+ }
+ } else {
+ r = prom_map_set_free_value_fn(self->samples, &prom_metric_sample_free_generic);
+ if (r) {
+ prom_metric_destroy(self);
+ return NULL;
+ }
+ }
+
+ self->formatter = prom_metric_formatter_new();
+ if (self->formatter == NULL) {
+ prom_metric_destroy(self);
+ return NULL;
+ }
+ self->rwlock = (pthread_rwlock_t*) prom_malloc(sizeof(pthread_rwlock_t));
+ r = pthread_rwlock_init(self->rwlock, NULL);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_INIT_ERROR);
+ return NULL;
+ }
+ return self;
+}
+
+int prom_metric_destroy(prom_metric_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+
+ int r = 0;
+ int ret = 0;
+
+ if (self->buckets != NULL) {
+ r = prom_histogram_buckets_destroy(self->buckets);
+ self->buckets = NULL;
+ if (r) ret = r;
+ }
+
+
+ r = prom_map_destroy(self->samples);
+ self->samples = NULL;
+ if (r) ret = r;
+
+ r = prom_metric_formatter_destroy(self->formatter);
+ self->formatter = NULL;
+ if (r) ret = r;
+
+ r = pthread_rwlock_unlock(self->rwlock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR);
+ ret = r;
+ }
+
+ r = pthread_rwlock_destroy(self->rwlock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_DESTROY_ERROR);
+ ret = r;
+ }
+
+ prom_free(self->rwlock);
+ self->rwlock = NULL;
+
+ for (int i = 0; i < self->label_key_count; i++) {
+ prom_free((void *) self->label_keys[i]);
+ self->label_keys[i] = NULL;
+ }
+ prom_free(self->label_keys);
+ self->label_keys = NULL;
+
+ prom_free(self);
+ self = NULL;
+
+ return ret;
+}
+
+int prom_metric_destroy_generic(void *item) {
+ int r = 0;
+ prom_metric_t *self = (prom_metric_t *) item;
+ r = prom_metric_destroy(self);
+ self = NULL;
+ return r;
+}
+
+void prom_metric_free_generic(void *item) {
+ prom_metric_t *self = (prom_metric_t *) item;
+ prom_metric_destroy(self);
+}
+
+prom_metric_sample_t* prom_metric_sample_from_labels(prom_metric_t *self, const char **label_values) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+ r = pthread_rwlock_wrlock(self->rwlock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_LOCK_ERROR);
+ return NULL;
+ }
+
+ #define PROM_METRIC_SAMPLE_FROM_LABELS_HANDLE_UNLOCK() \
+ r = pthread_rwlock_unlock(self->rwlock); \
+ if (r) PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR); \
+ return NULL;
+
+
+ // Get l_value
+ r = prom_metric_formatter_load_l_value(
+ self->formatter,
+ self->name,
+ NULL,
+ self->label_key_count,
+ self->label_keys,
+ label_values
+ );
+ if (r) {
+ PROM_METRIC_SAMPLE_FROM_LABELS_HANDLE_UNLOCK();
+ }
+
+ // This must be freed before returning
+ const char *l_value = prom_metric_formatter_dump(self->formatter);
+ if (l_value == NULL) {
+ PROM_METRIC_SAMPLE_FROM_LABELS_HANDLE_UNLOCK();
+ }
+
+ // Get sample
+ prom_metric_sample_t *sample = (prom_metric_sample_t*) prom_map_get(self->samples, l_value);
+ if (sample == NULL) {
+ sample = prom_metric_sample_new(self->type, l_value, 0.0);
+ r = prom_map_set(self->samples, l_value, sample);
+ if (r) {
+ PROM_METRIC_SAMPLE_FROM_LABELS_HANDLE_UNLOCK();
+ }
+ }
+ pthread_rwlock_unlock(self->rwlock);
+ prom_free((void *) l_value);
+ return sample;
+}
+
+prom_metric_sample_histogram_t* prom_metric_sample_histogram_from_labels(prom_metric_t *self, const char **label_values)
+{
+ PROM_ASSERT(self != NULL);
+
+ int r = 0;
+ r = pthread_rwlock_wrlock(self->rwlock);
+ if (r) {
+ PROM_LOG(PROM_PTHREAD_RWLOCK_LOCK_ERROR);
+ return NULL;
+ }
+
+ #define PROM_METRIC_SAMPLE_HISTOGRAM_FROM_LABELS_HANDLE_UNLOCK() \
+ r = pthread_rwlock_unlock(self->rwlock); \
+ if (r) { \
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR); \
+ return NULL; \
+ }
+
+ // Load the l_value
+ r = prom_metric_formatter_load_l_value(
+ self->formatter,
+ self->name,
+ NULL,
+ self->label_key_count,
+ self->label_keys,
+ label_values
+ );
+ if (r) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_FROM_LABELS_HANDLE_UNLOCK();
+ }
+
+ // This must be freed before returning
+ const char *l_value = prom_metric_formatter_dump(self->formatter);
+ if (l_value == NULL) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_FROM_LABELS_HANDLE_UNLOCK();
+ }
+
+ // Get sample
+ prom_metric_sample_histogram_t *sample = (prom_metric_sample_histogram_t*) prom_map_get(self->samples, l_value);
+ if (sample == NULL) {
+ sample = prom_metric_sample_histogram_new(
+ self->name, self->buckets, self->label_key_count, self->label_keys, label_values
+ );
+ if (sample == NULL) {
+ prom_free((void *) l_value);
+ PROM_METRIC_SAMPLE_HISTOGRAM_FROM_LABELS_HANDLE_UNLOCK();
+ }
+ r = prom_map_set(self->samples, l_value, sample);
+ if (r) {
+ prom_free((void *) l_value);
+ pthread_rwlock_unlock(self->rwlock);
+ PROM_METRIC_SAMPLE_HISTOGRAM_FROM_LABELS_HANDLE_UNLOCK();
+ }
+ }
+ pthread_rwlock_unlock(self->rwlock);
+ prom_free((void *) l_value);
+ return sample;
+}
diff --git a/prom/src/prom_metric_formatter.c b/prom/src/prom_metric_formatter.c
new file mode 100644
index 0000000..4858943
--- /dev/null
+++ b/prom/src/prom_metric_formatter.c
@@ -0,0 +1,281 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+// Public
+#include "prom_alloc.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_collector_t.h"
+#include "prom_metric_t.h"
+#include "prom_linked_list_t.h"
+#include "prom_metric_sample_t.h"
+#include "prom_metric_sample_histogram_t.h"
+
+#include "prom_metric_formatter_i.h"
+#include "prom_string_builder_i.h"
+#include "prom_map_i.h"
+
+
+prom_metric_formatter_t* prom_metric_formatter_new() {
+ prom_metric_formatter_t *self = (prom_metric_formatter_t*) prom_malloc(sizeof(prom_metric_formatter_t));
+ self->string_builder = prom_string_builder_new();
+ if (self->string_builder == NULL) {
+ prom_metric_formatter_destroy(self);
+ return NULL;
+ }
+ self->err_builder = prom_string_builder_new();
+ if (self->err_builder == NULL) {
+ prom_metric_formatter_destroy(self);
+ return NULL;
+ }
+ return self;
+}
+
+int prom_metric_formatter_destroy(prom_metric_formatter_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+
+ int r = 0;
+ int ret = 0;
+
+ r = prom_string_builder_destroy(self->string_builder);
+ self->string_builder = NULL;
+ if (r) ret = r;
+
+ r = prom_string_builder_destroy(self->err_builder);
+ self->err_builder = NULL;
+ if (r) ret = r;
+
+ prom_free(self);
+ self = NULL;
+ return ret;
+}
+
+int prom_metric_formatter_load_help(prom_metric_formatter_t* self, const char *name, const char *help) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+
+ int r = 0;
+
+ r = prom_string_builder_add_str(self->string_builder, "# HELP ");
+ if (r) return r;
+
+ r = prom_string_builder_add_str(self->string_builder, name);
+ if (r) return r;
+
+ r = prom_string_builder_add_char(self->string_builder, ' ');
+ if (r) return r;
+
+ r = prom_string_builder_add_str(self->string_builder, help);
+ if (r) return r;
+
+ return prom_string_builder_add_char(self->string_builder, '\n');
+}
+
+int prom_metric_formatter_load_type(prom_metric_formatter_t* self, const char *name, prom_metric_type_t metric_type) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+
+ int r = 0;
+
+ r = prom_string_builder_add_str(self->string_builder, "# TYPE ");
+ if (r) return r;
+
+ r = prom_string_builder_add_str(self->string_builder, name);
+ if (r) return r;
+
+ r = prom_string_builder_add_char(self->string_builder, ' ');
+ if (r) return r;
+
+ r = prom_string_builder_add_str(self->string_builder, prom_metric_type_map[metric_type]);
+ if (r) return r;
+
+ return prom_string_builder_add_char(self->string_builder, '\n');
+}
+
+int prom_metric_formatter_load_l_value(prom_metric_formatter_t* self,
+ const char *name,
+ const char *suffix,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values)
+{
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+
+ int r = 0;
+
+ r = prom_string_builder_add_str(self->string_builder, name);
+ if (r) return r;
+
+ if (suffix != NULL) {
+ r = prom_string_builder_add_char(self->string_builder, '_');
+ if (r) return r;
+
+ r = prom_string_builder_add_str(self->string_builder, suffix);
+ if (r) return r;
+ }
+
+ if (label_count == 0) return 0;
+
+ for (int i = 0; i < label_count; i++) {
+ if (i == 0) {
+ r = prom_string_builder_add_char(self->string_builder, '{');
+ if (r) return r;
+ }
+ r = prom_string_builder_add_str(self->string_builder, (const char *) label_keys[i]);
+ if (r) return r;
+
+ r = prom_string_builder_add_char(self->string_builder, '=');
+ if (r) return r;
+
+ r = prom_string_builder_add_char(self->string_builder, '"');
+ if (r) return r;
+
+ r = prom_string_builder_add_str(self->string_builder, (const char *) label_values[i]);
+ if (r) return r;
+
+ r = prom_string_builder_add_char(self->string_builder, '"');
+ if (r) return r;
+
+ if (i == label_count-1) {
+ r = prom_string_builder_add_char(self->string_builder, '}');
+ if (r) return r;
+ } else {
+ r = prom_string_builder_add_char(self->string_builder, ',');
+ if (r) return r;
+ }
+ }
+ return 0;
+}
+
+int prom_metric_formatter_load_sample(prom_metric_formatter_t *self, prom_metric_sample_t *sample){
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+
+ int r = 0;
+
+ r = prom_string_builder_add_str(self->string_builder, sample->l_value);
+ if (r) return r;
+
+ r = prom_string_builder_add_char(self->string_builder, ' ');
+ if (r) return r;
+
+ char buffer[50];
+ sprintf(buffer, "%f", sample->r_value);
+ r = prom_string_builder_add_str(self->string_builder, buffer);
+ if (r) return r;
+
+ return prom_string_builder_add_char(self->string_builder, '\n');
+}
+
+int prom_metric_formatter_clear(prom_metric_formatter_t *self) {
+ PROM_ASSERT(self != NULL);
+ return prom_string_builder_clear(self->string_builder);
+}
+
+char* prom_metric_formatter_dump(prom_metric_formatter_t *self) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+ if (self == NULL) return NULL;
+ char *data = prom_string_builder_dump(self->string_builder);
+ if (data == NULL) return NULL;
+ r = prom_string_builder_clear(self->string_builder);
+ if (r) {
+ prom_free(data);
+ return NULL;
+ }
+ return data;
+}
+
+int prom_metric_formatter_load_metric(prom_metric_formatter_t *self, prom_metric_t *metric) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+
+ int r = 0;
+
+ r = prom_metric_formatter_load_help(self, metric->name, metric->help);
+ if (r) return r;
+
+ r = prom_metric_formatter_load_type(self, metric->name, metric->type);
+ if (r) return r;
+
+ for (
+ prom_linked_list_node_t *current_node = metric->samples->keys->head;
+ current_node != NULL;
+ current_node = current_node->next
+ ) {
+ const char *key = (const char *) current_node->item;
+ if (metric->type == PROM_HISTOGRAM) {
+ prom_metric_sample_histogram_t *hist_sample = (prom_metric_sample_histogram_t*) prom_map_get(
+ metric->samples, key
+ );
+
+ if (hist_sample == NULL) return 1;
+
+ for (
+ prom_linked_list_node_t *current_hist_node = hist_sample->l_value_list->head;
+ current_hist_node != NULL;
+ current_hist_node = current_hist_node->next
+ ) {
+ const char *hist_key = (const char *) current_hist_node->item;
+ prom_metric_sample_t *sample = (prom_metric_sample_t*) prom_map_get(hist_sample->samples, hist_key);
+ if (sample == NULL) return 1;
+ r = prom_metric_formatter_load_sample(self, sample);
+ if (r) return r;
+ }
+ } else {
+ prom_metric_sample_t *sample = (prom_metric_sample_t*) prom_map_get(metric->samples, key);
+ if (sample == NULL) return 1;
+ r = prom_metric_formatter_load_sample(self, sample);
+ if (r) return r;
+ }
+ }
+ return prom_string_builder_add_char(self->string_builder, '\n');
+}
+
+int prom_metric_formatter_load_metrics(prom_metric_formatter_t *self, prom_map_t *collectors) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+ for (
+ prom_linked_list_node_t *current_node = collectors->keys->head;
+ current_node != NULL;
+ current_node = current_node->next
+ ) {
+ const char *collector_name = (const char *) current_node->item;
+ prom_collector_t *collector = (prom_collector_t *) prom_map_get(collectors, collector_name);
+ if (collector == NULL) return 1;
+
+ prom_map_t *metrics = collector->collect_fn(collector);
+ if (metrics == NULL) return 1;
+
+ for (
+ prom_linked_list_node_t *current_node = metrics->keys->head;
+ current_node != NULL;
+ current_node = current_node->next
+ ) {
+ const char *metric_name = (const char *) current_node->item;
+ prom_metric_t *metric = (prom_metric_t *) prom_map_get(metrics, metric_name);
+ if (metric == NULL) return 1;
+ r = prom_metric_formatter_load_metric(self, metric);
+ if (r) return r;
+ }
+ }
+ return r;
+}
diff --git a/prom/src/prom_metric_formatter_i.h b/prom/src/prom_metric_formatter_i.h
new file mode 100644
index 0000000..b62cfe4
--- /dev/null
+++ b/prom/src/prom_metric_formatter_i.h
@@ -0,0 +1,92 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+// Reference: https://prometheus.io/docs/instrumenting/exposition_formats/
+
+
+#ifndef PROM_METRIC_FORMATTER_I_H
+#define PROM_METRIC_FORMATTER_I_H
+
+// Private
+#include "prom_metric_formatter_t.h"
+#include "prom_metric_t.h"
+
+/**
+ * @brief API PRIVATE prom_metric_formatter constructor
+ */
+prom_metric_formatter_t* prom_metric_formatter_new();
+
+/**
+ * @brief API PRIVATE prom_metric_formatter destructor
+ */
+int prom_metric_formatter_destroy(prom_metric_formatter_t *self);
+
+
+/**
+ * @brief API PRIVATE Loads the help text
+ */
+int prom_metric_formatter_load_help(prom_metric_formatter_t* self, const char *name, const char *help);
+
+/**
+ * @brief API PRIVATE Loads the type text
+ */
+int prom_metric_formatter_load_type(prom_metric_formatter_t* self, const char *name, prom_metric_type_t metric_type);
+
+/**
+ * @brief API PRIVATE Loads the formatter with a metric sample L-value
+ * @param name The metric name
+ * @param suffix The metric suffix. This is applicable to Summary and Histogram metric types.
+ * @param label_count The number of labels for the given metric.
+ * @param label_keys An array of constant strings.
+ * @param label_values An array of constant strings.
+ *
+ * The number of const char **and prom_label_value must be the same.
+ */
+int prom_metric_formatter_load_l_value(prom_metric_formatter_t* metric_formatter,
+ const char *name,
+ const char *suffix,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values);
+
+/**
+ * @brief API PRIVATE Loads the formatter with a metric sample
+ */
+int prom_metric_formatter_load_sample(prom_metric_formatter_t* metric_formatter, prom_metric_sample_t *sample);
+
+/**
+ * @brief API PRIVATE Loads a metric in the string exposition format
+ */
+int prom_metric_formatter_load_metric(prom_metric_formatter_t *self, prom_metric_t *metric);
+
+/**
+ * @brief API PRIVATE Loads the given metrics
+ */
+int prom_metric_formatter_load_metrics(prom_metric_formatter_t *self, prom_map_t *collectors);
+
+/**
+ * @brief API PRIVATE Clear the underlying string_builder
+ */
+int prom_metric_formatter_clear(prom_metric_formatter_t *self);
+
+/**
+ * @brief API PRIVATE Returns the string built by prom_metric_formatter
+ */
+char* prom_metric_formatter_dump(prom_metric_formatter_t* metric_formatter);
+
+
+#endif // PROM_METRIC_FORMATTER_I_H
diff --git a/prom/src/prom_metric_formatter_t.h b/prom/src/prom_metric_formatter_t.h
new file mode 100644
index 0000000..f6af729
--- /dev/null
+++ b/prom/src/prom_metric_formatter_t.h
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef PROM_METRIC_FORMATTER_T_H
+#define PROM_METRIC_FORMATTER_T_H
+
+#include "prom_string_builder_t.h"
+
+typedef struct prom_metric_formatter {
+ prom_string_builder_t *string_builder;
+ prom_string_builder_t *err_builder;
+} prom_metric_formatter_t;
+
+#endif // PROM_METRIC_FORMATTER_T_H \ No newline at end of file
diff --git a/prom/src/prom_metric_i.h b/prom/src/prom_metric_i.h
new file mode 100644
index 0000000..310c63c
--- /dev/null
+++ b/prom/src/prom_metric_i.h
@@ -0,0 +1,49 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Private
+#include "prom_metric_t.h"
+#include "prom_metric_sample_histogram_t.h"
+
+#ifndef PROM_METRIC_I_INCLUDED
+#define PROM_METRIC_I_INCLUDED
+
+/**
+ * @brief API PRIVATE Returns a *prom_metric
+ */
+prom_metric_t* prom_metric_new(prom_metric_type_t type,
+ const char *name,
+ const char *help,
+ size_t label_key_count,
+ const char **label_keys);
+
+/**
+ * @brief API PRIVATE Destroys a *prom_metric
+ */
+int prom_metric_destroy(prom_metric_t *self);
+
+/**
+ * @brief API PRIVATE takes a generic item, casts to a *prom_metric_t and destroys it
+ */
+int prom_metric_destroy_generic(void *item);
+
+/**
+ * @brief API Private takes a generic item, casts to a *prom_metric_t and destroys it. Discards any errors.
+ */
+void prom_metric_free_generic(void *item);
+
+
+#endif // PROM_METRIC_I_INCLUDED
diff --git a/prom/src/prom_metric_sample.c b/prom/src/prom_metric_sample.c
new file mode 100644
index 0000000..ed9fbc2
--- /dev/null
+++ b/prom/src/prom_metric_sample.c
@@ -0,0 +1,99 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdatomic.h>
+
+// Public
+#include "prom_alloc.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_errors.h"
+#include "prom_log.h"
+#include "prom_metric_sample_i.h"
+#include "prom_metric_sample_t.h"
+
+
+prom_metric_sample_t* prom_metric_sample_new(prom_metric_type_t type, const char *l_value, double r_value) {
+ prom_metric_sample_t *self = (prom_metric_sample_t*) prom_malloc(sizeof(prom_metric_sample_t));
+ self->type = type;
+ self->l_value = prom_strdup(l_value);
+ self->r_value = ATOMIC_VAR_INIT(r_value);
+ return self;
+}
+
+int prom_metric_sample_destroy(prom_metric_sample_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+ prom_free((void *) self->l_value);
+ self->l_value = NULL;
+ prom_free((void *) self);
+ self = NULL;
+ return 0;
+}
+
+int prom_metric_sample_destroy_generic(void *gen) {
+ int r = 0;
+
+ prom_metric_sample_t *self = (prom_metric_sample_t*) gen;
+ r = prom_metric_sample_destroy(self);
+ self = NULL;
+ return r;
+}
+
+void prom_metric_sample_free_generic(void *gen) {
+ prom_metric_sample_t *self = (prom_metric_sample_t*) gen;
+ prom_metric_sample_destroy(self);
+}
+
+int prom_metric_sample_add(prom_metric_sample_t *self, double r_value) {
+ PROM_ASSERT(self != NULL);
+ if (r_value < 0) {
+ return 1;
+ }
+ _Atomic double old = atomic_load(&self->r_value);
+ for (;;) {
+ _Atomic double new = ATOMIC_VAR_INIT(old + r_value);
+ if (atomic_compare_exchange_weak(&self->r_value, &old, new)) {
+ return 0;
+ }
+ }
+}
+
+int prom_metric_sample_sub(prom_metric_sample_t *self, double r_value) {
+ PROM_ASSERT(self != NULL);
+ if (self->type != PROM_GAUGE) {
+ PROM_LOG(PROM_METRIC_INCORRECT_TYPE);
+ return 1;
+ }
+ _Atomic double old = atomic_load(&self->r_value);
+ for (;;) {
+ _Atomic double new = ATOMIC_VAR_INIT(old - r_value);
+ if (atomic_compare_exchange_weak(&self->r_value, &old, new)) {
+ return 0;
+ }
+ }
+}
+
+int prom_metric_sample_set(prom_metric_sample_t *self, double r_value) {
+ if (self->type != PROM_GAUGE) {
+ PROM_LOG(PROM_METRIC_INCORRECT_TYPE);
+ return 1;
+ }
+ atomic_store(&self->r_value, r_value);
+ return 0;
+} \ No newline at end of file
diff --git a/prom/src/prom_metric_sample_histogram.c b/prom/src/prom_metric_sample_histogram.c
new file mode 100644
index 0000000..4fe6cac
--- /dev/null
+++ b/prom/src/prom_metric_sample_histogram.c
@@ -0,0 +1,554 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <pthread.h>
+#include <stdio.h>
+
+// Public
+#include "prom_alloc.h"
+#include "prom_histogram.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_errors.h"
+#include "prom_linked_list_i.h"
+#include "prom_log.h"
+#include "prom_map_i.h"
+#include "prom_metric_formatter_i.h"
+#include "prom_metric_sample_i.h"
+#include "prom_metric_sample_histogram_i.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Static Declarations
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+static const char* prom_metric_sample_histogram_l_value_for_bucket(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values,
+ double bucket);
+
+static const char* prom_metric_sample_histogram_l_value_for_inf(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values);
+
+static void prom_metric_sample_histogram_free_str_generic(void *gen);
+
+static int prom_metric_sample_histogram_init_bucket_samples(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values);
+
+static int prom_metric_sample_histogram_init_inf(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values);
+
+static int prom_metric_sample_histogram_init_count(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values);
+
+static int prom_metric_sample_histogram_init_summary(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values);
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// End static declarations
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+prom_metric_sample_histogram_t* prom_metric_sample_histogram_new(const char *name,
+ prom_histogram_buckets_t *buckets,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values)
+{
+ // Capture return codes
+ int r = 0;
+
+ // Allocate and set self
+ prom_metric_sample_histogram_t *self = (prom_metric_sample_histogram_t*) prom_malloc(
+ sizeof(prom_metric_sample_histogram_t)
+ );
+
+ // Allocate and set the l_value_list
+ self->l_value_list = prom_linked_list_new();
+ if (self->l_value_list == NULL) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+
+ // Allocate and set the metric formatter
+ self->metric_formatter = prom_metric_formatter_new();
+ if (self->metric_formatter == NULL) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+
+ // Store map of l_value/prom_metric_sample_t
+ self->samples = prom_map_new();
+ if (self->samples == NULL) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+
+ // Set the free value function on the samples map
+ r = prom_map_set_free_value_fn(self->samples, &prom_metric_sample_free_generic);
+ if (r) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+
+ // Set a map of bucket: l_value
+ self->l_values = prom_map_new(); // Store map of bucket/l_value
+ if (self->l_values == NULL) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+
+ // Set the free value function for thhe l_values map
+ r = prom_map_set_free_value_fn(self->l_values, prom_metric_sample_histogram_free_str_generic);
+ if (r) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+
+ self->buckets = buckets;
+
+ // Allocate and initialize the lock
+ self->rwlock = (pthread_rwlock_t *) prom_malloc(sizeof(pthread_rwlock_t));
+ r = pthread_rwlock_init(self->rwlock, NULL);
+ if (r) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+
+ // Allocate and initialize bucket metric samples
+ r = prom_metric_sample_histogram_init_bucket_samples(self, name, label_count, label_keys, label_values);
+ if (r) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+
+
+ // Allocate and initialize the +Inf metric sample
+ r = prom_metric_sample_histogram_init_inf(self, name, label_count, label_keys, label_values);
+ if (r) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+
+ // Allocate and initialize the count metric sample
+ r = prom_metric_sample_histogram_init_count(self, name, label_count, label_keys, label_values);
+ if (r) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+
+ // Add summary sample
+ r = prom_metric_sample_histogram_init_summary(self, name, label_count, label_keys, label_values);
+ if (r) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+
+ // The value of nodes in this map will be simple prom_metric_sample pointers.
+ r = prom_map_set_free_value_fn(self->samples, &prom_metric_sample_free_generic);
+ if (r) {
+ prom_metric_sample_histogram_destroy(self);
+ return NULL;
+ }
+ return self;
+}
+
+static int prom_metric_sample_histogram_init_bucket_samples(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values)
+{
+ PROM_ASSERT(self);
+ int r = 0;
+ int bucket_count = prom_histogram_buckets_count(self->buckets);
+
+ // For each bucket, create an prom_metric_sample_t with an appropriate l_value and default value of 0.0. The
+ // l_value will contain the metric name, user labels, and finally, the le label and bucket value.
+ for (int i = 0; i < bucket_count; i++) {
+ const char *l_value = prom_metric_sample_histogram_l_value_for_bucket(
+ self, name, label_count, label_keys, label_values, self->buckets->upper_bounds[i]
+ );
+ if (l_value == NULL) return 1;
+
+ r = prom_linked_list_append(self->l_value_list, prom_strdup(l_value));
+ if (r) return r;
+
+ const char *bucket_key = prom_metric_sample_histogram_bucket_to_str(self->buckets->upper_bounds[i]);
+ if (bucket_key == NULL) return 1;
+
+ r = prom_map_set(self->l_values, bucket_key, (char *) l_value);
+ if (r) return r;
+
+ prom_metric_sample_t *sample = prom_metric_sample_new(PROM_HISTOGRAM, l_value, 0.0);
+ if (sample == NULL) return 1;
+
+ r = prom_map_set(self->samples, l_value, sample);
+ if (r) return r;
+
+ prom_free((void *) bucket_key);
+ }
+ return 0;
+}
+
+static int prom_metric_sample_histogram_init_inf(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values)
+{
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+ const char *inf_l_value = prom_metric_sample_histogram_l_value_for_inf(
+ self, name, label_count, label_keys, label_values
+ );
+ if (inf_l_value == NULL) return 1;
+
+ r = prom_linked_list_append(self->l_value_list, prom_strdup(inf_l_value));
+ if (r) return r;
+
+ r = prom_map_set(self->l_values, "+Inf", (char *) inf_l_value);
+ if (r) return r;
+
+ prom_metric_sample_t *inf_sample = prom_metric_sample_new(PROM_HISTOGRAM, (char *) inf_l_value, 0.0);
+ if (inf_sample == NULL) return 1;
+
+ return prom_map_set(self->samples, inf_l_value, inf_sample);
+}
+
+static int prom_metric_sample_histogram_init_count(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values)
+{
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+
+ r = prom_metric_formatter_load_l_value(self->metric_formatter, name, "count", label_count, label_keys, label_values);
+ if (r) return r;
+
+ const char *count_l_value = prom_metric_formatter_dump(self->metric_formatter);
+ if (count_l_value == NULL) return 1;
+
+ r = prom_linked_list_append(self->l_value_list, prom_strdup(count_l_value));
+ if (r) return r;
+
+ r = prom_map_set(self->l_values, "count", (char *) count_l_value);
+ if (r) return r;
+
+ prom_metric_sample_t *count_sample = prom_metric_sample_new(PROM_HISTOGRAM, count_l_value, 0.0);
+ if (count_sample == NULL) return 1;
+
+ return prom_map_set(self->samples, count_l_value, count_sample);
+}
+
+static int prom_metric_sample_histogram_init_summary(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values)
+{
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+
+ r = prom_metric_formatter_load_l_value(self->metric_formatter, name, "sum", label_count, label_keys, label_values);
+ if (r) return r;
+
+ const char *sum_l_value = prom_metric_formatter_dump(self->metric_formatter);
+ if (sum_l_value == NULL) return 1;
+
+ r = prom_linked_list_append(self->l_value_list, prom_strdup(sum_l_value));
+ if (r) return r;
+
+ r = prom_map_set(self->l_values, "sum", (char *) sum_l_value);
+ if (r) return r;
+
+ prom_metric_sample_t *sum_sample = prom_metric_sample_new(PROM_HISTOGRAM, sum_l_value, 0.0);
+ if (sum_sample == NULL) return 1;
+
+ return prom_map_set(self->samples, sum_l_value, sum_sample);
+}
+
+
+int prom_metric_sample_histogram_destroy(prom_metric_sample_histogram_t *self) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+ int ret = 0;
+
+ if (self == NULL) return 0;
+
+ r = prom_linked_list_destroy(self->l_value_list);
+ self->l_value_list = NULL;
+ if (r) ret = r;
+
+ r = prom_map_destroy(self->samples);
+ if (r) ret = r;
+ self->samples = NULL;
+
+ r = prom_map_destroy(self->l_values);
+ if (r) ret = r;
+ self->l_values = NULL;
+
+ r = prom_metric_formatter_destroy(self->metric_formatter);
+ if (r) ret = r;
+ self->metric_formatter = NULL;
+
+ r = pthread_rwlock_unlock(self->rwlock);
+ if (r) ret = r;
+
+ r = pthread_rwlock_destroy(self->rwlock);
+ if (r) ret = r;
+
+ prom_free(self->rwlock);
+ self->rwlock = NULL;
+
+ prom_free(self);
+ self = NULL;
+ return ret;
+}
+
+int prom_metric_sample_histogram_destroy_generic(void *gen) {
+ int r = 0;
+
+ prom_metric_sample_histogram_t *self = (prom_metric_sample_histogram_t*) gen;
+ r = prom_metric_sample_histogram_destroy(self);
+ self = NULL;
+ return r;
+}
+
+void prom_metric_sample_histogram_free_generic(void *gen) {
+ prom_metric_sample_histogram_t *self = (prom_metric_sample_histogram_t*) gen;
+ prom_metric_sample_histogram_destroy(self);
+}
+
+int prom_metric_sample_histogram_observe(prom_metric_sample_histogram_t *self, double value) {
+ int r = 0;
+
+ r = pthread_rwlock_wrlock(self->rwlock);
+ if (r) {
+ printf("RETURN CODE: %d\n", r);
+ PROM_LOG(PROM_PTHREAD_RWLOCK_LOCK_ERROR);
+ return r;
+ }
+
+ #define PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(r) \
+ int rr = 0; \
+ rr = pthread_rwlock_unlock(self->rwlock); \
+ if (rr) { \
+ PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR); \
+ return rr; \
+ } else { \
+ return r; \
+ }
+
+ // Update the counter for the proper bucket if found
+ int bucket_count = prom_histogram_buckets_count(self->buckets);
+ for (int i = (bucket_count - 1); i >= 0; i--) {
+ if (value > self->buckets->upper_bounds[i]) {
+ break;
+ }
+
+
+ const char *bucket_key = prom_metric_sample_histogram_bucket_to_str(self->buckets->upper_bounds[i]);
+ if (bucket_key == NULL) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(1)
+ }
+
+ const char *l_value = prom_map_get(self->l_values, bucket_key);
+ if (l_value == NULL) {
+ prom_free((void *) bucket_key);
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(1)
+ }
+
+ prom_metric_sample_t *sample = prom_map_get(self->samples, l_value);
+ if (sample == NULL) {
+ prom_free((void *) bucket_key);
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(1)
+ }
+
+ prom_free((void *) bucket_key);
+ r = prom_metric_sample_add(sample, 1.0);
+ if (r) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(r);
+ }
+ }
+
+ // Update the +Inf and count samples
+ const char *inf_l_value = prom_map_get(self->l_values, "+Inf");
+ if (inf_l_value == NULL) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(1);
+ }
+
+ prom_metric_sample_t *inf_sample = prom_map_get(self->samples, inf_l_value);
+ if (inf_sample == NULL) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(1);
+ }
+
+ r = prom_metric_sample_add(inf_sample, 1.0);
+ if (r) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(1);
+ }
+
+ const char *count_l_value = prom_map_get(self->l_values, "count");
+ if (count_l_value == NULL) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(1);
+ }
+
+ prom_metric_sample_t *count_sample = prom_map_get(self->samples, count_l_value);
+ if (count_sample == NULL) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(1);
+ }
+
+ r = prom_metric_sample_add(count_sample, 1.0);
+ if (r) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(1);
+ }
+
+ // Update the sum sample
+ const char *sum_l_value = prom_map_get(self->l_values, "sum");
+ if (sum_l_value == NULL) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(1);
+ }
+
+ prom_metric_sample_t *sum_sample = prom_map_get(self->samples, sum_l_value);
+ if (sum_sample == NULL) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(1);
+ }
+
+ r = prom_metric_sample_add(sum_sample, value);
+ PROM_METRIC_SAMPLE_HISTOGRAM_OBSERVE_HANDLE_UNLOCK(r);
+ return r;
+}
+
+static const char* prom_metric_sample_histogram_l_value_for_bucket(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values,
+ double bucket)
+{
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+
+ #define PROM_METRIC_SAMPLE_HISTOGRAM_L_VALUE_FOR_BUCKET_CLEANUP() \
+ for (size_t i = 0; i < label_count+1; i++) { \
+ prom_free((char*) new_keys[i]); \
+ prom_free((char*) new_values[i]); \
+ } \
+ prom_free(new_keys); \
+ prom_free(new_values);
+
+ // Make new array to hold label_keys with le label key
+ const char **new_keys = (const char **) prom_malloc((label_count + 1) * sizeof(char*));
+ for (size_t i = 0; i < label_count; i++) {
+ new_keys[i] = prom_strdup(label_keys[i]);
+ }
+ new_keys[label_count] = prom_strdup("le");
+
+
+ // Make new array to hold label_values with le label value
+ const char **new_values = (const char **) prom_malloc((label_count+1) * sizeof(char*));
+ for (size_t i = 0; i < label_count; i++) {
+ new_values[i] = prom_strdup(label_values[i]);
+ }
+
+ new_values[label_count] = prom_metric_sample_histogram_bucket_to_str(bucket);
+
+ r = prom_metric_formatter_load_l_value(self->metric_formatter, name, NULL, label_count+1, new_keys, new_values);
+ if (r) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_L_VALUE_FOR_BUCKET_CLEANUP();
+ return NULL;
+ }
+ const char *ret = (const char*) prom_metric_formatter_dump(self->metric_formatter);
+ PROM_METRIC_SAMPLE_HISTOGRAM_L_VALUE_FOR_BUCKET_CLEANUP();
+ return ret;
+}
+
+static const char* prom_metric_sample_histogram_l_value_for_inf(prom_metric_sample_histogram_t *self,
+ const char *name,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_values)
+{
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+
+ #define PROM_METRIC_SAMPLE_HISTOGRAM_L_VALUE_FOR_INF_CLEANUP() \
+ for (size_t i = 0; i < label_count+1; i++) { \
+ prom_free((char*) new_keys[i]); \
+ prom_free((char*) new_values[i]); \
+ } \
+ prom_free(new_keys); \
+ prom_free(new_values);
+
+ // Make new array to hold label_keys with le label key
+ const char **new_keys = (const char **) prom_malloc((label_count + 1) * sizeof(char*));
+ for (size_t i = 0; i < label_count; i++) {
+ new_keys[i] = prom_strdup(label_keys[i]);
+ }
+ new_keys[label_count] = prom_strdup("le");
+
+
+ // Make new array to hold label_values with le label value
+ const char **new_values = (const char **) prom_malloc((label_count+1) * sizeof(char*));
+ for (size_t i = 0; i < label_count; i++) {
+ new_values[i] = prom_strdup(label_values[i]);
+ }
+
+ new_values[label_count] = prom_strdup("+Inf");
+
+ r = prom_metric_formatter_load_l_value(self->metric_formatter, name, NULL, label_count+1, new_keys, new_values);
+ if (r) {
+ PROM_METRIC_SAMPLE_HISTOGRAM_L_VALUE_FOR_INF_CLEANUP()
+ return NULL;
+ }
+ const char *ret = (const char*) prom_metric_formatter_dump(self->metric_formatter);
+ PROM_METRIC_SAMPLE_HISTOGRAM_L_VALUE_FOR_INF_CLEANUP()
+ return ret;
+}
+
+static void prom_metric_sample_histogram_free_str_generic(void *gen) {
+ char * str = (char *) gen;
+ prom_free((void *) str);
+ str = NULL;
+}
+
+char* prom_metric_sample_histogram_bucket_to_str(double bucket) {
+ char *buf = (char*) prom_malloc(sizeof(char) * 50);
+ sprintf(buf, "%f", bucket);
+ return buf;
+} \ No newline at end of file
diff --git a/prom/src/prom_metric_sample_histogram_i.h b/prom/src/prom_metric_sample_histogram_i.h
new file mode 100644
index 0000000..906afd8
--- /dev/null
+++ b/prom/src/prom_metric_sample_histogram_i.h
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef PROM_METRIC_HISTOGRAM_SAMPLE_I_H
+#define PROM_METRIC_HISTOGRAM_SAMPLE_I_H
+
+// Public
+#include "prom_metric_sample_histogram.h"
+
+// Private
+#include "prom_metric_sample_histogram_t.h"
+
+/**
+ * @brief API PRIVATE Create a pointer to a prom_metric_sample_histogram_t
+ */
+prom_metric_sample_histogram_t* prom_metric_sample_histogram_new(const char *name,
+ prom_histogram_buckets_t *buckets,
+ size_t label_count,
+ const char **label_keys,
+ const char **label_vales);
+
+/**
+ * @brief API PRIVATE Destroy a prom_metric_sample_histogram_t
+ */
+int prom_metric_sample_histogram_destroy(prom_metric_sample_histogram_t *self);
+
+/**
+ * @brief API PRIVATE Destroy a void pointer that is cast to a prom_metric_sample_histogram_t*
+ */
+int prom_metric_sample_histogram_destroy_generic(void *gen);
+
+char* prom_metric_sample_histogram_bucket_to_str(double bucket);
+
+void prom_metric_sample_histogram_free_generic(void *gen);
+
+#endif // PROM_METRIC_HISTOGRAM_SAMPLE_I_H \ No newline at end of file
diff --git a/prom/src/prom_metric_sample_histogram_t.h b/prom/src/prom_metric_sample_histogram_t.h
new file mode 100644
index 0000000..d53c7c2
--- /dev/null
+++ b/prom/src/prom_metric_sample_histogram_t.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pthread.h>
+
+// Public
+#include "prom_histogram_buckets.h"
+#include "prom_metric_sample_histogram.h"
+
+// Private
+#include "prom_map_t.h"
+#include "prom_metric_formatter_t.h"
+
+#ifndef PROM_METRIC_HISTOGRAM_SAMPLE_T_H
+#define PROM_METRIC_HISTOGRAM_SAMPLE_T_H
+
+struct prom_metric_sample_histogram {
+ prom_linked_list_t *l_value_list;
+ prom_map_t *l_values;
+ prom_map_t *samples;
+ prom_metric_formatter_t *metric_formatter;
+ prom_histogram_buckets_t *buckets;
+ pthread_rwlock_t *rwlock;
+};
+
+#endif // PROM_METRIC_HISTOGRAM_SAMPLE_T_H \ No newline at end of file
diff --git a/prom/src/prom_metric_sample_i.h b/prom/src/prom_metric_sample_i.h
new file mode 100644
index 0000000..901f275
--- /dev/null
+++ b/prom/src/prom_metric_sample_i.h
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "prom_metric_t.h"
+#include "prom_metric_sample_t.h"
+
+#ifndef PROM_METRIC_SAMPLE_I_H
+#define PROM_METRIC_SAMPLE_I_H
+
+/**
+ * @brief API PRIVATE Return a prom_metric_sample_t*
+ *
+ * @param type The type of metric sample
+ * @param l_value The entire left value of the metric e.g metric_name{foo="bar"}
+ * @param r_value A double representing the value of the sample
+ */
+prom_metric_sample_t* prom_metric_sample_new(prom_metric_type_t type, const char *l_value, double r_value);
+
+/**
+ * @brief API PRIVATE Destroy the prom_metric_sample**
+ */
+int prom_metric_sample_destroy(prom_metric_sample_t *self);
+
+/**
+ * @brief API PRIVATE A prom_linked_list_free_item_fn to enable item destruction within a linked list's destructor
+ */
+int prom_metric_sample_destroy_generic(void *);
+
+
+/**
+ * @brief API PRIVATE A prom_linked_list_free_item_fn to enable item destruction within a linked list's destructor.
+ *
+ * This function ignores any errors.
+ */
+void prom_metric_sample_free_generic(void *gen);
+
+#endif // PROM_METRIC_SAMPLE_I_H \ No newline at end of file
diff --git a/prom/src/prom_metric_sample_t.h b/prom/src/prom_metric_sample_t.h
new file mode 100644
index 0000000..35f2e4a
--- /dev/null
+++ b/prom/src/prom_metric_sample_t.h
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef PROM_METRIC_SAMPLE_T_H
+#define PROM_METRIC_SAMPLE_T_H
+
+#include "prom_metric_t.h"
+#include "prom_metric_sample.h"
+
+struct prom_metric_sample {
+ prom_metric_type_t type; /**< type is the metric type for the sample */
+ char *l_value; /**< l_value is the full metric name and label set represeted as a string */
+ _Atomic double r_value; /**< r_value is the value of the metric sample */
+};
+
+#endif // PROM_METRIC_SAMPLE_T_H
+
+
+
diff --git a/prom/src/prom_metric_t.h b/prom/src/prom_metric_t.h
new file mode 100644
index 0000000..cab93d6
--- /dev/null
+++ b/prom/src/prom_metric_t.h
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PROM_METRIC_T_H
+#define PROM_METRIC_T_H
+
+#include <pthread.h>
+
+// Public
+#include "prom_metric.h"
+#include "prom_histogram_buckets.h"
+
+// Private
+#include "prom_metric_formatter_t.h"
+#include "prom_map_i.h"
+#include "prom_map_t.h"
+
+
+/**
+ * @brief API PRIVATE Contains metric type constants
+ */
+typedef enum prom_metric_type {
+ PROM_COUNTER,
+ PROM_GAUGE,
+ PROM_HISTOGRAM,
+ PROM_SUMMARY
+} prom_metric_type_t;
+
+/**
+ * @brief API PRIVATE Maps metric type constants to human readable string values
+ */
+char *prom_metric_type_map[4];
+
+/**
+ * @brief API PRIVATE An opaque struct to users containing metric metadata; one or more metric samples; and a metric formatter
+ * for locating metric samples and exporting metric data
+ */
+struct prom_metric {
+ prom_metric_type_t type; /**< metric_type The type of metric */
+ const char *name; /**< name The name of the metric */
+ const char *help; /**< help The help output for the metric */
+ prom_map_t *samples; /**< samples Map comprised of samples for the given metric */
+ prom_histogram_buckets_t* buckets; /**< buckets Array of histogram bucket upper bound values */
+ size_t label_key_count; /**< label_keys_count The count of labe_keys*/
+ prom_metric_formatter_t *formatter; /**< formatter The metric formatter */
+ pthread_rwlock_t *rwlock; /**< rwlock Required for locking on certain non-atomic operations */
+ const char **label_keys; /**< labels Array comprised of const char **/
+};
+
+#endif // PROM_METRIC_T_H
diff --git a/prom/src/prom_process_fds.c b/prom/src/prom_process_fds.c
new file mode 100644
index 0000000..c8a5f4e
--- /dev/null
+++ b/prom/src/prom_process_fds.c
@@ -0,0 +1,77 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+#include <stdio.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+// Public
+#include "prom_alloc.h"
+#include "prom_gauge.h"
+
+// Private
+#include "prom_errors.h"
+#include "prom_log.h"
+#include "prom_process_fds_t.h"
+
+int prom_process_fds_count(const char *path) {
+ int count = 0;
+ int r = 0;
+ struct dirent *de;
+ DIR *d;
+ if (path) {
+ d = opendir(path);
+ if (d == NULL) {
+ PROM_LOG(PROM_STDIO_OPEN_DIR_ERROR);
+ return -1;
+ }
+ } else {
+ int pid = (int) getpid();
+ char p[50];
+ sprintf(p, "/proc/%d/fd", pid);
+ d = opendir(p);
+ if (d == NULL) {
+ PROM_LOG(PROM_STDIO_OPEN_DIR_ERROR);
+ return -1;
+ }
+ }
+
+ while ((de = readdir(d)) != NULL) {
+ if (strcmp(".", de->d_name) == 0 || strcmp("..", de->d_name) == 0) {
+ continue;
+ }
+ count++;
+ }
+ r = closedir(d);
+ if (r) {
+ PROM_LOG(PROM_STDIO_CLOSE_DIR_ERROR);
+ return -1;
+ }
+ return count;
+}
+
+
+int prom_process_fds_init(void) {
+ prom_process_open_fds = prom_gauge_new(
+ "process_open_fds",
+ "Number of open file descriptors.",
+ 0, NULL
+ );
+ return 0;
+} \ No newline at end of file
diff --git a/prom/src/prom_process_fds_i.h b/prom/src/prom_process_fds_i.h
new file mode 100644
index 0000000..1e10c85
--- /dev/null
+++ b/prom/src/prom_process_fds_i.h
@@ -0,0 +1,25 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef PROM_PROESS_FDS_I_INCLUDED
+#define PROM_PROESS_FDS_I_INCLUDED
+
+
+int prom_process_fds_count(const char *path);
+int prom_process_fds_init(void);
+
+#endif // PROM_PROESS_FDS_I_INCLUDED \ No newline at end of file
diff --git a/prom/src/prom_process_fds_t.h b/prom/src/prom_process_fds_t.h
new file mode 100644
index 0000000..d7f3e2b
--- /dev/null
+++ b/prom/src/prom_process_fds_t.h
@@ -0,0 +1,24 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "prom_gauge.h"
+
+#ifndef PROM_PROESS_FDS_T_H
+#define PROM_PROESS_FDS_T_H
+
+prom_gauge_t *prom_process_open_fds;
+
+#endif // PROM_PROESS_FDS_T_H \ No newline at end of file
diff --git a/prom/src/prom_process_limits.c b/prom/src/prom_process_limits.c
new file mode 100644
index 0000000..685a31c
--- /dev/null
+++ b/prom/src/prom_process_limits.c
@@ -0,0 +1,489 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+// Public
+#include "prom_alloc.h"
+#include "prom_gauge.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_map_i.h"
+#include "prom_procfs_i.h"
+#include "prom_process_limits_i.h"
+#include "prom_process_limits_t.h"
+
+
+const char PROM_PROCESS_LIMITS_RDP_LETTERS[] = {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z'
+};
+
+const char PROM_PROCESS_LIMITS_RDP_DIGITS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' } ;
+
+const char *PROM_PROCESS_LIMITS_RDP_UNLIMITED = "unlimited";
+
+typedef enum prom_process_limit_rdp_limit_type {
+ PROM_PROCESS_LIMITS_RDP_SOFT,
+ PROM_PROCESS_LIMITS_RDP_HARD
+} prom_process_limit_rdp_limit_type_t;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// prom_process_limits_row_t
+
+prom_process_limits_row_t* prom_process_limits_row_new(const char *limit,
+ const int soft,
+ const int hard,
+ const char *units)
+{
+ prom_process_limits_row_t *self = (prom_process_limits_row_t*) prom_malloc(sizeof(prom_process_limits_row_t));
+
+ self->limit = prom_strdup(limit);
+ self->units = prom_strdup(units);
+
+ self->soft = soft;
+ self->hard = hard;
+
+ return self;
+}
+
+int prom_process_limits_row_destroy(prom_process_limits_row_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+ prom_free((void *) self->limit);
+ self->limit = NULL;
+
+ prom_free((void *) self->units);
+ self->units = NULL;
+
+ prom_free(self);
+ self = NULL;
+ return 0;
+}
+
+prom_process_limits_current_row_t* prom_process_limits_current_row_new(void) {
+ prom_process_limits_current_row_t *self = (prom_process_limits_current_row_t *) prom_malloc(
+ sizeof(prom_process_limits_current_row_t)
+ );
+
+ self->limit = NULL;
+ self->soft = 0;
+ self->hard = 0;
+ self->units = NULL;
+ return self;
+}
+
+int prom_process_limits_current_row_set_limit(prom_process_limits_current_row_t *self, char *limit) {
+ PROM_ASSERT(self != NULL);
+ self->limit = prom_strdup(limit);
+ return 0;
+}
+
+int prom_process_limits_current_row_set_units(prom_process_limits_current_row_t *self, char *units) {
+ PROM_ASSERT(self != NULL);
+ self->units = prom_strdup(units);
+ return 0;
+}
+
+int prom_process_limits_current_row_clear(prom_process_limits_current_row_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self->limit) {
+ prom_free((void *) self->limit);
+ self->limit = NULL;
+ }
+ if (self->units) {
+ prom_free((void *) self->units);
+ self->units = NULL;
+ }
+ self->soft = 0;
+ self->hard = 0;
+ return 0;
+}
+
+int prom_process_limits_current_row_destroy(prom_process_limits_current_row_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+ int r = 0;
+
+ r = prom_process_limits_current_row_clear(self);
+ prom_free(self);
+ self = NULL;
+ return r;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// prom_process_limits_file_t
+
+prom_process_limits_file_t* prom_process_limits_file_new(const char *path) {
+ if (path) {
+ return prom_procfs_buf_new(path);
+ } else {
+ int pid = (int) getpid();
+ char path[255];
+ sprintf(path, "/proc/%d/limits", pid);
+ return prom_procfs_buf_new(path);
+ }
+}
+
+int prom_process_limits_file_destroy(prom_process_limits_file_t *self) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+
+ if (self == NULL) return 0;
+ r = prom_procfs_buf_destroy(self);
+ self = NULL;
+ return r;
+}
+
+static void prom_process_limits_file_free_map_item_fn(void *gen) {
+ prom_process_limits_row_t *row = (prom_process_limits_row_t *) gen;
+ prom_process_limits_row_destroy(row);
+ row = NULL;
+}
+
+/**
+ * @brief Returns a map. Each key is a key in /proc/[pid]/limits. Each value is a pointer to a
+ * prom_process_limits_row_t. Returns NULL upon failure.
+ *
+ * EBNF
+ *
+ * limits_file = first_line , data_line , { data_line } ;
+ * first_line = character, { character } , "\n" ;
+ * character = " " | letter | digit ;
+ * letter = "A" | "B" | "C" | "D" | "E" | "F" | "G"
+ * | "H" | "I" | "J" | "K" | "L" | "M" | "N"
+ * | "O" | "P" | "Q" | "R" | "S" | "T" | "U"
+ * | "V" | "W" | "X" | "Y" | "Z" | "a" | "b"
+ * | "c" | "d" | "e" | "f" | "g" | "h" | "i"
+ * | "j" | "k" | "l" | "m" | "n" | "o" | "p"
+ * | "q" | "r" | "s" | "t" | "u" | "v" | "w"
+ * | "x" | "y" | "z" ;
+ * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
+ * data_line = limit , space, space, { " " }, soft_limit, " ", " ", { " " }, hard_limit, " ", " ", { " " }, { units }, { space_char }, "\n" ;
+ * space_char = " " | "\t" ;
+ * limit = { word_and_space } , word ;
+ * word_and_space = word, " " ;
+ * word = letter, { letter } ;
+ * soft_limit = ( digit, { digit } ) | "unlimited" ;
+ * hard_limit = soft_limit ;
+ * units = word ;
+ */
+prom_map_t* prom_process_limits(prom_process_limits_file_t *f) {
+ prom_map_t *m = prom_map_new();
+ if (m == NULL) return NULL;
+ int r = 0;
+
+ r = prom_map_set_free_value_fn(m, &prom_process_limits_file_free_map_item_fn);
+ if (r) {
+ prom_map_destroy(m);
+ m = NULL;
+ return NULL;
+ }
+
+ prom_process_limits_current_row_t *current_row = prom_process_limits_current_row_new();
+ if (!prom_process_limits_rdp_file(f, m, current_row)) {
+ prom_process_limits_current_row_destroy(current_row);
+ current_row = NULL;
+ prom_map_destroy(m);
+ m = NULL;
+ return NULL;
+ }
+ r = prom_process_limits_current_row_destroy(current_row);
+ current_row = NULL;
+ if (r) return NULL;
+ return m;
+}
+
+bool prom_process_limits_rdp_file(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ if (!prom_process_limits_rdp_first_line(f, map, current_row)) return false;
+
+ while (f->index < f->size - 1) {
+ if (!prom_process_limits_rdp_data_line(f, map, current_row)) return false;
+ }
+
+ return true;
+}
+
+bool prom_process_limits_rdp_first_line(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ while(prom_process_limits_rdp_character(f, map, current_row)){}
+ if (f->buf[f->index] == '\n') {
+ f->index++;
+ return true;
+ }
+ return false;
+}
+
+
+bool prom_process_limits_rdp_character(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ if (prom_process_limits_rdp_letter(f, map, current_row)) return true;
+ if (prom_process_limits_rdp_digit(f, map, current_row)) return true;
+ if (f->buf[f->index] == ' ' && f->buf[f->index] < f->size - 1) {
+ f->index++;
+ return true;
+ }
+ return false;
+}
+
+bool prom_process_limits_rdp_letter(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ if (f->index >= f->size - 1) return false;
+ unsigned int size = sizeof(PROM_PROCESS_LIMITS_RDP_LETTERS);
+ for (int i = 0; i < size; i++) {
+ int letter = PROM_PROCESS_LIMITS_RDP_LETTERS[i];
+ int in_buff = f->buf[f->index];
+ if (letter == in_buff) {
+
+ f->index++;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool prom_process_limits_rdp_digit(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ if (f->index >= f->size - 1) return false;
+ unsigned int size = sizeof(PROM_PROCESS_LIMITS_RDP_DIGITS);
+ for (int i = 0; i < size; i++) {
+ int digit = PROM_PROCESS_LIMITS_RDP_DIGITS[i];
+ int in_buff = f->buf[f->index];
+ if (digit == in_buff) {
+ f->index++;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool prom_process_limits_rdp_data_line(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ // Process and parse data line, loading relevant data into the current_row
+ if (!prom_process_limits_rdp_limit(f, map, current_row)) return false;
+ prom_process_limits_rdp_next_token(f);
+ if (!prom_process_limits_rdp_soft_limit(f, map, current_row)) return false;
+ prom_process_limits_rdp_next_token(f);
+ if (!prom_process_limits_rdp_hard_limit(f, map, current_row)) return false;
+ prom_process_limits_rdp_next_token(f);
+ prom_process_limits_rdp_units(f, map, current_row);
+
+ // Load data from the current row into the map
+ const char *limit = (const char *) current_row->limit;
+ int soft = current_row->soft;
+ int hard = current_row->hard;
+ const char *units = (const char *) current_row->units;
+ prom_process_limits_row_t *row = prom_process_limits_row_new(limit, soft, hard, units);
+ prom_map_set(map, limit, row);
+ prom_process_limits_current_row_clear(current_row);
+
+ // Progress to the next token
+ prom_process_limits_rdp_next_token(f);
+ return true;
+
+}
+
+/**
+ * @brief EBNF: space_char = " " | "\t" ;
+ */
+bool prom_process_limits_rdp_space_char(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ char c = f->buf[f->index];
+ if (c == ' ' || c == '\t') {
+ f->index++;
+ return true;
+ }
+ return false;
+}
+
+/**
+ * @brief EBNF: limit = { word_and_space } , word ;
+ */
+bool prom_process_limits_rdp_limit(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ size_t current_index = f->index;
+ while(prom_process_limits_rdp_word_and_space(f, map, current_row)) {}
+
+ if (prom_process_limits_rdp_word(f, map, current_row)) {
+ size_t size = f->index - current_index + 1; // Add one for \0
+ char limit[size];
+ for (int i = 0; i < size - 1; i++) {
+ limit[i] = f->buf[current_index+i];
+ }
+ limit[size-1] = '\0';
+ prom_process_limits_current_row_set_limit(current_row, limit);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * @brief EBNF: word_and_space = letter, { letter }, " " ;
+ */
+bool prom_process_limits_rdp_word_and_space(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ size_t current_index = f->index;
+ if (prom_process_limits_rdp_word(f, map, current_row) && f->buf[f->index] == ' ') {
+ f->index++;
+ if (f->index+1 < f->size && f->buf[f->index+1] != ' ' && f->buf[f->index+1] != '\t') {
+ return true;
+ }
+ }
+ f->index = current_index;
+ return false;
+}
+
+bool prom_process_limits_rdp_word(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ size_t original_index = f->index;
+ while(prom_process_limits_rdp_letter(f, map, current_row)) {}
+ return (f->index - original_index) > 0;
+}
+
+static bool prom_process_limits_rdp_generic_limit(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row,
+ prom_process_limit_rdp_limit_type_t type)
+{
+ size_t current_index = f->index;
+ int value = 0;
+ if (prom_process_limits_rdp_match(f, PROM_PROCESS_LIMITS_RDP_UNLIMITED)) {
+ value = -1;
+ } else {
+ while(prom_process_limits_rdp_digit(f, map, current_row)){}
+ size_t num_digits = f->index - current_index + 1;
+ if (num_digits <= 0) return false;
+
+ char buf[num_digits+1];
+
+ for (size_t i = 0; i < num_digits - 1; i++) {
+ buf[i] = f->buf[current_index+i];
+ }
+ buf[num_digits-1] = '\0';
+ value = atoi(buf);
+ f->index += num_digits;
+ }
+
+ switch (type) {
+ case PROM_PROCESS_LIMITS_RDP_SOFT:
+ current_row->soft = value;
+ case PROM_PROCESS_LIMITS_RDP_HARD:
+ current_row->hard = value;
+ }
+
+ return true;
+}
+
+
+bool prom_process_limits_rdp_soft_limit(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ return prom_process_limits_rdp_generic_limit(f, map, current_row, PROM_PROCESS_LIMITS_RDP_SOFT);
+}
+
+bool prom_process_limits_rdp_hard_limit(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ return prom_process_limits_rdp_generic_limit(f, map, current_row, PROM_PROCESS_LIMITS_RDP_HARD);
+}
+
+bool prom_process_limits_rdp_units(prom_process_limits_file_t *f,
+ prom_map_t *map,
+ prom_process_limits_current_row_t *current_row)
+{
+ size_t current_index = f->index;
+ if (prom_process_limits_rdp_word(f, map, current_row)) {
+ size_t num_chars = f->index - current_index + 1;
+ char buf[num_chars];
+ for (size_t i = 0; i < num_chars - 1; i++) {
+ buf[i] = f->buf[current_index+i];
+ }
+ buf[num_chars-1] = '\0';
+ prom_process_limits_current_row_set_units(current_row, buf);
+ return true;
+ }
+ return false;
+}
+
+
+int prom_process_limits_rdp_next_token(prom_process_limits_file_t *f) {
+ while (f->buf[f->index] == ' ' || f->buf[f->index] == '\n' || f->buf[f->index] == '\t') {
+ f->index++;
+ }
+ return 0;
+}
+
+bool prom_process_limits_rdp_match(prom_process_limits_file_t *f, const char *token) {
+ size_t current_index = f->index;
+ for (size_t i = 0; i < strlen(token); i++) {
+ if (f->buf[current_index + i] != token[i]) {
+ return false;
+ }
+ }
+ f->index += strlen(token);
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @brief Initializes each gauge metric found in prom_process_t.h
+ */
+int prom_process_limits_init(void) {
+ prom_process_max_fds = prom_gauge_new(
+ "process_max_fds",
+ "Maximum number of open file descriptors.",
+ 0, NULL
+ );
+
+ prom_process_virtual_memory_max_bytes = prom_gauge_new(
+ "process_virtual_memory_max_bytes",
+ "Maximum amount of virtual memory available in bytes.",
+ 0, NULL
+ );
+ return 0;
+}
diff --git a/prom/src/prom_process_limits_i.h b/prom/src/prom_process_limits_i.h
new file mode 100644
index 0000000..80142d8
--- /dev/null
+++ b/prom/src/prom_process_limits_i.h
@@ -0,0 +1,68 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PROM_PROCESS_I_H
+#define PROM_PROCESS_I_H
+
+#include <stdbool.h>
+
+#include "prom_map_t.h"
+#include "prom_process_limits_t.h"
+
+/**
+ * @brief Initialize the process gauge metrics
+ */
+int prom_process_init(void);
+
+prom_process_limits_row_t* prom_process_limits_row_new(const char *limit,
+ const int soft,
+ const int hard,
+ const char *units);
+int prom_process_limits_row_destroy(prom_process_limits_row_t *self);
+
+
+prom_process_limits_current_row_t* prom_process_limits_current_row_new(void);
+int prom_process_limits_current_row_set_limit(prom_process_limits_current_row_t *self, char *limit);
+int prom_process_limits_current_row_set_units(prom_process_limits_current_row_t *self, char *units);
+int prom_process_limits_current_row_clear(prom_process_limits_current_row_t *self);
+int prom_process_limits_current_row_destroy(prom_process_limits_current_row_t *self);
+
+
+prom_process_limits_file_t* prom_process_limits_file_new(const char *path);
+int prom_process_limits_file_destroy(prom_process_limits_file_t *self);
+
+
+prom_map_t* prom_process_limits(prom_process_limits_file_t *f);
+bool prom_process_limits_rdp_file(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);
+bool prom_process_limits_rdp_first_line(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);
+bool prom_process_limits_rdp_character(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);
+bool prom_process_limits_rdp_letter(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);
+bool prom_process_limits_rdp_digit(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);
+bool prom_process_limits_rdp_data_line(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);
+bool prom_process_limits_rdp_limit(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);
+bool prom_process_limits_rdp_word_and_space(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);
+bool prom_process_limits_rdp_word(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);
+bool prom_process_limits_rdp_soft_limit(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);;
+bool prom_process_limits_rdp_hard_limit(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);
+bool prom_process_limits_rdp_units(prom_process_limits_file_t *f, prom_map_t *data, prom_process_limits_current_row_t *current_row);
+
+
+int prom_process_limits_rdp_next_token(prom_process_limits_file_t *f);
+bool prom_process_limits_rdp_match(prom_process_limits_file_t *f, const char *token);
+
+int prom_process_limits_init(void);
+
+#endif // PROM_PROCESS_I_H \ No newline at end of file
diff --git a/prom/src/prom_process_limits_t.h b/prom/src/prom_process_limits_t.h
new file mode 100644
index 0000000..9435a8b
--- /dev/null
+++ b/prom/src/prom_process_limits_t.h
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PROM_PROCESS_T_H
+#define PROM_PROCESS_T_H
+
+#include "prom_gauge.h"
+#include "prom_procfs_t.h"
+
+
+prom_gauge_t *prom_process_open_fds;
+prom_gauge_t *prom_process_max_fds;
+prom_gauge_t *prom_process_virtual_memory_max_bytes;
+prom_gauge_t *prom_process_resident_memory_bytes;
+
+
+typedef struct prom_process_limits_row {
+ const char *limit; /**< Pointer to a string */
+ int soft; /**< Soft value */
+ int hard; /**< Hard value */
+ const char *units; /**< Units */
+} prom_process_limits_row_t;
+
+typedef struct prom_process_limits_current_row {
+ char *limit; /**< Pointer to a string */
+ int soft; /**< Soft value */
+ int hard; /**< Hard value */
+ char *units; /**< Units */
+} prom_process_limits_current_row_t;
+
+typedef prom_procfs_buf_t prom_process_limits_file_t;
+
+#endif // PROM_PROCESS_T_H \ No newline at end of file
diff --git a/prom/src/prom_process_stat.c b/prom/src/prom_process_stat.c
new file mode 100644
index 0000000..9deb717
--- /dev/null
+++ b/prom/src/prom_process_stat.c
@@ -0,0 +1,198 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+
+
+// Public
+#include "prom_alloc.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_process_stat_t.h"
+#include "prom_procfs_i.h"
+
+prom_process_stat_file_t* prom_process_stat_file_new(const char *path) {
+ if (path) {
+ return prom_procfs_buf_new(path);
+ } else {
+ int pid = (int) getpid();
+ char path[50];
+ sprintf(path, "/proc/%d/stat", pid);
+ return prom_procfs_buf_new(path);
+ }
+}
+
+int prom_process_stat_file_destroy(prom_process_stat_file_t *self) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+
+ r = prom_procfs_buf_destroy(self);
+ self = NULL;
+ return r;
+}
+
+prom_process_stat_t* prom_process_stat_new(prom_process_stat_file_t *stat_f) {
+ prom_process_stat_t *self = (prom_process_stat_t*) prom_malloc(sizeof(prom_process_stat_t));
+ self->comm = prom_malloc(128);
+
+ sscanf(
+ (const char *) stat_f->buf,
+ "%d " // (1) pid %d
+ "%s " // (2) comm %s
+ "%c " // (3) state %c
+ "%d " // (4) ppid %d
+ "%d " // (5) pgrp %d
+ "%d " // (6) session %d
+ "%d " // (7) tty_nr %d
+ "%d " // (8) tpgid %d
+ "%u " // (9) flags %u
+ "%lu " // (10) minflt %lu
+ "%lu " // (11) cminflt %lu
+ "%lu " // (12) majflt %lu
+ "%lu " // (13) cmajflt %lu
+ "%lu " // (14) utime %lu
+ "%lu " // (15) stime %lu
+ "%ld " // (16) cutime %ld
+ "%ld " // (17) cstime %ld
+ "%ld " // (18) priority %ld
+ "%ld " // (19) nice %ld
+ "%ld " // (20) num_threads %ld
+ "%ld " // (21) itrealvalue %ld
+ "%llu " // (22) starttime %llu
+ "%lu " // (23) vsize %lu
+ "%ld " // (24) rss %ld
+ "%lu " // (25) rsslim %lu
+ "%lu " // (26) startcode %lu [PT]
+ "%lu " // (27) endcode %lu [PT]
+ "%lu " // (28) startstack %lu [PT]
+ "%lu " // (29) kstkesp %lu [PT]
+ "%lu " // (30) kstkeip %lu [PT]
+ "%lu " // (31) signal %lu
+ "%lu " // (32) blocked %lu
+ "%lu " // (33) sigignore %lu
+ "%lu " // (34) sigcatch %lu
+ "%lu " // (35) wchan %lu [PT]
+ "%lu " // (36) nswap %lu
+ "%lu " // (37) cnswap %lu
+ "%d " // (38) exit_signal %d (since Linux 2.1.22)
+ "%d " // (39) processor %d (since Linux 2.2.8)
+ "%u " // (40) rt_priority %u (since Linux 2.5.19)
+ "%u " // (41) policy %u (since Linux 2.5.19)
+ "%llu " // (42) delayacct_blkio_ticks %llu (since Linux 2.6.18)
+ "%lu " // (43) guest_time %lu (since Linux 2.6.24)
+ "%ld " // (44) cguest_time %ld (since Linux 2.6.24)
+ "%lu " // (45) start_data %lu (since Linux 3.3) [PT]
+ "%lu " // (46) end_data %lu (since Linux 3.3) [PT]
+ "%lu " // (47) start_brk %lu (since Linux 3.3) [PT]
+ "%lu " // (48) arg_start %lu (since Linux 3.5) [PT]
+ "%lu " // (49) arg_end %lu (since Linux 3.5) [PT]
+ "%lu " // (50) env_start %lu (since Linux 3.5) [PT]
+ "%lu " // (51) env_end %lu (since Linux 3.5) [PT]
+ "%d ", // (52) exit_code %d (since Linux 3.5) [PT]
+ &self->pid, // (1) pid %d
+ self->comm, // (2) comm %s
+ &self->state, // (3) state %c
+ &self->ppid, // (4) ppid %d
+ &self->pgrp, // (5) pgrp %d
+ &self->session, // (6) session %d
+ &self->tty_nr, // (7) tty_nr %d
+ &self->tpgid, // (8) tpgid %d
+ &self->flags, // (9) flags %u
+ &self->minflt, // (10) minflt %lu
+ &self->cminflt, // (11) cminflt %lu
+ &self->majflt, // (12) majflt %lu
+ &self->cmajflt, // (13) cmajflt %lu
+ &self->utime, // (14) utime %lu
+ &self->stime, // (15) stime %lu
+ &self->cutime, // (16) cutime %ld
+ &self->cstime, // (17) cstime %ld
+ &self->priority, // (18) priority %ld
+ &self->nice, // (19) nice %ld
+ &self->num_threads, // (20) num_threads %ld
+ &self->itrealvalue, // (21) itrealvalue %ld
+ &self->starttime, // (22) starttime %llu
+ &self->vsize, // (23) vsize %lu
+ &self->rss, // (24) rss %ld
+ &self->rsslim, // (25) rsslim %lu
+ &self->startcode, // (26) startcode %lu [PT]
+ &self->endcode, // (27) endcode %lu [PT]
+ &self->startstack, // (28) startstack %lu [PT]
+ &self->kstkesp, // (29) kstkesp %lu [PT]
+ &self->kstkeip, // (30) kstkeip %lu [PT]
+ &self->signal, // (31) signal %lu
+ &self->blocked, // (32) blocked %lu
+ &self->sigignore, // (33) sigignore %lu
+ &self->sigcatch, // (34) sigcatch %lu
+ &self->wchan, // (35) wchan %lu [PT]
+ &self->nswap, // (36) nswap %lu
+ &self->cnswap, // (37) cnswap %lu
+ &self->exit_signal, // (38) exit_signal %d (since Linux 2.1.22)
+ &self->processor, // (39) processor %d (since Linux 2.2.8)
+ &self->rt_priority, // (40) rt_priority %u (since Linux 2.5.19)
+ &self->policy, // (41) policy %u (since Linux 2.5.19)
+ &self->delayacct_blkio_ticks, // (42) delayacct_blkio_ticks %llu (since Linux 2.6.18)
+ &self->guest_time, // (43) guest_time %lu (since Linux 2.6.24)
+ &self->cguest_time, // (44) cguest_time %ld (since Linux 2.6.24)
+ &self->start_data, // (45) start_data %lu (since Linux 3.3) [PT]
+ &self->end_data, // (46) end_data %lu (since Linux 3.3) [PT]
+ &self->start_brk, // (47) start_brk %lu (since Linux 3.3) [PT]
+ &self->arg_start, // (48) arg_start %lu (since Linux 3.5) [PT]
+ &self->arg_end, // (49) arg_end %lu (since Linux 3.5) [PT]
+ &self->env_start, // (50) env_start %lu (since Linux 3.5) [PT]
+ &self->env_end, // (51) env_end %lu (since Linux 3.5) [PT]
+ &self->exit_code // (52) exit_code %d (since Linux 3.5) [PT]
+ );
+ return self;
+}
+
+int prom_process_stat_destroy(prom_process_stat_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+ prom_free((void *) self->comm);
+ prom_free((void *) self);
+ self = NULL;
+ return 0;
+}
+
+/**
+ * @brief Initializes each gauge metric
+ */
+int prom_process_stats_init(void) {
+ // /proc/[pid]stat cutime + cstime / 100
+ prom_process_cpu_seconds_total = prom_gauge_new(
+ "process_cpu_seconds_total",
+ "Total user and system CPU time spent in seconds.",
+ 0, NULL
+ );
+
+ // /proc/[pid]/stat Field 23
+ prom_process_virtual_memory_bytes = prom_gauge_new(
+ "process_virtual_memory_bytes",
+ "Virtual memory size in bytes.",
+ 0, NULL
+ );
+
+ prom_process_start_time_seconds = prom_gauge_new(
+ "process_start_time_seconds",
+ "Start time of the process since unix epoch in seconds.",
+ 0, NULL
+ );
+ return 0;
+} \ No newline at end of file
diff --git a/prom/src/prom_process_stat_i.h b/prom/src/prom_process_stat_i.h
new file mode 100644
index 0000000..f98c745
--- /dev/null
+++ b/prom/src/prom_process_stat_i.h
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef PROM_PROCESS_STATS_I_H
+#define PROM_PROCESS_STATS_I_H
+
+#include "prom_process_stat_t.h"
+
+prom_process_stat_file_t* prom_process_stat_file_new(const char *path);
+int prom_process_stat_file_destroy(prom_process_stat_file_t *self);
+prom_process_stat_t* prom_process_stat_new(prom_process_stat_file_t *stat_f);
+int prom_process_stat_destroy(prom_process_stat_t *self);
+int prom_process_stats_init(void);
+
+#endif // PROM_PROCESS_STATS_I_H \ No newline at end of file
diff --git a/prom/src/prom_process_stat_t.h b/prom/src/prom_process_stat_t.h
new file mode 100644
index 0000000..e9c6a7c
--- /dev/null
+++ b/prom/src/prom_process_stat_t.h
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef PROM_PROCESS_STATS_T_H
+#define PROM_PROCESS_STATS_T_H
+
+#include "prom_gauge.h"
+
+#include "prom_procfs_t.h"
+
+prom_gauge_t *prom_process_cpu_seconds_total;
+prom_gauge_t *prom_process_virtual_memory_bytes;
+prom_gauge_t *prom_process_start_time_seconds;
+
+/**
+ * @brief Refer to man proc and search for /proc/[pid]/stat
+ */
+typedef struct prom_process_stat {
+ int pid; // (1) pid %d
+ char *comm; // (2) comm %s
+ char state; // (3) state %c
+ int ppid; // (4) ppid %d
+ int pgrp; // (5) pgrp %d
+ int session; // (6) session %d
+ int tty_nr; // (7) tty_nr %d
+ int tpgid; // (8) tpgid %d
+ unsigned flags; // (9) flags %u
+ unsigned long minflt; // (10) minflt %lu
+ unsigned long cminflt; // (11) cminflt %lu
+ unsigned long majflt; // (12) majflt %lu
+ unsigned long cmajflt; // (13) cmajflt %lu
+ unsigned long utime; // (14) utime %lu
+ unsigned long stime; // (15) stime %lu
+ long int cutime; // (16) cutime %ld
+ long int cstime; // (17) cstime %ld
+ long int priority; // (18) priority %ld
+ long int nice; // (19) nice %ld
+ long int num_threads; // (20) num_threads %ld
+ long int itrealvalue; // (21) itrealvalue %ld
+ unsigned long long starttime; // (22) starttime %llu
+ unsigned long vsize; // (23) vsize %lu
+ long int rss; // (24) rss %ld
+ unsigned long rsslim; // (25) rsslim %lu
+ unsigned long startcode; // (26) startcode %lu [PT]
+ unsigned long endcode; // (27) endcode %lu [PT]
+ unsigned long startstack; // (28) startstack %lu [PT]
+ unsigned long kstkesp; // (29) kstkesp %lu [PT]
+ unsigned long kstkeip; // (30) kstkeip %lu [PT]
+ unsigned long signal; // (31) signal %lu
+ unsigned long blocked; // (32) blocked %lu
+ unsigned long sigignore; // (33) sigignore %lu
+ unsigned long sigcatch; // (34) sigcatch %lu
+ unsigned long wchan; // (35) wchan %lu [PT]
+ unsigned long nswap; // (36) nswap %lu
+ unsigned long cnswap; // (37) cnswap %lu
+ int exit_signal; // (38) exit_signal %d (since Linux 2.1.22)
+ int processor; // (39) processor %d (since Linux 2.2.8)
+ unsigned rt_priority; // (40) rt_priority %u (since Linux 2.5.19)
+ unsigned policy; // (41) policy %u (since Linux 2.5.19)
+ unsigned long long delayacct_blkio_ticks; // (42) delayacct_blkio_ticks
+ unsigned long guest_time; // (43) guest_time %lu (since Linux 2.6.24)
+ long int cguest_time; // (44) cguest_time %ld (since Linux 2.6.24)
+ unsigned long start_data; // (45) start_data %lu (since Linux 3.3) [PT]
+ unsigned long end_data; // (46) end_data %lu (since Linux 3.3) [PT]
+ unsigned long start_brk; // (47) start_brk %lu (since Linux 3.3) [PT]
+ unsigned long arg_start; // (48) arg_start %lu (since Linux 3.5) [PT]
+ unsigned long arg_end; // (49) arg_end %lu (since Linux 3.5) [PT]
+ unsigned long env_start; // (50) env_start %lu (since Linux 3.5) [PT]
+ unsigned long env_end; // (51) env_end %lu (since Linux 3.5) [PT]
+ int exit_code; // (52) exit_code %d (since Linux 3.5) [PT]
+} prom_process_stat_t;
+
+typedef prom_procfs_buf_t prom_process_stat_file_t;
+
+#endif // PROM_PROCESS_STATS_T_H \ No newline at end of file
diff --git a/prom/src/prom_procfs.c b/prom/src/prom_procfs.c
new file mode 100644
index 0000000..1bea1a3
--- /dev/null
+++ b/prom/src/prom_procfs.c
@@ -0,0 +1,104 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+// Public
+#include "prom_alloc.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_log.h"
+#include "prom_procfs_i.h"
+
+
+static int prom_procfs_ensure_buf_size(prom_procfs_buf_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self->allocated >= self->size+1) return 0;
+ while (self->allocated < self->size+1) self->allocated <<= 1;
+ self->buf = (char *) prom_realloc(self->buf, self->allocated);
+ return 0;
+}
+
+prom_procfs_buf_t* prom_procfs_buf_new(const char *path) {
+ int r = 0;
+
+ FILE *f = fopen(path, "r");
+ char errbuf[100];
+
+ if (f == NULL) {
+ strerror_r(errno, errbuf, 100);
+ PROM_LOG(errbuf);
+ return NULL;
+ }
+
+ #define PROM_PROCFS_BUF_NEW_HANDLE_F_CLOSE(f) \
+ r = fclose(f); \
+ if (r) { \
+ strerror_r(errno, errbuf, 100); \
+ PROM_LOG(errbuf); \
+ }
+
+ unsigned short int initial_size = 32;
+ prom_procfs_buf_t *self = prom_malloc(sizeof(prom_procfs_buf_t));
+ self->buf = prom_malloc(initial_size);
+ self->size = 0;
+ self->index = 0;
+ self->allocated = initial_size;
+
+ for (
+ int current_char = getc(f), i = 0;
+ current_char != EOF;
+ current_char = getc(f), i++
+ ) {
+ r = prom_procfs_ensure_buf_size(self);
+ if (r) {
+ prom_procfs_buf_destroy(self);
+ self = NULL;
+ PROM_PROCFS_BUF_NEW_HANDLE_F_CLOSE(f);
+ return NULL;
+ }
+ self->buf[i] = current_char;
+ self->size++;
+ }
+ r = prom_procfs_ensure_buf_size(self);
+ if (r) {
+ prom_procfs_buf_destroy(self);
+ self = NULL;
+ PROM_PROCFS_BUF_NEW_HANDLE_F_CLOSE(f);
+ return NULL;
+ }
+
+ self->buf[self->size] = '\0';
+ self->size++;
+
+ PROM_PROCFS_BUF_NEW_HANDLE_F_CLOSE(f);
+ if (r) return NULL;
+ return self;
+}
+
+int prom_procfs_buf_destroy(prom_procfs_buf_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+ prom_free(self->buf);
+ prom_free(self);
+ self = NULL;
+ return 0;
+}
diff --git a/prom/src/prom_procfs_i.h b/prom/src/prom_procfs_i.h
new file mode 100644
index 0000000..12c79ad
--- /dev/null
+++ b/prom/src/prom_procfs_i.h
@@ -0,0 +1,27 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PROM_PROCFS_I_H
+#define PROM_PROCFS_I_H
+
+#include "prom_procfs_t.h"
+
+prom_procfs_buf_t* prom_procfs_buf_new(const char *path);
+
+int prom_procfs_buf_destroy(prom_procfs_buf_t *self);
+
+#endif // PROM_PROCFS_I_H
+
diff --git a/prom/src/prom_procfs_t.h b/prom/src/prom_procfs_t.h
new file mode 100644
index 0000000..876af58
--- /dev/null
+++ b/prom/src/prom_procfs_t.h
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PROM_PROCFS_T_H
+#define PROM_PROCFS_T_H
+
+
+typedef struct prom_procfs_buf {
+ size_t allocated;
+ size_t size;
+ size_t index;
+ char *buf;
+} prom_procfs_buf_t;
+
+
+#endif // PROM_PROCFS_T_H \ No newline at end of file
diff --git a/prom/src/prom_string_builder.c b/prom/src/prom_string_builder.c
new file mode 100644
index 0000000..8d9ca89
--- /dev/null
+++ b/prom/src/prom_string_builder.c
@@ -0,0 +1,155 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stddef.h>
+
+// Public
+#include "prom_alloc.h"
+
+// Private
+#include "prom_assert.h"
+#include "prom_string_builder_i.h"
+#include "prom_string_builder_t.h"
+
+// The initial size of a string created via prom_string_builder
+#define PROM_STRING_BUILDER_INIT_SIZE 32
+
+// prom_string_builder_init prototype declaration
+int prom_string_builder_init(prom_string_builder_t *self);
+
+struct prom_string_builder {
+ char *str; /**< the target string */
+ size_t allocated; /**< the size allocated to the string in bytes */
+ size_t len; /**< the length of str */
+ size_t init_size; /**< the initialize size of space to allocate */
+};
+
+prom_string_builder_t* prom_string_builder_new(void) {
+ int r = 0;
+
+ prom_string_builder_t *self = (prom_string_builder_t*) prom_malloc(sizeof(prom_string_builder_t));
+ self->init_size = PROM_STRING_BUILDER_INIT_SIZE;
+ r = prom_string_builder_init(self);
+ if (r) {
+ prom_string_builder_destroy(self);
+ return NULL;
+ }
+
+ return self;
+}
+
+int prom_string_builder_init(prom_string_builder_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ self->str = (char*) prom_malloc(self->init_size);
+ *self->str = '\0';
+ self->allocated = self->init_size;
+ self->len = 0;
+ return 0;
+}
+
+
+int prom_string_builder_destroy(prom_string_builder_t *self) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 0;
+ prom_free(self->str);
+ self->str = NULL;
+ prom_free(self);
+ self = NULL;
+ return 0;
+}
+
+/**
+ * @brief API PRIVATE Grows the size of the string given the value we want to add
+ *
+ * The method continuously shifts left until the new size is large enough to accommodate add_len. This private method
+ * is called in methods that need to add one or more characters to the underlying string.
+ */
+static int prom_string_builder_ensure_space(prom_string_builder_t *self, size_t add_len) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (add_len == 0 || self->allocated >= self->len+add_len+1) return 0;
+ while (self->allocated < self->len+add_len+1) self->allocated <<= 1;
+ self->str = (char *) prom_realloc(self->str, self->allocated);
+ return 0;
+}
+
+int prom_string_builder_add_str(prom_string_builder_t *self, const char *str) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+
+ if (self == NULL) return 1;
+ if (str == NULL || *str == '\0') return 0;
+
+ size_t len = strlen(str);
+ r = prom_string_builder_ensure_space(self, len);
+ if (r) return r;
+
+ memcpy(self->str+self->len, str, len);
+ self->len += len;
+ self->str[self->len] = '\0';
+ return 0;
+}
+
+int prom_string_builder_add_char(prom_string_builder_t *self, char c) {
+ PROM_ASSERT(self != NULL);
+ int r = 0;
+
+ if (self == NULL) return 1;
+ r = prom_string_builder_ensure_space(self, 1);
+ if (r) return r;
+
+ self->str[self->len] = c;
+ self->len++;
+ self->str[self->len] = '\0';
+ return 0;
+}
+
+int prom_string_builder_truncate(prom_string_builder_t *self, size_t len) {
+ PROM_ASSERT(self != NULL);
+ if (self == NULL) return 1;
+ if (len >= self->len) return 0;
+
+ self->len = len;
+ self->str[self->len] = '\0';
+ return 0;
+}
+
+int prom_string_builder_clear(prom_string_builder_t *self) {
+ PROM_ASSERT(self != NULL);
+ prom_free(self->str);
+ self->str = NULL;
+ return prom_string_builder_init(self);
+}
+
+size_t prom_string_builder_len(prom_string_builder_t *self) {
+ PROM_ASSERT(self != NULL);
+ return self->len;
+}
+
+char* prom_string_builder_dump(prom_string_builder_t *self) {
+ PROM_ASSERT(self != NULL);
+ // +1 to accommodate \0
+ char* out = (char*) prom_malloc((self->len+1) * sizeof(char));
+ memcpy(out, self->str, self->len+1);
+ return out;
+}
+
+char* prom_string_builder_str(prom_string_builder_t *self) {
+ PROM_ASSERT(self != NULL);
+ return self->str;
+}
diff --git a/prom/src/prom_string_builder_i.h b/prom/src/prom_string_builder_i.h
new file mode 100644
index 0000000..a5cdf5c
--- /dev/null
+++ b/prom/src/prom_string_builder_i.h
@@ -0,0 +1,82 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef PROM_STRING_BUILDER_I_H
+#define PROM_STRING_BUILDER_I_H
+
+#include <stddef.h>
+
+#include "prom_string_builder_t.h"
+
+/**
+ * API PRIVATE
+ * @brief Constructor for prom_string_builder
+ */
+prom_string_builder_t *prom_string_builder_new(void);
+
+/**
+ * API PRIVATE
+ * @brief Destroys a prom_string_builder*
+ */
+int prom_string_builder_destroy(prom_string_builder_t *self);
+
+/**
+ * API PRIVATE
+ * @brief Adds a string
+ */
+int prom_string_builder_add_str(prom_string_builder_t *self, const char* str);
+
+
+/**
+ * API PRIVATE
+ * @brief Adds a char
+ */
+int prom_string_builder_add_char(prom_string_builder_t *self, char c);
+
+
+/**
+ * API PRIVATE
+ * @brief Clear the string
+ */
+int prom_string_builder_clear(prom_string_builder_t *self);
+
+/**
+ * API PRIVATE
+ * @brief Remove data from the end
+ */
+int prom_string_buillder_truncate(prom_string_builder_t *self, size_t len);
+
+/**
+ * API PRIVATE
+ * @brief Returns the length of the string
+ */
+size_t prom_string_builder_len(prom_string_builder_t *self);
+
+/**
+ * API PRIVATE
+ * @brief Returns a copy of the string. The returned string must be deallocated when no longer needed.
+ */
+char* prom_string_builder_dump(prom_string_builder_t *self);
+
+
+/**
+ * API PRIVATE
+ * @brief Getter for str member
+ */
+char* prom_string_builder_str(prom_string_builder_t *self);
+
+#endif // PROM_STRING_BUILDER_I_H
diff --git a/prom/src/prom_string_builder_t.h b/prom/src/prom_string_builder_t.h
new file mode 100644
index 0000000..7248733
--- /dev/null
+++ b/prom/src/prom_string_builder_t.h
@@ -0,0 +1,30 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+#ifndef PROM_STRING_BUILDER_T_H
+#define PROM_STRING_BUILDER_T_H
+
+
+struct prom_string_builder;
+/**
+ * @brief API PRIVATE A structure with functions responsible for building a string
+ */
+typedef struct prom_string_builder prom_string_builder_t;
+
+
+#endif // PROM_STRING_BUILDER_T_H \ No newline at end of file
diff --git a/prom/test/CMakeLists.txt b/prom/test/CMakeLists.txt
new file mode 100644
index 0000000..7939b7f
--- /dev/null
+++ b/prom/test/CMakeLists.txt
@@ -0,0 +1,69 @@
+enable_testing()
+set(vendor_dir ${CMAKE_SOURCE_DIR}/../vendor)
+set(test_dir ${CMAKE_SOURCE_DIR}/test)
+
+# Unity Dependency
+set(unity_version 2.4.3)
+set(unity_output ${build_dir}/unity-v${unity_version}.tar.gz)
+set(unity_package ${vendor_dir}/unity)
+set(unity_src ${vendor_dir}/Unity-${unity_version}/src)
+
+if(NOT EXISTS ${vendor_dir}/Unity-${unity_version})
+ execute_process(
+ COMMAND curl -L https://github.com/ThrowTheSwitch/Unity/archive/v${unity_version}.tar.gz
+ COMMAND tar xzvf - -C ${vendor_dir}
+ )
+endif()
+
+set(
+ unity_files
+ ${unity_src}/unity.c
+ ${unity_src}/unity.h
+ ${unity_src}/unity_internals.h
+)
+
+add_library(Unity SHARED)
+target_include_directories(Unity PUBLIC ${unity_src})
+target_sources(Unity PUBLIC ${unity_files})
+target_compile_options(Unity PUBLIC "-D UNITY_INCLUDE_DOUBLE")
+
+# promTest library exposes the headers in src for testing
+add_library(promTest STATIC)
+target_compile_options(promTest PUBLIC "-g3" "-Wall" "-DPROM_PROCESS_LIMITS_TEST_FILE_PATH=1" "-DPROM_ASSERT_ENABLE" "-DPROM_LOG_ENABLE")
+target_include_directories(
+ promTest
+ PUBLIC ${public_dir} ${private_dir} ${test_dir}
+)
+target_sources(promTest PUBLIC ${public_files} ${private_files})
+
+include(FindThreads)
+
+function(register_test test_name)
+ add_executable(${test_name} ${test_dir}/${test_name}.c ${test_dir}/prom_test_helpers.h ${test_dir}/prom_test_helpers.c)
+ target_link_libraries(${test_name} Unity promTest Threads::Threads)
+ add_test(
+ NAME ${test_name}
+ COMMAND ${test_name}
+ )
+endfunction()
+
+foreach(
+ t
+ prom_gauge_test
+ prom_collector_test
+ prom_collector_registry_test
+ prom_counter_test
+ prom_linked_list_test
+ prom_histogram_test
+ prom_histogram_buckets_test
+ prom_map_test
+ prom_metric_formatter_test
+ prom_metric_test
+ prom_metric_sample_test
+ prom_process_limits_test
+ prom_string_builder_test
+ prom_procfs_test
+
+)
+ register_test(${t})
+endforeach()
diff --git a/prom/test/fixtures/limits b/prom/test/fixtures/limits
new file mode 100644
index 0000000..27922b8
--- /dev/null
+++ b/prom/test/fixtures/limits
@@ -0,0 +1,17 @@
+Limit Soft Limit Hard Limit Units
+Max cpu time unlimited unlimited seconds
+Max file size unlimited unlimited bytes
+Max data size unlimited unlimited bytes
+Max stack size 8388608 unlimited bytes
+Max core file size 0 unlimited bytes
+Max resident set unlimited unlimited bytes
+Max processes unlimited unlimited processes
+Max open files 1048576 1048576 files
+Max locked memory 83968000 83968000 bytes
+Max address space unlimited unlimited bytes
+Max file locks unlimited unlimited locks
+Max pending signals 23701 23701 signals
+Max msgqueue size 819200 819200 bytes
+Max nice priority 0 0
+Max realtime priority 0 0
+Max realtime timeout unlimited unlimited us \ No newline at end of file
diff --git a/prom/test/fixtures/stat b/prom/test/fixtures/stat
new file mode 100644
index 0000000..346d44e
--- /dev/null
+++ b/prom/test/fixtures/stat
@@ -0,0 +1 @@
+1 (bash) S 0 1 1 34816 410 4210944 1463 89550 0 7 3 4 165 193 20 0 1 0 29414985 19058688 885 18446744073709551615 94298705027072 94298706087992 140736141303504 0 0 0 65536 3670020 1266777851 0 0 0 17 0 0 0 0 0 0 94298708188560 94298708235620 94298741563392 140736141311847 140736141311857 140736141311857 140736141311982 0 \ No newline at end of file
diff --git a/prom/test/prom_collector_registry_test.c b/prom/test/prom_collector_registry_test.c
new file mode 100644
index 0000000..2229ea7
--- /dev/null
+++ b/prom/test/prom_collector_registry_test.c
@@ -0,0 +1,116 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "prom_test_helpers.h"
+
+
+static void prom_registry_test_init(void);
+static void prom_registry_test_destroy(void);
+
+prom_counter_t *test_counter;
+prom_gauge_t *test_gauge;
+prom_histogram_t *test_histogram;
+
+void test_large_registry(void) {
+ prom_collector_registry_default_init();
+ for (int i = 0; i < 1000; i++) {
+ char metric[6];
+ sprintf(metric, "%d", i);
+ prom_collector_registry_must_register_metric(prom_counter_new(metric, metric, 0, NULL));
+ }
+ prom_registry_test_destroy();
+}
+
+
+void test_prom_collector_registry_must_register(void) {
+ prom_registry_test_init();
+ int r = 0;
+
+ const char *labels[] = { "foo" };
+ r = prom_counter_inc(test_counter, labels);
+ if (r) TEST_FAIL();
+ r = prom_gauge_add(test_gauge, 2.0, labels);
+ if (r) TEST_FAIL();
+
+ prom_metric_sample_t *test_sample_a = prom_metric_sample_from_labels(test_counter, labels);
+ prom_metric_sample_t *test_sample_b = prom_metric_sample_from_labels(test_gauge, labels);
+
+ TEST_ASSERT_EQUAL_DOUBLE(1.0, test_sample_a->r_value);
+ TEST_ASSERT_EQUAL_DOUBLE(2.0, test_sample_b->r_value);
+ prom_registry_test_destroy();
+}
+
+void test_prom_collector_registry_bridge(void) {
+ prom_registry_test_init();
+ int r = 0;
+
+ if (test_histogram == NULL) TEST_FAIL_MESSAGE("histogram failed to initialize");
+
+ const char *labels[] = { "foo" };
+ prom_counter_inc(test_counter, labels);
+ prom_gauge_set(test_gauge, 2.0, labels);
+ r = prom_histogram_observe(test_histogram, 3.0, NULL);
+ if (r) TEST_FAIL();
+ r = prom_histogram_observe(test_histogram, 7.0, NULL);
+ if (r) TEST_FAIL();
+
+ const char *result = prom_collector_registry_bridge(PROM_COLLECTOR_REGISTRY_DEFAULT);
+
+ const char *expected = "# HELP test_counter counter under test\n# TYPE test_counter counter\ntest_counter{label=\"foo\"} 1.000000\n\n# HELP test_gauge gauge under test\n# TYPE test_gauge gauge\ntest_gauge{label=\"foo\"} 2.000000\n\n# HELP test_histogram histogram under test\n# TYPE test_histogram histogram\ntest_histogram{le=\"5.000000\"} 1.000000\ntest_histogram{le=\"10.000000\"} 2.000000\ntest_histogram{le=\"+Inf\"} 2.000000\ntest_histogram_count 2.000000\ntest_histogram_sum 10.000000\n\n# HELP process_max_fds Maximum number of open file descriptors.\n# TYPE process_max_fds gauge\nprocess_max_fds 1048576.000000\n\n# HELP process_virtual_memory_max_bytes Maximum amount of virtual memory available in bytes.\n# TYPE process_virtual_memory_max_bytes gauge\nprocess_virtual_memory_max_bytes -1.000000\n\n";
+ TEST_ASSERT_NOT_NULL(strstr(result, expected));
+ free((char *) result);
+ result = NULL;
+
+ prom_registry_test_destroy();
+}
+
+void test_prom_collector_registry_validate_metric_name(void){
+ prom_registry_test_init();
+
+ TEST_ASSERT_EQUAL_INT(0, prom_collector_registry_validate_metric_name(PROM_COLLECTOR_REGISTRY_DEFAULT, "this_is_a_name09"));
+ prom_registry_test_destroy();
+}
+
+void prom_registry_test_init(void) {
+ prom_collector_registry_default_init();
+ const char *label[] = { "label" };
+ test_counter = prom_collector_registry_must_register_metric(prom_counter_new(
+ "test_counter", "counter under test", 1, label
+ ));
+ test_gauge = prom_collector_registry_must_register_metric(prom_gauge_new(
+ "test_gauge", "gauge under test", 1, label
+ ));
+ test_histogram = prom_collector_registry_must_register_metric(prom_histogram_new(
+ "test_histogram", "histogram under test", prom_histogram_buckets_linear(5.0, 5.0, 2), 0, NULL
+ ));
+}
+
+static void prom_registry_test_destroy(void) {
+ int r = 0;
+ r = prom_collector_registry_destroy(PROM_COLLECTOR_REGISTRY_DEFAULT);
+ PROM_COLLECTOR_REGISTRY_DEFAULT = NULL;
+ if (r) TEST_FAIL_MESSAGE("failed to destroy PROM_COLLECTOR_REGISTRY_DEFAULT");
+}
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ // RUN_TEST(test_prom_collector_registry_must_register);
+ RUN_TEST(test_prom_collector_registry_bridge);
+ // RUN_TEST(test_prom_collector_registry_validate_metric_name);
+ // RUN_TEST(test_large_registry);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_collector_test.c b/prom/test/prom_collector_test.c
new file mode 100644
index 0000000..95576a9
--- /dev/null
+++ b/prom/test/prom_collector_test.c
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "prom_test_helpers.h"
+
+void test_prom_collector(void) {
+ prom_collector_t *collector = prom_collector_new("test");
+ prom_counter_t *counter = prom_counter_new( "test_counter", "counter under test", 0, NULL);
+ prom_collector_add_metric(collector, counter);
+ prom_map_t *m = collector->collect_fn(collector);
+ TEST_ASSERT_EQUAL_INT(1, prom_map_size(m));
+ prom_collector_destroy(collector);
+ collector = NULL;
+}
+
+void test_prom_process_collector(void) {
+ prom_collector_t *collector = prom_collector_process_new(
+ "/code/prom/test/fixtures/limits", "/code/prom/test/fixtures/stat"
+ );
+ prom_map_t *m = collector->collect_fn(collector);
+ TEST_ASSERT_EQUAL_INT(6, prom_map_size(m));
+ prom_collector_destroy(collector);
+ collector = NULL;
+}
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_prom_collector);
+ RUN_TEST(test_prom_process_collector);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_counter_test.c b/prom/test/prom_counter_test.c
new file mode 100644
index 0000000..855a8a1
--- /dev/null
+++ b/prom/test/prom_counter_test.c
@@ -0,0 +1,60 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include "prom_test_helpers.h"
+
+
+const char *sample_labels_a[] = {"f", "b"};
+const char *sample_labels_b[] = {"o", "r"};
+
+void test_counter_inc(void) {
+ prom_counter_t *c = prom_counter_new("test_counter", "counter under test", 2, (const char *[]) { "foo", "bar" });
+ TEST_ASSERT(c);
+
+ prom_counter_inc(c, sample_labels_a);
+
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(c, sample_labels_a);
+ TEST_ASSERT_EQUAL_DOUBLE(1.0, sample->r_value);
+
+ sample = prom_metric_sample_from_labels(c, sample_labels_b);
+ TEST_ASSERT_EQUAL_DOUBLE(0.0, sample->r_value);
+
+ prom_counter_destroy(c);
+ c = NULL;
+}
+
+void test_counter_add(void) {
+ prom_counter_t *c = prom_counter_new("test_counter", "counter under test", 2, (const char *[]) { "foo", "bar"});
+ TEST_ASSERT(c);
+
+ prom_counter_add(c, 100000000.1, sample_labels_a);
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(c, sample_labels_a);
+ TEST_ASSERT_EQUAL_DOUBLE(100000000.1, sample->r_value);
+
+ sample = prom_metric_sample_from_labels(c, sample_labels_b);
+ TEST_ASSERT_EQUAL_DOUBLE(0.0, sample->r_value);
+
+ prom_counter_destroy(c);
+ c = NULL;
+}
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_counter_inc);
+ RUN_TEST(test_counter_add);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_gauge_test.c b/prom/test/prom_gauge_test.c
new file mode 100644
index 0000000..88e7c72
--- /dev/null
+++ b/prom/test/prom_gauge_test.c
@@ -0,0 +1,116 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "prom_test_helpers.h"
+
+
+const char *sample_labels_a[] = {"f", "b"};
+const char *sample_labels_b[] = {"o", "r"};
+
+void test_gauge_inc(void) {
+ prom_gauge_t *g = prom_gauge_new("test_gauge", "gauge under test", 2, (const char *[]) { "foo", "bar" });
+ TEST_ASSERT(g);
+
+ prom_gauge_inc(g, sample_labels_a);
+
+
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(g, sample_labels_a);
+
+ TEST_ASSERT_EQUAL_DOUBLE(1.0, sample->r_value);
+
+ sample = prom_metric_sample_from_labels(g, sample_labels_b);
+ TEST_ASSERT_EQUAL_DOUBLE(0.0, sample->r_value);
+
+ prom_gauge_destroy(g);
+ g = NULL;
+}
+
+void test_gauge_dec(void) {
+ prom_gauge_t *g = prom_gauge_new("test_gauge", "gauge under test", 2, (const char *[]) { "foo", "bar" });
+ TEST_ASSERT(g);
+
+ prom_gauge_dec(g, sample_labels_a);
+
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(g, sample_labels_a);
+ TEST_ASSERT_EQUAL_DOUBLE(-1.0, sample->r_value);
+
+ sample = prom_metric_sample_from_labels(g, sample_labels_b);
+ TEST_ASSERT_EQUAL_DOUBLE(0.0, sample->r_value);
+
+ prom_gauge_destroy(g);
+ g = NULL;
+}
+
+void test_gauge_add(void) {
+ prom_gauge_t *g = prom_gauge_new("test_gauge", "gauge under test", 2, (const char *[]) { "foo", "bar" });
+ TEST_ASSERT(g);
+
+ prom_gauge_add(g, 100000000.1, sample_labels_a);
+
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(g, sample_labels_a);
+ TEST_ASSERT_EQUAL_DOUBLE(100000000.1, sample->r_value);
+
+ sample = prom_metric_sample_from_labels(g, sample_labels_b);
+ TEST_ASSERT_EQUAL_DOUBLE(0.0, sample->r_value);
+
+ prom_gauge_destroy(g);
+ g = NULL;
+}
+
+void test_gauge_sub(void) {
+ prom_gauge_t *g = prom_gauge_new("test_gauge", "gauge under test", 2, (const char *[]) { "foo", "bar" });
+ TEST_ASSERT(g);
+
+ prom_gauge_sub(g, 100000000.1, sample_labels_a);
+
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(g, sample_labels_a);
+ TEST_ASSERT_EQUAL_DOUBLE(-100000000.1, sample->r_value);
+
+ sample = prom_metric_sample_from_labels(g, sample_labels_b);
+ TEST_ASSERT_EQUAL_DOUBLE(0.0, sample->r_value);
+
+ prom_gauge_destroy(g);
+ g = NULL;
+}
+
+
+void test_gauge_set(void) {
+ prom_gauge_t *g = prom_gauge_new("test_gauge", "gauge under test", 2, (const char *[]) { "foo", "bar" });
+ TEST_ASSERT(g);
+
+ prom_gauge_set(g, 100000000.1, sample_labels_a);
+
+ prom_metric_sample_t *sample = prom_metric_sample_from_labels(g, sample_labels_a);
+ TEST_ASSERT_EQUAL_DOUBLE(100000000.1, sample->r_value);
+
+ sample = prom_metric_sample_from_labels(g, sample_labels_b);
+ TEST_ASSERT_EQUAL_DOUBLE(0.0, sample->r_value);
+
+ prom_gauge_destroy(g);
+ g = NULL;
+}
+
+
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_gauge_inc);
+ RUN_TEST(test_gauge_dec);
+ RUN_TEST(test_gauge_add);
+ RUN_TEST(test_gauge_sub);
+ RUN_TEST(test_gauge_set);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_histogram_buckets_test.c b/prom/test/prom_histogram_buckets_test.c
new file mode 100644
index 0000000..72018ce
--- /dev/null
+++ b/prom/test/prom_histogram_buckets_test.c
@@ -0,0 +1,54 @@
+
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "prom_test_helpers.h"
+
+void test_prom_histogram_buckets_new(void) {
+ prom_histogram_buckets_t *result = prom_histogram_buckets_new(3, 1.0, 2.0, 3.0);
+ TEST_ASSERT_EQUAL_DOUBLE(1.0, result->upper_bounds[0]);
+ TEST_ASSERT_EQUAL_DOUBLE(2.0, result->upper_bounds[1]);
+ TEST_ASSERT_EQUAL_DOUBLE(3.0, result->upper_bounds[2]);
+ prom_histogram_buckets_destroy(result);
+ result = NULL;
+}
+
+
+void test_prom_histogram_buckets_linear(void){
+ prom_histogram_buckets_t *result = prom_histogram_buckets_linear(0.0, 1.5, 3);
+ TEST_ASSERT_EQUAL_DOUBLE(0.0, result->upper_bounds[0]);
+ TEST_ASSERT_EQUAL_DOUBLE(1.5, result->upper_bounds[1]);
+ TEST_ASSERT_EQUAL_DOUBLE(3.0, result->upper_bounds[2]);
+ prom_histogram_buckets_destroy(result);
+ result = NULL;
+}
+
+void test_prom_histogram_buckets_expontential(void) {
+ prom_histogram_buckets_t *result = prom_histogram_buckets_exponential(1, 2, 3);
+ TEST_ASSERT_EQUAL_DOUBLE(1.0, result->upper_bounds[0]);
+ TEST_ASSERT_EQUAL_DOUBLE(2.0, result->upper_bounds[1]);
+ TEST_ASSERT_EQUAL_DOUBLE(4.0, result->upper_bounds[2]);
+ prom_histogram_buckets_destroy(result);
+}
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_prom_histogram_buckets_new);
+ RUN_TEST(test_prom_histogram_buckets_linear);
+ RUN_TEST(test_prom_histogram_buckets_expontential);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_histogram_test.c b/prom/test/prom_histogram_test.c
new file mode 100644
index 0000000..9fe3f33
--- /dev/null
+++ b/prom/test/prom_histogram_test.c
@@ -0,0 +1,84 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "prom_test_helpers.h"
+
+
+void test_prom_histogram(void){
+ prom_histogram_t *h = prom_histogram_new(
+ "test_histogram", "histogram under test", prom_histogram_buckets_linear(5.0, 5.0, 3), 0, NULL
+ );
+
+ prom_histogram_observe(h, 1.0, NULL);
+ prom_histogram_observe(h, 7.0, NULL);
+ prom_histogram_observe(h, 11.0, NULL);
+ prom_histogram_observe(h, 22.0, NULL);
+
+ prom_metric_sample_histogram_t *h_sample = prom_metric_sample_histogram_from_labels(h, NULL);
+
+ // Test counter for each bucket
+ char *bucket_key = prom_metric_sample_histogram_bucket_to_str(5.0);
+ const char *l_value = prom_map_get(h_sample->l_values, bucket_key);
+ prom_metric_sample_t *sample = (prom_metric_sample_t*) prom_map_get(h_sample->samples, l_value);
+ TEST_ASSERT_EQUAL_STRING("test_histogram{le=\"5.000000\"}", sample->l_value);
+ TEST_ASSERT_EQUAL_DOUBLE(1.0, sample->r_value);
+ free((char *) bucket_key);
+ bucket_key = NULL;
+
+ bucket_key = prom_metric_sample_histogram_bucket_to_str(10.0);
+ l_value = prom_map_get(h_sample->l_values, bucket_key);
+ sample = (prom_metric_sample_t*) prom_map_get(h_sample->samples, l_value);
+ TEST_ASSERT_EQUAL_STRING("test_histogram{le=\"10.000000\"}", sample->l_value);
+ TEST_ASSERT_EQUAL_DOUBLE(2.0, sample->r_value);
+ free((char *) bucket_key);
+ bucket_key = NULL;
+
+ bucket_key = prom_metric_sample_histogram_bucket_to_str(15.0);
+ l_value = prom_map_get(h_sample->l_values, bucket_key);
+ sample = (prom_metric_sample_t*) prom_map_get(h_sample->samples, l_value);
+ TEST_ASSERT_EQUAL_STRING("test_histogram{le=\"15.000000\"}", sample->l_value);
+ TEST_ASSERT_EQUAL_DOUBLE(3.0, sample->r_value);
+ free((char *) bucket_key);
+ bucket_key = NULL;
+
+ l_value = prom_map_get(h_sample->l_values, "+Inf");
+ sample = (prom_metric_sample_t*) prom_map_get(h_sample->samples, l_value);
+ TEST_ASSERT_EQUAL_STRING("test_histogram{le=\"+Inf\"}", sample->l_value);
+ TEST_ASSERT_EQUAL_DOUBLE(4.0, sample->r_value);
+
+ // Test total count. Should equal value ini +Inf
+ l_value = prom_map_get(h_sample->l_values, "count");
+ prom_metric_sample_t *sample_count = (prom_metric_sample_t*) prom_map_get(h_sample->samples, l_value);
+ TEST_ASSERT_EQUAL_STRING("test_histogram_count", sample_count->l_value);
+ TEST_ASSERT_EQUAL_DOUBLE(4.0, sample_count->r_value);
+
+ // Test sum
+ l_value = prom_map_get(h_sample->l_values, "sum");
+ sample = (prom_metric_sample_t*) prom_map_get(h_sample->samples, l_value);
+ TEST_ASSERT_EQUAL_STRING("test_histogram_sum", sample->l_value);
+ TEST_ASSERT_EQUAL_DOUBLE(41.0, sample->r_value);
+
+ prom_histogram_destroy(h);
+ h = NULL;
+}
+
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_prom_histogram);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_linked_list_test.c b/prom/test/prom_linked_list_test.c
new file mode 100644
index 0000000..4e610b0
--- /dev/null
+++ b/prom/test/prom_linked_list_test.c
@@ -0,0 +1,107 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "prom_test_helpers.h"
+
+
+void test_prom_linked_list_append(void) {
+ prom_linked_list_t *l = prom_linked_list_new();
+ TEST_ASSERT(l);
+ prom_linked_list_set_free_fn(l, prom_linked_list_no_op_free);
+
+ char *one = "one";
+ char *two = "two";
+ char *three = "three";
+
+ prom_linked_list_append(l, one);
+ prom_linked_list_append(l, two);
+ prom_linked_list_append(l, three);
+
+ prom_linked_list_node_t* current_node = l->head;
+ char *current_str = (char *) current_node->item;
+ TEST_ASSERT_EQUAL_STRING("one", current_str);
+ current_node = current_node->next;
+ current_str = current_node->item;
+ TEST_ASSERT_EQUAL_STRING("two", current_str);
+ current_node = current_node->next;
+ current_str = current_node->item;
+ TEST_ASSERT_EQUAL_STRING("three", current_str);
+
+ prom_linked_list_destroy(l);
+ l = NULL;
+}
+
+void test_prom_linked_list_push(void) {
+ prom_linked_list_t *l = prom_linked_list_new();
+ TEST_ASSERT(l);
+ prom_linked_list_set_free_fn(l, prom_linked_list_no_op_free);
+
+ char *one = "one";
+ char *two = "two";
+ char *three = "three";
+
+ prom_linked_list_push(l, one);
+ prom_linked_list_push(l, two);
+ prom_linked_list_push(l, three);
+
+ prom_linked_list_node_t* current_node = l->head;
+ char *current_str = (char *) current_node->item;
+ TEST_ASSERT_EQUAL_STRING("three", current_str);
+ current_node = current_node->next;
+ current_str = current_node->item;
+ TEST_ASSERT_EQUAL_STRING("two", current_str);
+ current_node = current_node->next;
+ current_str = current_node->item;
+ TEST_ASSERT_EQUAL_STRING("one", current_str);
+
+ prom_linked_list_destroy(l);
+ l = NULL;
+}
+
+void test_prom_linked_list_remove(void) {
+ auto prom_linked_list_compare_t compare_fn(void *item_a, void *item_b) {
+ const char *str_a = (const char *) item_a;
+ const char *str_b = (const char *) item_b;
+ return strcmp(str_a, str_b);
+ }
+
+ prom_linked_list_t *list = prom_linked_list_new();
+ prom_linked_list_set_free_fn(list, prom_linked_list_no_op_free);
+ prom_linked_list_set_compare_fn(list, compare_fn);
+
+ prom_linked_list_append(list, "node_a");
+ prom_linked_list_append(list, "node_b");
+ prom_linked_list_append(list, "node_c");
+
+ prom_linked_list_remove(list, "node_b");
+ const char *result_a = list->head->item;
+ TEST_ASSERT_EQUAL_STRING("node_a", result_a);
+ const char *result_c = list->head->next->item;
+ TEST_ASSERT_EQUAL_STRING("node_c", result_c);
+
+ prom_linked_list_destroy(list);
+ list = NULL;
+}
+
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_prom_linked_list_append);
+ RUN_TEST(test_prom_linked_list_push);
+ RUN_TEST(test_prom_linked_list_remove);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_map_test.c b/prom/test/prom_map_test.c
new file mode 100644
index 0000000..2241988
--- /dev/null
+++ b/prom/test/prom_map_test.c
@@ -0,0 +1,101 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "prom_test_helpers.h"
+
+
+void test_prom_map(void) {
+ prom_map_t *map = prom_map_new();
+ prom_map_set(map, "foo", "bar");
+ prom_map_set(map, "bing", "bang");
+ TEST_ASSERT_EQUAL_STRING("bar", (const char*) prom_map_get(map, "foo"));
+ TEST_ASSERT_EQUAL_STRING("bang", (const char*) prom_map_get(map, "bing"));
+ TEST_ASSERT_NULL(prom_map_get(map, "nope"));
+ TEST_ASSERT_EQUAL_INT(2, prom_map_size(map));
+
+ for (
+ prom_linked_list_node_t *current_node = map->keys->head;
+ current_node != NULL;
+ current_node = current_node->next
+ ) {
+ const char *key = (const char *) current_node->item;
+
+ const char *expected;
+ if (strcmp(key, "foo") == 0) {
+ expected = "bar";
+ } else if (strcmp(key, "bing") == 0) {
+ expected = "bang";
+ }
+
+ const char *result = prom_map_get(map, key);
+
+ TEST_ASSERT_EQUAL_STRING(expected, result);
+ }
+
+ prom_map_destroy(map);
+ map = NULL;
+}
+
+void test_prom_map_when_large(void) {
+
+ prom_map_t *map = prom_map_new();
+ prom_map_set_free_value_fn(map, free);
+
+ // Ensure each inserted key and value are present
+ for (int i = 1; i <= 10000; i++) {
+ char buf[4];
+ sprintf(buf, "%d", i);
+ const char *k = (const char *) buf;
+ int *set = malloc(sizeof(int));
+ *set = i;
+ prom_map_set(map, k, (void *) set);
+ TEST_ASSERT_EQUAL_INT(i, *((int*) prom_map_get(map, k)));
+ }
+
+ // Update one of the keys
+ int *at_50 = malloc(sizeof(int));
+ *at_50 = 5000;
+ prom_map_set(map, "50", (void *) at_50);
+ TEST_ASSERT_EQUAL_INT(5000, *((int*) prom_map_get(map, "50")));
+
+ // Ensure each key and value is correct
+ for (int i = 1; i <= 10000; i++) {
+ char buf[5];
+ sprintf(buf, "%d", i);
+ const char *k = (const char *) buf;
+ int actual = *((int*) prom_map_get(map, k));
+ if (i == 50) {
+ TEST_ASSERT_EQUAL_INT(5000, actual);
+ } else {
+ TEST_ASSERT_EQUAL_INT(i, actual);
+ }
+ }
+
+ // Ensure the size and max_size are correct
+ TEST_ASSERT_EQUAL_INT(10000, map->size);
+ TEST_ASSERT_EQUAL_INT(32768, map->max_size);
+
+ prom_map_destroy(map);
+ map = NULL;
+}
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_prom_map);
+ RUN_TEST(test_prom_map_when_large);
+ return UNITY_END();
+}
diff --git a/prom/test/prom_metric_formatter_test.c b/prom/test/prom_metric_formatter_test.c
new file mode 100644
index 0000000..c774620
--- /dev/null
+++ b/prom/test/prom_metric_formatter_test.c
@@ -0,0 +1,117 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "prom_test_helpers.h"
+
+
+void test_prom_metric_formatter_load_l_value(void) {
+ prom_metric_formatter_t *mf = prom_metric_formatter_new();
+ const char *keys[] = { "foo", "bar", "bing" };
+ const char *values[] = { "one", "two", "three" };
+ prom_metric_formatter_load_l_value(mf, "test", NULL, 3, keys, values);
+ char *actual = prom_metric_formatter_dump(mf);
+ char *expected = "test{foo=\"one\",bar=\"two\",bing=\"three\"}";
+ TEST_ASSERT_EQUAL_STRING(expected, actual);
+
+ free(actual);
+ actual = NULL;
+ prom_metric_formatter_destroy(mf);
+ mf = NULL;
+}
+
+void test_prom_metric_formatter_load_sample(void) {
+ prom_metric_formatter_t *mf = prom_metric_formatter_new();
+ const char *l_value = "test{foo=\"one\",bar=\"two\",bing=\"three\"}";
+ prom_metric_sample_t *sample = prom_metric_sample_new(PROM_COUNTER, l_value, 22.2);
+ prom_metric_formatter_load_sample(mf, sample);
+ char *actual = prom_metric_formatter_dump(mf);
+ char *expected = "test{foo=\"one\",bar=\"two\",bing=\"three\"} 22.200000\n";
+ TEST_ASSERT_EQUAL_STRING(expected, actual);
+
+ free(actual);
+ actual = NULL;
+ prom_metric_sample_destroy(sample);
+ prom_metric_formatter_destroy(mf);
+ mf = NULL;
+}
+
+void test_prom_metric_formatter_load_metric(void){
+ prom_metric_formatter_t *mf = prom_metric_formatter_new();
+ const char *counter_keys[] = { "foo", "bar" };
+ const char *sample_a[] = { "f", "b" };
+ const char *sample_b[] = { "o", "r" };
+ prom_metric_t *m = prom_metric_new(PROM_COUNTER, "test_counter", "counter under test", 2, counter_keys);
+ prom_metric_sample_t *s_a = prom_metric_sample_from_labels(m, sample_a);
+ prom_metric_sample_add(s_a, 2.3);
+ prom_metric_sample_t *s_b = prom_metric_sample_from_labels(m, sample_b);
+ prom_metric_sample_add(s_b, 4.6);
+ prom_metric_formatter_load_metric(mf, m);
+ const char *result = prom_metric_formatter_dump(mf);
+
+ TEST_ASSERT_EQUAL_STRING("# HELP test_counter counter under test\n# TYPE test_counter counter\ntest_counter{foo=\"f\",bar=\"b\"} 2.300000\ntest_counter{foo=\"o\",bar=\"r\"} 4.600000\n\n", result);
+
+ free((char *) result);
+ result = NULL;
+ prom_metric_destroy(m);
+ m = NULL;
+ prom_metric_formatter_destroy(mf);
+ mf = NULL;
+}
+
+void test_prom_metric_formatter_load_metrics(void) {
+ int r = 0;
+
+ prom_metric_formatter_t *mf = prom_metric_formatter_new();
+ const char *counter_keys[] = {};
+ prom_collector_registry_default_init();
+ prom_metric_t *m_a = prom_metric_new(PROM_COUNTER, "test_counter_a", "counter under test", 0, counter_keys);
+ prom_metric_t *m_b = prom_metric_new(PROM_COUNTER, "test_counter_b", "counter under test", 0, counter_keys);
+ prom_metric_sample_t *s_a = prom_metric_sample_from_labels(m_a, counter_keys);
+ prom_metric_sample_add(s_a, 2.3);
+ prom_metric_sample_t *s_b = prom_metric_sample_from_labels(m_b, counter_keys);
+ prom_metric_sample_add(s_b, 4.6);
+ prom_collector_registry_register_metric(m_a);
+ prom_collector_registry_register_metric(m_b);
+
+ prom_metric_formatter_load_metrics(mf, PROM_COLLECTOR_REGISTRY_DEFAULT->collectors);
+
+ const char *result = prom_metric_formatter_dump(mf);
+ const char *expected = "# HELP test_counter_a counter under test\n# TYPE test_counter_a counter\ntest_counter_a 2.300000\n\n# HELP test_counter_b counter under test\n# TYPE test_counter_b counter\ntest_counter_b 4.600000\n\n# HELP process_max_fds Maximum number of open file descriptors.\n# TYPE process_max_fds gauge\nprocess_max_fds 1048576.000000\n\n# HELP process_virtual_memory_max_bytes Maximum amount of virtual memory available in bytes.\n# TYPE process_virtual_memory_max_bytes gauge\nprocess_virtual_memory_max_bytes -1.000000\n\n";
+ TEST_ASSERT_NOT_NULL(strstr(result, expected));
+ free((char *) result);
+ result = NULL;
+
+ r = prom_metric_formatter_destroy(mf);
+ if (r) {
+ TEST_FAIL_MESSAGE("Failed to destroy metric formatter");
+ }
+ mf = NULL;
+ r = prom_collector_registry_destroy(PROM_COLLECTOR_REGISTRY_DEFAULT);
+ if (r) {
+ TEST_FAIL_MESSAGE("Failed to destroy default collector registry");
+ }
+ PROM_COLLECTOR_REGISTRY_DEFAULT = NULL;
+}
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_prom_metric_formatter_load_l_value);
+ RUN_TEST(test_prom_metric_formatter_load_sample);
+ RUN_TEST(test_prom_metric_formatter_load_metric);
+ RUN_TEST(test_prom_metric_formatter_load_metrics);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_metric_sample_test.c b/prom/test/prom_metric_sample_test.c
new file mode 100644
index 0000000..d2a42bb
--- /dev/null
+++ b/prom/test/prom_metric_sample_test.c
@@ -0,0 +1,75 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+#include "prom_test_helpers.h"
+
+
+const char* l_value = "test{foo=\"bar\"}";
+
+void test_prom_metric_sample_add(void) {
+ prom_metric_sample_t *s = prom_metric_sample_new(PROM_COUNTER, l_value, 0.0);
+ TEST_ASSERT(s);
+
+ prom_metric_sample_add(s, 2.6);
+ TEST_ASSERT_EQUAL_DOUBLE(2.6, s->r_value);
+
+ prom_metric_sample_add(s, 29.9);
+ TEST_ASSERT_EQUAL_DOUBLE(32.5, s->r_value);
+
+ prom_metric_sample_add(s, 1000001.125);
+ TEST_ASSERT_EQUAL_DOUBLE(1000033.625, s->r_value);
+
+ prom_metric_sample_destroy(s);
+ s = NULL;
+}
+
+void test_prom_metric_sample_sub(void) {
+ prom_metric_sample_t *s = prom_metric_sample_new(PROM_GAUGE, l_value, 100.1145321);
+ TEST_ASSERT(s);
+
+ prom_metric_sample_sub(s, 99.91);
+ TEST_ASSERT_EQUAL_DOUBLE(0.20453210000000865, s->r_value);
+
+ prom_metric_sample_sub(s, 0.20453210000000865);
+ TEST_ASSERT_EQUAL_DOUBLE(0.0, s->r_value);
+
+ prom_metric_sample_destroy(s);
+ s = NULL;
+}
+
+void test_prom_metric_set(void) {
+ prom_metric_sample_t *s = prom_metric_sample_new(PROM_GAUGE, l_value, 100.1145321);
+ TEST_ASSERT(s);
+
+ prom_metric_sample_set(s, 99.91);
+ TEST_ASSERT_EQUAL_DOUBLE(99.91, s->r_value);
+
+ prom_metric_sample_set(s, 0.20453210000000865);
+ TEST_ASSERT_EQUAL_DOUBLE(0.20453210000000865, s->r_value);
+
+ prom_metric_sample_destroy(s);
+ s = NULL;
+}
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_prom_metric_sample_add);
+ RUN_TEST(test_prom_metric_sample_sub);
+ RUN_TEST(test_prom_metric_set);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_metric_test.c b/prom/test/prom_metric_test.c
new file mode 100644
index 0000000..959060f
--- /dev/null
+++ b/prom/test/prom_metric_test.c
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "prom_test_helpers.h"
+
+void test_metric_with_no_labels(void) {
+ prom_metric_t *metric = prom_metric_new(PROM_GAUGE, "test_counter", "counter under test", 0, NULL);
+ prom_metric_sample_t* sample = prom_metric_sample_from_labels(metric, NULL);
+ prom_metric_sample_set(sample, 1.0);
+ sample = prom_metric_sample_from_labels(metric, NULL);
+ TEST_ASSERT_EQUAL_DOUBLE(1.0, (_Atomic double) sample->r_value);
+ prom_metric_destroy(metric);
+ metric = NULL;
+}
+
+
+void test_metric_sample_from_labels(void) {
+ prom_metric_t *metric = prom_metric_new(PROM_GAUGE, "test_metric", "test counter", 2, (const char *[]) {"foo", "bar"});
+ const char *values[] = { "bing", "bang" };
+ prom_metric_sample_t* sample = prom_metric_sample_from_labels(metric, values);
+ prom_metric_sample_set(sample, 1.0);
+ sample = prom_metric_sample_from_labels(metric, values);
+ TEST_ASSERT_EQUAL_DOUBLE(1.0, (_Atomic double) sample->r_value);
+ prom_metric_destroy(metric);
+ metric = NULL;
+}
+
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_metric_with_no_labels);
+ RUN_TEST(test_metric_sample_from_labels);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_process_limits_test.c b/prom/test/prom_process_limits_test.c
new file mode 100644
index 0000000..05dc511
--- /dev/null
+++ b/prom/test/prom_process_limits_test.c
@@ -0,0 +1,217 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "unity.h"
+
+#include "prom_map_i.h"
+#include "prom_process_limits_i.h"
+#include "prom_process_limits_t.h"
+
+const char *path = "/code/prom/test/fixtures/limits";
+
+void test_prom_process_limits_file_parsing(void) {
+ prom_process_limits_file_t *f = prom_process_limits_file_new(path);
+ char *result = strstr(f->buf, "Max realtime timeout");
+ TEST_ASSERT_NOT_NULL(result);
+
+ prom_map_t *m = prom_process_limits(f);
+ if (!m) TEST_FAIL();
+
+ TEST_ASSERT_EQUAL_INT(16, prom_map_size(m));
+
+ prom_process_limits_row_t *row = (prom_process_limits_row_t*) prom_map_get(m, "Max cpu time");
+ if (!row) TEST_FAIL();
+ TEST_ASSERT_EQUAL_INT(-1, row->soft);
+ TEST_ASSERT_EQUAL_INT(-1, row->hard);
+ TEST_ASSERT_EQUAL_STRING("Max cpu time", row->limit);
+ TEST_ASSERT_EQUAL_STRING("seconds", row->units);
+
+ row = (prom_process_limits_row_t*) prom_map_get(m, "Max file size");
+ TEST_ASSERT_EQUAL_INT(-1, row->soft);
+ TEST_ASSERT_EQUAL_INT(-1, row->hard);
+ TEST_ASSERT_EQUAL_STRING("Max file size", row->limit);
+ TEST_ASSERT_EQUAL_STRING("bytes", row->units);
+
+ row = (prom_process_limits_row_t*) prom_map_get(m, "Max data size");
+ TEST_ASSERT_EQUAL_INT(-1, row->soft);
+ TEST_ASSERT_EQUAL_INT(-1, row->hard);
+ TEST_ASSERT_EQUAL_STRING("Max data size", row->limit);
+ TEST_ASSERT_EQUAL_STRING("bytes", row->units);
+
+ row = (prom_process_limits_row_t*) prom_map_get(m, "Max stack size");
+ TEST_ASSERT_EQUAL_INT(8388608, row->soft);
+ TEST_ASSERT_EQUAL_INT(-1, row->hard);
+ TEST_ASSERT_EQUAL_STRING("Max stack size", row->limit);
+ TEST_ASSERT_EQUAL_STRING("bytes", row->units);
+
+ row = (prom_process_limits_row_t*) prom_map_get(m, "Max processes");
+ TEST_ASSERT_EQUAL_INT(-1, row->soft);
+ TEST_ASSERT_EQUAL_INT(-1, row->hard);
+ TEST_ASSERT_EQUAL_STRING("Max processes", row->limit);
+ TEST_ASSERT_EQUAL_STRING("processes", row->units);
+
+ row = (prom_process_limits_row_t*) prom_map_get(m, "Max pending signals");
+ TEST_ASSERT_EQUAL_INT(23701, row->soft);
+ TEST_ASSERT_EQUAL_INT(23701, row->hard);
+ TEST_ASSERT_EQUAL_STRING("Max pending signals", row->limit);
+ TEST_ASSERT_EQUAL_STRING("signals", row->units);
+
+ prom_map_destroy(m);
+ m = NULL;
+ prom_process_limits_file_destroy(f);
+ f = NULL;
+}
+
+void test_prom_process_limits_rdp_next_token(void) {
+ prom_process_limits_file_t f = { .size = 4, .index = 0, .buf = " \t!" };
+ prom_process_limits_file_t *fp = &f;
+ prom_process_limits_rdp_next_token(fp);
+
+
+ TEST_ASSERT_EQUAL_INT(2, fp->index);
+ TEST_ASSERT_EQUAL_INT('!', fp->buf[fp->index]);
+}
+
+void test_prom_process_limits_rdp_match(void) {
+ prom_process_limits_file_t f = { .size = 4, .index = 0, .buf = "foo" };
+ prom_process_limits_file_t *fp = &f;
+
+ TEST_ASSERT_TRUE(prom_process_limits_rdp_match(fp, "foo"));
+}
+
+void test_prom_process_limits_rdp_hard_limit(void){
+ // Test unlimited value
+ prom_process_limits_file_t f = { .size = 13, .index = 0, .buf = "unlimited " };
+ prom_process_limits_file_t *fp = &f;
+
+ prom_process_limits_current_row_t *cr = prom_process_limits_current_row_new();
+ prom_map_t* m = prom_map_new();
+
+ TEST_ASSERT_TRUE(prom_process_limits_rdp_hard_limit(fp, m, cr));
+ TEST_ASSERT_EQUAL_INT(-1, cr->hard);
+
+ prom_process_limits_current_row_clear(cr);
+
+ // Test int value
+ fp->buf = "123 ";
+ fp->size = 6;
+ fp->index = 0;
+
+ TEST_ASSERT_TRUE(prom_process_limits_rdp_hard_limit(fp, m, cr));
+ TEST_ASSERT_EQUAL_INT(123, cr->hard);
+
+ prom_map_destroy(m);
+ m = NULL;
+ prom_process_limits_current_row_destroy(cr);
+ cr = NULL;
+}
+
+void test_prom_process_limits_rdp_word(void){
+ // Test unlimited value
+ prom_process_limits_file_t f = { .size = 13, .index = 0, .buf = "unlimited " };
+ prom_process_limits_file_t *fp = &f;
+
+ prom_process_limits_current_row_t *cr = prom_process_limits_current_row_new();
+ prom_map_t* m = prom_map_new();
+
+ TEST_ASSERT_TRUE(prom_process_limits_rdp_word(fp, m, cr));
+ TEST_ASSERT_EQUAL_INT(9, fp->index);
+
+ prom_map_destroy(m);
+ m = NULL;
+ prom_process_limits_current_row_destroy(cr);
+ cr = NULL;
+}
+
+void test_prom_process_limits_rdp_word_and_space(void){
+ prom_process_limits_file_t f = { .size = 8, .index = 0, .buf = "foo bar" };
+ prom_process_limits_file_t *fp = &f;
+
+ prom_process_limits_current_row_t *cr = prom_process_limits_current_row_new();
+ prom_map_t* m = prom_map_new();
+
+ TEST_ASSERT_TRUE(prom_process_limits_rdp_word_and_space(fp, m, cr));
+ TEST_ASSERT_EQUAL_INT(4, fp->index);
+ TEST_ASSERT_EQUAL_INT('b', fp->buf[fp->index]);
+
+ prom_map_destroy(m);
+ m = NULL;
+ prom_process_limits_current_row_destroy(cr);
+ cr = NULL;
+}
+
+void test_prom_process_limits_rdp_limit(void) {
+ prom_process_limits_file_t f = { .size = 16, .index = 0, .buf = "Max cpu time " };
+ prom_process_limits_file_t *fp = &f;
+
+ prom_process_limits_current_row_t *cr = prom_process_limits_current_row_new();
+ prom_map_t* m = prom_map_new();
+
+ TEST_ASSERT_TRUE(prom_process_limits_rdp_limit(fp, m, cr));
+ TEST_ASSERT_EQUAL_INT(12, fp->index);
+ TEST_ASSERT_EQUAL_INT(' ', fp->buf[fp->index]);
+ TEST_ASSERT_EQUAL_STRING("Max cpu time", cr->limit);
+
+ prom_map_destroy(m);
+ m = NULL;
+ prom_process_limits_current_row_destroy(cr);
+ cr = NULL;
+}
+
+void test_prom_process_limits_rdp_letter(void) {
+ prom_process_limits_file_t f = { .size = 4, .index = 0, .buf = "foo" };
+ prom_process_limits_file_t *fp = &f;
+
+ prom_process_limits_current_row_t *cr = prom_process_limits_current_row_new();
+ prom_map_t* m = prom_map_new();
+
+ TEST_ASSERT_TRUE(prom_process_limits_rdp_letter(fp, m, cr));
+
+ fp->size = 1;
+ fp->index = 0;
+ fp->buf = "";
+
+ TEST_ASSERT_FALSE(prom_process_limits_rdp_letter(fp, m, cr));
+
+ fp->size = 2;
+ fp->index = 0;
+ fp->buf = "2";
+
+ TEST_ASSERT_FALSE(prom_process_limits_rdp_letter(fp, m, cr));
+
+ prom_map_destroy(m);
+ m = NULL;
+ prom_process_limits_current_row_destroy(cr);
+ cr = NULL;
+}
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_prom_process_limits_rdp_next_token);
+ RUN_TEST(test_prom_process_limits_rdp_match);
+ RUN_TEST(test_prom_process_limits_rdp_hard_limit);
+ RUN_TEST(test_prom_process_limits_rdp_word);
+ RUN_TEST(test_prom_process_limits_rdp_word_and_space);
+ RUN_TEST(test_prom_process_limits_rdp_limit);
+ RUN_TEST(test_prom_process_limits_rdp_letter);
+
+ RUN_TEST(test_prom_process_limits_file_parsing);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_procfs_test.c b/prom/test/prom_procfs_test.c
new file mode 100644
index 0000000..8a4bf07
--- /dev/null
+++ b/prom/test/prom_procfs_test.c
@@ -0,0 +1,31 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "prom_test_helpers.h"
+
+void test_prom_procfs_buf(void) {
+ prom_procfs_buf_t *buf = prom_procfs_buf_new("/proc/1/limits");
+ TEST_ASSERT_NOT_NULL(buf);
+ TEST_ASSERT_NOT_NULL(strstr(buf->buf, "Max realtime timeout"));
+ prom_procfs_buf_destroy(buf);
+ buf = NULL;
+}
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_prom_procfs_buf);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_string_builder_test.c b/prom/test/prom_string_builder_test.c
new file mode 100644
index 0000000..552efff
--- /dev/null
+++ b/prom/test/prom_string_builder_test.c
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "prom_test_helpers.h"
+
+void test_prom_string_builder_add_str(void) {
+ prom_string_builder_t *sb = prom_string_builder_new();
+ prom_string_builder_add_str(sb, "fooooooooooooooooooooooooooooooooo");
+ prom_string_builder_add_str(sb, " baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar");
+ TEST_ASSERT_EQUAL_STRING(prom_string_builder_str(sb), "fooooooooooooooooooooooooooooooooo baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar");
+
+ prom_string_builder_destroy(sb);
+ sb = NULL;
+}
+
+void test_prom_string_builder_add_char(void) {
+ prom_string_builder_t *sb = prom_string_builder_new();
+ const char *foobar = "foo bar";
+ for (int i = 0; i < strlen(foobar); i++) {
+ prom_string_builder_add_char(sb, foobar[i]);
+ }
+ TEST_ASSERT_EQUAL_STRING(prom_string_builder_str(sb), "foo bar");
+
+ prom_string_builder_destroy(sb);
+ sb = NULL;
+}
+
+void test_prom_string_builder_dump(void) {
+ prom_string_builder_t *sb = prom_string_builder_new();
+ const char *original = "foo bar";
+ prom_string_builder_add_str(sb, original);
+ const char *result = prom_string_builder_dump(sb);
+ prom_string_builder_clear(sb);
+ TEST_ASSERT(original != result);
+ TEST_ASSERT_EQUAL_STRING(original, result);
+
+ prom_string_builder_destroy(sb);
+ free((char *) result);
+ result = NULL;
+ sb = NULL;
+}
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(test_prom_string_builder_add_str);
+ RUN_TEST(test_prom_string_builder_add_char);
+ RUN_TEST(test_prom_string_builder_dump);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/prom/test/prom_test_helpers.c b/prom/test/prom_test_helpers.c
new file mode 100644
index 0000000..45385cc
--- /dev/null
+++ b/prom/test/prom_test_helpers.c
@@ -0,0 +1,18 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "prom_test_helpers.h"
+
diff --git a/prom/test/prom_test_helpers.h b/prom/test/prom_test_helpers.h
new file mode 100644
index 0000000..053fa0a
--- /dev/null
+++ b/prom/test/prom_test_helpers.h
@@ -0,0 +1,33 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "unity.h"
+
+#include "prom.h"
+#include "prom_map_i.h"
+#include "prom_metric_t.h"
+#include "prom_string_builder_i.h"
+#include "prom_process_fds_t.h"
+#include "prom_metric_sample_histogram_t.h"
+#include "prom_metric_sample_t.h"
+#include "prom_linked_list_t.h"
+#include "prom_metric_formatter_i.h"
+#include "prom_process_limits_t.h"
+#include "prom_process_stat_i.h"
+#include "prom_process_stat_t.h"
+#include "prom_metric_formatter_t.h"
+#include "prom_process_limits_i.h"
+#include "prom_linked_list_i.h"
+#include "prom_metric_sample_i.h"
+#include "prom_metric_sample_histogram_i.h"
+#include "prom_collector_registry_t.h"
+#include "prom_collector_t.h"
+#include "prom_string_builder_t.h"
+#include "prom_metric_i.h"
+#include "prom_map_t.h"
+#include "prom_procfs_i.h"
+#include "prom_procfs_t.h"
+#include "prom_process_fds_i.h"
+#include "prom_process_fds_t.h" \ No newline at end of file
diff --git a/promhttp/CMakeLists.txt b/promhttp/CMakeLists.txt
new file mode 100644
index 0000000..acbd767
--- /dev/null
+++ b/promhttp/CMakeLists.txt
@@ -0,0 +1,76 @@
+cmake_minimum_required(VERSION 3.14.5)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ OUTPUT_VARIABLE Version
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ COMMAND sed --regexp-extended "s/([0-9]+)\.([0-9])+\.([0-9]+)/\\1/g"
+ OUTPUT_VARIABLE MajorVersion
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ COMMAND sed --regexp-extended "s/([0-9]+)\.([0-9])+\.([0-9]+)/\\2/"
+ OUTPUT_VARIABLE MinorVersion
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ COMMAND sed --regexp-extended "s/([0-9]+)\.([0-9])+\.([0-9]+)/\\3/"
+ OUTPUT_VARIABLE PatchVersion
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+project(libpromhttp VERSION ${Version} LANGUAGES C)
+
+set(build_dir ${CMAKE_CURRENT_SOURCE_DIR}/build)
+set(public_dir ${CMAKE_CURRENT_SOURCE_DIR}/include)
+set(private_dir ${CMAKE_CURRENT_SOURCE_DIR}/src)
+set(prom_include_dir ${CMAKE_CURRENT_SOURCE_DIR}/../prom/include)
+set(public_files ${public_dir}/promhttp.h)
+set(private_files ${private_dir}/promhttp.c)
+
+link_directories(${CMAKE_CURRENT_SOURCE_DIR}/../prom/build)
+
+include(FindThreads)
+
+add_library(promhttp SHARED)
+
+target_include_directories(
+ promhttp
+ PUBLIC ${public_dir} /usr/include ${prom_include_dir}
+ PRIVATE ${private_dir}
+)
+
+target_sources(
+ promhttp
+ PUBLIC ${public_files}
+ PRIVATE ${private_files}
+)
+
+find_library(prom prom HINTS ${CMAKE_CURRENT_SOURCE_DIR}/../prom/build)
+find_library(microhttpd microhttpd)
+
+target_link_libraries(promhttp PUBLIC Threads::Threads prom microhttpd)
+
+set(CPACK_PACKAGE_NAME libpromhttp-dev)
+set(CPACK_GENERATOR TGZ;DEB)
+set(CPACK_PACKAGE_VENDOR DigitalOcean)
+set(CPACK_PACKAGE_VERSION_MAJOR ${MajorVersion})
+set(CPACK_PACKAGE_VERSION_MINOR ${MinorVersion})
+set(CPACK_PACKAGE_VERSION_PATCH ${PatchVersion})
+set(CPACK_PACKAGE_DESCRIPTION_FILE /code/README.md)
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A library providing a lightweight HTTP Server for Prometheus metric scraping")
+set(CPACK_PACKAGE_HOMEPAGE_URL https://github.internal.digitalocean.com/timeseries/prometheus-client-c)
+set(CPACK_DEBIAN_PACKAGE_DEPENDS "libprom-dev (= ${Version})")
+set(CPACK_DEBIAN_PACKAGE_DEPENDS "libmicrohttpd-dev")
+
+include(CPack)
+install(TARGETS promhttp ARCHIVE)
+install(DIRECTORY include/ DESTINATION /usr/include/) \ No newline at end of file
diff --git a/promhttp/include/promhttp.h b/promhttp/include/promhttp.h
new file mode 100644
index 0000000..ab7f94f
--- /dev/null
+++ b/promhttp/include/promhttp.h
@@ -0,0 +1,46 @@
+/*
+ Copyright 2019 DigitalOcean Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * @file promhttp.h
+ * @brief Provides a HTTP endpoint for metric exposition
+ * References:
+ * * MHD_FLAG: https://www.gnu.org/software/libmicrohttpd/manual/libmicrohttpd.html#microhttpd_002dconst
+ * * MHD_AcceptPolicyCallback: https://www.gnu.org/software/libmicrohttpd/manual/libmicrohttpd.html#index-_002aMHD_005fAcceptPolicyCallback
+ */
+
+#include <string.h>
+
+#include "microhttpd.h"
+
+
+/**
+ * @brief Sets the active registry for metric scraping.
+ *
+ * If null is passed, the default registry is used. The registry MUST be initialized.
+ */
+void promhttp_set_active_collector_registry(prom_collector_registry_t *active_registry);
+
+/**
+ * @brief Starts a daemon in the background and returns a pointer to an HMD_Daemon.
+ *
+ * References:
+ * * https://www.gnu.org/software/libmicrohttpd/manual/libmicrohttpd.html#microhttpd_002dinit
+ */
+struct MHD_Daemon* promhttp_start_daemon(unsigned int flags,
+ unsigned short port,
+ MHD_AcceptPolicyCallback apc,
+ void *apc_cls); \ No newline at end of file
diff --git a/promhttp/src/promhttp.c b/promhttp/src/promhttp.c
new file mode 100644
index 0000000..be38f1d
--- /dev/null
+++ b/promhttp/src/promhttp.c
@@ -0,0 +1,79 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <string.h>
+
+#include "microhttpd.h"
+
+#include "prom.h"
+
+prom_collector_registry_t *PROM_ACTIVE_REGISTRY;
+
+void promhttp_set_active_collector_registry(prom_collector_registry_t *active_registry) {
+ if (!active_registry) {
+ PROM_ACTIVE_REGISTRY = PROM_COLLECTOR_REGISTRY_DEFAULT;
+ } else {
+ PROM_ACTIVE_REGISTRY = active_registry;
+ }
+}
+
+int promhttp_handler(void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **con_cls)
+{
+ if (strcmp(method, "GET") != 0) {
+ char *buf = "Invalid HTTP Method\n";
+ struct MHD_Response *response = MHD_create_response_from_buffer(strlen(buf), (void*) buf, MHD_RESPMEM_PERSISTENT);
+ int ret = MHD_queue_response(connection, MHD_HTTP_BAD_REQUEST, response);
+ MHD_destroy_response(response);
+ return ret;
+ }
+ if (strcmp(url, "/") == 0) {
+ char *buf = "OK\n";
+ struct MHD_Response *response = MHD_create_response_from_buffer(strlen(buf), (void*) buf, MHD_RESPMEM_PERSISTENT);
+ int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
+ MHD_destroy_response(response);
+ return ret;
+ }
+ if (strcmp(url, "/metrics") == 0) {
+ const char *buf = prom_collector_registry_bridge(PROM_ACTIVE_REGISTRY);
+ struct MHD_Response *response = MHD_create_response_from_buffer(strlen(buf), (void*) buf, MHD_RESPMEM_MUST_FREE);
+ int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
+ MHD_destroy_response(response);
+ return ret;
+ }
+ char *buf = "Bad Request\n";
+ struct MHD_Response *response = MHD_create_response_from_buffer(strlen(buf), (void*) buf, MHD_RESPMEM_PERSISTENT);
+ int ret = MHD_queue_response(connection, MHD_HTTP_BAD_REQUEST, response);
+ MHD_destroy_response(response);
+ return ret;
+}
+
+
+struct MHD_Daemon* promhttp_start_daemon(unsigned int flags,
+ unsigned short port,
+ MHD_AcceptPolicyCallback apc,
+ void *apc_cls)
+{
+ return MHD_start_daemon(flags, port, apc, apc_cls, &promhttp_handler, NULL, MHD_OPTION_END);
+}
+
diff --git a/promtest/CMakeLists.txt b/promtest/CMakeLists.txt
new file mode 100644
index 0000000..2e48001
--- /dev/null
+++ b/promtest/CMakeLists.txt
@@ -0,0 +1,101 @@
+cmake_minimum_required(VERSION 3.14.5)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ OUTPUT_VARIABLE Version
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ COMMAND sed --regexp-extended "s/([0-9]+)\.([0-9])+\.([0-9]+)/\\1/g"
+ OUTPUT_VARIABLE MajorVersion
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ COMMAND sed --regexp-extended "s/([0-9]+)\.([0-9])+\.([0-9]+)/\\2/"
+ OUTPUT_VARIABLE MinorVersion
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+execute_process(
+ COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
+ COMMAND sed --regexp-extended "s/([0-9]+)\.([0-9])+\.([0-9]+)/\\3/"
+ OUTPUT_VARIABLE PatchVersion
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+project(promtest VERSION ${Version} LANGUAGES C)
+
+execute_process(COMMAND dpkg -i ${CMAKE_CURRENT_SOURCE_DIR}/../prom/libprom-dev-${Version}-Linux.deb)
+execute_process(COMMAND dpkg -i ${CMAKE_CURRENT_SOURCE_DIR}/../promhttp/libpromhttp-dev-${Version}-Linux.deb)
+
+enable_testing()
+set(vendor_dir ${CMAKE_SOURCE_DIR}/../vendor)
+set(test_dir ${CMAKE_SOURCE_DIR}/test)
+
+# Unity Dependency
+set(unity_version 2.4.3)
+set(unity_output ${build_dir}/unity-v${unity_version}.tar.gz)
+set(unity_package ${vendor_dir}/unity)
+set(unity_src ${vendor_dir}/Unity-${unity_version}/src)
+
+if(NOT EXISTS ${vendor_dir}/Unity-${unity_version})
+ execute_process(
+ COMMAND curl -L https://github.com/ThrowTheSwitch/Unity/archive/v${unity_version}.tar.gz
+ COMMAND tar xzvf - -C ${vendor_dir}
+ )
+endif()
+
+set(
+ unity_files
+ ${unity_src}/unity.c
+ ${unity_src}/unity.h
+ ${unity_src}/unity_internals.h
+)
+
+add_library(Unity SHARED)
+target_include_directories(Unity PUBLIC ${unity_src})
+target_sources(Unity PUBLIC ${unity_files})
+target_compile_options(Unity PUBLIC "-D UNITY_INCLUDE_DOUBLE")
+
+
+# Parson dependency
+set(parson_src ${vendor_dir}/parson)
+
+if (NOT EXISTS ${vendor_dir}/parson)
+ execute_process(
+ COMMAND git clone https://github.com/kgabis/parson ${vendor_dir}/parson
+ )
+endif()
+
+set(
+ parson_files
+ ${parson_src}/parson.c
+ ${parson_src}/parson.h
+)
+
+add_library(parson SHARED)
+target_include_directories(parson PUBLIC ${parson_src})
+target_sources(parson PUBLIC ${parson_files})
+
+include(FindThreads)
+
+add_executable(
+ promtest
+ ${test_dir}/promtest.c
+ ${test_dir}/promtest_helpers.c
+ ${test_dir}/promtest_helpers.h
+ ${test_dir}/promtest_counter.c
+ ${test_dir}/promtest_counter.h
+ ${test_dir}/promtest_gauge.c
+ ${test_dir}/promtest_gauge.h
+)
+target_link_libraries(promtest microhttpd prom promhttp Unity parson Threads::Threads)
+target_include_directories(promtest PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
+add_test(
+ NAME promtest
+ COMMAND promtest
+)
diff --git a/promtest/test/promtest.c b/promtest/test/promtest.c
new file mode 100644
index 0000000..446de16
--- /dev/null
+++ b/promtest/test/promtest.c
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "unity.h"
+
+#include "promtest_helpers.h"
+#include "promtest_counter.h"
+#include "promtest_gauge.h"
+
+
+int main(int argc, const char **argv) {
+ UNITY_BEGIN();
+ RUN_TEST(promtest_counter);
+ RUN_TEST(promtest_gauge);
+ return UNITY_END();
+} \ No newline at end of file
diff --git a/promtest/test/promtest_counter.c b/promtest/test/promtest_counter.c
new file mode 100644
index 0000000..f3d9ffc
--- /dev/null
+++ b/promtest/test/promtest_counter.c
@@ -0,0 +1,182 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pthread.h>
+
+#include "parson.h"
+#include "unity.h"
+
+#include "prom.h"
+#include "promhttp.h"
+#include "promtest_helpers.h"
+#include "promtest_counter.h"
+
+
+static void *promtest_counter_handler(void *data);
+static int promtest_parse_counter_output(const char *output, char **value);
+
+/**
+ * @brief For each thread in a threadpool of 10 we increment a single counter 1 million times
+ *
+ * The purpose of this test is to check for deadlock and race conditions
+ */
+void promtest_counter(void) {
+ if (promtest_counter_setup()) {
+ TEST_FAIL_MESSAGE("failed to setup promtest_counter");
+ }
+
+ void *retvals[PROMTEST_THREAD_POOL_SIZE];
+ pthread_t thread_pool[PROMTEST_THREAD_POOL_SIZE];
+
+ // Start each thread
+ for (int i = 0; i < PROMTEST_THREAD_POOL_SIZE; i++) {
+ if (pthread_create(&(thread_pool[i]), NULL, promtest_counter_handler, NULL)) {
+ TEST_FAIL_MESSAGE("failed to create thread");
+ }
+ }
+
+ // Join each thread
+ for (int i = 0; i < PROMTEST_THREAD_POOL_SIZE; i++) {
+ if (pthread_join(thread_pool[i], (void**) &(retvals[i]))) {
+ TEST_FAIL_MESSAGE("thread failed to join");
+ }
+ }
+
+ // verify clean exit for each thread
+ for (int i = 0; i < PROMTEST_THREAD_POOL_SIZE; i++) {
+ if (*((int *) retvals[i]) != 0) {
+ TEST_FAIL_MESSAGE("thread did not exit properly");
+ }
+ }
+
+ // scrape the endpoint
+ FILE *f = popen("prom2json http://0.0.0.0:8000/metrics", "r");
+ if (f == NULL) {
+ TEST_FAIL_MESSAGE("shell out failed");
+ }
+ promtest_popen_buf_t *buf = promtest_popen_buf_new(f);
+ if (promtest_popen_buf_read(buf)) {
+ TEST_FAIL_MESSAGE("failed to scrape endpoint");
+ }
+
+ const char *output = strdup(buf->buf);
+ if (promtest_popen_buf_destroy(buf)) {
+ TEST_FAIL_MESSAGE("failed to duplicate buf");
+ }
+
+ // Parse the output
+ char *value = (char *) malloc(sizeof(char)*100);
+ if (promtest_parse_counter_output(output, &value)) {
+ TEST_FAIL_MESSAGE("failed to parse output");
+ }
+
+ // Assert
+ TEST_ASSERT_EQUAL_STRING("5e+06", value);
+ if (promtest_counter_teardown()) {
+ TEST_FAIL_MESSAGE("failed to teardown promtest_counter");
+ }
+
+ free(value);
+}
+
+int promtest_counter_setup(void) {
+ // Initialize the default collector registry
+ prom_collector_registry_default_init();
+
+ // Set the counter
+ foo_counter = prom_collector_registry_must_register_metric(prom_counter_new(
+ "foo_counter", "counter for foo", 0, NULL
+ ));
+
+ // Set the collector registry on the handler to the default registry
+ promhttp_set_active_collector_registry(NULL);
+
+ // Start the HTTP server
+ promtest_daemon = promhttp_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD, 8000, NULL, NULL);
+
+ if (promtest_daemon == NULL) return 1;
+ else return 0;
+}
+
+int promtest_counter_teardown(void) {
+ // Destroy the default registry. This effectively deallocates all metrics registered to it, including itself
+ prom_collector_registry_destroy(PROM_COLLECTOR_REGISTRY_DEFAULT);
+
+ // Stop the HTTP server
+ MHD_stop_daemon(promtest_daemon);
+
+ return 0;
+}
+
+
+/**
+ * @brief The entrypoint to a worker thread within the prom_counter_test
+ */
+static void *promtest_counter_handler(void *data) {
+ for (int i = 0; i < 1000000; i++) {
+ prom_counter_inc(foo_counter, NULL);
+ }
+ int *retval = (int*) malloc(sizeof(int));
+ *retval = 0;
+ return (void*) retval;
+}
+
+/**
+ * @brief Parse the output and set the value of the foo_counter metric.
+ *
+ * We must past a pointer to a char* so the value gets updated
+ */
+static int promtest_parse_counter_output(const char *output, char **value) {
+ // Parse the JSON output
+ JSON_Value *root = json_parse_string(output);
+ if (json_value_get_type(root) != JSONArray) {
+ TEST_FAIL_MESSAGE("JSON Parse error...expected JSONArray type");
+ }
+
+ JSON_Array *collection = json_value_get_array(root);
+ if (collection == NULL) {
+ TEST_FAIL_MESSAGE("Failed to extract array from JSON_Value");
+ }
+
+ for (int i = 0; i < json_array_get_count(collection); i++) {
+ JSON_Object *obj = json_array_get_object(collection, i);
+ if (obj == NULL) {
+ TEST_FAIL_MESSAGE("failed to retrieve single object within JSON_Array");
+ }
+ const char *name = json_object_get_string(obj, "name");
+ if (strcmp(name, "foo_counter")) {
+ continue;
+ }
+ JSON_Array *samples = json_object_dotget_array(obj, "metrics");
+ if (samples == NULL) {
+ TEST_FAIL_MESSAGE("failed to retrieve metrics from JSON_Object");
+ }
+ if (json_array_get_count(samples) < 1){
+ TEST_FAIL_MESSAGE("No samples found");
+ }
+ JSON_Object *sample = json_array_get_object(samples, 0);
+ if (sample == NULL) {
+ TEST_FAIL_MESSAGE("failed to get metric sample");
+ }
+ *value = (char *) json_object_get_string(sample, "value");
+ break;
+ }
+ if (strlen(*value) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
diff --git a/promtest/test/promtest_counter.h b/promtest/test/promtest_counter.h
new file mode 100644
index 0000000..a8fd719
--- /dev/null
+++ b/promtest/test/promtest_counter.h
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "prom.h"
+
+#ifndef PROMTEST_COUNTER_H
+#define PROMTEST_COUNTER_H
+
+prom_counter_t *foo_counter;
+
+int promtest_counter_setup(void);
+int promtest_counter_teardown(void);
+
+void promtest_counter(void);
+
+#endif // PROMTEST_COUNTER_H \ No newline at end of file
diff --git a/promtest/test/promtest_gauge.c b/promtest/test/promtest_gauge.c
new file mode 100644
index 0000000..7bd211e
--- /dev/null
+++ b/promtest/test/promtest_gauge.c
@@ -0,0 +1,182 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pthread.h>
+
+#include "parson.h"
+#include "unity.h"
+
+#include "prom.h"
+#include "promhttp.h"
+#include "promtest_helpers.h"
+#include "promtest_gauge.h"
+
+
+static void *promtest_gauge_handler(void *data);
+static int promtest_parse_gauge_output(const char *output, char **value);
+
+/**
+ * @brief For each thread in a threadpool of 10 we increment a single gauge 1 million times
+ *
+ * The purpose of this test is to check for deadlock and race conditions
+ */
+void promtest_gauge(void) {
+ if (promtest_gauge_setup()) {
+ TEST_FAIL_MESSAGE("failed to setup promtest_gauge");
+ }
+
+ void *retvals[PROMTEST_THREAD_POOL_SIZE];
+ pthread_t thread_pool[PROMTEST_THREAD_POOL_SIZE];
+
+ // Start each thread
+ for (int i = 0; i < PROMTEST_THREAD_POOL_SIZE; i++) {
+ if (pthread_create(&(thread_pool[i]), NULL, promtest_gauge_handler, NULL)) {
+ TEST_FAIL_MESSAGE("failed to create thread");
+ }
+ }
+
+ // Join each thread
+ for (int i = 0; i < PROMTEST_THREAD_POOL_SIZE; i++) {
+ if (pthread_join(thread_pool[i], (void**) &(retvals[i]))) {
+ TEST_FAIL_MESSAGE("thread failed to join");
+ }
+ }
+
+ // verify clean exit for each thread
+ for (int i = 0; i < PROMTEST_THREAD_POOL_SIZE; i++) {
+ if (*((int *) retvals[i]) != 0) {
+ TEST_FAIL_MESSAGE("thread did not exit properly");
+ }
+ }
+
+ // scrape the endpoint
+ FILE *f = popen("prom2json http://0.0.0.0:8000/metrics", "r");
+ if (f == NULL) {
+ TEST_FAIL_MESSAGE("shell out failed");
+ }
+ promtest_popen_buf_t *buf = promtest_popen_buf_new(f);
+ if (promtest_popen_buf_read(buf)) {
+ TEST_FAIL_MESSAGE("failed to scrape endpoint");
+ }
+
+ const char *output = strdup(buf->buf);
+ if (promtest_popen_buf_destroy(buf)) {
+ TEST_FAIL_MESSAGE("failed to duplicate buf");
+ }
+
+ // Parse the output
+ char *value = (char *) malloc(sizeof(char)*100);
+ if (promtest_parse_gauge_output(output, &value)) {
+ TEST_FAIL_MESSAGE("failed to parse output");
+ }
+
+ // Assert
+ TEST_ASSERT_EQUAL_STRING("5e+06", value);
+ if (promtest_gauge_teardown()) {
+ TEST_FAIL_MESSAGE("failed to teardown promtest_gauge");
+ }
+
+ free(value);
+}
+
+int promtest_gauge_setup(void) {
+ // Initialize the default collector registry
+ prom_collector_registry_default_init();
+
+ // Set the gauge
+ foo_gauge = prom_collector_registry_must_register_metric(prom_gauge_new(
+ "foo_gauge", "gauge for foo", 0, NULL
+ ));
+
+ // Set the collector registry on the handler to the default registry
+ promhttp_set_active_collector_registry(NULL);
+
+ // Start the HTTP server
+ promtest_daemon = promhttp_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD, 8000, NULL, NULL);
+
+ if (promtest_daemon == NULL) return 1;
+ else return 0;
+}
+
+int promtest_gauge_teardown(void) {
+ // Destroy the default registry. This effectively deallocates all metrics registered to it, including itself
+ prom_collector_registry_destroy(PROM_COLLECTOR_REGISTRY_DEFAULT);
+
+ // Stop the HTTP server
+ MHD_stop_daemon(promtest_daemon);
+
+ return 0;
+}
+
+
+/**
+ * @brief The entrypoint to a worker thread within the prom_gauge_test
+ */
+static void *promtest_gauge_handler(void *data) {
+ for (int i = 0; i < 1000000; i++) {
+ prom_gauge_inc(foo_gauge, NULL);
+ }
+ int *retval = (int*) malloc(sizeof(int));
+ *retval = 0;
+ return (void*) retval;
+}
+
+/**
+ * @brief Parse the output and set the value of the foo_gauge metric.
+ *
+ * We must past a pointer to a char* so the value gets updated
+ */
+static int promtest_parse_gauge_output(const char *output, char **value) {
+ // Parse the JSON output
+ JSON_Value *root = json_parse_string(output);
+ if (json_value_get_type(root) != JSONArray) {
+ TEST_FAIL_MESSAGE("JSON Parse error...expected JSONArray type");
+ }
+
+ JSON_Array *collection = json_value_get_array(root);
+ if (collection == NULL) {
+ TEST_FAIL_MESSAGE("Failed to extract array from JSON_Value");
+ }
+
+ for (int i = 0; i < json_array_get_count(collection); i++) {
+ JSON_Object *obj = json_array_get_object(collection, i);
+ if (obj == NULL) {
+ TEST_FAIL_MESSAGE("failed to retrieve single object within JSON_Array");
+ }
+ const char *name = json_object_get_string(obj, "name");
+ if (strcmp(name, "foo_gauge")) {
+ continue;
+ }
+ JSON_Array *samples = json_object_dotget_array(obj, "metrics");
+ if (samples == NULL) {
+ TEST_FAIL_MESSAGE("failed to retrieve metrics from JSON_Object");
+ }
+ if (json_array_get_count(samples) < 1){
+ TEST_FAIL_MESSAGE("No samples found");
+ }
+ JSON_Object *sample = json_array_get_object(samples, 0);
+ if (sample == NULL) {
+ TEST_FAIL_MESSAGE("failed to get metric sample");
+ }
+ *value = (char *) json_object_get_string(sample, "value");
+ break;
+ }
+ if (strlen(*value) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
diff --git a/promtest/test/promtest_gauge.h b/promtest/test/promtest_gauge.h
new file mode 100644
index 0000000..3b68f4c
--- /dev/null
+++ b/promtest/test/promtest_gauge.h
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "prom.h"
+
+#ifndef PROMTEST_GAUGE_H
+#define PROMTEST_GAUGE_H
+
+prom_counter_t *foo_gauge;
+
+int promtest_gauge_setup(void);
+int promtest_gauge_teardown(void);
+
+void promtest_gauge(void);
+
+#endif // PROMTEST_GAUGE_H \ No newline at end of file
diff --git a/promtest/test/promtest_helpers.c b/promtest/test/promtest_helpers.c
new file mode 100644
index 0000000..01a0da2
--- /dev/null
+++ b/promtest/test/promtest_helpers.c
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "prom.h"
+#include "promtest_helpers.h"
+
+
+promtest_popen_buf_t *promtest_popen_buf_new(FILE *f) {
+ promtest_popen_buf_t *self = (promtest_popen_buf_t*) malloc(sizeof(promtest_popen_buf_t));
+ self->buf = malloc(32);
+ self->size = 32;
+ self->allocated = 32;
+ self->f = f;
+ return self;
+}
+
+int promtest_popen_buf_ensure_space(promtest_popen_buf_t *self) {
+ if (self->allocated >= self->size+1) return 0;
+ while (self->allocated < self->size+1) self->allocated <<= 1;
+ self->buf = (char *) prom_realloc(self->buf, self->allocated);
+ return 0;
+}
+
+int promtest_popen_buf_destroy(promtest_popen_buf_t *self) {
+ if (self == NULL) {
+ return 0;
+ }
+ free((void*) self->buf);
+ self->buf = NULL;
+ free((void*) self);
+ self = NULL;
+ return 0;
+}
+
+int promtest_popen_buf_read(promtest_popen_buf_t* self) {
+ for (
+ int current_char = fgetc(self->f), i = 0;
+ current_char != EOF;
+ current_char = fgetc(self->f), i++
+ ) {
+ promtest_popen_buf_ensure_space(self);
+ self->buf[i] = current_char;
+ self->size++;
+ }
+ promtest_popen_buf_ensure_space(self);
+ self->buf[self->size] = '\0';
+ self->size++;
+ return 0;
+} \ No newline at end of file
diff --git a/promtest/test/promtest_helpers.h b/promtest/test/promtest_helpers.h
new file mode 100644
index 0000000..4bdc6a2
--- /dev/null
+++ b/promtest/test/promtest_helpers.h
@@ -0,0 +1,40 @@
+/**
+ * Copyright 2019 DigitalOcean Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#ifndef PROMTTEST_HELPERS_H
+#define PROMTTEST_HELPERS_H
+
+#define PROMTEST_THREAD_POOL_SIZE 5
+
+struct MHD_Daemon *promtest_daemon;
+
+typedef struct promtest_popen_buf {
+ char *buf;
+ int size;
+ int allocated;
+ FILE *f;
+} promtest_popen_buf_t;
+
+promtest_popen_buf_t *promtest_popen_buf_new(FILE *f);
+int promtest_popen_buf_destroy(promtest_popen_buf_t *self);
+int promtest_popen_buf_read(promtest_popen_buf_t* self);
+int promtest_popen_buf_ensure_space(promtest_popen_buf_t *self);
+
+
+#endif // PROMTEST_HELPERS_H
+
diff --git a/vendor/Unity-2.4.3/.gitattributes b/vendor/Unity-2.4.3/.gitattributes
new file mode 100644
index 0000000..ad95226
--- /dev/null
+++ b/vendor/Unity-2.4.3/.gitattributes
@@ -0,0 +1,30 @@
+* text=auto
+
+# These files are text and should be normalized (convert crlf to lf)
+*.rb text
+*.test text
+*.c text
+*.cpp text
+*.h text
+*.txt text
+*.yml text
+*.s79 text
+*.bat text
+*.xcl text
+*.inc text
+*.info text
+*.md text
+makefile text
+rakefile text
+
+
+#These files are binary and should not be normalized
+*.doc binary
+*.odt binary
+*.pdf binary
+*.ewd binary
+*.eww binary
+*.dni binary
+*.wsdt binary
+*.dbgdt binary
+*.mac binary
diff --git a/vendor/Unity-2.4.3/.gitignore b/vendor/Unity-2.4.3/.gitignore
new file mode 100644
index 0000000..a383c3c
--- /dev/null
+++ b/vendor/Unity-2.4.3/.gitignore
@@ -0,0 +1,9 @@
+build/
+test/sandbox
+.DS_Store
+examples/example_1/test1.exe
+examples/example_1/test2.exe
+examples/example_2/all_tests.exe
+examples/example_1/test1.out
+examples/example_1/test2.out
+examples/example_2/all_tests.out
diff --git a/vendor/Unity-2.4.3/.travis.yml b/vendor/Unity-2.4.3/.travis.yml
new file mode 100644
index 0000000..bd165b1
--- /dev/null
+++ b/vendor/Unity-2.4.3/.travis.yml
@@ -0,0 +1,29 @@
+language: c
+
+matrix:
+ include:
+ - os: osx
+ compiler: clang
+ osx_image: xcode7.3
+ - os: linux
+ dist: trusty
+ compiler: gcc
+
+before_install:
+ - if [ "$TRAVIS_OS_NAME" == "osx" ]; then rvm install 2.1 && rvm use 2.1 && ruby -v; fi
+ - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install --assume-yes --quiet gcc-multilib; fi
+install:
+ - gem install rspec
+ - gem install rubocop
+script:
+ - cd test && rake ci
+ - make -s
+ - make -s DEBUG=-m32 #32-bit architecture with 64-bit support
+ - make -s DEBUG=-m32 UNITY_SUPPORT_64= #32-bit build without 64-bit types
+ - make -s UNITY_INCLUDE_DOUBLE= # without double
+ - cd ../extras/fixture/test && rake ci
+ - make -s default noStdlibMalloc
+ - make -s C89
+ - cd ../../../examples/example_1 && make -s ci
+ - cd ../example_2 && make -s ci
+ - cd ../example_3 && rake
diff --git a/vendor/Unity-2.4.3/README.md b/vendor/Unity-2.4.3/README.md
new file mode 100644
index 0000000..ec73b4a
--- /dev/null
+++ b/vendor/Unity-2.4.3/README.md
@@ -0,0 +1,231 @@
+Unity Test API
+==============
+
+[![Unity Build Status](https://api.travis-ci.org/ThrowTheSwitch/Unity.png?branch=master)](https://travis-ci.org/ThrowTheSwitch/Unity)
+__Copyright (c) 2007 - 2017 Unity Project by Mike Karlesky, Mark VanderVoord, and Greg Williams__
+
+Running Tests
+-------------
+
+ RUN_TEST(func, linenum)
+
+Each Test is run within the macro `RUN_TEST`. This macro performs necessary setup before the test is called and handles cleanup and result tabulation afterwards.
+
+Ignoring Tests
+--------------
+
+There are times when a test is incomplete or not valid for some reason. At these times, TEST_IGNORE can be called. Control will immediately be returned to the caller of the test, and no failures will be returned.
+
+ TEST_IGNORE()
+
+Ignore this test and return immediately
+
+ TEST_IGNORE_MESSAGE (message)
+
+Ignore this test and return immediately. Output a message stating why the test was ignored.
+
+Aborting Tests
+--------------
+
+There are times when a test will contain an infinite loop on error conditions, or there may be reason to escape from the test early without executing the rest of the test. A pair of macros support this functionality in Unity. The first `TEST_PROTECT` sets up the feature, and handles emergency abort cases. `TEST_ABORT` can then be used at any time within the tests to return to the last `TEST_PROTECT` call.
+
+ TEST_PROTECT()
+
+Setup and Catch macro
+
+ TEST_ABORT()
+
+Abort Test macro
+
+Example:
+
+ main()
+ {
+ if (TEST_PROTECT())
+ {
+ MyTest();
+ }
+ }
+
+If MyTest calls `TEST_ABORT`, program control will immediately return to `TEST_PROTECT` with a return value of zero.
+
+
+Unity Assertion Summary
+=======================
+
+Basic Validity Tests
+--------------------
+
+ TEST_ASSERT_TRUE(condition)
+
+Evaluates whatever code is in condition and fails if it evaluates to false
+
+ TEST_ASSERT_FALSE(condition)
+
+Evaluates whatever code is in condition and fails if it evaluates to true
+
+ TEST_ASSERT(condition)
+
+Another way of calling `TEST_ASSERT_TRUE`
+
+ TEST_ASSERT_UNLESS(condition)
+
+Another way of calling `TEST_ASSERT_FALSE`
+
+ TEST_FAIL()
+ TEST_FAIL_MESSAGE(message)
+
+This test is automatically marked as a failure. The message is output stating why.
+
+Numerical Assertions: Integers
+------------------------------
+
+ TEST_ASSERT_EQUAL_INT(expected, actual)
+ TEST_ASSERT_EQUAL_INT8(expected, actual)
+ TEST_ASSERT_EQUAL_INT16(expected, actual)
+ TEST_ASSERT_EQUAL_INT32(expected, actual)
+ TEST_ASSERT_EQUAL_INT64(expected, actual)
+
+Compare two integers for equality and display errors as signed integers. A cast will be performed
+to your natural integer size so often this can just be used. When you need to specify the exact size,
+like when comparing arrays, you can use a specific version:
+
+ TEST_ASSERT_EQUAL_UINT(expected, actual)
+ TEST_ASSERT_EQUAL_UINT8(expected, actual)
+ TEST_ASSERT_EQUAL_UINT16(expected, actual)
+ TEST_ASSERT_EQUAL_UINT32(expected, actual)
+ TEST_ASSERT_EQUAL_UINT64(expected, actual)
+
+Compare two integers for equality and display errors as unsigned integers. Like INT, there are
+variants for different sizes also.
+
+ TEST_ASSERT_EQUAL_HEX(expected, actual)
+ TEST_ASSERT_EQUAL_HEX8(expected, actual)
+ TEST_ASSERT_EQUAL_HEX16(expected, actual)
+ TEST_ASSERT_EQUAL_HEX32(expected, actual)
+ TEST_ASSERT_EQUAL_HEX64(expected, actual)
+
+Compares two integers for equality and display errors as hexadecimal. Like the other integer comparisons,
+you can specify the size... here the size will also effect how many nibbles are shown (for example, `HEX16`
+will show 4 nibbles).
+
+ TEST_ASSERT_EQUAL(expected, actual)
+
+Another way of calling TEST_ASSERT_EQUAL_INT
+
+ TEST_ASSERT_INT_WITHIN(delta, expected, actual)
+
+Asserts that the actual value is within plus or minus delta of the expected value. This also comes in
+size specific variants.
+
+
+ TEST_ASSERT_GREATER_THAN(threshold, actual)
+
+Asserts that the actual value is greater than the threshold. This also comes in size specific variants.
+
+
+ TEST_ASSERT_LESS_THAN(threshold, actual)
+
+Asserts that the actual value is less than the threshold. This also comes in size specific variants.
+
+
+Arrays
+------
+
+ _ARRAY
+
+You can append `_ARRAY` to any of these macros to make an array comparison of that type. Here you will
+need to care a bit more about the actual size of the value being checked. You will also specify an
+additional argument which is the number of elements to compare. For example:
+
+ TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, elements)
+
+ _EACH_EQUAL
+
+Another array comparison option is to check that EVERY element of an array is equal to a single expected
+value. You do this by specifying the EACH_EQUAL macro. For example:
+
+ TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, elements)
+
+Numerical Assertions: Bitwise
+-----------------------------
+
+ TEST_ASSERT_BITS(mask, expected, actual)
+
+Use an integer mask to specify which bits should be compared between two other integers. High bits in the mask are compared, low bits ignored.
+
+ TEST_ASSERT_BITS_HIGH(mask, actual)
+
+Use an integer mask to specify which bits should be inspected to determine if they are all set high. High bits in the mask are compared, low bits ignored.
+
+ TEST_ASSERT_BITS_LOW(mask, actual)
+
+Use an integer mask to specify which bits should be inspected to determine if they are all set low. High bits in the mask are compared, low bits ignored.
+
+ TEST_ASSERT_BIT_HIGH(bit, actual)
+
+Test a single bit and verify that it is high. The bit is specified 0-31 for a 32-bit integer.
+
+ TEST_ASSERT_BIT_LOW(bit, actual)
+
+Test a single bit and verify that it is low. The bit is specified 0-31 for a 32-bit integer.
+
+Numerical Assertions: Floats
+----------------------------
+
+ TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual)
+
+Asserts that the actual value is within plus or minus delta of the expected value.
+
+ TEST_ASSERT_EQUAL_FLOAT(expected, actual)
+ TEST_ASSERT_EQUAL_DOUBLE(expected, actual)
+
+Asserts that two floating point values are "equal" within a small % delta of the expected value.
+
+String Assertions
+-----------------
+
+ TEST_ASSERT_EQUAL_STRING(expected, actual)
+
+Compare two null-terminate strings. Fail if any character is different or if the lengths are different.
+
+ TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len)
+
+Compare two strings. Fail if any character is different, stop comparing after len characters.
+
+ TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message)
+
+Compare two null-terminate strings. Fail if any character is different or if the lengths are different. Output a custom message on failure.
+
+ TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message)
+
+Compare two strings. Fail if any character is different, stop comparing after len characters. Output a custom message on failure.
+
+Pointer Assertions
+------------------
+
+Most pointer operations can be performed by simply using the integer comparisons above. However, a couple of special cases are added for clarity.
+
+ TEST_ASSERT_NULL(pointer)
+
+Fails if the pointer is not equal to NULL
+
+ TEST_ASSERT_NOT_NULL(pointer)
+
+Fails if the pointer is equal to NULL
+
+Memory Assertions
+-----------------
+
+ TEST_ASSERT_EQUAL_MEMORY(expected, actual, len)
+
+Compare two blocks of memory. This is a good generic assertion for types that can't be coerced into acting like
+standard types... but since it's a memory compare, you have to be careful that your data types are packed.
+
+_MESSAGE
+--------
+
+you can append _MESSAGE to any of the macros to make them take an additional argument. This argument
+is a string that will be printed at the end of the failure strings. This is useful for specifying more
+information about the problem.
+
diff --git a/vendor/Unity-2.4.3/auto/colour_prompt.rb b/vendor/Unity-2.4.3/auto/colour_prompt.rb
new file mode 100644
index 0000000..0f1dc4e
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/colour_prompt.rb
@@ -0,0 +1,118 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+if RUBY_PLATFORM =~ /(win|w)32$/
+ begin
+ require 'Win32API'
+ rescue LoadError
+ puts 'ERROR! "Win32API" library not found'
+ puts '"Win32API" is required for colour on a windows machine'
+ puts ' try => "gem install Win32API" on the command line'
+ puts
+ end
+ # puts
+ # puts 'Windows Environment Detected...'
+ # puts 'Win32API Library Found.'
+ # puts
+end
+
+class ColourCommandLine
+ def initialize
+ return unless RUBY_PLATFORM =~ /(win|w)32$/
+ get_std_handle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L')
+ @set_console_txt_attrb =
+ Win32API.new('kernel32', 'SetConsoleTextAttribute', %w(L N), 'I')
+ @hout = get_std_handle.call(-11)
+ end
+
+ def change_to(new_colour)
+ if RUBY_PLATFORM =~ /(win|w)32$/
+ @set_console_txt_attrb.call(@hout, win32_colour(new_colour))
+ else
+ "\033[30;#{posix_colour(new_colour)};22m"
+ end
+ end
+
+ def win32_colour(colour)
+ case colour
+ when :black then 0
+ when :dark_blue then 1
+ when :dark_green then 2
+ when :dark_cyan then 3
+ when :dark_red then 4
+ when :dark_purple then 5
+ when :dark_yellow, :narrative then 6
+ when :default_white, :default, :dark_white then 7
+ when :silver then 8
+ when :blue then 9
+ when :green, :success then 10
+ when :cyan, :output then 11
+ when :red, :failure then 12
+ when :purple then 13
+ when :yellow then 14
+ when :white then 15
+ else
+ 0
+ end
+ end
+
+ def posix_colour(colour)
+ # ANSI Escape Codes - Foreground colors
+ # | Code | Color |
+ # | 39 | Default foreground color |
+ # | 30 | Black |
+ # | 31 | Red |
+ # | 32 | Green |
+ # | 33 | Yellow |
+ # | 34 | Blue |
+ # | 35 | Magenta |
+ # | 36 | Cyan |
+ # | 37 | Light gray |
+ # | 90 | Dark gray |
+ # | 91 | Light red |
+ # | 92 | Light green |
+ # | 93 | Light yellow |
+ # | 94 | Light blue |
+ # | 95 | Light magenta |
+ # | 96 | Light cyan |
+ # | 97 | White |
+
+ case colour
+ when :black then 30
+ when :red, :failure then 31
+ when :green, :success then 32
+ when :yellow then 33
+ when :blue, :narrative then 34
+ when :purple, :magenta then 35
+ when :cyan, :output then 36
+ when :white, :default_white then 37
+ when :default then 39
+ else
+ 39
+ end
+ end
+
+ def out_c(mode, colour, str)
+ case RUBY_PLATFORM
+ when /(win|w)32$/
+ change_to(colour)
+ $stdout.puts str if mode == :puts
+ $stdout.print str if mode == :print
+ change_to(:default_white)
+ else
+ $stdout.puts("#{change_to(colour)}#{str}\033[0m") if mode == :puts
+ $stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print
+ end
+ end
+end # ColourCommandLine
+
+def colour_puts(role, str)
+ ColourCommandLine.new.out_c(:puts, role, str)
+end
+
+def colour_print(role, str)
+ ColourCommandLine.new.out_c(:print, role, str)
+end
diff --git a/vendor/Unity-2.4.3/auto/colour_reporter.rb b/vendor/Unity-2.4.3/auto/colour_reporter.rb
new file mode 100644
index 0000000..bb1fbfc
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/colour_reporter.rb
@@ -0,0 +1,39 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+require "#{File.expand_path(File.dirname(__FILE__))}/colour_prompt"
+
+$colour_output = true
+
+def report(message)
+ if !$colour_output
+ $stdout.puts(message)
+ else
+ message = message.join('\n') if message.class == Array
+ message.each_line do |line|
+ line.chomp!
+ colour = case line
+ when /(?:total\s+)?tests:?\s+(\d+)\s+(?:total\s+)?failures:?\s+\d+\s+Ignored:?/i
+ Regexp.last_match(1).to_i.zero? ? :green : :red
+ when /PASS/
+ :green
+ when /^OK$/
+ :green
+ when /(?:FAIL|ERROR)/
+ :red
+ when /IGNORE/
+ :yellow
+ when /^(?:Creating|Compiling|Linking)/
+ :white
+ else
+ :silver
+ end
+ colour_puts(colour, line)
+ end
+ end
+ $stdout.flush
+ $stderr.flush
+end
diff --git a/vendor/Unity-2.4.3/auto/generate_config.yml b/vendor/Unity-2.4.3/auto/generate_config.yml
new file mode 100644
index 0000000..4a5e474
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/generate_config.yml
@@ -0,0 +1,36 @@
+#this is a sample configuration file for generate_module
+#you would use it by calling generate_module with the -ygenerate_config.yml option
+#files like this are useful for customizing generate_module to your environment
+:generate_module:
+ :defaults:
+ #these defaults are used in place of any missing options at the command line
+ :path_src: ../src/
+ :path_inc: ../src/
+ :path_tst: ../test/
+ :update_svn: true
+ :includes:
+ #use [] for no additional includes, otherwise list the includes on separate lines
+ :src:
+ - Defs.h
+ - Board.h
+ :inc: []
+ :tst:
+ - Defs.h
+ - Board.h
+ - Exception.h
+ :boilerplates:
+ #these are inserted at the top of generated files.
+ #just comment out or remove if not desired.
+ #use %1$s where you would like the file name to appear (path/extension not included)
+ :src: |
+ //-------------------------------------------
+ // %1$s.c
+ //-------------------------------------------
+ :inc: |
+ //-------------------------------------------
+ // %1$s.h
+ //-------------------------------------------
+ :tst: |
+ //-------------------------------------------
+ // Test%1$s.c : Units tests for %1$s.c
+ //-------------------------------------------
diff --git a/vendor/Unity-2.4.3/auto/generate_module.rb b/vendor/Unity-2.4.3/auto/generate_module.rb
new file mode 100644
index 0000000..13b4cc7
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/generate_module.rb
@@ -0,0 +1,308 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+# This script creates all the files with start code necessary for a new module.
+# A simple module only requires a source file, header file, and test file.
+# Triad modules require a source, header, and test file for each triad type (like model, conductor, and hardware).
+
+require 'rubygems'
+require 'fileutils'
+require 'pathname'
+
+# TEMPLATE_TST
+TEMPLATE_TST ||= '#include "unity.h"
+%2$s#include "%1$s.h"
+
+void setUp(void)
+{
+}
+
+void tearDown(void)
+{
+}
+
+void test_%1$s_NeedToImplement(void)
+{
+ TEST_IGNORE_MESSAGE("Need to Implement %1$s");
+}
+'.freeze
+
+# TEMPLATE_SRC
+TEMPLATE_SRC ||= '%2$s#include "%1$s.h"
+'.freeze
+
+# TEMPLATE_INC
+TEMPLATE_INC ||= '#ifndef _%3$s_H
+#define _%3$s_H
+%2$s
+
+#endif // _%3$s_H
+'.freeze
+
+class UnityModuleGenerator
+ ############################
+ def initialize(options = nil)
+ here = File.expand_path(File.dirname(__FILE__)) + '/'
+
+ @options = UnityModuleGenerator.default_options
+ case options
+ when NilClass then @options
+ when String then @options.merge!(UnityModuleGenerator.grab_config(options))
+ when Hash then @options.merge!(options)
+ else raise 'If you specify arguments, it should be a filename or a hash of options'
+ end
+
+ # Create default file paths if none were provided
+ @options[:path_src] = here + '../src/' if @options[:path_src].nil?
+ @options[:path_inc] = @options[:path_src] if @options[:path_inc].nil?
+ @options[:path_tst] = here + '../test/' if @options[:path_tst].nil?
+ @options[:path_src] += '/' unless @options[:path_src][-1] == 47
+ @options[:path_inc] += '/' unless @options[:path_inc][-1] == 47
+ @options[:path_tst] += '/' unless @options[:path_tst][-1] == 47
+
+ # Built in patterns
+ @patterns = {
+ 'src' => {
+ '' => { inc: [] }
+ },
+ 'test' => {
+ '' => { inc: [] }
+ },
+ 'dh' => {
+ 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h')] },
+ 'Hardware' => { inc: [] }
+ },
+ 'dih' => {
+ 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h'), create_filename('%1$s', 'Interrupt.h')] },
+ 'Interrupt' => { inc: [create_filename('%1$s', 'Hardware.h')] },
+ 'Hardware' => { inc: [] }
+ },
+ 'mch' => {
+ 'Model' => { inc: [] },
+ 'Conductor' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'Hardware.h')] },
+ 'Hardware' => { inc: [] }
+ },
+ 'mvp' => {
+ 'Model' => { inc: [] },
+ 'Presenter' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'View.h')] },
+ 'View' => { inc: [] }
+ }
+ }
+ end
+
+ ############################
+ def self.default_options
+ {
+ pattern: 'src',
+ includes: {
+ src: [],
+ inc: [],
+ tst: []
+ },
+ update_svn: false,
+ boilerplates: {},
+ test_prefix: 'Test',
+ mock_prefix: 'Mock'
+ }
+ end
+
+ ############################
+ def self.grab_config(config_file)
+ options = default_options
+ unless config_file.nil? || config_file.empty?
+ require 'yaml'
+ yaml_guts = YAML.load_file(config_file)
+ options.merge!(yaml_guts[:unity] || yaml_guts[:cmock])
+ raise "No :unity or :cmock section found in #{config_file}" unless options
+ end
+ options
+ end
+
+ ############################
+ def files_to_operate_on(module_name, pattern = nil)
+ # strip any leading path information from the module name and save for later
+ subfolder = File.dirname(module_name)
+ module_name = File.basename(module_name)
+
+ # create triad definition
+ prefix = @options[:test_prefix] || 'Test'
+ triad = [{ ext: '.c', path: @options[:path_src], prefix: '', template: TEMPLATE_SRC, inc: :src, boilerplate: @options[:boilerplates][:src] },
+ { ext: '.h', path: @options[:path_inc], prefix: '', template: TEMPLATE_INC, inc: :inc, boilerplate: @options[:boilerplates][:inc] },
+ { ext: '.c', path: @options[:path_tst], prefix: prefix, template: TEMPLATE_TST, inc: :tst, boilerplate: @options[:boilerplates][:tst] }]
+
+ # prepare the pattern for use
+ pattern = (pattern || @options[:pattern] || 'src').downcase
+ patterns = @patterns[pattern]
+ raise "ERROR: The design pattern '#{pattern}' specified isn't one that I recognize!" if patterns.nil?
+
+ # single file patterns (currently just 'test') can reject the other parts of the triad
+ triad.select! { |v| v[:inc] == :tst } if pattern == 'test'
+
+ # Assemble the path/names of the files we need to work with.
+ files = []
+ triad.each do |cfg|
+ patterns.each_pair do |pattern_file, pattern_traits|
+ submodule_name = create_filename(module_name, pattern_file)
+ filename = cfg[:prefix] + submodule_name + cfg[:ext]
+ files << {
+ path: (Pathname.new("#{cfg[:path]}#{subfolder}") + filename).cleanpath,
+ name: submodule_name,
+ template: cfg[:template],
+ boilerplate: cfg[:boilerplate],
+ includes: case (cfg[:inc])
+ when :src then (@options[:includes][:src] || []) | (pattern_traits[:inc].map { |f| format(f, module_name) })
+ when :inc then (@options[:includes][:inc] || [])
+ when :tst then (@options[:includes][:tst] || []) | (pattern_traits[:inc].map { |f| format("#{@options[:mock_prefix]}#{f}", module_name) })
+ end
+ }
+ end
+ end
+
+ files
+ end
+
+ ############################
+ def create_filename(part1, part2 = '')
+ if part2.empty?
+ case (@options[:naming])
+ when 'bumpy' then part1
+ when 'camel' then part1
+ when 'snake' then part1.downcase
+ when 'caps' then part1.upcase
+ else part1
+ end
+ else
+ case (@options[:naming])
+ when 'bumpy' then part1 + part2
+ when 'camel' then part1 + part2
+ when 'snake' then part1.downcase + '_' + part2.downcase
+ when 'caps' then part1.upcase + '_' + part2.upcase
+ else part1 + '_' + part2
+ end
+ end
+ end
+
+ ############################
+ def generate(module_name, pattern = nil)
+ files = files_to_operate_on(module_name, pattern)
+
+ # Abort if all of the module files already exist
+ all_files_exist = true
+ files.each do |file|
+ all_files_exist = false unless File.exist?(file[:path])
+ end
+ raise "ERROR: File #{files[0][:name]} already exists. Exiting." if all_files_exist
+
+ # Create Source Modules
+ files.each_with_index do |file, _i|
+ # If this file already exists, don't overwrite it.
+ if File.exist?(file[:path])
+ puts "File #{file[:path]} already exists!"
+ next
+ end
+ # Create the path first if necessary.
+ FileUtils.mkdir_p(File.dirname(file[:path]), verbose: false)
+ File.open(file[:path], 'w') do |f|
+ f.write("#{file[:boilerplate]}\n" % [file[:name]]) unless file[:boilerplate].nil?
+ f.write(file[:template] % [file[:name],
+ file[:includes].map { |ff| "#include \"#{ff}\"\n" }.join,
+ file[:name].upcase])
+ end
+ if @options[:update_svn]
+ `svn add \"#{file[:path]}\"`
+ if $!.exitstatus.zero?
+ puts "File #{file[:path]} created and added to source control"
+ else
+ puts "File #{file[:path]} created but FAILED adding to source control!"
+ end
+ else
+ puts "File #{file[:path]} created"
+ end
+ end
+ puts 'Generate Complete'
+ end
+
+ ############################
+ def destroy(module_name, pattern = nil)
+ files_to_operate_on(module_name, pattern).each do |filespec|
+ file = filespec[:path]
+ if File.exist?(file)
+ if @options[:update_svn]
+ `svn delete \"#{file}\" --force`
+ puts "File #{file} deleted and removed from source control"
+ else
+ FileUtils.remove(file)
+ puts "File #{file} deleted"
+ end
+ else
+ puts "File #{file} does not exist so cannot be removed."
+ end
+ end
+ puts 'Destroy Complete'
+ end
+end
+
+############################
+# Handle As Command Line If Called That Way
+if $0 == __FILE__
+ destroy = false
+ options = {}
+ module_name = nil
+
+ # Parse the command line parameters.
+ ARGV.each do |arg|
+ case arg
+ when /^-d/ then destroy = true
+ when /^-u/ then options[:update_svn] = true
+ when /^-p\"?(\w+)\"?/ then options[:pattern] = Regexp.last_match(1)
+ when /^-s\"?(.+)\"?/ then options[:path_src] = Regexp.last_match(1)
+ when /^-i\"?(.+)\"?/ then options[:path_inc] = Regexp.last_match(1)
+ when /^-t\"?(.+)\"?/ then options[:path_tst] = Regexp.last_match(1)
+ when /^-n\"?(.+)\"?/ then options[:naming] = Regexp.last_match(1)
+ when /^-y\"?(.+)\"?/ then options = UnityModuleGenerator.grab_config(Regexp.last_match(1))
+ when /^(\w+)/
+ raise "ERROR: You can't have more than one Module name specified!" unless module_name.nil?
+ module_name = arg
+ when /^-(h|-help)/
+ ARGV = [].freeze
+ else
+ raise "ERROR: Unknown option specified '#{arg}'"
+ end
+ end
+
+ unless ARGV[0]
+ puts ["\nGENERATE MODULE\n-------- ------",
+ "\nUsage: ruby generate_module [options] module_name",
+ " -i\"include\" sets the path to output headers to 'include' (DEFAULT ../src)",
+ " -s\"../src\" sets the path to output source to '../src' (DEFAULT ../src)",
+ " -t\"C:/test\" sets the path to output source to 'C:/test' (DEFAULT ../test)",
+ ' -p"MCH" sets the output pattern to MCH.',
+ ' dh - driver hardware.',
+ ' dih - driver interrupt hardware.',
+ ' mch - model conductor hardware.',
+ ' mvp - model view presenter.',
+ ' src - just a source module, header and test. (DEFAULT)',
+ ' test - just a test file.',
+ ' -d destroy module instead of creating it.',
+ ' -n"camel" sets the file naming convention.',
+ ' bumpy - BumpyCaseFilenames.',
+ ' camel - camelCaseFilenames.',
+ ' snake - snake_case_filenames.',
+ ' caps - CAPS_CASE_FILENAMES.',
+ ' -u update subversion too (requires subversion command line)',
+ ' -y"my.yml" selects a different yaml config file for module generation',
+ ''].join("\n")
+ exit
+ end
+
+ raise 'ERROR: You must have a Module name specified! (use option -h for help)' if module_name.nil?
+ if destroy
+ UnityModuleGenerator.new(options).destroy(module_name)
+ else
+ UnityModuleGenerator.new(options).generate(module_name)
+ end
+
+end
diff --git a/vendor/Unity-2.4.3/auto/generate_test_runner.rb b/vendor/Unity-2.4.3/auto/generate_test_runner.rb
new file mode 100644
index 0000000..344a2d0
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/generate_test_runner.rb
@@ -0,0 +1,454 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+File.expand_path(File.join(File.dirname(__FILE__), 'colour_prompt'))
+
+class UnityTestRunnerGenerator
+ def initialize(options = nil)
+ @options = UnityTestRunnerGenerator.default_options
+ case options
+ when NilClass then @options
+ when String then @options.merge!(UnityTestRunnerGenerator.grab_config(options))
+ when Hash then @options.merge!(options)
+ else raise 'If you specify arguments, it should be a filename or a hash of options'
+ end
+ require "#{File.expand_path(File.dirname(__FILE__))}/type_sanitizer"
+ end
+
+ def self.default_options
+ {
+ includes: [],
+ defines: [],
+ plugins: [],
+ framework: :unity,
+ test_prefix: 'test|spec|should',
+ mock_prefix: 'Mock',
+ setup_name: 'setUp',
+ teardown_name: 'tearDown',
+ main_name: 'main', # set to :auto to automatically generate each time
+ main_export_decl: '',
+ cmdline_args: false,
+ use_param_tests: false
+ }
+ end
+
+ def self.grab_config(config_file)
+ options = default_options
+ unless config_file.nil? || config_file.empty?
+ require 'yaml'
+ yaml_guts = YAML.load_file(config_file)
+ options.merge!(yaml_guts[:unity] || yaml_guts[:cmock])
+ raise "No :unity or :cmock section found in #{config_file}" unless options
+ end
+ options
+ end
+
+ def run(input_file, output_file, options = nil)
+ @options.merge!(options) unless options.nil?
+
+ # pull required data from source file
+ source = File.read(input_file)
+ source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
+ tests = find_tests(source)
+ headers = find_includes(source)
+ testfile_includes = (headers[:local] + headers[:system])
+ used_mocks = find_mocks(testfile_includes)
+ testfile_includes = (testfile_includes - used_mocks)
+ testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ }
+
+ # build runner file
+ generate(input_file, output_file, tests, used_mocks, testfile_includes)
+
+ # determine which files were used to return them
+ all_files_used = [input_file, output_file]
+ all_files_used += testfile_includes.map { |filename| filename + '.c' } unless testfile_includes.empty?
+ all_files_used += @options[:includes] unless @options[:includes].empty?
+ all_files_used += headers[:linkonly] unless headers[:linkonly].empty?
+ all_files_used.uniq
+ end
+
+ def generate(input_file, output_file, tests, used_mocks, testfile_includes)
+ File.open(output_file, 'w') do |output|
+ create_header(output, used_mocks, testfile_includes)
+ create_externs(output, tests, used_mocks)
+ create_mock_management(output, used_mocks)
+ create_suite_setup(output)
+ create_suite_teardown(output)
+ create_reset(output, used_mocks)
+ create_main(output, input_file, tests, used_mocks)
+ end
+
+ return unless @options[:header_file] && !@options[:header_file].empty?
+
+ File.open(@options[:header_file], 'w') do |output|
+ create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks)
+ end
+ end
+
+ def find_tests(source)
+ tests_and_line_numbers = []
+
+ source_scrubbed = source.clone
+ source_scrubbed = source_scrubbed.gsub(/"[^"\n]*"/, '') # remove things in strings
+ source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '') # remove line comments
+ source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments
+ lines = source_scrubbed.split(/(^\s*\#.*$) # Treat preprocessor directives as a logical line
+ | (;|\{|\}) /x) # Match ;, {, and } as end of lines
+
+ lines.each_with_index do |line, _index|
+ # find tests
+ next unless line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/
+ arguments = Regexp.last_match(1)
+ name = Regexp.last_match(2)
+ call = Regexp.last_match(3)
+ params = Regexp.last_match(4)
+ args = nil
+ if @options[:use_param_tests] && !arguments.empty?
+ args = []
+ arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) { |a| args << a[0] }
+ end
+ tests_and_line_numbers << { test: name, args: args, call: call, params: params, line_number: 0 }
+ end
+ tests_and_line_numbers.uniq! { |v| v[:test] }
+
+ # determine line numbers and create tests to run
+ source_lines = source.split("\n")
+ source_index = 0
+ tests_and_line_numbers.size.times do |i|
+ source_lines[source_index..-1].each_with_index do |line, index|
+ next unless line =~ /\s+#{tests_and_line_numbers[i][:test]}(?:\s|\()/
+ source_index += index
+ tests_and_line_numbers[i][:line_number] = source_index + 1
+ break
+ end
+ end
+
+ tests_and_line_numbers
+ end
+
+ def find_includes(source)
+ # remove comments (block and line, in three steps to ensure correct precedence)
+ source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks
+ source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
+ source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain)
+
+ # parse out includes
+ includes = {
+ local: source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten,
+ system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" },
+ linkonly: source.scan(/^TEST_FILE\(\s*\"\s*(.+)\.[cC]\w*\s*\"/).flatten
+ }
+ includes
+ end
+
+ def find_mocks(includes)
+ mock_headers = []
+ includes.each do |include_path|
+ include_file = File.basename(include_path)
+ mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}/i
+ end
+ mock_headers
+ end
+
+ def create_header(output, mocks, testfile_includes = [])
+ output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
+ create_runtest(output, mocks)
+ output.puts("\n/*=======Automagically Detected Files To Include=====*/")
+ output.puts('#ifdef __WIN32__')
+ output.puts('#define UNITY_INCLUDE_SETUP_STUBS')
+ output.puts('#endif')
+ output.puts("#include \"#{@options[:framework]}.h\"")
+ output.puts('#include "cmock.h"') unless mocks.empty?
+ output.puts('#include <setjmp.h>')
+ output.puts('#include <stdio.h>')
+ if @options[:defines] && !@options[:defines].empty?
+ @options[:defines].each { |d| output.puts("#define #{d}") }
+ end
+ if @options[:header_file] && !@options[:header_file].empty?
+ output.puts("#include \"#{File.basename(@options[:header_file])}\"")
+ else
+ @options[:includes].flatten.uniq.compact.each do |inc|
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
+ end
+ testfile_includes.each do |inc|
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
+ end
+ end
+ mocks.each do |mock|
+ output.puts("#include \"#{mock.gsub('.h', '')}.h\"")
+ end
+ output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception)
+
+ return unless @options[:enforce_strict_ordering]
+
+ output.puts('')
+ output.puts('int GlobalExpectCount;')
+ output.puts('int GlobalVerifyOrder;')
+ output.puts('char* GlobalOrderError;')
+ end
+
+ def create_externs(output, tests, _mocks)
+ output.puts("\n/*=======External Functions This Runner Calls=====*/")
+ output.puts("extern void #{@options[:setup_name]}(void);")
+ output.puts("extern void #{@options[:teardown_name]}(void);")
+ tests.each do |test|
+ output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});")
+ end
+ output.puts('')
+ end
+
+ def create_mock_management(output, mock_headers)
+ return if mock_headers.empty?
+
+ output.puts("\n/*=======Mock Management=====*/")
+ output.puts('static void CMock_Init(void)')
+ output.puts('{')
+
+ if @options[:enforce_strict_ordering]
+ output.puts(' GlobalExpectCount = 0;')
+ output.puts(' GlobalVerifyOrder = 0;')
+ output.puts(' GlobalOrderError = NULL;')
+ end
+
+ mocks = mock_headers.map { |mock| File.basename(mock) }
+ mocks.each do |mock|
+ mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+ output.puts(" #{mock_clean}_Init();")
+ end
+ output.puts("}\n")
+
+ output.puts('static void CMock_Verify(void)')
+ output.puts('{')
+ mocks.each do |mock|
+ mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+ output.puts(" #{mock_clean}_Verify();")
+ end
+ output.puts("}\n")
+
+ output.puts('static void CMock_Destroy(void)')
+ output.puts('{')
+ mocks.each do |mock|
+ mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+ output.puts(" #{mock_clean}_Destroy();")
+ end
+ output.puts("}\n")
+ end
+
+ def create_suite_setup(output)
+ output.puts("\n/*=======Suite Setup=====*/")
+ output.puts('static void suite_setup(void)')
+ output.puts('{')
+ if @options[:suite_setup].nil?
+ # New style, call suiteSetUp() if we can use weak symbols
+ output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)')
+ output.puts(' suiteSetUp();')
+ output.puts('#endif')
+ else
+ # Old style, C code embedded in the :suite_setup option
+ output.puts(@options[:suite_setup])
+ end
+ output.puts('}')
+ end
+
+ def create_suite_teardown(output)
+ output.puts("\n/*=======Suite Teardown=====*/")
+ output.puts('static int suite_teardown(int num_failures)')
+ output.puts('{')
+ if @options[:suite_teardown].nil?
+ # New style, call suiteTearDown() if we can use weak symbols
+ output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)')
+ output.puts(' return suiteTearDown(num_failures);')
+ output.puts('#else')
+ output.puts(' return num_failures;')
+ output.puts('#endif')
+ else
+ # Old style, C code embedded in the :suite_teardown option
+ output.puts(@options[:suite_teardown])
+ end
+ output.puts('}')
+ end
+
+ def create_runtest(output, used_mocks)
+ cexception = @options[:plugins].include? :cexception
+ va_args1 = @options[:use_param_tests] ? ', ...' : ''
+ va_args2 = @options[:use_param_tests] ? '__VA_ARGS__' : ''
+ output.puts("\n/*=======Test Runner Used To Run Each Test Below=====*/")
+ output.puts('#define RUN_TEST_NO_ARGS') if @options[:use_param_tests]
+ output.puts("#define RUN_TEST(TestFunc, TestLineNum#{va_args1}) \\")
+ output.puts('{ \\')
+ output.puts(" Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\")
+ output.puts(' Unity.CurrentTestLineNumber = TestLineNum; \\')
+ output.puts(' if (UnityTestMatches()) { \\') if @options[:cmdline_args]
+ output.puts(' Unity.NumberOfTests++; \\')
+ output.puts(' CMock_Init(); \\') unless used_mocks.empty?
+ output.puts(' UNITY_CLR_DETAILS(); \\') unless used_mocks.empty?
+ output.puts(' if (TEST_PROTECT()) \\')
+ output.puts(' { \\')
+ output.puts(' CEXCEPTION_T e; \\') if cexception
+ output.puts(' Try { \\') if cexception
+ output.puts(" #{@options[:setup_name]}(); \\")
+ output.puts(" TestFunc(#{va_args2}); \\")
+ output.puts(' } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \\') if cexception
+ output.puts(' } \\')
+ output.puts(' if (TEST_PROTECT()) \\')
+ output.puts(' { \\')
+ output.puts(" #{@options[:teardown_name]}(); \\")
+ output.puts(' CMock_Verify(); \\') unless used_mocks.empty?
+ output.puts(' } \\')
+ output.puts(' CMock_Destroy(); \\') unless used_mocks.empty?
+ output.puts(' UnityConcludeTest(); \\')
+ output.puts(' } \\') if @options[:cmdline_args]
+ output.puts("}\n")
+ end
+
+ def create_reset(output, used_mocks)
+ output.puts("\n/*=======Test Reset Option=====*/")
+ output.puts('void resetTest(void);')
+ output.puts('void resetTest(void)')
+ output.puts('{')
+ output.puts(' CMock_Verify();') unless used_mocks.empty?
+ output.puts(' CMock_Destroy();') unless used_mocks.empty?
+ output.puts(" #{@options[:teardown_name]}();")
+ output.puts(' CMock_Init();') unless used_mocks.empty?
+ output.puts(" #{@options[:setup_name]}();")
+ output.puts('}')
+ end
+
+ def create_main(output, filename, tests, used_mocks)
+ output.puts("\n\n/*=======MAIN=====*/")
+ main_name = @options[:main_name].to_sym == :auto ? "main_#{filename.gsub('.c', '')}" : (@options[:main_name]).to_s
+ if @options[:cmdline_args]
+ if main_name != 'main'
+ output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv);")
+ end
+ output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)")
+ output.puts('{')
+ output.puts(' int parse_status = UnityParseOptions(argc, argv);')
+ output.puts(' if (parse_status != 0)')
+ output.puts(' {')
+ output.puts(' if (parse_status < 0)')
+ output.puts(' {')
+ output.puts(" UnityPrint(\"#{filename.gsub('.c', '')}.\");")
+ output.puts(' UNITY_PRINT_EOL();')
+ if @options[:use_param_tests]
+ tests.each do |test|
+ if test[:args].nil? || test[:args].empty?
+ output.puts(" UnityPrint(\" #{test[:test]}(RUN_TEST_NO_ARGS)\");")
+ output.puts(' UNITY_PRINT_EOL();')
+ else
+ test[:args].each do |args|
+ output.puts(" UnityPrint(\" #{test[:test]}(#{args})\");")
+ output.puts(' UNITY_PRINT_EOL();')
+ end
+ end
+ end
+ else
+ tests.each { |test| output.puts(" UnityPrint(\" #{test[:test]}\");\n UNITY_PRINT_EOL();") }
+ end
+ output.puts(' return 0;')
+ output.puts(' }')
+ output.puts(' return parse_status;')
+ output.puts(' }')
+ else
+ if main_name != 'main'
+ output.puts("#{@options[:main_export_decl]} int #{main_name}(void);")
+ end
+ output.puts("int #{main_name}(void)")
+ output.puts('{')
+ end
+ output.puts(' suite_setup();')
+ output.puts(" UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");")
+ if @options[:use_param_tests]
+ tests.each do |test|
+ if test[:args].nil? || test[:args].empty?
+ output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, RUN_TEST_NO_ARGS);")
+ else
+ test[:args].each { |args| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, #{args});") }
+ end
+ end
+ else
+ tests.each { |test| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]});") }
+ end
+ output.puts
+ output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty?
+ output.puts(" return suite_teardown(UnityEnd());")
+ output.puts('}')
+ end
+
+ def create_h_file(output, filename, tests, testfile_includes, used_mocks)
+ filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, '_').upcase
+ output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
+ output.puts("#ifndef _#{filename}")
+ output.puts("#define _#{filename}\n\n")
+ output.puts("#include \"#{@options[:framework]}.h\"")
+ output.puts('#include "cmock.h"') unless used_mocks.empty?
+ @options[:includes].flatten.uniq.compact.each do |inc|
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
+ end
+ testfile_includes.each do |inc|
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
+ end
+ output.puts "\n"
+ tests.each do |test|
+ if test[:params].nil? || test[:params].empty?
+ output.puts("void #{test[:test]}(void);")
+ else
+ output.puts("void #{test[:test]}(#{test[:params]});")
+ end
+ end
+ output.puts("#endif\n\n")
+ end
+end
+
+if $0 == __FILE__
+ options = { includes: [] }
+
+ # parse out all the options first (these will all be removed as we go)
+ ARGV.reject! do |arg|
+ case arg
+ when '-cexception'
+ options[:plugins] = [:cexception]
+ true
+ when /\.*\.ya?ml/
+ options = UnityTestRunnerGenerator.grab_config(arg)
+ true
+ when /--(\w+)=\"?(.*)\"?/
+ options[Regexp.last_match(1).to_sym] = Regexp.last_match(2)
+ true
+ when /\.*\.h/
+ options[:includes] << arg
+ true
+ else false
+ end
+ end
+
+ # make sure there is at least one parameter left (the input file)
+ unless ARGV[0]
+ puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)",
+ "\n input_test_file - this is the C file you want to create a runner for",
+ ' output - this is the name of the runner file to generate',
+ ' defaults to (input_test_file)_Runner',
+ ' files:',
+ ' *.yml / *.yaml - loads configuration from here in :unity or :cmock',
+ ' *.h - header files are added as #includes in runner',
+ ' options:',
+ ' -cexception - include cexception support',
+ ' --setup_name="" - redefine setUp func name to something else',
+ ' --teardown_name="" - redefine tearDown func name to something else',
+ ' --main_name="" - redefine main func name to something else',
+ ' --test_prefix="" - redefine test prefix from default test|spec|should',
+ ' --suite_setup="" - code to execute for setup of entire suite',
+ ' --suite_teardown="" - code to execute for teardown of entire suite',
+ ' --use_param_tests=1 - enable parameterized tests (disabled by default)',
+ ' --header_file="" - path/name of test header file to generate too'].join("\n")
+ exit 1
+ end
+
+ # create the default test runner name if not specified
+ ARGV[1] = ARGV[0].gsub('.c', '_Runner.c') unless ARGV[1]
+
+ UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1])
+end
diff --git a/vendor/Unity-2.4.3/auto/parse_output.rb b/vendor/Unity-2.4.3/auto/parse_output.rb
new file mode 100644
index 0000000..f16cdb0
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/parse_output.rb
@@ -0,0 +1,220 @@
+#============================================================
+# Author: John Theofanopoulos
+# A simple parser. Takes the output files generated during the build process and
+# extracts information relating to the tests.
+#
+# Notes:
+# To capture an output file under VS builds use the following:
+# devenv [build instructions] > Output.txt & type Output.txt
+#
+# To capture an output file under GCC/Linux builds use the following:
+# make | tee Output.txt
+#
+# To use this parser use the following command
+# ruby parseOutput.rb [options] [file]
+# options: -xml : produce a JUnit compatible XML file
+# file : file to scan for results
+#============================================================
+
+class ParseOutput
+ def initialize
+ @test_flag = false
+ @xml_out = false
+ @array_list = false
+ @total_tests = false
+ @class_index = false
+ end
+
+ # Set the flag to indicate if there will be an XML output file or not
+ def set_xml_output
+ @xml_out = true
+ end
+
+ # if write our output to XML
+ def write_xml_output
+ output = File.open('report.xml', 'w')
+ output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ @array_list.each do |item|
+ output << item << "\n"
+ end
+ output << "</testsuite>\n"
+ end
+
+ # This function will try and determine when the suite is changed. This is
+ # is the name that gets added to the classname parameter.
+ def test_suite_verify(test_suite_name)
+ return if @test_flag
+
+ @test_flag = true
+ # Split the path name
+ test_name = test_suite_name.split('/')
+ # Remove the extension
+ base_name = test_name[test_name.size - 1].split('.')
+ @test_suite = 'test.' + base_name[0]
+ printf "New Test: %s\n", @test_suite
+ end
+
+ # Test was flagged as having passed so format the output
+ def test_passed(array)
+ last_item = array.length - 1
+ test_name = array[last_item - 1]
+ test_suite_verify(array[@class_name])
+ printf "%-40s PASS\n", test_name
+
+ return unless @xml_out
+
+ @array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '"/>'
+ end
+
+ # Test was flagged as having passed so format the output.
+ # This is using the Unity fixture output and not the original Unity output.
+ def test_passed_unity_fixture(array)
+ test_suite = array[0].sub('TEST(', '')
+ test_suite = test_suite.sub(',', '')
+ test_name = array[1].sub(')', '')
+
+ return unless @xml_out
+
+ @array_list.push ' <testcase classname="' + test_suite + '" name="' + test_name + '"/>'
+ end
+
+ # Test was flagged as being ingored so format the output
+ def test_ignored(array)
+ last_item = array.length - 1
+ test_name = array[last_item - 2]
+ reason = array[last_item].chomp
+ test_suite_verify(array[@class_name])
+ printf "%-40s IGNORED\n", test_name
+
+ if test_name.start_with? 'TEST('
+ array2 = test_name.split(' ')
+ @test_suite = array2[0].sub('TEST(', '')
+ @test_suite = @test_suite.sub(',', '')
+ test_name = array2[1].sub(')', '')
+ end
+
+ return unless @xml_out
+
+ @array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
+ @array_list.push ' <skipped type="TEST IGNORED"> ' + reason + ' </skipped>'
+ @array_list.push ' </testcase>'
+ end
+
+ # Test was flagged as having failed so format the line
+ def test_failed(array)
+ last_item = array.length - 1
+ test_name = array[last_item - 2]
+ reason = array[last_item].chomp + ' at line: ' + array[last_item - 3]
+ test_suite_verify(array[@class_name])
+ printf "%-40s FAILED\n", test_name
+
+ if test_name.start_with? 'TEST('
+ array2 = test_name.split(' ')
+ @test_suite = array2[0].sub('TEST(', '')
+ @test_suite = @test_suite.sub(',', '')
+ test_name = array2[1].sub(')', '')
+ end
+
+ return unless @xml_out
+
+ @array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
+ @array_list.push ' <failure type="ASSERT FAILED"> ' + reason + ' </failure>'
+ @array_list.push ' </testcase>'
+ end
+
+ # Figure out what OS we are running on. For now we are assuming if it's not Windows it must
+ # be Unix based.
+ def detect_os
+ os = RUBY_PLATFORM.split('-')
+ @class_name = if os.size == 2
+ if os[1] == 'mingw32'
+ 1
+ else
+ 0
+ end
+ else
+ 0
+ end
+ end
+
+ # Main function used to parse the file that was captured.
+ def process(name)
+ @test_flag = false
+ @array_list = []
+
+ detect_os
+
+ puts 'Parsing file: ' + name
+
+ test_pass = 0
+ test_fail = 0
+ test_ignore = 0
+ puts ''
+ puts '=================== RESULTS ====================='
+ puts ''
+ File.open(name).each do |line|
+ # Typical test lines look like this:
+ # <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0
+ # <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented
+ # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS
+ #
+ # where path is different on Unix vs Windows devices (Windows leads with a drive letter)
+ line_array = line.split(':')
+
+ # If we were able to split the line then we can look to see if any of our target words
+ # were found. Case is important.
+ if (line_array.size >= 4) || (line.start_with? 'TEST(')
+ # Determine if this test passed
+ if line.include? ':PASS'
+ test_passed(line_array)
+ test_pass += 1
+ elsif line.include? ':FAIL:'
+ test_failed(line_array)
+ test_fail += 1
+ elsif line.include? ':IGNORE:'
+ test_ignored(line_array)
+ test_ignore += 1
+ elsif line.start_with? 'TEST('
+ if line.include? ' PASS'
+ line_array = line.split(' ')
+ test_passed_unity_fixture(line_array)
+ test_pass += 1
+ end
+ # If none of the keywords are found there are no more tests for this suite so clear
+ # the test flag
+ else
+ @test_flag = false
+ end
+ else
+ @test_flag = false
+ end
+ end
+ puts ''
+ puts '=================== SUMMARY ====================='
+ puts ''
+ puts 'Tests Passed : ' + test_pass.to_s
+ puts 'Tests Failed : ' + test_fail.to_s
+ puts 'Tests Ignored : ' + test_ignore.to_s
+ @total_tests = test_pass + test_fail + test_ignore
+
+ return unless @xml_out
+
+ heading = '<testsuite tests="' + @total_tests.to_s + '" failures="' + test_fail.to_s + '"' + ' skips="' + test_ignore.to_s + '">'
+ @array_list.insert(0, heading)
+ write_xml_output
+ end
+end
+
+# If the command line has no values in, used a default value of Output.txt
+parse_my_file = ParseOutput.new
+
+if ARGV.size >= 1
+ ARGV.each do |a|
+ if a == '-xml'
+ parse_my_file.set_xml_output
+ else
+ parse_my_file.process(a)
+ break
+ end
+ end
+end
diff --git a/vendor/Unity-2.4.3/auto/stylize_as_junit.rb b/vendor/Unity-2.4.3/auto/stylize_as_junit.rb
new file mode 100755
index 0000000..b3d8f40
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/stylize_as_junit.rb
@@ -0,0 +1,252 @@
+#!/usr/bin/ruby
+#
+# unity_to_junit.rb
+#
+require 'fileutils'
+require 'optparse'
+require 'ostruct'
+require 'set'
+
+require 'pp'
+
+VERSION = 1.0
+
+class ArgvParser
+ #
+ # Return a structure describing the options.
+ #
+ def self.parse(args)
+ # The options specified on the command line will be collected in *options*.
+ # We set default values here.
+ options = OpenStruct.new
+ options.results_dir = '.'
+ options.root_path = '.'
+ options.out_file = 'results.xml'
+
+ opts = OptionParser.new do |o|
+ o.banner = 'Usage: unity_to_junit.rb [options]'
+
+ o.separator ''
+ o.separator 'Specific options:'
+
+ o.on('-r', '--results <dir>', 'Look for Unity Results files here.') do |results|
+ # puts "results #{results}"
+ options.results_dir = results
+ end
+
+ o.on('-p', '--root_path <path>', 'Prepend this path to files in results.') do |root_path|
+ options.root_path = root_path
+ end
+
+ o.on('-o', '--output <filename>', 'XML file to generate.') do |out_file|
+ # puts "out_file: #{out_file}"
+ options.out_file = out_file
+ end
+
+ o.separator ''
+ o.separator 'Common options:'
+
+ # No argument, shows at tail. This will print an options summary.
+ o.on_tail('-h', '--help', 'Show this message') do
+ puts o
+ exit
+ end
+
+ # Another typical switch to print the version.
+ o.on_tail('--version', 'Show version') do
+ puts "unity_to_junit.rb version #{VERSION}"
+ exit
+ end
+ end
+
+ opts.parse!(args)
+ options
+ end # parse()
+end # class OptparseExample
+
+class UnityToJUnit
+ include FileUtils::Verbose
+ attr_reader :report, :total_tests, :failures, :ignored
+ attr_writer :targets, :root, :out_file
+
+ def initialize
+ @report = ''
+ @unit_name = ''
+ end
+
+ def run
+ # Clean up result file names
+ results = @targets.map { |target| target.tr('\\', '/') }
+ # puts "Output File: #{@out_file}"
+ f = File.new(@out_file, 'w')
+ write_xml_header(f)
+ write_suites_header(f)
+ results.each do |result_file|
+ lines = File.readlines(result_file).map(&:chomp)
+
+ raise "Empty test result file: #{result_file}" if lines.empty?
+
+ result_output = get_details(result_file, lines)
+ tests, failures, ignored = parse_test_summary(lines)
+ result_output[:counts][:total] = tests
+ result_output[:counts][:failed] = failures
+ result_output[:counts][:ignored] = ignored
+ result_output[:counts][:passed] = (result_output[:counts][:total] - result_output[:counts][:failed] - result_output[:counts][:ignored])
+
+ # use line[0] from the test output to get the test_file path and name
+ test_file_str = lines[0].tr('\\', '/')
+ test_file_str = test_file_str.split(':')
+ test_file = if test_file_str.length < 2
+ result_file
+ else
+ test_file_str[0] + ':' + test_file_str[1]
+ end
+ result_output[:source][:path] = File.dirname(test_file)
+ result_output[:source][:file] = File.basename(test_file)
+
+ # save result_output
+ @unit_name = File.basename(test_file, '.*')
+
+ write_suite_header(result_output[:counts], f)
+ write_failures(result_output, f)
+ write_tests(result_output, f)
+ write_ignored(result_output, f)
+ write_suite_footer(f)
+ end
+ write_suites_footer(f)
+ f.close
+ end
+
+ def usage(err_msg = nil)
+ puts "\nERROR: "
+ puts err_msg if err_msg
+ puts 'Usage: unity_to_junit.rb [options]'
+ puts ''
+ puts 'Specific options:'
+ puts ' -r, --results <dir> Look for Unity Results files here.'
+ puts ' -p, --root_path <path> Prepend this path to files in results.'
+ puts ' -o, --output <filename> XML file to generate.'
+ puts ''
+ puts 'Common options:'
+ puts ' -h, --help Show this message'
+ puts ' --version Show version'
+
+ exit 1
+ end
+
+ protected
+
+ def get_details(_result_file, lines)
+ results = results_structure
+ lines.each do |line|
+ line = line.tr('\\', '/')
+ _src_file, src_line, test_name, status, msg = line.split(/:/)
+ case status
+ when 'IGNORE' then results[:ignores] << { test: test_name, line: src_line, message: msg }
+ when 'FAIL' then results[:failures] << { test: test_name, line: src_line, message: msg }
+ when 'PASS' then results[:successes] << { test: test_name, line: src_line, message: msg }
+ end
+ end
+ results
+ end
+
+ def parse_test_summary(summary)
+ raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ }
+ [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i]
+ end
+
+ def here
+ File.expand_path(File.dirname(__FILE__))
+ end
+
+ private
+
+ def results_structure
+ {
+ source: { path: '', file: '' },
+ successes: [],
+ failures: [],
+ ignores: [],
+ counts: { total: 0, passed: 0, failed: 0, ignored: 0 },
+ stdout: []
+ }
+ end
+
+ def write_xml_header(stream)
+ stream.puts "<?xml version='1.0' encoding='utf-8' ?>"
+ end
+
+ def write_suites_header(stream)
+ stream.puts '<testsuites>'
+ end
+
+ def write_suite_header(counts, stream)
+ stream.puts "\t<testsuite errors=\"0\" skipped=\"#{counts[:ignored]}\" failures=\"#{counts[:failed]}\" tests=\"#{counts[:total]}\" name=\"unity\">"
+ end
+
+ def write_failures(results, stream)
+ result = results[:failures]
+ result.each do |item|
+ filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
+ stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
+ stream.puts "\t\t\t<failure message=\"#{item[:message]}\" type=\"Assertion\"/>"
+ stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
+ stream.puts "\t\t</testcase>"
+ end
+ end
+
+ def write_tests(results, stream)
+ result = results[:successes]
+ result.each do |item|
+ stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\" />"
+ end
+ end
+
+ def write_ignored(results, stream)
+ result = results[:ignores]
+ result.each do |item|
+ filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
+ puts "Writing ignored tests for test harness: #{filename}"
+ stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
+ stream.puts "\t\t\t<skipped message=\"#{item[:message]}\" type=\"Assertion\"/>"
+ stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
+ stream.puts "\t\t</testcase>"
+ end
+ end
+
+ def write_suite_footer(stream)
+ stream.puts "\t</testsuite>"
+ end
+
+ def write_suites_footer(stream)
+ stream.puts '</testsuites>'
+ end
+end # UnityToJUnit
+
+if __FILE__ == $0
+ # parse out the command options
+ options = ArgvParser.parse(ARGV)
+
+ # create an instance to work with
+ utj = UnityToJUnit.new
+ begin
+ # look in the specified or current directory for result files
+ targets = "#{options.results_dir.tr('\\', '/')}**/*.test*"
+
+ results = Dir[targets]
+ raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty?
+ utj.targets = results
+
+ # set the root path
+ utj.root = options.root_path
+
+ # set the output XML file name
+ # puts "Output File from options: #{options.out_file}"
+ utj.out_file = options.out_file
+
+ # run the summarizer
+ puts utj.run
+ rescue StandardError => e
+ utj.usage e.message
+ end
+end
diff --git a/vendor/Unity-2.4.3/auto/test_file_filter.rb b/vendor/Unity-2.4.3/auto/test_file_filter.rb
new file mode 100644
index 0000000..aad28e3
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/test_file_filter.rb
@@ -0,0 +1,25 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+require'yaml'
+
+module RakefileHelpers
+ class TestFileFilter
+ def initialize(all_files = false)
+ @all_files = all_files
+
+ return false unless @all_files
+ return false unless File.exist?('test_file_filter.yml')
+
+ filters = YAML.load_file('test_file_filter.yml')
+ @all_files = filters[:all_files]
+ @only_files = filters[:only_files]
+ @exclude_files = filters[:exclude_files]
+ end
+
+ attr_accessor :all_files, :only_files, :exclude_files
+ end
+end
diff --git a/vendor/Unity-2.4.3/auto/type_sanitizer.rb b/vendor/Unity-2.4.3/auto/type_sanitizer.rb
new file mode 100644
index 0000000..dafb882
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/type_sanitizer.rb
@@ -0,0 +1,6 @@
+module TypeSanitizer
+ def self.sanitize_c_identifier(unsanitized)
+ # convert filename to valid C identifier by replacing invalid chars with '_'
+ unsanitized.gsub(/[-\/\\\.\,\s]/, '_')
+ end
+end
diff --git a/vendor/Unity-2.4.3/auto/unity_test_summary.py b/vendor/Unity-2.4.3/auto/unity_test_summary.py
new file mode 100644
index 0000000..4c20e52
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/unity_test_summary.py
@@ -0,0 +1,139 @@
+#! python3
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2015 Alexander Mueller / XelaRellum@web.de
+# [Released under MIT License. Please refer to license.txt for details]
+# Based on the ruby script by Mike Karlesky, Mark VanderVoord, Greg Williams
+# ==========================================
+import sys
+import os
+import re
+from glob import glob
+
+class UnityTestSummary:
+ def __init__(self):
+ self.report = ''
+ self.total_tests = 0
+ self.failures = 0
+ self.ignored = 0
+
+ def run(self):
+ # Clean up result file names
+ results = []
+ for target in self.targets:
+ results.append(target.replace('\\', '/'))
+
+ # Dig through each result file, looking for details on pass/fail:
+ failure_output = []
+ ignore_output = []
+
+ for result_file in results:
+ lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n')))
+ if len(lines) == 0:
+ raise Exception("Empty test result file: %s" % result_file)
+
+ details = self.get_details(result_file, lines)
+ failures = details['failures']
+ ignores = details['ignores']
+ if len(failures) > 0: failure_output.append('\n'.join(failures))
+ if len(ignores) > 0: ignore_output.append('n'.join(ignores))
+ tests,failures,ignored = self.parse_test_summary('\n'.join(lines))
+ self.total_tests += tests
+ self.failures += failures
+ self.ignored += ignored
+
+ if self.ignored > 0:
+ self.report += "\n"
+ self.report += "--------------------------\n"
+ self.report += "UNITY IGNORED TEST SUMMARY\n"
+ self.report += "--------------------------\n"
+ self.report += "\n".join(ignore_output)
+
+ if self.failures > 0:
+ self.report += "\n"
+ self.report += "--------------------------\n"
+ self.report += "UNITY FAILED TEST SUMMARY\n"
+ self.report += "--------------------------\n"
+ self.report += '\n'.join(failure_output)
+
+ self.report += "\n"
+ self.report += "--------------------------\n"
+ self.report += "OVERALL UNITY TEST SUMMARY\n"
+ self.report += "--------------------------\n"
+ self.report += "{total_tests} TOTAL TESTS {failures} TOTAL FAILURES {ignored} IGNORED\n".format(total_tests = self.total_tests, failures=self.failures, ignored=self.ignored)
+ self.report += "\n"
+
+ return self.report
+
+ def set_targets(self, target_array):
+ self.targets = target_array
+
+ def set_root_path(self, path):
+ self.root = path
+
+ def usage(self, err_msg=None):
+ print("\nERROR: ")
+ if err_msg:
+ print(err_msg)
+ print("\nUsage: unity_test_summary.py result_file_directory/ root_path/")
+ print(" result_file_directory - The location of your results files.")
+ print(" Defaults to current directory if not specified.")
+ print(" Should end in / if specified.")
+ print(" root_path - Helpful for producing more verbose output if using relative paths.")
+ sys.exit(1)
+
+ def get_details(self, result_file, lines):
+ results = { 'failures': [], 'ignores': [], 'successes': [] }
+ for line in lines:
+ parts = line.split(':')
+ if len(parts) == 5:
+ src_file,src_line,test_name,status,msg = parts
+ elif len(parts) == 4:
+ src_file,src_line,test_name,status = parts
+ msg = ''
+ else:
+ continue
+ if len(self.root) > 0:
+ line_out = "%s%s" % (self.root, line)
+ else:
+ line_out = line
+ if status == 'IGNORE':
+ results['ignores'].append(line_out)
+ elif status == 'FAIL':
+ results['failures'].append(line_out)
+ elif status == 'PASS':
+ results['successes'].append(line_out)
+ return results
+
+ def parse_test_summary(self, summary):
+ m = re.search(r"([0-9]+) Tests ([0-9]+) Failures ([0-9]+) Ignored", summary)
+ if not m:
+ raise Exception("Couldn't parse test results: %s" % summary)
+
+ return int(m.group(1)), int(m.group(2)), int(m.group(3))
+
+
+if __name__ == '__main__':
+ uts = UnityTestSummary()
+ try:
+ #look in the specified or current directory for result files
+ if len(sys.argv) > 1:
+ targets_dir = sys.argv[1]
+ else:
+ targets_dir = './'
+ targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*')))
+ if len(targets) == 0:
+ raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir)
+ uts.set_targets(targets)
+
+ #set the root path
+ if len(sys.argv) > 2:
+ root_path = sys.argv[2]
+ else:
+ root_path = os.path.split(__file__)[0]
+ uts.set_root_path(root_path)
+
+ #run the summarizer
+ print(uts.run())
+ except Exception as e:
+ uts.usage(e)
diff --git a/vendor/Unity-2.4.3/auto/unity_test_summary.rb b/vendor/Unity-2.4.3/auto/unity_test_summary.rb
new file mode 100644
index 0000000..b37dc5f
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/unity_test_summary.rb
@@ -0,0 +1,136 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+# !/usr/bin/ruby
+#
+# unity_test_summary.rb
+#
+require 'fileutils'
+require 'set'
+
+class UnityTestSummary
+ include FileUtils::Verbose
+
+ attr_reader :report, :total_tests, :failures, :ignored
+ attr_writer :targets, :root
+
+ def initialize(_opts = {})
+ @report = ''
+ @total_tests = 0
+ @failures = 0
+ @ignored = 0
+ end
+
+ def run
+ # Clean up result file names
+ results = @targets.map { |target| target.tr('\\', '/') }
+
+ # Dig through each result file, looking for details on pass/fail:
+ failure_output = []
+ ignore_output = []
+
+ results.each do |result_file|
+ lines = File.readlines(result_file).map(&:chomp)
+
+ raise "Empty test result file: #{result_file}" if lines.empty?
+
+ output = get_details(result_file, lines)
+ failure_output << output[:failures] unless output[:failures].empty?
+ ignore_output << output[:ignores] unless output[:ignores].empty?
+ tests, failures, ignored = parse_test_summary(lines)
+ @total_tests += tests
+ @failures += failures
+ @ignored += ignored
+ end
+
+ if @ignored > 0
+ @report += "\n"
+ @report += "--------------------------\n"
+ @report += "UNITY IGNORED TEST SUMMARY\n"
+ @report += "--------------------------\n"
+ @report += ignore_output.flatten.join("\n")
+ end
+
+ if @failures > 0
+ @report += "\n"
+ @report += "--------------------------\n"
+ @report += "UNITY FAILED TEST SUMMARY\n"
+ @report += "--------------------------\n"
+ @report += failure_output.flatten.join("\n")
+ end
+
+ @report += "\n"
+ @report += "--------------------------\n"
+ @report += "OVERALL UNITY TEST SUMMARY\n"
+ @report += "--------------------------\n"
+ @report += "#{@total_tests} TOTAL TESTS #{@failures} TOTAL FAILURES #{@ignored} IGNORED\n"
+ @report += "\n"
+ end
+
+ def usage(err_msg = nil)
+ puts "\nERROR: "
+ puts err_msg if err_msg
+ puts "\nUsage: unity_test_summary.rb result_file_directory/ root_path/"
+ puts ' result_file_directory - The location of your results files.'
+ puts ' Defaults to current directory if not specified.'
+ puts ' Should end in / if specified.'
+ puts ' root_path - Helpful for producing more verbose output if using relative paths.'
+ exit 1
+ end
+
+ protected
+
+ def get_details(_result_file, lines)
+ results = { failures: [], ignores: [], successes: [] }
+ lines.each do |line|
+ _src_file, _src_line, _test_name, status, _msg = line.split(/:/)
+ line_out = (@root && (@root != 0) ? "#{@root}#{line}" : line).gsub(/\//, '\\')
+ case status
+ when 'IGNORE' then results[:ignores] << line_out
+ when 'FAIL' then results[:failures] << line_out
+ when 'PASS' then results[:successes] << line_out
+ end
+ end
+ results
+ end
+
+ def parse_test_summary(summary)
+ raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ }
+ [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i]
+ end
+
+ def here
+ File.expand_path(File.dirname(__FILE__))
+ end
+end
+
+if $0 == __FILE__
+
+ # parse out the command options
+ opts, args = ARGV.partition { |v| v =~ /^--\w+/ }
+ opts.map! { |v| v[2..-1].to_sym }
+
+ # create an instance to work with
+ uts = UnityTestSummary.new(opts)
+
+ begin
+ # look in the specified or current directory for result files
+ args[0] ||= './'
+ targets = "#{ARGV[0].tr('\\', '/')}**/*.test*"
+ results = Dir[targets]
+ raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty?
+ uts.targets = results
+
+ # set the root path
+ args[1] ||= Dir.pwd + '/'
+ uts.root = ARGV[1]
+
+ # run the summarizer
+ puts uts.run
+ rescue StandardError => e
+ uts.usage e.message
+ end
+end
diff --git a/vendor/Unity-2.4.3/auto/unity_to_junit.py b/vendor/Unity-2.4.3/auto/unity_to_junit.py
new file mode 100644
index 0000000..71dd568
--- /dev/null
+++ b/vendor/Unity-2.4.3/auto/unity_to_junit.py
@@ -0,0 +1,146 @@
+import sys
+import os
+from glob import glob
+
+from pyparsing import *
+from junit_xml import TestSuite, TestCase
+
+
+class UnityTestSummary:
+ def __init__(self):
+ self.report = ''
+ self.total_tests = 0
+ self.failures = 0
+ self.ignored = 0
+ self.targets = 0
+ self.root = None
+ self.test_suites = dict()
+
+ def run(self):
+ # Clean up result file names
+ results = []
+ for target in self.targets:
+ results.append(target.replace('\\', '/'))
+
+ # Dig through each result file, looking for details on pass/fail:
+ for result_file in results:
+ lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n')))
+ if len(lines) == 0:
+ raise Exception("Empty test result file: %s" % result_file)
+
+ # define an expression for your file reference
+ entry_one = Combine(
+ oneOf(list(alphas)) + ':/' +
+ Word(alphanums + '_-./'))
+
+ entry_two = Word(printables + ' ', excludeChars=':')
+ entry = entry_one | entry_two
+
+ delimiter = Literal(':').suppress()
+ tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName(
+ 'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName(
+ 'tc_status') + Optional(
+ delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line")
+
+ eol = LineEnd().suppress()
+ sol = LineStart().suppress()
+ blank_line = sol + eol
+
+ tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName(
+ "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName(
+ "tc_summary")
+ tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result")
+
+ # run it and see...
+ pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line)
+ pp1.ignore(blank_line | OneOrMore("-"))
+
+ result = list()
+ for l in lines:
+ result.append((pp1.parseString(l)).asDict())
+ # delete empty results
+ result = filter(None, result)
+
+ tc_list = list()
+ for r in result:
+ if 'tc_line' in r:
+ tmp_tc_line = r['tc_line']
+
+ # get only the file name which will be used as the classname
+ file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0]
+ tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name)
+ if 'tc_status' in tmp_tc_line:
+ if str(tmp_tc_line['tc_status']) == 'IGNORE':
+ if 'tc_msg' in tmp_tc_line:
+ tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'],
+ output=r'[File]={0}, [Line]={1}'.format(
+ tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
+ else:
+ tmp_tc.add_skipped_info(message=" ")
+ elif str(tmp_tc_line['tc_status']) == 'FAIL':
+ if 'tc_msg' in tmp_tc_line:
+ tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'],
+ output=r'[File]={0}, [Line]={1}'.format(
+ tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
+ else:
+ tmp_tc.add_failure_info(message=" ")
+
+ tc_list.append((str(result_file), tmp_tc))
+
+ for k, v in tc_list:
+ try:
+ self.test_suites[k].append(v)
+ except KeyError:
+ self.test_suites[k] = [v]
+ ts = []
+ for suite_name in self.test_suites:
+ ts.append(TestSuite(suite_name, self.test_suites[suite_name]))
+
+ with open('result.xml', 'w') as f:
+ TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8')
+
+ return self.report
+
+ def set_targets(self, target_array):
+ self.targets = target_array
+
+ def set_root_path(self, path):
+ self.root = path
+
+ @staticmethod
+ def usage(err_msg=None):
+ print("\nERROR: ")
+ if err_msg:
+ print(err_msg)
+ print("\nUsage: unity_test_summary.py result_file_directory/ root_path/")
+ print(" result_file_directory - The location of your results files.")
+ print(" Defaults to current directory if not specified.")
+ print(" Should end in / if specified.")
+ print(" root_path - Helpful for producing more verbose output if using relative paths.")
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ uts = UnityTestSummary()
+ try:
+ # look in the specified or current directory for result files
+ if len(sys.argv) > 1:
+ targets_dir = sys.argv[1]
+ else:
+ targets_dir = './'
+ targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*')))
+ if len(targets) == 0:
+ raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir)
+ uts.set_targets(targets)
+
+ # set the root path
+ if len(sys.argv) > 2:
+ root_path = sys.argv[2]
+ else:
+ root_path = os.path.split(__file__)[0]
+ uts.set_root_path(root_path)
+
+ # run the summarizer
+ print(uts.run())
+ except Exception as e:
+ UnityTestSummary.usage(e)
diff --git a/vendor/Unity-2.4.3/docs/ThrowTheSwitchCodingStandard.md b/vendor/Unity-2.4.3/docs/ThrowTheSwitchCodingStandard.md
new file mode 100644
index 0000000..a85adef
--- /dev/null
+++ b/vendor/Unity-2.4.3/docs/ThrowTheSwitchCodingStandard.md
@@ -0,0 +1,207 @@
+# ThrowTheSwitch.org Coding Standard
+
+Hi. Welcome to the coding standard for ThrowTheSwitch.org. For the most part,
+we try to follow these standards to unify our contributors' code into a cohesive
+unit (puns intended). You might find places where these standards aren't
+followed. We're not perfect. Please be polite where you notice these discrepancies
+and we'll try to be polite when we notice yours.
+
+;)
+
+
+## Why Have A Coding Standard?
+
+Being consistent makes code easier to understand. We've made an attempt to keep
+our standard simple because we also believe that we can only expect someone to
+follow something that is understandable. Please do your best.
+
+
+## Our Philosophy
+
+Before we get into details on syntax, let's take a moment to talk about our
+vision for these tools. We're C developers and embedded software developers.
+These tools are great to test any C code, but catering to embedded software has
+made us more tolerant of compiler quirks. There are a LOT of quirky compilers
+out there. By quirky I mean "doesn't follow standards because they feel like
+they have a license to do as they wish."
+
+Our philosophy is "support every compiler we can". Most often, this means that
+we aim for writing C code that is standards compliant (often C89... that seems
+to be a sweet spot that is almost always compatible). But it also means these
+tools are tolerant of things that aren't common. Some that aren't even
+compliant. There are configuration options to override the size of standard
+types. There are configuration options to force Unity to not use certain
+standard library functions. A lot of Unity is configurable and we have worked
+hard to make it not TOO ugly in the process.
+
+Similarly, our tools that parse C do their best. They aren't full C parsers
+(yet) and, even if they were, they would still have to accept non-standard
+additions like gcc extensions or specifying `@0x1000` to force a variable to
+compile to a particular location. It's just what we do, because we like
+everything to Just Work™.
+
+Speaking of having things Just Work™, that's our second philosophy. By that, we
+mean that we do our best to have EVERY configuration option have a logical
+default. We believe that if you're working with a simple compiler and target,
+you shouldn't need to configure very much... we try to make the tools guess as
+much as they can, but give the user the power to override it when it's wrong.
+
+
+## Naming Things
+
+Let's talk about naming things. Programming is all about naming things. We name
+files, functions, variables, and so much more. While we're not always going to
+find the best name for something, we actually put quite a bit of effort into
+finding *What Something WANTS to be Called*™.
+
+When naming things, we more or less follow this hierarchy, the first being the
+most important to us (but we do all four whenever possible):
+1. Readable
+2. Descriptive
+3. Consistent
+4. Memorable
+
+
+#### Readable
+
+We want to read our code. This means we like names and flow that are more
+naturally read. We try to avoid double negatives. We try to avoid cryptic
+abbreviations (sticking to ones we feel are common).
+
+
+#### Descriptive
+
+We like descriptive names for things, especially functions and variables.
+Finding the right name for something is an important endeavor. You might notice
+from poking around our code that this often results in names that are a little
+longer than the average. Guilty. We're okay with a tiny bit more typing if it
+means our code is easier to understand.
+
+There are two exceptions to this rule that we also stick to as religiously as
+possible:
+
+First, while we realize hungarian notation (and similar systems for encoding
+type information into variable names) is providing a more descriptive name, we
+feel that (for the average developer) it takes away from readability and
+therefore is to be avoided.
+
+Second, loop counters and other local throw-away variables often have a purpose
+which is obvious. There's no need, therefore, to get carried away with complex
+naming. We find i, j, and k are better loop counters than loopCounterVar or
+whatnot. We only break this rule when we see that more description could improve
+understanding of an algorithm.
+
+
+#### Consistent
+
+We like consistency, but we're not really obsessed with it. We try to name our
+configuration macros in a consistent fashion... you'll notice a repeated use of
+UNITY_EXCLUDE_BLAH or UNITY_USES_BLAH macros. This helps users avoid having to
+remember each macro's details.
+
+
+#### Memorable
+
+Where ever it doesn't violate the above principles, we try to apply memorable
+names. Sometimes this means using something that is simply descriptive, but
+often we strive for descriptive AND unique... we like quirky names that stand
+out in our memory and are easier to search for. Take a look through the file
+names in Ceedling and you'll get a good idea of what we are talking about here.
+Why use preprocess when you can use preprocessinator? Or what better describes a
+module in charge of invoking tasks during releases than release_invoker? Don't
+get carried away. The names are still descriptive and fulfill the above
+requirements, but they don't feel stale.
+
+
+## C and C++ Details
+
+We don't really want to add to the style battles out there. Tabs or spaces?
+How many spaces? Where do the braces go? These are age-old questions that will
+never be answered... or at least not answered in a way that will make everyone
+happy.
+
+We've decided on our own style preferences. If you'd like to contribute to these
+projects (and we hope that you do), then we ask if you do your best to follow
+the same. It will only hurt a little. We promise.
+
+
+#### Whitespace
+
+Our C-style is to use spaces and to use 4 of them per indent level. It's a nice
+power-of-2 number that looks decent on a wide screen. We have no more reason
+than that. We break that rule when we have lines that wrap (macros or function
+arguments or whatnot). When that happens, we like to indent further to line
+things up in nice tidy columns.
+
+```C
+ if (stuff_happened)
+ {
+ do_something();
+ }
+```
+
+
+#### Case
+
+- Files - all lower case with underscores.
+- Variables - all lower case with underscores
+- Macros - all caps with underscores.
+- Typedefs - all caps with underscores. (also ends with _T).
+- Functions - camel cased. Usually named ModuleName_FuncName
+- Constants and Globals - camel cased.
+
+
+#### Braces
+
+The left brace is on the next line after the declaration. The right brace is
+directly below that. Everything in between in indented one level. If you're
+catching an error and you have a one-line, go ahead and to it on the same line.
+
+```C
+ while (blah)
+ {
+ //Like so. Even if only one line, we use braces.
+ }
+```
+
+
+#### Comments
+
+Do you know what we hate? Old-school C block comments. BUT, we're using them
+anyway. As we mentioned, our goal is to support every compiler we can,
+especially embedded compilers. There are STILL C compilers out there that only
+support old-school block comments. So that is what we're using. We apologize. We
+think they are ugly too.
+
+
+## Ruby Details
+
+Is there really such thing as a Ruby coding standard? Ruby is such a free form
+language, it seems almost sacrilegious to suggest that people should comply to
+one method! We'll keep it really brief!
+
+
+#### Whitespace
+
+Our Ruby style is to use spaces and to use 2 of them per indent level. It's a
+nice power-of-2 number that really grooves with Ruby's compact style. We have no
+more reason than that. We break that rule when we have lines that wrap. When
+that happens, we like to indent further to line things up in nice tidy columns.
+
+
+#### Case
+
+- Files - all lower case with underscores.
+- Variables - all lower case with underscores
+- Classes, Modules, etc - Camel cased.
+- Functions - all lower case with underscores
+- Constants - all upper case with underscores
+
+
+## Documentation
+
+Egad. Really? We use markdown and we like pdf files because they can be made to
+look nice while still being portable. Good enough?
+
+
+*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
diff --git a/vendor/Unity-2.4.3/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf b/vendor/Unity-2.4.3/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf
new file mode 100644
index 0000000..28f0c32
--- /dev/null
+++ b/vendor/Unity-2.4.3/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf
Binary files differ
diff --git a/vendor/Unity-2.4.3/docs/UnityAssertionsReference.md b/vendor/Unity-2.4.3/docs/UnityAssertionsReference.md
new file mode 100644
index 0000000..2dcf5e3
--- /dev/null
+++ b/vendor/Unity-2.4.3/docs/UnityAssertionsReference.md
@@ -0,0 +1,770 @@
+# Unity Assertions Reference
+
+## Background and Overview
+
+### Super Condensed Version
+
+- An assertion establishes truth (i.e. boolean True) for a single condition.
+Upon boolean False, an assertion stops execution and reports the failure.
+- Unity is mainly a rich collection of assertions and the support to gather up
+and easily execute those assertions.
+- The structure of Unity allows you to easily separate test assertions from
+source code in, well, test code.
+- Unity's assertions:
+- Come in many, many flavors to handle different C types and assertion cases.
+- Use context to provide detailed and helpful failure messages.
+- Document types, expected values, and basic behavior in your source code for
+free.
+
+
+### Unity Is Several Things But Mainly It's Assertions
+
+One way to think of Unity is simply as a rich collection of assertions you can
+use to establish whether your source code behaves the way you think it does.
+Unity provides a framework to easily organize and execute those assertions in
+test code separate from your source code.
+
+
+### What's an Assertion?
+
+At their core, assertions are an establishment of truth - boolean truth. Was this
+thing equal to that thing? Does that code doohickey have such-and-such property
+or not? You get the idea. Assertions are executable code (to appreciate the big
+picture on this read up on the difference between
+[link:Dynamic Verification and Static Analysis]). A failing assertion stops
+execution and reports an error through some appropriate I/O channel (e.g.
+stdout, GUI, file, blinky light).
+
+Fundamentally, for dynamic verification all you need is a single assertion
+mechanism. In fact, that's what the [assert() macro in C's standard library](http://en.wikipedia.org/en/wiki/Assert.h)
+is for. So why not just use it? Well, we can do far better in the reporting
+department. C's `assert()` is pretty dumb as-is and is particularly poor for
+handling common data types like arrays, structs, etc. And, without some other
+support, it's far too tempting to litter source code with C's `assert()`'s. It's
+generally much cleaner, manageable, and more useful to separate test and source
+code in the way Unity facilitates.
+
+
+### Unity's Assertions: Helpful Messages _and_ Free Source Code Documentation
+
+Asserting a simple truth condition is valuable, but using the context of the
+assertion is even more valuable. For instance, if you know you're comparing bit
+flags and not just integers, then why not use that context to give explicit,
+readable, bit-level feedback when an assertion fails?
+
+That's what Unity's collection of assertions do - capture context to give you
+helpful, meaningful assertion failure messages. In fact, the assertions
+themselves also serve as executable documentation about types and values in your
+source code. So long as your tests remain current with your source and all those
+tests pass, you have a detailed, up-to-date view of the intent and mechanisms in
+your source code. And due to a wondrous mystery, well-tested code usually tends
+to be well designed code.
+
+
+## Assertion Conventions and Configurations
+
+### Naming and Parameter Conventions
+
+The convention of assertion parameters generally follows this order:
+
+ TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} )
+
+The very simplest assertion possible uses only a single "actual" parameter (e.g.
+a simple null check).
+
+"Actual" is the value being tested and unlike the other parameters in an
+assertion construction is the only parameter present in all assertion variants.
+"Modifiers" are masks, ranges, bit flag specifiers, floating point deltas.
+"Expected" is your expected value (duh) to compare to an "actual" value; it's
+marked as an optional parameter because some assertions only need a single
+"actual" parameter (e.g. null check).
+"Size/count" refers to string lengths, number of array elements, etc.
+
+Many of Unity's assertions are apparent duplications in that the same data type
+is handled by several assertions. The differences among these are in how failure
+messages are presented. For instance, a `_HEX` variant of an assertion prints
+the expected and actual values of that assertion formatted as hexadecimal.
+
+
+#### TEST_ASSERT_X_MESSAGE Variants
+
+_All_ assertions are complemented with a variant that includes a simple string
+message as a final parameter. The string you specify is appended to an assertion
+failure message in Unity output.
+
+For brevity, the assertion variants with a message parameter are not listed
+below. Just tack on `_MESSAGE` as the final component to any assertion name in
+the reference list below and add a string as the final parameter.
+
+_Example:_
+
+ TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} )
+
+becomes messageified like thus...
+
+ TEST_ASSERT_X_MESSAGE( {modifiers}, {expected}, actual, {size/count}, message )
+
+
+#### TEST_ASSERT_X_ARRAY Variants
+
+Unity provides a collection of assertions for arrays containing a variety of
+types. These are documented in the Array section below. These are almost on par
+with the `_MESSAGE`variants of Unity's Asserts in that for pretty much any Unity
+type assertion you can tack on `_ARRAY` and run assertions on an entire block of
+memory.
+
+ TEST_ASSERT_EQUAL_TYPEX_ARRAY( expected, actual, {size/count} )
+
+"Expected" is an array itself.
+"Size/count" is one or two parameters necessary to establish the number of array
+elements and perhaps the length of elements within the array.
+
+Notes:
+- The `_MESSAGE` variant convention still applies here to array assertions. The
+`_MESSAGE` variants of the `_ARRAY` assertions have names ending with
+`_ARRAY_MESSAGE`.
+- Assertions for handling arrays of floating point values are grouped with float
+and double assertions (see immediately following section).
+
+
+### TEST_ASSERT_EACH_EQUAL_X Variants
+
+Unity provides a collection of assertions for arrays containing a variety of
+types which can be compared to a single value as well. These are documented in
+the Each Equal section below. these are almost on par with the `_MESSAGE`
+variants of Unity's Asserts in that for pretty much any Unity type assertion you
+can inject _EACH_EQUAL and run assertions on an entire block of memory.
+
+ TEST_ASSERT_EACH_EQUAL_TYPEX( expected, actual, {size/count} )
+
+"Expected" is a single value to compare to.
+"Actual" is an array where each element will be compared to the expected value.
+"Size/count" is one of two parameters necessary to establish the number of array
+elements and perhaps the length of elements within the array.
+
+Notes:
+- The `_MESSAGE` variant convention still applies here to Each Equal assertions.
+- Assertions for handling Each Equal of floating point values are grouped with
+float and double assertions (see immediately following section).
+
+
+### Configuration
+
+#### Floating Point Support Is Optional
+
+Support for floating point types is configurable. That is, by defining the
+appropriate preprocessor symbols, floats and doubles can be individually enabled
+or disabled in Unity code. This is useful for embedded targets with no floating
+point math support (i.e. Unity compiles free of errors for fixed point only
+platforms). See Unity documentation for specifics.
+
+
+#### Maximum Data Type Width Is Configurable
+
+Not all targets support 64 bit wide types or even 32 bit wide types. Define the
+appropriate preprocessor symbols and Unity will omit all operations from
+compilation that exceed the maximum width of your target. See Unity
+documentation for specifics.
+
+
+## The Assertions in All Their Blessed Glory
+
+### Basic Fail and Ignore
+
+##### `TEST_FAIL()`
+
+This fella is most often used in special conditions where your test code is
+performing logic beyond a simple assertion. That is, in practice, `TEST_FAIL()`
+will always be found inside a conditional code block.
+
+_Examples:_
+- Executing a state machine multiple times that increments a counter your test
+code then verifies as a final step.
+- Triggering an exception and verifying it (as in Try / Catch / Throw - see the
+[CException](https://github.com/ThrowTheSwitch/CException) project).
+
+##### `TEST_IGNORE()`
+
+Marks a test case (i.e. function meant to contain test assertions) as ignored.
+Usually this is employed as a breadcrumb to come back and implement a test case.
+An ignored test case has effects if other assertions are in the enclosing test
+case (see Unity documentation for more).
+
+### Boolean
+
+##### `TEST_ASSERT (condition)`
+
+##### `TEST_ASSERT_TRUE (condition)`
+
+##### `TEST_ASSERT_FALSE (condition)`
+
+##### `TEST_ASSERT_UNLESS (condition)`
+
+A simple wording variation on `TEST_ASSERT_FALSE`.The semantics of
+`TEST_ASSERT_UNLESS` aid readability in certain test constructions or
+conditional statements.
+
+##### `TEST_ASSERT_NULL (pointer)`
+
+##### `TEST_ASSERT_NOT_NULL (pointer)`
+
+
+### Signed and Unsigned Integers (of all sizes)
+
+Large integer sizes can be disabled for build targets that do not support them.
+For example, if your target only supports up to 16 bit types, by defining the
+appropriate symbols Unity can be configured to omit 32 and 64 bit operations
+that would break compilation (see Unity documentation for more). Refer to
+Advanced Asserting later in this document for advice on dealing with other word
+sizes.
+
+##### `TEST_ASSERT_EQUAL_INT (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_INT8 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_INT16 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_INT32 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_INT64 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL (expected, actual)`
+
+##### `TEST_ASSERT_NOT_EQUAL (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_UINT (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_UINT8 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_UINT16 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_UINT32 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_UINT64 (expected, actual)`
+
+
+### Unsigned Integers (of all sizes) in Hexadecimal
+
+All `_HEX` assertions are identical in function to unsigned integer assertions
+but produce failure messages with the `expected` and `actual` values formatted
+in hexadecimal. Unity output is big endian.
+
+##### `TEST_ASSERT_EQUAL_HEX (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_HEX8 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_HEX16 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_HEX32 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_HEX64 (expected, actual)`
+
+
+### Masked and Bit-level Assertions
+
+Masked and bit-level assertions produce output formatted in hexadecimal. Unity
+output is big endian.
+
+
+##### `TEST_ASSERT_BITS (mask, expected, actual)`
+
+Only compares the masked (i.e. high) bits of `expected` and `actual` parameters.
+
+
+##### `TEST_ASSERT_BITS_HIGH (mask, actual)`
+
+Asserts the masked bits of the `actual` parameter are high.
+
+
+##### `TEST_ASSERT_BITS_LOW (mask, actual)`
+
+Asserts the masked bits of the `actual` parameter are low.
+
+
+##### `TEST_ASSERT_BIT_HIGH (bit, actual)`
+
+Asserts the specified bit of the `actual` parameter is high.
+
+
+##### `TEST_ASSERT_BIT_LOW (bit, actual)`
+
+Asserts the specified bit of the `actual` parameter is low.
+
+### Integer Less Than / Greater Than
+
+These assertions verify that the `actual` parameter is less than or greater
+than `threshold` (exclusive). For example, if the threshold value is 0 for the
+greater than assertion will fail if it is 0 or less.
+
+##### `TEST_ASSERT_GREATER_THAN (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_INT (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_INT8 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_INT16 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_INT32 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_UINT (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_UINT8 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_UINT16 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_UINT32 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_HEX8 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_HEX16 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_HEX32 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_INT (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_INT8 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_INT16 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_INT32 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_UINT (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_UINT8 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_UINT16 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_UINT32 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_HEX8 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_HEX16 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_HEX32 (threshold, actual)`
+
+
+### Integer Ranges (of all sizes)
+
+These assertions verify that the `expected` parameter is within +/- `delta`
+(inclusive) of the `actual` parameter. For example, if the expected value is 10
+and the delta is 3 then the assertion will fail for any value outside the range
+of 7 - 13.
+
+##### `TEST_ASSERT_INT_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_INT8_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_INT16_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_INT32_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_INT64_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_UINT_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_UINT8_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_UINT16_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_UINT32_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_UINT64_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_HEX_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_HEX8_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_HEX16_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_HEX32_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_HEX64_WITHIN (delta, expected, actual)`
+
+
+### Structs and Strings
+
+##### `TEST_ASSERT_EQUAL_PTR (expected, actual)`
+
+Asserts that the pointers point to the same memory location.
+
+
+##### `TEST_ASSERT_EQUAL_STRING (expected, actual)`
+
+Asserts that the null terminated (`'\0'`)strings are identical. If strings are
+of different lengths or any portion of the strings before their terminators
+differ, the assertion fails. Two NULL strings (i.e. zero length) are considered
+equivalent.
+
+
+##### `TEST_ASSERT_EQUAL_MEMORY (expected, actual, len)`
+
+Asserts that the contents of the memory specified by the `expected` and `actual`
+pointers is identical. The size of the memory blocks in bytes is specified by
+the `len` parameter.
+
+
+### Arrays
+
+`expected` and `actual` parameters are both arrays. `num_elements` specifies the
+number of elements in the arrays to compare.
+
+`_HEX` assertions produce failure messages with expected and actual array
+contents formatted in hexadecimal.
+
+For array of strings comparison behavior, see comments for
+`TEST_ASSERT_EQUAL_STRING` in the preceding section.
+
+Assertions fail upon the first element in the compared arrays found not to
+match. Failure messages specify the array index of the failed comparison.
+
+##### `TEST_ASSERT_EQUAL_INT_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_INT8_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_INT16_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_INT32_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_INT64_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_UINT_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_UINT8_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_UINT16_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_UINT32_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_UINT64_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_HEX_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_HEX8_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_HEX16_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_HEX32_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_HEX64_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_PTR_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_STRING_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_MEMORY_ARRAY (expected, actual, len, num_elements)`
+
+`len` is the memory in bytes to be compared at each array element.
+
+
+### Each Equal (Arrays to Single Value)
+
+`expected` are single values and `actual` are arrays. `num_elements` specifies
+the number of elements in the arrays to compare.
+
+`_HEX` assertions produce failure messages with expected and actual array
+contents formatted in hexadecimal.
+
+Assertions fail upon the first element in the compared arrays found not to
+match. Failure messages specify the array index of the failed comparison.
+
+#### `TEST_ASSERT_EACH_EQUAL_INT (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_INT8 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_INT16 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_INT32 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_INT64 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_UINT (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_UINT8 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_UINT16 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_UINT32 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_UINT64 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_HEX (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_HEX8 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_HEX16 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_HEX32 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_HEX64 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_PTR (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_STRING (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_MEMORY (expected, actual, len, num_elements)`
+
+`len` is the memory in bytes to be compared at each array element.
+
+
+### Floating Point (If enabled)
+
+##### `TEST_ASSERT_FLOAT_WITHIN (delta, expected, actual)`
+
+Asserts that the `actual` value is within +/- `delta` of the `expected` value.
+The nature of floating point representation is such that exact evaluations of
+equality are not guaranteed.
+
+
+##### `TEST_ASSERT_EQUAL_FLOAT (expected, actual)`
+
+Asserts that the ?actual?value is "close enough to be considered equal" to the
+`expected` value. If you are curious about the details, refer to the Advanced
+Asserting section for more details on this. Omitting a user-specified delta in a
+floating point assertion is both a shorthand convenience and a requirement of
+code generation conventions for CMock.
+
+
+##### `TEST_ASSERT_EQUAL_FLOAT_ARRAY (expected, actual, num_elements)`
+
+See Array assertion section for details. Note that individual array element
+float comparisons are executed using T?EST_ASSERT_EQUAL_FLOAT?.That is, user
+specified delta comparison values requires a custom-implemented floating point
+array assertion.
+
+
+##### `TEST_ASSERT_FLOAT_IS_INF (actual)`
+
+Asserts that `actual` parameter is equivalent to positive infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NEG_INF (actual)`
+
+Asserts that `actual` parameter is equivalent to negative infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NAN (actual)`
+
+Asserts that `actual` parameter is a Not A Number floating point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_DETERMINATE (actual)`
+
+Asserts that ?actual?parameter is a floating point representation usable for
+mathematical operations. That is, the `actual` parameter is neither positive
+infinity nor negative infinity nor Not A Number floating point representations.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NOT_INF (actual)`
+
+Asserts that `actual` parameter is a value other than positive infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NOT_NEG_INF (actual)`
+
+Asserts that `actual` parameter is a value other than negative infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NOT_NAN (actual)`
+
+Asserts that `actual` parameter is a value other than Not A Number floating
+point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE (actual)`
+
+Asserts that `actual` parameter is not usable for mathematical operations. That
+is, the `actual` parameter is either positive infinity or negative infinity or
+Not A Number floating point representations.
+
+
+### Double (If enabled)
+
+##### `TEST_ASSERT_DOUBLE_WITHIN (delta, expected, actual)`
+
+Asserts that the `actual` value is within +/- `delta` of the `expected` value.
+The nature of floating point representation is such that exact evaluations of
+equality are not guaranteed.
+
+
+##### `TEST_ASSERT_EQUAL_DOUBLE (expected, actual)`
+
+Asserts that the `actual` value is "close enough to be considered equal" to the
+`expected` value. If you are curious about the details, refer to the Advanced
+Asserting section for more details. Omitting a user-specified delta in a
+floating point assertion is both a shorthand convenience and a requirement of
+code generation conventions for CMock.
+
+
+##### `TEST_ASSERT_EQUAL_DOUBLE_ARRAY (expected, actual, num_elements)`
+
+See Array assertion section for details. Note that individual array element
+double comparisons are executed using `TEST_ASSERT_EQUAL_DOUBLE`.That is, user
+specified delta comparison values requires a custom implemented double array
+assertion.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_INF (actual)`
+
+Asserts that `actual` parameter is equivalent to positive infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NEG_INF (actual)`
+
+Asserts that `actual` parameter is equivalent to negative infinity floating point
+representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NAN (actual)`
+
+Asserts that `actual` parameter is a Not A Number floating point representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_DETERMINATE (actual)`
+
+Asserts that `actual` parameter is a floating point representation usable for
+mathematical operations. That is, the ?actual?parameter is neither positive
+infinity nor negative infinity nor Not A Number floating point representations.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NOT_INF (actual)`
+
+Asserts that `actual` parameter is a value other than positive infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF (actual)`
+
+Asserts that `actual` parameter is a value other than negative infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NOT_NAN (actual)`
+
+Asserts that `actual` parameter is a value other than Not A Number floating
+point representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE (actual)`
+
+Asserts that `actual` parameter is not usable for mathematical operations. That
+is, the `actual` parameter is either positive infinity or negative infinity or
+Not A Number floating point representations.
+
+
+## Advanced Asserting: Details On Tricky Assertions
+
+This section helps you understand how to deal with some of the trickier
+assertion situations you may run into. It will give you a glimpse into some of
+the under-the-hood details of Unity's assertion mechanisms. If you're one of
+those people who likes to know what is going on in the background, read on. If
+not, feel free to ignore the rest of this document until you need it.
+
+
+### How do the EQUAL assertions work for FLOAT and DOUBLE?
+
+As you may know, directly checking for equality between a pair of floats or a
+pair of doubles is sloppy at best and an outright no-no at worst. Floating point
+values can often be represented in multiple ways, particularly after a series of
+operations on a value. Initializing a variable to the value of 2.0 is likely to
+result in a floating point representation of 2 x 20,but a series of
+mathematical operations might result in a representation of 8 x 2-2
+that also evaluates to a value of 2. At some point repeated operations cause
+equality checks to fail.
+
+So Unity doesn't do direct floating point comparisons for equality. Instead, it
+checks if two floating point values are "really close." If you leave Unity
+running with defaults, "really close" means "within a significant bit or two."
+Under the hood, `TEST_ASSERT_EQUAL_FLOAT` is really `TEST_ASSERT_FLOAT_WITHIN`
+with the `delta` parameter calculated on the fly. For single precision, delta is
+the expected value multiplied by 0.00001, producing a very small proportional
+range around the expected value.
+
+If you are expecting a value of 20,000.0 the delta is calculated to be 0.2. So
+any value between 19,999.8 and 20,000.2 will satisfy the equality check. This
+works out to be roughly a single bit of range for a single-precision number, and
+that's just about as tight a tolerance as you can reasonably get from a floating
+point value.
+
+So what happens when it's zero? Zero - even more than other floating point
+values - can be represented many different ways. It doesn't matter if you have
+0 x 20or 0 x 263.It's still zero, right? Luckily, if you
+subtract these values from each other, they will always produce a difference of
+zero, which will still fall between 0 plus or minus a delta of 0. So it still
+works!
+
+Double precision floating point numbers use a much smaller multiplier, again
+approximating a single bit of error.
+
+If you don't like these ranges and you want to make your floating point equality
+assertions less strict, you can change these multipliers to whatever you like by
+defining UNITY_FLOAT_PRECISION and UNITY_DOUBLE_PRECISION. See Unity
+documentation for more.
+
+
+### How do we deal with targets with non-standard int sizes?
+
+It's "fun" that C is a standard where something as fundamental as an integer
+varies by target. According to the C standard, an `int` is to be the target's
+natural register size, and it should be at least 16-bits and a multiple of a
+byte. It also guarantees an order of sizes:
+
+```C
+char <= short <= int <= long <= long long
+```
+
+Most often, `int` is 32-bits. In many cases in the embedded world, `int` is
+16-bits. There are rare microcontrollers out there that have 24-bit integers,
+and this remains perfectly standard C.
+
+To make things even more interesting, there are compilers and targets out there
+that have a hard choice to make. What if their natural register size is 10-bits
+or 12-bits? Clearly they can't fulfill _both_ the requirement to be at least
+16-bits AND the requirement to match the natural register size. In these
+situations, they often choose the natural register size, leaving us with
+something like this:
+
+```C
+char (8 bit) <= short (12 bit) <= int (12 bit) <= long (16 bit)
+```
+
+Um... yikes. It's obviously breaking a rule or two... but they had to break SOME
+rules, so they made a choice.
+
+When the C99 standard rolled around, it introduced alternate standard-size types.
+It also introduced macros for pulling in MIN/MAX values for your integer types.
+It's glorious! Unfortunately, many embedded compilers can't be relied upon to
+use the C99 types (Sometimes because they have weird register sizes as described
+above. Sometimes because they don't feel like it?).
+
+A goal of Unity from the beginning was to support every combination of
+microcontroller or microprocessor and C compiler. Over time, we've gotten really
+close to this. There are a few tricks that you should be aware of, though, if
+you're going to do this effectively on some of these more idiosyncratic targets.
+
+First, when setting up Unity for a new target, you're going to want to pay
+special attention to the macros for automatically detecting types
+(where available) or manually configuring them yourself. You can get information
+on both of these in Unity's documentation.
+
+What about the times where you suddenly need to deal with something odd, like a
+24-bit `int`? The simplest solution is to use the next size up. If you have a
+24-bit `int`, configure Unity to use 32-bit integers. If you have a 12-bit
+`int`, configure Unity to use 16 bits. There are two ways this is going to
+affect you:
+
+1. When Unity displays errors for you, it's going to pad the upper unused bits
+with zeros.
+2. You're going to have to be careful of assertions that perform signed
+operations, particularly `TEST_ASSERT_INT_WITHIN`.Such assertions might wrap
+your `int` in the wrong place, and you could experience false failures. You can
+always back down to a simple `TEST_ASSERT` and do the operations yourself.
+
+
+*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
diff --git a/vendor/Unity-2.4.3/docs/UnityConfigurationGuide.md b/vendor/Unity-2.4.3/docs/UnityConfigurationGuide.md
new file mode 100644
index 0000000..96e5358
--- /dev/null
+++ b/vendor/Unity-2.4.3/docs/UnityConfigurationGuide.md
@@ -0,0 +1,435 @@
+# Unity Configuration Guide
+
+## C Standards, Compilers and Microcontrollers
+
+The embedded software world contains its challenges. Compilers support different
+revisions of the C Standard. They ignore requirements in places, sometimes to
+make the language more usable in some special regard. Sometimes it's to simplify
+their support. Sometimes it's due to specific quirks of the microcontroller they
+are targeting. Simulators add another dimension to this menagerie.
+
+Unity is designed to run on almost anything that is targeted by a C compiler. It
+would be awesome if this could be done with zero configuration. While there are
+some targets that come close to this dream, it is sadly not universal. It is
+likely that you are going to need at least a couple of the configuration options
+described in this document.
+
+All of Unity's configuration options are `#defines`. Most of these are simple
+definitions. A couple are macros with arguments. They live inside the
+unity_internals.h header file. We don't necessarily recommend opening that file
+unless you really need to. That file is proof that a cross-platform library is
+challenging to build. From a more positive perspective, it is also proof that a
+great deal of complexity can be centralized primarily to one place in order to
+provide a more consistent and simple experience elsewhere.
+
+
+### Using These Options
+
+It doesn't matter if you're using a target-specific compiler and a simulator or
+a native compiler. In either case, you've got a couple choices for configuring
+these options:
+
+1. Because these options are specified via C defines, you can pass most of these
+options to your compiler through command line compiler flags. Even if you're
+using an embedded target that forces you to use their overbearing IDE for all
+configuration, there will be a place somewhere in your project to configure
+defines for your compiler.
+2. You can create a custom `unity_config.h` configuration file (present in your
+toolchain's search paths). In this file, you will list definitions and macros
+specific to your target. All you must do is define `UNITY_INCLUDE_CONFIG_H` and
+Unity will rely on `unity_config.h` for any further definitions it may need.
+
+
+## The Options
+
+### Integer Types
+
+If you've been a C developer for long, you probably already know that C's
+concept of an integer varies from target to target. The C Standard has rules
+about the `int` matching the register size of the target microprocessor. It has
+rules about the `int` and how its size relates to other integer types. An `int`
+on one target might be 16 bits while on another target it might be 64. There are
+more specific types in compilers compliant with C99 or later, but that's
+certainly not every compiler you are likely to encounter. Therefore, Unity has a
+number of features for helping to adjust itself to match your required integer
+sizes. It starts off by trying to do it automatically.
+
+
+##### `UNITY_EXCLUDE_STDINT_H`
+
+The first thing that Unity does to guess your types is check `stdint.h`.
+This file includes defines like `UINT_MAX` that Unity can make use of to
+learn a lot about your system. It's possible you don't want it to do this
+(um. why not?) or (more likely) it's possible that your system doesn't
+support `stdint.h`. If that's the case, you're going to want to define this.
+That way, Unity will know to skip the inclusion of this file and you won't
+be left with a compiler error.
+
+_Example:_
+ #define UNITY_EXCLUDE_STDINT_H
+
+
+##### `UNITY_EXCLUDE_LIMITS_H`
+
+The second attempt to guess your types is to check `limits.h`. Some compilers
+that don't support `stdint.h` could include `limits.h` instead. If you don't
+want Unity to check this file either, define this to make it skip the inclusion.
+
+_Example:_
+ #define UNITY_EXCLUDE_LIMITS_H
+
+
+If you've disabled both of the automatic options above, you're going to have to
+do the configuration yourself. Don't worry. Even this isn't too bad... there are
+just a handful of defines that you are going to specify if you don't like the
+defaults.
+
+
+##### `UNITY_INT_WIDTH`
+
+Define this to be the number of bits an `int` takes up on your system. The
+default, if not autodetected, is 32 bits.
+
+_Example:_
+ #define UNITY_INT_WIDTH 16
+
+
+##### `UNITY_LONG_WIDTH`
+
+Define this to be the number of bits a `long` takes up on your system. The
+default, if not autodetected, is 32 bits. This is used to figure out what kind
+of 64-bit support your system can handle. Does it need to specify a `long` or a
+`long long` to get a 64-bit value. On 16-bit systems, this option is going to be
+ignored.
+
+_Example:_
+ #define UNITY_LONG_WIDTH 16
+
+
+##### `UNITY_POINTER_WIDTH`
+
+Define this to be the number of bits a pointer takes up on your system. The
+default, if not autodetected, is 32-bits. If you're getting ugly compiler
+warnings about casting from pointers, this is the one to look at.
+
+_Example:_
+ #define UNITY_POINTER_WIDTH 64
+
+
+##### `UNITY_SUPPORT_64`
+
+Unity will automatically include 64-bit support if it auto-detects it, or if
+your `int`, `long`, or pointer widths are greater than 32-bits. Define this to
+enable 64-bit support if none of the other options already did it for you. There
+can be a significant size and speed impact to enabling 64-bit support on small
+targets, so don't define it if you don't need it.
+
+_Example:_
+ #define UNITY_SUPPORT_64
+
+
+### Floating Point Types
+
+In the embedded world, it's not uncommon for targets to have no support for
+floating point operations at all or to have support that is limited to only
+single precision. We are able to guess integer sizes on the fly because integers
+are always available in at least one size. Floating point, on the other hand, is
+sometimes not available at all. Trying to include `float.h` on these platforms
+would result in an error. This leaves manual configuration as the only option.
+
+
+##### `UNITY_INCLUDE_FLOAT`
+
+##### `UNITY_EXCLUDE_FLOAT`
+
+##### `UNITY_INCLUDE_DOUBLE`
+
+##### `UNITY_EXCLUDE_DOUBLE`
+
+By default, Unity guesses that you will want single precision floating point
+support, but not double precision. It's easy to change either of these using the
+include and exclude options here. You may include neither, either, or both, as
+suits your needs. For features that are enabled, the following floating point
+options also become available.
+
+_Example:_
+
+ //what manner of strange processor is this?
+ #define UNITY_EXCLUDE_FLOAT
+ #define UNITY_INCLUDE_DOUBLE
+
+
+##### `UNITY_EXCLUDE_FLOAT_PRINT`
+
+Unity aims for as small of a footprint as possible and avoids most standard
+library calls (some embedded platforms don’t have a standard library!). Because
+of this, its routines for printing integer values are minimalist and hand-coded.
+Therefore, the display of floating point values during a failure are optional.
+By default, Unity will print the actual results of floating point assertion
+failure (e.g. ”Expected 4.56 Was 4.68”). To not include this extra support, you
+can use this define to instead respond to a failed assertion with a message like
+”Values Not Within Delta”. If you would like verbose failure messages for floating
+point assertions, use these options to give more explicit failure messages.
+
+_Example:_
+ #define UNITY_EXCLUDE_FLOAT_PRINT
+
+
+##### `UNITY_FLOAT_TYPE`
+
+If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C
+floats. If your compiler supports a specialty floating point type, you can
+always override this behavior by using this definition.
+
+_Example:_
+ #define UNITY_FLOAT_TYPE float16_t
+
+
+##### `UNITY_DOUBLE_TYPE`
+
+If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard C
+doubles. If you would like to change this, you can specify something else by
+using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long double`
+could enable gargantuan floating point types on your 64-bit processor instead of
+the standard `double`.
+
+_Example:_
+ #define UNITY_DOUBLE_TYPE long double
+
+
+##### `UNITY_FLOAT_PRECISION`
+
+##### `UNITY_DOUBLE_PRECISION`
+
+If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as
+documented in the big daddy Unity Assertion Guide, you will learn that they are
+not really asserting that two values are equal but rather that two values are
+"close enough" to equal. "Close enough" is controlled by these precision
+configuration options. If you are working with 32-bit floats and/or 64-bit
+doubles (the normal on most processors), you should have no need to change these
+options. They are both set to give you approximately 1 significant bit in either
+direction. The float precision is 0.00001 while the double is 10-12.
+For further details on how this works, see the appendix of the Unity Assertion
+Guide.
+
+_Example:_
+ #define UNITY_FLOAT_PRECISION 0.001f
+
+
+### Toolset Customization
+
+In addition to the options listed above, there are a number of other options
+which will come in handy to customize Unity's behavior for your specific
+toolchain. It is possible that you may not need to touch any of these... but
+certain platforms, particularly those running in simulators, may need to jump
+through extra hoops to operate properly. These macros will help in those
+situations.
+
+
+##### `UNITY_OUTPUT_CHAR(a)`
+
+##### `UNITY_OUTPUT_FLUSH()`
+
+##### `UNITY_OUTPUT_START()`
+
+##### `UNITY_OUTPUT_COMPLETE()`
+
+By default, Unity prints its results to `stdout` as it runs. This works
+perfectly fine in most situations where you are using a native compiler for
+testing. It works on some simulators as well so long as they have `stdout`
+routed back to the command line. There are times, however, where the simulator
+will lack support for dumping results or you will want to route results
+elsewhere for other reasons. In these cases, you should define the
+`UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time (as
+an `int`, since this is the parameter type of the standard C `putchar` function
+most commonly used). You may replace this with whatever function call you like.
+
+_Example:_
+Say you are forced to run your test suite on an embedded processor with no
+`stdout` option. You decide to route your test result output to a custom serial
+`RS232_putc()` function you wrote like thus:
+
+ #define UNITY_OUTPUT_CHAR(a) RS232_putc(a)
+ #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0)
+ #define UNITY_OUTPUT_FLUSH() RS232_flush()
+ #define UNITY_OUTPUT_COMPLETE() RS232_close()
+
+_Note:_
+`UNITY_OUTPUT_FLUSH()` can be set to the standard out flush function simply by
+specifying `UNITY_USE_FLUSH_STDOUT`. No other defines are required. If you
+specify a custom flush function instead with `UNITY_OUTPUT_FLUSH` directly, it
+will declare an instance of your function by default. If you want to disable
+this behavior, add `UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION`.
+
+
+##### `UNITY_WEAK_ATTRIBUTE`
+
+##### `UNITY_WEAK_PRAGMA`
+
+##### `UNITY_NO_WEAK`
+
+For some targets, Unity can make the otherwise required setUp() and tearDown()
+functions optional. This is a nice convenience for test writers since setUp and
+tearDown don’t often actually do anything. If you’re using gcc or clang, this
+option is automatically defined for you. Other compilers can also support this
+behavior, if they support a C feature called weak functions. A weak function is
+a function that is compiled into your executable unless a non-weak version of
+the same function is defined elsewhere. If a non-weak version is found, the weak
+version is ignored as if it never existed. If your compiler supports this feature,
+you can let Unity know by defining UNITY_WEAK_ATTRIBUTE or UNITY_WEAK_PRAGMA as
+the function attributes that would need to be applied to identify a function as
+weak. If your compiler lacks support for weak functions, you will always need to
+define setUp and tearDown functions (though they can be and often will be just
+empty). You can also force Unity to NOT use weak functions by defining
+UNITY_NO_WEAK. The most common options for this feature are:
+
+_Example:_
+ #define UNITY_WEAK_ATTRIBUTE weak
+ #define UNITY_WEAK_ATTRIBUTE __attribute__((weak))
+ #define UNITY_WEAK_PRAGMA
+ #define UNITY_NO_WEAK
+
+
+##### `UNITY_PTR_ATTRIBUTE`
+
+Some compilers require a custom attribute to be assigned to pointers, like
+`near` or `far`. In these cases, you can give Unity a safe default for these by
+defining this option with the attribute you would like.
+
+_Example:_
+ #define UNITY_PTR_ATTRIBUTE __attribute__((far))
+ #define UNITY_PTR_ATTRIBUTE near
+
+
+##### `UNITY_PRINT_EOL`
+
+By default, Unity outputs \n at the end of each line of output. This is easy
+to parse by the scripts, by Ceedling, etc, but it might not be ideal for YOUR
+system. Feel free to override this and to make it whatever you wish.
+
+_Example:_
+ #define UNITY_PRINT_EOL { UNITY_OUTPUT_CHAR('\r'); UNITY_OUTPUT_CHAR('\n') }
+
+
+
+##### `UNITY_EXCLUDE_DETAILS`
+
+This is an option for if you absolutely must squeeze every byte of memory out of
+your system. Unity stores a set of internal scratchpads which are used to pass
+extra detail information around. It's used by systems like CMock in order to
+report which function or argument flagged an error. If you're not using CMock and
+you're not using these details for other things, then you can exclude them.
+
+_Example:_
+ #define UNITY_EXCLUDE_DETAILS
+
+
+
+##### `UNITY_EXCLUDE_SETJMP`
+
+If your embedded system doesn't support the standard library setjmp, you can
+exclude Unity's reliance on this by using this define. This dropped dependence
+comes at a price, though. You will be unable to use custom helper functions for
+your tests, and you will be unable to use tools like CMock. Very likely, if your
+compiler doesn't support setjmp, you wouldn't have had the memory space for those
+things anyway, though... so this option exists for those situations.
+
+_Example:_
+ #define UNITY_EXCLUDE_SETJMP
+
+##### `UNITY_OUTPUT_COLOR`
+
+If you want to add color using ANSI escape codes you can use this define.
+t
+_Example:_
+ #define UNITY_OUTPUT_COLOR
+
+
+
+## Getting Into The Guts
+
+There will be cases where the options above aren't quite going to get everything
+perfect. They are likely sufficient for any situation where you are compiling
+and executing your tests with a native toolchain (e.g. clang on Mac). These
+options may even get you through the majority of cases encountered in working
+with a target simulator run from your local command line. But especially if you
+must run your test suite on your target hardware, your Unity configuration will
+require special help. This special help will usually reside in one of two
+places: the `main()` function or the `RUN_TEST` macro. Let's look at how these
+work.
+
+
+##### `main()`
+
+Each test module is compiled and run on its own, separate from the other test
+files in your project. Each test file, therefore, has a `main` function. This
+`main` function will need to contain whatever code is necessary to initialize
+your system to a workable state. This is particularly true for situations where
+you must set up a memory map or initialize a communication channel for the
+output of your test results.
+
+A simple main function looks something like this:
+
+ int main(void) {
+ UNITY_BEGIN();
+ RUN_TEST(test_TheFirst);
+ RUN_TEST(test_TheSecond);
+ RUN_TEST(test_TheThird);
+ return UNITY_END();
+ }
+
+You can see that our main function doesn't bother taking any arguments. For our
+most barebones case, we'll never have arguments because we just run all the
+tests each time. Instead, we start by calling `UNITY_BEGIN`. We run each test
+(in whatever order we wish). Finally, we call `UNITY_END`, returning its return
+value (which is the total number of failures).
+
+It should be easy to see that you can add code before any test cases are run or
+after all the test cases have completed. This allows you to do any needed
+system-wide setup or teardown that might be required for your special
+circumstances.
+
+
+##### `RUN_TEST`
+
+The `RUN_TEST` macro is called with each test case function. Its job is to
+perform whatever setup and teardown is necessary for executing a single test
+case function. This includes catching failures, calling the test module's
+`setUp()` and `tearDown()` functions, and calling `UnityConcludeTest()`. If
+using CMock or test coverage, there will be additional stubs in use here. A
+simple minimalist RUN_TEST macro looks something like this:
+
+ #define RUN_TEST(testfunc) \
+ UNITY_NEW_TEST(#testfunc) \
+ if (TEST_PROTECT()) { \
+ setUp(); \
+ testfunc(); \
+ } \
+ if (TEST_PROTECT() && (!TEST_IS_IGNORED)) \
+ tearDown(); \
+ UnityConcludeTest();
+
+So that's quite a macro, huh? It gives you a glimpse of what kind of stuff Unity
+has to deal with for every single test case. For each test case, we declare that
+it is a new test. Then we run `setUp` and our test function. These are run
+within a `TEST_PROTECT` block, the function of which is to handle failures that
+occur during the test. Then, assuming our test is still running and hasn't been
+ignored, we run `tearDown`. No matter what, our last step is to conclude this
+test before moving on to the next.
+
+Let's say you need to add a call to `fsync` to force all of your output data to
+flush to a file after each test. You could easily insert this after your
+`UnityConcludeTest` call. Maybe you want to write an xml tag before and after
+each result set. Again, you could do this by adding lines to this macro. Updates
+to this macro are for the occasions when you need an action before or after
+every single test case throughout your entire suite of tests.
+
+
+## Happy Porting
+
+The defines and macros in this guide should help you port Unity to just about
+any C target we can imagine. If you run into a snag or two, don't be afraid of
+asking for help on the forums. We love a good challenge!
+
+
+*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
diff --git a/vendor/Unity-2.4.3/docs/UnityGettingStartedGuide.md b/vendor/Unity-2.4.3/docs/UnityGettingStartedGuide.md
new file mode 100644
index 0000000..50fc91c
--- /dev/null
+++ b/vendor/Unity-2.4.3/docs/UnityGettingStartedGuide.md
@@ -0,0 +1,191 @@
+# Unity - Getting Started
+
+## Welcome
+
+Congratulations. You're now the proud owner of your very own pile of bits! What
+are you going to do with all these ones and zeros? This document should be able
+to help you decide just that.
+
+Unity is a unit test framework. The goal has been to keep it small and
+functional. The core Unity test framework is three files: a single C file and a
+couple header files. These team up to provide functions and macros to make
+testing easier.
+
+Unity was designed to be cross platform. It works hard to stick with C standards
+while still providing support for the many embedded C compilers that bend the
+rules. Unity has been used with many compilers, including GCC, IAR, Clang,
+Green Hills, Microchip, and MS Visual Studio. It's not much work to get it to
+work with a new target.
+
+
+### Overview of the Documents
+
+#### Unity Assertions reference
+
+This document will guide you through all the assertion options provided by
+Unity. This is going to be your unit testing bread and butter. You'll spend more
+time with assertions than any other part of Unity.
+
+
+#### Unity Assertions Cheat Sheet
+
+This document contains an abridged summary of the assertions described in the
+previous document. It's perfect for printing and referencing while you
+familiarize yourself with Unity's options.
+
+
+#### Unity Configuration Guide
+
+This document is the one to reference when you are going to use Unity with a new
+target or compiler. It'll guide you through the configuration options and will
+help you customize your testing experience to meet your needs.
+
+
+#### Unity Helper Scripts
+
+This document describes the helper scripts that are available for simplifying
+your testing workflow. It describes the collection of optional Ruby scripts
+included in the auto directory of your Unity installation. Neither Ruby nor
+these scripts are necessary for using Unity. They are provided as a convenience
+for those who wish to use them.
+
+
+#### Unity License
+
+What's an open source project without a license file? This brief document
+describes the terms you're agreeing to when you use this software. Basically, we
+want it to be useful to you in whatever context you want to use it, but please
+don't blame us if you run into problems.
+
+
+### Overview of the Folders
+
+If you have obtained Unity through Github or something similar, you might be
+surprised by just how much stuff you suddenly have staring you in the face.
+Don't worry, Unity itself is very small. The rest of it is just there to make
+your life easier. You can ignore it or use it at your convenience. Here's an
+overview of everything in the project.
+
+- `src` - This is the code you care about! This folder contains a C file and two
+header files. These three files _are_ Unity.
+- `docs` - You're reading this document, so it's possible you have found your way
+into this folder already. This is where all the handy documentation can be
+found.
+- `examples` - This contains a few examples of using Unity.
+- `extras` - These are optional add ons to Unity that are not part of the core
+project. If you've reached us through James Grenning's book, you're going to
+want to look here.
+- `test` - This is how Unity and its scripts are all tested. If you're just using
+Unity, you'll likely never need to go in here. If you are the lucky team member
+who gets to port Unity to a new toolchain, this is a good place to verify
+everything is configured properly.
+- `auto` - Here you will find helpful Ruby scripts for simplifying your test
+workflow. They are purely optional and are not required to make use of Unity.
+
+
+## How to Create A Test File
+
+Test files are C files. Most often you will create a single test file for each C
+module that you want to test. The test file should include unity.h and the
+header for your C module to be tested.
+
+Next, a test file will include a `setUp()` and `tearDown()` function. The setUp
+function can contain anything you would like to run before each test. The
+tearDown function can contain anything you would like to run after each test.
+Both functions accept no arguments and return nothing. You may leave either or
+both of these blank if you have no need for them. If you're using a compiler
+that is configured to make these functions optional, you may leave them off
+completely. Not sure? Give it a try. If you compiler complains that it can't
+find setUp or tearDown when it links, you'll know you need to at least include
+an empty function for these.
+
+The majority of the file will be a series of test functions. Test functions
+follow the convention of starting with the word "test" or "spec". You don't HAVE
+to name them this way, but it makes it clear what functions are tests for other
+developers. Test functions take no arguments and return nothing. All test
+accounting is handled internally in Unity.
+
+Finally, at the bottom of your test file, you will write a `main()` function.
+This function will call `UNITY_BEGIN()`, then `RUN_TEST` for each test, and
+finally `UNITY_END()`.This is what will actually trigger each of those test
+functions to run, so it is important that each function gets its own `RUN_TEST`
+call.
+
+Remembering to add each test to the main function can get to be tedious. If you
+enjoy using helper scripts in your build process, you might consider making use
+of our handy generate_test_runner.rb script. This will create the main function
+and all the calls for you, assuming that you have followed the suggested naming
+conventions. In this case, there is no need for you to include the main function
+in your test file at all.
+
+When you're done, your test file will look something like this:
+
+```C
+#include "unity.h"
+#include "file_to_test.h"
+
+void setUp(void) {
+ // set stuff up here
+}
+
+void tearDown(void) {
+ // clean stuff up here
+}
+
+void test_function_should_doBlahAndBlah(void) {
+ //test stuff
+}
+
+void test_function_should_doAlsoDoBlah(void) {
+ //more test stuff
+}
+
+int main(void) {
+ UNITY_BEGIN();
+ RUN_TEST(test_function_should_doBlahAndBlah);
+ RUN_TEST(test_function_should_doAlsoDoBlah);
+ return UNITY_END();
+}
+```
+
+It's possible that you will require more customization than this, eventually.
+For that sort of thing, you're going to want to look at the configuration guide.
+This should be enough to get you going, though.
+
+
+## How to Build and Run A Test File
+
+This is the single biggest challenge to picking up a new unit testing framework,
+at least in a language like C or C++. These languages are REALLY good at getting
+you "close to the metal" (why is the phrase metal? Wouldn't it be more accurate
+to say "close to the silicon"?). While this feature is usually a good thing, it
+can make testing more challenging.
+
+You have two really good options for toolchains. Depending on where you're
+coming from, it might surprise you that neither of these options is running the
+unit tests on your hardware.
+There are many reasons for this, but here's a short version:
+- On hardware, you have too many constraints (processing power, memory, etc),
+- On hardware, you don't have complete control over all registers,
+- On hardware, unit testing is more challenging,
+- Unit testing isn't System testing. Keep them separate.
+
+Instead of running your tests on your actual hardware, most developers choose to
+develop them as native applications (using gcc or MSVC for example) or as
+applications running on a simulator. Either is a good option. Native apps have
+the advantages of being faster and easier to set up. Simulator apps have the
+advantage of working with the same compiler as your target application. The
+options for configuring these are discussed in the configuration guide.
+
+To get either to work, you might need to make a few changes to the file
+containing your register set (discussed later).
+
+In either case, a test is built by linking unity, the test file, and the C
+file(s) being tested. These files create an executable which can be run as the
+test set for that module. Then, this process is repeated for the next test file.
+This flexibility of separating tests into individual executables allows us to
+much more thoroughly unit test our system and it keeps all the test code out of
+our final release!
+
+
+*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
diff --git a/vendor/Unity-2.4.3/docs/UnityHelperScriptsGuide.md b/vendor/Unity-2.4.3/docs/UnityHelperScriptsGuide.md
new file mode 100644
index 0000000..4242990
--- /dev/null
+++ b/vendor/Unity-2.4.3/docs/UnityHelperScriptsGuide.md
@@ -0,0 +1,254 @@
+# Unity Helper Scripts
+
+## With a Little Help From Our Friends
+
+Sometimes what it takes to be a really efficient C programmer is a little non-C.
+The Unity project includes a couple Ruby scripts for making your life just a tad
+easier. They are completely optional. If you choose to use them, you'll need a
+copy of Ruby, of course. Just install whatever the latest version is, and it is
+likely to work. You can find Ruby at [ruby-lang.org](https://ruby-labg.org/).
+
+
+### `generate_test_runner.rb`
+
+Are you tired of creating your own `main` function in your test file? Do you
+keep forgetting to add a `RUN_TEST` call when you add a new test case to your
+suite? Do you want to use CMock or other fancy add-ons but don't want to figure
+out how to create your own `RUN_TEST` macro?
+
+Well then we have the perfect script for you!
+
+The `generate_test_runner` script processes a given test file and automatically
+creates a separate test runner file that includes ?main?to execute the test
+cases within the scanned test file. All you do then is add the generated runner
+to your list of files to be compiled and linked, and presto you're done!
+
+This script searches your test file for void function signatures having a
+function name beginning with "test" or "spec". It treats each of these
+functions as a test case and builds up a test suite of them. For example, the
+following includes three test cases:
+
+```C
+void testVerifyThatUnityIsAwesomeAndWillMakeYourLifeEasier(void)
+{
+ ASSERT_TRUE(1);
+}
+void test_FunctionName_should_WorkProperlyAndReturn8(void) {
+ ASSERT_EQUAL_INT(8, FunctionName());
+}
+void spec_Function_should_DoWhatItIsSupposedToDo(void) {
+ ASSERT_NOT_NULL(Function(5));
+}
+```
+
+You can run this script a couple of ways. The first is from the command line:
+
+```Shell
+ruby generate_test_runner.rb TestFile.c NameOfRunner.c
+```
+
+Alternatively, if you include only the test file parameter, the script will copy
+the name of the test file and automatically append "_Runner" to the name of the
+generated file. The example immediately below will create TestFile_Runner.c.
+
+```Shell
+ruby generate_test_runner.rb TestFile.c
+```
+
+You can also add a [YAML](http://www.yaml.org/) file to configure extra options.
+Conveniently, this YAML file is of the same format as that used by Unity and
+CMock. So if you are using YAML files already, you can simply pass the very same
+file into the generator script.
+
+```Shell
+ruby generate_test_runner.rb TestFile.c my_config.yml
+```
+
+The contents of the YAML file `my_config.yml` could look something like the
+example below. If you're wondering what some of these options do, you're going
+to love the next section of this document.
+
+```YAML
+:unity:
+ :includes:
+ - stdio.h
+ - microdefs.h
+ :cexception: 1
+ :suit_setup: "blah = malloc(1024);"
+ :suite_teardown: "free(blah);"
+```
+
+If you would like to force your generated test runner to include one or more
+header files, you can just include those at the command line too. Just make sure
+these are _after_ the YAML file, if you are using one:
+
+```Shell
+ruby generate_test_runner.rb TestFile.c my_config.yml extras.h
+```
+
+Another option, particularly if you are already using Ruby to orchestrate your
+builds - or more likely the Ruby-based build tool Rake - is requiring this
+script directly. Anything that you would have specified in a YAML file can be
+passed to the script as part of a hash. Let's push the exact same requirement
+set as we did above but this time through Ruby code directly:
+
+```Ruby
+require "generate_test_runner.rb"
+options = {
+ :includes => ["stdio.h", "microdefs.h"],
+ :cexception => 1,
+ :suite_setup => "blah = malloc(1024);",
+ :suite_teardown => "free(blah);"
+}
+UnityTestRunnerGenerator.new.run(testfile, runner_name, options)
+```
+
+If you have multiple files to generate in a build script (such as a Rakefile),
+you might want to instantiate a generator object with your options and call it
+to generate each runner thereafter. Like thus:
+
+```Ruby
+gen = UnityTestRunnerGenerator.new(options)
+test_files.each do |f|
+ gen.run(f, File.basename(f,'.c')+"Runner.c"
+end
+```
+
+#### Options accepted by generate_test_runner.rb:
+
+The following options are available when executing `generate_test_runner`. You
+may pass these as a Ruby hash directly or specify them in a YAML file, both of
+which are described above. In the `examples` directory, Example 3's Rakefile
+demonstrates using a Ruby hash.
+
+
+##### `:includes`
+
+This option specifies an array of file names to be `#include`'d at the top of
+your runner C file. You might use it to reference custom types or anything else
+universally needed in your generated runners.
+
+
+##### `:suite_setup`
+
+Define this option with C code to be executed _before any_ test cases are run.
+
+Alternatively, if your C compiler supports weak symbols, you can leave this
+option unset and instead provide a `void suiteSetUp(void)` function in your test
+suite. The linker will look for this symbol and fall back to a Unity-provided
+stub if it is not found.
+
+
+##### `:suite_teardown`
+
+Define this option with C code to be executed _after all_ test cases have
+finished. An integer variable `num_failures` is available for diagnostics.
+The code should end with a `return` statement; the value returned will become
+the exit code of `main`. You can normally just return `num_failures`.
+
+Alternatively, if your C compiler supports weak symbols, you can leave this
+option unset and instead provide a `int suiteTearDown(int num_failures)`
+function in your test suite. The linker will look for this symbol and fall
+back to a Unity-provided stub if it is not found.
+
+
+##### `:enforce_strict_ordering`
+
+This option should be defined if you have the strict order feature enabled in
+CMock (see CMock documentation). This generates extra variables required for
+everything to run smoothly. If you provide the same YAML to the generator as
+used in CMock's configuration, you've already configured the generator properly.
+
+
+##### `:plugins`
+
+This option specifies an array of plugins to be used (of course, the array can
+contain only a single plugin). This is your opportunity to enable support for
+CException support, which will add a check for unhandled exceptions in each
+test, reporting a failure if one is detected. To enable this feature using Ruby:
+
+```Ruby
+:plugins => [ :cexception ]
+```
+
+Or as a yaml file:
+
+```YAML
+:plugins:
+ -:cexception
+```
+
+If you are using CMock, it is very likely that you are already passing an array
+of plugins to CMock. You can just use the same array here. This script will just
+ignore the plugins that don't require additional support.
+
+
+### `unity_test_summary.rb`
+
+A Unity test file contains one or more test case functions. Each test case can
+pass, fail, or be ignored. Each test file is run individually producing results
+for its collection of test cases. A given project will almost certainly be
+composed of multiple test files. Therefore, the suite of tests is comprised of
+one or more test cases spread across one or more test files. This script
+aggregates individual test file results to generate a summary of all executed
+test cases. The output includes how many tests were run, how many were ignored,
+and how many failed. In addition, the output includes a listing of which
+specific tests were ignored and failed. A good example of the breadth and
+details of these results can be found in the `examples` directory. Intentionally
+ignored and failing tests in this project generate corresponding entries in the
+summary report.
+
+If you're interested in other (prettier?) output formats, check into the
+Ceedling build tool project (ceedling.sourceforge.net) that works with Unity and
+CMock and supports xunit-style xml as well as other goodies.
+
+This script assumes the existence of files ending with the extensions
+`.testpass` and `.testfail`.The contents of these files includes the test
+results summary corresponding to each test file executed with the extension set
+according to the presence or absence of failures for that test file. The script
+searches a specified path for these files, opens each one it finds, parses the
+results, and aggregates and prints a summary. Calling it from the command line
+looks like this:
+
+```Shell
+ruby unity_test_summary.rb build/test/
+```
+
+You can optionally specify a root path as well. This is really helpful when you
+are using relative paths in your tools' setup, but you want to pull the summary
+into an IDE like Eclipse for clickable shortcuts.
+
+```Shell
+ruby unity_test_summary.rb build/test/ ~/projects/myproject/
+```
+
+Or, if you're more of a Windows sort of person:
+
+```Shell
+ruby unity_test_summary.rb build\teat\ C:\projects\myproject\
+```
+
+When configured correctly, you'll see a final summary, like so:
+
+```Shell
+--------------------------
+UNITY IGNORED TEST SUMMARY
+--------------------------
+blah.c:22:test_sandwiches_should_HaveBreadOnTwoSides:IGNORE
+
+-------------------------
+UNITY FAILED TEST SUMMARY
+-------------------------
+blah.c:87:test_sandwiches_should_HaveCondiments:FAIL:Expected 1 was 0
+meh.c:38:test_soda_should_BeCalledPop:FAIL:Expected "pop" was "coke"
+
+--------------------------
+OVERALL UNITY TEST SUMMARY
+--------------------------
+45 TOTAL TESTS 2 TOTAL FAILURES 1 IGNORED
+```
+
+How convenient is that?
+
+
+*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
diff --git a/vendor/Unity-2.4.3/docs/license.txt b/vendor/Unity-2.4.3/docs/license.txt
new file mode 100644
index 0000000..d66fba5
--- /dev/null
+++ b/vendor/Unity-2.4.3/docs/license.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <year> 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
+
+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.
diff --git a/vendor/Unity-2.4.3/examples/example_1/makefile b/vendor/Unity-2.4.3/examples/example_1/makefile
new file mode 100644
index 0000000..cca79b4
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_1/makefile
@@ -0,0 +1,71 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+#We try to detect the OS we are running on, and adjust commands as needed
+ifeq ($(OS),Windows_NT)
+ ifeq ($(shell uname -s),) # not in a bash-like shell
+ CLEANUP = del /F /Q
+ MKDIR = mkdir
+ else # in a bash-like shell, like msys
+ CLEANUP = rm -f
+ MKDIR = mkdir -p
+ endif
+ TARGET_EXTENSION=.exe
+else
+ CLEANUP = rm -f
+ MKDIR = mkdir -p
+ TARGET_EXTENSION=.out
+endif
+
+C_COMPILER=gcc
+ifeq ($(shell uname -s), Darwin)
+C_COMPILER=clang
+endif
+
+UNITY_ROOT=../..
+
+CFLAGS=-std=c89
+CFLAGS += -Wall
+CFLAGS += -Wextra
+CFLAGS += -Wpointer-arith
+CFLAGS += -Wcast-align
+CFLAGS += -Wwrite-strings
+CFLAGS += -Wswitch-default
+CFLAGS += -Wunreachable-code
+CFLAGS += -Winit-self
+CFLAGS += -Wmissing-field-initializers
+CFLAGS += -Wno-unknown-pragmas
+CFLAGS += -Wstrict-prototypes
+CFLAGS += -Wundef
+CFLAGS += -Wold-style-definition
+
+TARGET_BASE1=test1
+TARGET_BASE2=test2
+TARGET1 = $(TARGET_BASE1)$(TARGET_EXTENSION)
+TARGET2 = $(TARGET_BASE2)$(TARGET_EXTENSION)
+SRC_FILES1=$(UNITY_ROOT)/src/unity.c src/ProductionCode.c test/TestProductionCode.c test/test_runners/TestProductionCode_Runner.c
+SRC_FILES2=$(UNITY_ROOT)/src/unity.c src/ProductionCode2.c test/TestProductionCode2.c test/test_runners/TestProductionCode2_Runner.c
+INC_DIRS=-Isrc -I$(UNITY_ROOT)/src
+SYMBOLS=
+
+all: clean default
+
+default: $(SRC_FILES1) $(SRC_FILES2)
+ $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) -o $(TARGET1)
+ $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES2) -o $(TARGET2)
+ - ./$(TARGET1)
+ ./$(TARGET2)
+
+test/test_runners/TestProductionCode_Runner.c: test/TestProductionCode.c
+ ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/TestProductionCode.c test/test_runners/TestProductionCode_Runner.c
+test/test_runners/TestProductionCode2_Runner.c: test/TestProductionCode2.c
+ ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/TestProductionCode2.c test/test_runners/TestProductionCode2_Runner.c
+
+clean:
+ $(CLEANUP) $(TARGET1) $(TARGET2)
+
+ci: CFLAGS += -Werror
+ci: default
diff --git a/vendor/Unity-2.4.3/examples/example_1/readme.txt b/vendor/Unity-2.4.3/examples/example_1/readme.txt
new file mode 100644
index 0000000..dfed815
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_1/readme.txt
@@ -0,0 +1,5 @@
+Example 1
+=========
+
+Close to the simplest possible example of Unity, using only basic features.
+Run make to build & run the example tests. \ No newline at end of file
diff --git a/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode.c b/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode.c
new file mode 100644
index 0000000..d039c3e
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode.c
@@ -0,0 +1,24 @@
+
+#include "ProductionCode.h"
+
+int Counter = 0;
+int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; /* some obnoxious array to search that is 1-based indexing instead of 0. */
+
+/* This function is supposed to search through NumbersToFind and find a particular number.
+ * If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since
+ * NumbersToFind is indexed from 1. Unfortunately it's broken
+ * (and should therefore be caught by our tests) */
+int FindFunction_WhichIsBroken(int NumberToFind)
+{
+ int i = 0;
+ while (i <= 8) /* Notice I should have been in braces */
+ i++;
+ if (NumbersToFind[i] == NumberToFind) /* Yikes! I'm getting run after the loop finishes instead of during it! */
+ return i;
+ return 0;
+}
+
+int FunctionWhichReturnsLocalVariable(void)
+{
+ return Counter;
+}
diff --git a/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode.h b/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode.h
new file mode 100644
index 0000000..250ca0d
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode.h
@@ -0,0 +1,3 @@
+
+int FindFunction_WhichIsBroken(int NumberToFind);
+int FunctionWhichReturnsLocalVariable(void);
diff --git a/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode2.c b/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode2.c
new file mode 100644
index 0000000..98ee7ee
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode2.c
@@ -0,0 +1,11 @@
+
+#include "ProductionCode2.h"
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction)
+{
+ (void)Poor;
+ (void)LittleFunction;
+ /* Since There Are No Tests Yet, This Function Could Be Empty For All We Know.
+ * Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget */
+ return (char*)0;
+}
diff --git a/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode2.h b/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode2.h
new file mode 100644
index 0000000..34ae980
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_1/src/ProductionCode2.h
@@ -0,0 +1,2 @@
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction);
diff --git a/vendor/Unity-2.4.3/examples/example_1/test/TestProductionCode.c b/vendor/Unity-2.4.3/examples/example_1/test/TestProductionCode.c
new file mode 100644
index 0000000..8060886
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_1/test/TestProductionCode.c
@@ -0,0 +1,62 @@
+
+#include "ProductionCode.h"
+#include "unity.h"
+
+/* sometimes you may want to get at local data in a module.
+ * for example: If you plan to pass by reference, this could be useful
+ * however, it should often be avoided */
+extern int Counter;
+
+void setUp(void)
+{
+ /* This is run before EACH TEST */
+ Counter = 0x5a5a;
+}
+
+void tearDown(void)
+{
+}
+
+void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void)
+{
+ /* All of these should pass */
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1));
+}
+
+void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void)
+{
+ /* You should see this line fail in your test summary */
+ TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34));
+
+ /* Notice the rest of these didn't get a chance to run because the line above failed.
+ * Unit tests abort each test function on the first sign of trouble.
+ * Then NEXT test function runs as normal. */
+ TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888));
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void)
+{
+ /* This should be true because setUp set this up for us before this test */
+ TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+
+ /* This should be true because we can still change our answer */
+ Counter = 0x1234;
+ TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void)
+{
+ /* This should be true again because setup was rerun before this test (and after we changed it to 0x1234) */
+ TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void)
+{
+ /* Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell
+ * you what actually happened...which in this case was a failure to setup the initial condition. */
+ TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
diff --git a/vendor/Unity-2.4.3/examples/example_1/test/TestProductionCode2.c b/vendor/Unity-2.4.3/examples/example_1/test/TestProductionCode2.c
new file mode 100644
index 0000000..7d940c1
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_1/test/TestProductionCode2.c
@@ -0,0 +1,31 @@
+
+#include "ProductionCode2.h"
+#include "unity.h"
+
+/* These should be ignored because they are commented out in various ways:
+#include "whatever.h"
+#include "somethingelse.h"
+*/
+
+void setUp(void)
+{
+}
+
+void tearDown(void)
+{
+}
+
+void test_IgnoredTest(void)
+{
+ TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose");
+}
+
+void test_AnotherIgnoredTest(void)
+{
+ TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet");
+}
+
+void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void)
+{
+ TEST_IGNORE(); /* Like This */
+}
diff --git a/vendor/Unity-2.4.3/examples/example_1/test/test_runners/TestProductionCode2_Runner.c b/vendor/Unity-2.4.3/examples/example_1/test/test_runners/TestProductionCode2_Runner.c
new file mode 100644
index 0000000..cf72c21
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_1/test/test_runners/TestProductionCode2_Runner.c
@@ -0,0 +1,53 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(); \
+ } \
+ if (TEST_PROTECT()) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "ProductionCode2.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_IgnoredTest(void);
+extern void test_AnotherIgnoredTest(void);
+extern void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("test/TestProductionCode2.c");
+ RUN_TEST(test_IgnoredTest, 18);
+ RUN_TEST(test_AnotherIgnoredTest, 23);
+ RUN_TEST(test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented, 28);
+
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/examples/example_1/test/test_runners/TestProductionCode_Runner.c b/vendor/Unity-2.4.3/examples/example_1/test/test_runners/TestProductionCode_Runner.c
new file mode 100644
index 0000000..3b49af7
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_1/test/test_runners/TestProductionCode_Runner.c
@@ -0,0 +1,57 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(); \
+ } \
+ if (TEST_PROTECT()) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "ProductionCode.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void);
+extern void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void);
+extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void);
+extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void);
+extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("test/TestProductionCode.c");
+ RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode, 20);
+ RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken, 30);
+ RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue, 41);
+ RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain, 51);
+ RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed, 57);
+
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/examples/example_2/makefile b/vendor/Unity-2.4.3/examples/example_2/makefile
new file mode 100644
index 0000000..99d8d96
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_2/makefile
@@ -0,0 +1,70 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+#We try to detect the OS we are running on, and adjust commands as needed
+ifeq ($(OS),Windows_NT)
+ ifeq ($(shell uname -s),) # not in a bash-like shell
+ CLEANUP = del /F /Q
+ MKDIR = mkdir
+ else # in a bash-like shell, like msys
+ CLEANUP = rm -f
+ MKDIR = mkdir -p
+ endif
+ TARGET_EXTENSION=.exe
+else
+ CLEANUP = rm -f
+ MKDIR = mkdir -p
+ TARGET_EXTENSION=.out
+endif
+
+C_COMPILER=gcc
+ifeq ($(shell uname -s), Darwin)
+C_COMPILER=clang
+endif
+
+UNITY_ROOT=../..
+
+CFLAGS=-std=c99
+CFLAGS += -Wall
+CFLAGS += -Wextra
+CFLAGS += -Wpointer-arith
+CFLAGS += -Wcast-align
+CFLAGS += -Wwrite-strings
+CFLAGS += -Wswitch-default
+CFLAGS += -Wunreachable-code
+CFLAGS += -Winit-self
+CFLAGS += -Wmissing-field-initializers
+CFLAGS += -Wno-unknown-pragmas
+CFLAGS += -Wstrict-prototypes
+CFLAGS += -Wundef
+CFLAGS += -Wold-style-definition
+
+TARGET_BASE1=all_tests
+TARGET1 = $(TARGET_BASE1)$(TARGET_EXTENSION)
+SRC_FILES1=\
+ $(UNITY_ROOT)/src/unity.c \
+ $(UNITY_ROOT)/extras/fixture/src/unity_fixture.c \
+ src/ProductionCode.c \
+ src/ProductionCode2.c \
+ test/TestProductionCode.c \
+ test/TestProductionCode2.c \
+ test/test_runners/TestProductionCode_Runner.c \
+ test/test_runners/TestProductionCode2_Runner.c \
+ test/test_runners/all_tests.c
+INC_DIRS=-Isrc -I$(UNITY_ROOT)/src -I$(UNITY_ROOT)/extras/fixture/src
+SYMBOLS=
+
+all: clean default
+
+default:
+ $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) -o $(TARGET1)
+ - ./$(TARGET1) -v
+
+clean:
+ $(CLEANUP) $(TARGET1)
+
+ci: CFLAGS += -Werror
+ci: default
diff --git a/vendor/Unity-2.4.3/examples/example_2/readme.txt b/vendor/Unity-2.4.3/examples/example_2/readme.txt
new file mode 100644
index 0000000..f0fce65
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_2/readme.txt
@@ -0,0 +1,5 @@
+Example 2
+=========
+
+Same as the first example, but now using Unity's test fixture to group tests
+together. Using the test fixture also makes writing test runners much easier. \ No newline at end of file
diff --git a/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode.c b/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode.c
new file mode 100644
index 0000000..500b44b
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode.c
@@ -0,0 +1,24 @@
+
+#include "ProductionCode.h"
+
+int Counter = 0;
+int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obnoxious array to search that is 1-based indexing instead of 0.
+
+// This function is supposed to search through NumbersToFind and find a particular number.
+// If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since
+// NumbersToFind is indexed from 1. Unfortunately it's broken
+// (and should therefore be caught by our tests)
+int FindFunction_WhichIsBroken(int NumberToFind)
+{
+ int i = 0;
+ while (i <= 8) //Notice I should have been in braces
+ i++;
+ if (NumbersToFind[i] == NumberToFind) //Yikes! I'm getting run after the loop finishes instead of during it!
+ return i;
+ return 0;
+}
+
+int FunctionWhichReturnsLocalVariable(void)
+{
+ return Counter;
+}
diff --git a/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode.h b/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode.h
new file mode 100644
index 0000000..250ca0d
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode.h
@@ -0,0 +1,3 @@
+
+int FindFunction_WhichIsBroken(int NumberToFind);
+int FunctionWhichReturnsLocalVariable(void);
diff --git a/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode2.c b/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode2.c
new file mode 100644
index 0000000..77c969f
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode2.c
@@ -0,0 +1,11 @@
+
+#include "ProductionCode2.h"
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction)
+{
+ (void)Poor;
+ (void)LittleFunction;
+ //Since There Are No Tests Yet, This Function Could Be Empty For All We Know.
+ // Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget
+ return (char*)0;
+}
diff --git a/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode2.h b/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode2.h
new file mode 100644
index 0000000..34ae980
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_2/src/ProductionCode2.h
@@ -0,0 +1,2 @@
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction);
diff --git a/vendor/Unity-2.4.3/examples/example_2/test/TestProductionCode.c b/vendor/Unity-2.4.3/examples/example_2/test/TestProductionCode.c
new file mode 100644
index 0000000..ff318ab
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_2/test/TestProductionCode.c
@@ -0,0 +1,64 @@
+#include "ProductionCode.h"
+#include "unity.h"
+#include "unity_fixture.h"
+
+TEST_GROUP(ProductionCode);
+
+//sometimes you may want to get at local data in a module.
+//for example: If you plan to pass by reference, this could be useful
+//however, it should often be avoided
+extern int Counter;
+
+TEST_SETUP(ProductionCode)
+{
+ //This is run before EACH TEST
+ Counter = 0x5a5a;
+}
+
+TEST_TEAR_DOWN(ProductionCode)
+{
+}
+
+TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode)
+{
+ //All of these should pass
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1));
+}
+
+TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken)
+{
+ // You should see this line fail in your test summary
+ TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34));
+
+ // Notice the rest of these didn't get a chance to run because the line above failed.
+ // Unit tests abort each test function on the first sign of trouble.
+ // Then NEXT test function runs as normal.
+ TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888));
+}
+
+TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue)
+{
+ //This should be true because setUp set this up for us before this test
+ TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+
+ //This should be true because we can still change our answer
+ Counter = 0x1234;
+ TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
+
+TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain)
+{
+ //This should be true again because setup was rerun before this test (and after we changed it to 0x1234)
+ TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+}
+
+TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed)
+{
+ //Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell
+ // you what actually happened...which in this case was a failure to setup the initial condition.
+ TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
diff --git a/vendor/Unity-2.4.3/examples/example_2/test/TestProductionCode2.c b/vendor/Unity-2.4.3/examples/example_2/test/TestProductionCode2.c
new file mode 100644
index 0000000..d9f4efe
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_2/test/TestProductionCode2.c
@@ -0,0 +1,33 @@
+#include "ProductionCode2.h"
+#include "unity.h"
+#include "unity_fixture.h"
+
+TEST_GROUP(ProductionCode2);
+
+/* These should be ignored because they are commented out in various ways:
+#include "whatever.h"
+*/
+//#include "somethingelse.h"
+
+TEST_SETUP(ProductionCode2)
+{
+}
+
+TEST_TEAR_DOWN(ProductionCode2)
+{
+}
+
+TEST(ProductionCode2, IgnoredTest)
+{
+ TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose");
+}
+
+TEST(ProductionCode2, AnotherIgnoredTest)
+{
+ TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet");
+}
+
+TEST(ProductionCode2, ThisFunctionHasNotBeenTested_NeedsToBeImplemented)
+{
+ TEST_IGNORE(); //Like This
+}
diff --git a/vendor/Unity-2.4.3/examples/example_2/test/test_runners/TestProductionCode2_Runner.c b/vendor/Unity-2.4.3/examples/example_2/test/test_runners/TestProductionCode2_Runner.c
new file mode 100644
index 0000000..6fcc3b1
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_2/test/test_runners/TestProductionCode2_Runner.c
@@ -0,0 +1,9 @@
+#include "unity.h"
+#include "unity_fixture.h"
+
+TEST_GROUP_RUNNER(ProductionCode2)
+{
+ RUN_TEST_CASE(ProductionCode2, IgnoredTest);
+ RUN_TEST_CASE(ProductionCode2, AnotherIgnoredTest);
+ RUN_TEST_CASE(ProductionCode2, ThisFunctionHasNotBeenTested_NeedsToBeImplemented);
+} \ No newline at end of file
diff --git a/vendor/Unity-2.4.3/examples/example_2/test/test_runners/TestProductionCode_Runner.c b/vendor/Unity-2.4.3/examples/example_2/test/test_runners/TestProductionCode_Runner.c
new file mode 100644
index 0000000..41a416a
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_2/test/test_runners/TestProductionCode_Runner.c
@@ -0,0 +1,11 @@
+#include "unity.h"
+#include "unity_fixture.h"
+
+TEST_GROUP_RUNNER(ProductionCode)
+{
+ RUN_TEST_CASE(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode);
+ RUN_TEST_CASE(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken);
+ RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue);
+ RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain);
+ RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed);
+} \ No newline at end of file
diff --git a/vendor/Unity-2.4.3/examples/example_2/test/test_runners/all_tests.c b/vendor/Unity-2.4.3/examples/example_2/test/test_runners/all_tests.c
new file mode 100644
index 0000000..e706ece
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_2/test/test_runners/all_tests.c
@@ -0,0 +1,12 @@
+#include "unity_fixture.h"
+
+static void RunAllTests(void)
+{
+ RUN_TEST_GROUP(ProductionCode);
+ RUN_TEST_GROUP(ProductionCode2);
+}
+
+int main(int argc, const char * argv[])
+{
+ return UnityMain(argc, argv, RunAllTests);
+}
diff --git a/vendor/Unity-2.4.3/examples/example_3/helper/UnityHelper.c b/vendor/Unity-2.4.3/examples/example_3/helper/UnityHelper.c
new file mode 100644
index 0000000..9cf42c6
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/helper/UnityHelper.c
@@ -0,0 +1,10 @@
+#include "unity.h"
+#include "UnityHelper.h"
+#include <stdio.h>
+#include <string.h>
+
+void AssertEqualExampleStruct(const EXAMPLE_STRUCT_T expected, const EXAMPLE_STRUCT_T actual, const unsigned short line)
+{
+ UNITY_TEST_ASSERT_EQUAL_INT(expected.x, actual.x, line, "Example Struct Failed For Field x");
+ UNITY_TEST_ASSERT_EQUAL_INT(expected.y, actual.y, line, "Example Struct Failed For Field y");
+}
diff --git a/vendor/Unity-2.4.3/examples/example_3/helper/UnityHelper.h b/vendor/Unity-2.4.3/examples/example_3/helper/UnityHelper.h
new file mode 100644
index 0000000..1516111
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/helper/UnityHelper.h
@@ -0,0 +1,12 @@
+#ifndef _TESTHELPER_H
+#define _TESTHELPER_H
+
+#include "Types.h"
+
+void AssertEqualExampleStruct(const EXAMPLE_STRUCT_T expected, const EXAMPLE_STRUCT_T actual, const unsigned short line);
+
+#define UNITY_TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual, line, message) AssertEqualExampleStruct(expected, actual, line);
+
+#define TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual) UNITY_TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual, __LINE__, NULL);
+
+#endif // _TESTHELPER_H
diff --git a/vendor/Unity-2.4.3/examples/example_3/rakefile.rb b/vendor/Unity-2.4.3/examples/example_3/rakefile.rb
new file mode 100644
index 0000000..bf9f42b
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/rakefile.rb
@@ -0,0 +1,43 @@
+HERE = File.expand_path(File.dirname(__FILE__)) + '/'
+UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/../..'
+
+require 'rake'
+require 'rake/clean'
+require HERE + 'rakefile_helper'
+
+TEMP_DIRS = [
+ File.join(HERE, 'build')
+].freeze
+
+TEMP_DIRS.each do |dir|
+ directory(dir)
+ CLOBBER.include(dir)
+end
+
+task prepare_for_tests: TEMP_DIRS
+
+include RakefileHelpers
+
+# Load default configuration, for now
+DEFAULT_CONFIG_FILE = 'target_gcc_32.yml'.freeze
+configure_toolchain(DEFAULT_CONFIG_FILE)
+
+task unit: [:prepare_for_tests] do
+ run_tests unit_test_files
+end
+
+desc 'Generate test summary'
+task :summary do
+ report_summary
+end
+
+desc 'Build and test Unity'
+task all: %i(clean unit summary)
+task default: %i(clobber all)
+task ci: [:default]
+task cruise: [:default]
+
+desc 'Load configuration'
+task :config, :config_file do |_t, args|
+ configure_toolchain(args[:config_file])
+end
diff --git a/vendor/Unity-2.4.3/examples/example_3/rakefile_helper.rb b/vendor/Unity-2.4.3/examples/example_3/rakefile_helper.rb
new file mode 100644
index 0000000..a186cf0
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/rakefile_helper.rb
@@ -0,0 +1,249 @@
+require 'yaml'
+require 'fileutils'
+require UNITY_ROOT + '/auto/unity_test_summary'
+require UNITY_ROOT + '/auto/generate_test_runner'
+require UNITY_ROOT + '/auto/colour_reporter'
+
+module RakefileHelpers
+ C_EXTENSION = '.c'.freeze
+
+ def load_configuration(config_file)
+ $cfg_file = config_file
+ $cfg = YAML.load(File.read($cfg_file))
+ end
+
+ def configure_clean
+ CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil?
+ end
+
+ def configure_toolchain(config_file = DEFAULT_CONFIG_FILE)
+ config_file += '.yml' unless config_file =~ /\.yml$/
+ load_configuration(config_file)
+ configure_clean
+ end
+
+ def unit_test_files
+ path = $cfg['compiler']['unit_tests_path'] + 'Test*' + C_EXTENSION
+ path.tr!('\\', '/')
+ FileList.new(path)
+ end
+
+ def local_include_dirs
+ include_dirs = $cfg['compiler']['includes']['items'].dup
+ include_dirs.delete_if { |dir| dir.is_a?(Array) }
+ include_dirs
+ end
+
+ def extract_headers(filename)
+ includes = []
+ lines = File.readlines(filename)
+ lines.each do |line|
+ m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/)
+ includes << m[1] unless m.nil?
+ end
+ includes
+ end
+
+ def find_source_file(header, paths)
+ paths.each do |dir|
+ src_file = dir + header.ext(C_EXTENSION)
+ return src_file if File.exist?(src_file)
+ end
+ nil
+ end
+
+ def tackit(strings)
+ result = if strings.is_a?(Array)
+ "\"#{strings.join}\""
+ else
+ strings
+ end
+ result
+ end
+
+ def squash(prefix, items)
+ result = ''
+ items.each { |item| result += " #{prefix}#{tackit(item)}" }
+ result
+ end
+
+ def build_compiler_fields
+ command = tackit($cfg['compiler']['path'])
+ defines = if $cfg['compiler']['defines']['items'].nil?
+ ''
+ else
+ squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'])
+ end
+ options = squash('', $cfg['compiler']['options'])
+ includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
+ includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+
+ { command: command, defines: defines, options: options, includes: includes }
+ end
+
+ def compile(file, _defines = [])
+ compiler = build_compiler_fields
+ cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " \
+ "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}"
+ obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}"
+ execute(cmd_str + obj_file)
+ obj_file
+ end
+
+ def build_linker_fields
+ command = tackit($cfg['linker']['path'])
+ options = if $cfg['linker']['options'].nil?
+ ''
+ else
+ squash('', $cfg['linker']['options'])
+ end
+ includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?
+ ''
+ else
+ squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items'])
+ end.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+
+ { command: command, options: options, includes: includes }
+ end
+
+ def link_it(exe_name, obj_list)
+ linker = build_linker_fields
+ cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " +
+ (obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join +
+ $cfg['linker']['bin_files']['prefix'] + ' ' +
+ $cfg['linker']['bin_files']['destination'] +
+ exe_name + $cfg['linker']['bin_files']['extension']
+ execute(cmd_str)
+ end
+
+ def build_simulator_fields
+ return nil if $cfg['simulator'].nil?
+ command = if $cfg['simulator']['path'].nil?
+ ''
+ else
+ (tackit($cfg['simulator']['path']) + ' ')
+ end
+ pre_support = if $cfg['simulator']['pre_support'].nil?
+ ''
+ else
+ squash('', $cfg['simulator']['pre_support'])
+ end
+ post_support = if $cfg['simulator']['post_support'].nil?
+ ''
+ else
+ squash('', $cfg['simulator']['post_support'])
+ end
+
+ { command: command, pre_support: pre_support, post_support: post_support }
+ end
+
+ def execute(command_string, verbose = true, raise_on_fail = true)
+ report command_string
+ output = `#{command_string}`.chomp
+ report(output) if verbose && !output.nil? && !output.empty?
+ if !$?.exitstatus.zero? && raise_on_fail
+ raise "Command failed. (Returned #{$?.exitstatus})"
+ end
+ output
+ end
+
+ def report_summary
+ summary = UnityTestSummary.new
+ summary.root = HERE
+ results_glob = "#{$cfg['compiler']['build_path']}*.test*"
+ results_glob.tr!('\\', '/')
+ results = Dir[results_glob]
+ summary.targets = results
+ summary.run
+ fail_out 'FAIL: There were failures' if summary.failures > 0
+ end
+
+ def run_tests(test_files)
+ report 'Running system tests...'
+
+ # Tack on TEST define for compiling unit tests
+ load_configuration($cfg_file)
+ test_defines = ['TEST']
+ $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil?
+ $cfg['compiler']['defines']['items'] << 'TEST'
+
+ include_dirs = local_include_dirs
+
+ # Build and execute each unit test
+ test_files.each do |test|
+ obj_list = []
+
+ # Detect dependencies and build required required modules
+ extract_headers(test).each do |header|
+ # Compile corresponding source file if it exists
+ src_file = find_source_file(header, include_dirs)
+ obj_list << compile(src_file, test_defines) unless src_file.nil?
+ end
+
+ # Build the test runner (generate if configured to do so)
+ test_base = File.basename(test, C_EXTENSION)
+ runner_name = test_base + '_Runner.c'
+ if $cfg['compiler']['runner_path'].nil?
+ runner_path = $cfg['compiler']['build_path'] + runner_name
+ test_gen = UnityTestRunnerGenerator.new($cfg_file)
+ test_gen.run(test, runner_path)
+ else
+ runner_path = $cfg['compiler']['runner_path'] + runner_name
+ end
+
+ obj_list << compile(runner_path, test_defines)
+
+ # Build the test module
+ obj_list << compile(test, test_defines)
+
+ # Link the test executable
+ link_it(test_base, obj_list)
+
+ # Execute unit test and generate results file
+ simulator = build_simulator_fields
+ executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension']
+ cmd_str = if simulator.nil?
+ executable
+ else
+ "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}"
+ end
+ output = execute(cmd_str, true, false)
+ test_results = $cfg['compiler']['build_path'] + test_base
+ test_results += if output.match(/OK$/m).nil?
+ '.testfail'
+ else
+ '.testpass'
+ end
+ File.open(test_results, 'w') { |f| f.print output }
+ end
+ end
+
+ def build_application(main)
+ report 'Building application...'
+
+ obj_list = []
+ load_configuration($cfg_file)
+ main_path = $cfg['compiler']['source_path'] + main + C_EXTENSION
+
+ # Detect dependencies and build required required modules
+ include_dirs = get_local_include_dirs
+ extract_headers(main_path).each do |header|
+ src_file = find_source_file(header, include_dirs)
+ obj_list << compile(src_file) unless src_file.nil?
+ end
+
+ # Build the main source file
+ main_base = File.basename(main_path, C_EXTENSION)
+ obj_list << compile(main_path)
+
+ # Create the executable
+ link_it(main_base, obj_list)
+ end
+
+ def fail_out(msg)
+ puts msg
+ puts 'Not returning exit code so continuous integration can pass'
+ # exit(-1) # Only removed to pass example_3, which has failing tests on purpose.
+ # Still fail if the build fails for any other reason.
+ end
+end
diff --git a/vendor/Unity-2.4.3/examples/example_3/readme.txt b/vendor/Unity-2.4.3/examples/example_3/readme.txt
new file mode 100644
index 0000000..7371fea
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/readme.txt
@@ -0,0 +1,13 @@
+Example 3
+=========
+
+This example project gives an example of some passing, ignored, and failing tests.
+It's simple and meant for you to look over and get an idea for what all of this stuff does.
+
+You can build and test using rake. The rake version will let you test with gcc or a couple
+versions of IAR. You can tweak the yaml files to get those versions running.
+
+Ruby is required if you're using the rake version (obviously). This version shows off most of
+Unity's advanced features (automatically creating test runners, fancy summaries, etc.)
+Without ruby, you have to maintain your own test runners. Do that for a while and you'll learn
+why you really want to start using the Ruby tools.
diff --git a/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode.c b/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode.c
new file mode 100644
index 0000000..500b44b
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode.c
@@ -0,0 +1,24 @@
+
+#include "ProductionCode.h"
+
+int Counter = 0;
+int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obnoxious array to search that is 1-based indexing instead of 0.
+
+// This function is supposed to search through NumbersToFind and find a particular number.
+// If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since
+// NumbersToFind is indexed from 1. Unfortunately it's broken
+// (and should therefore be caught by our tests)
+int FindFunction_WhichIsBroken(int NumberToFind)
+{
+ int i = 0;
+ while (i <= 8) //Notice I should have been in braces
+ i++;
+ if (NumbersToFind[i] == NumberToFind) //Yikes! I'm getting run after the loop finishes instead of during it!
+ return i;
+ return 0;
+}
+
+int FunctionWhichReturnsLocalVariable(void)
+{
+ return Counter;
+}
diff --git a/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode.h b/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode.h
new file mode 100644
index 0000000..250ca0d
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode.h
@@ -0,0 +1,3 @@
+
+int FindFunction_WhichIsBroken(int NumberToFind);
+int FunctionWhichReturnsLocalVariable(void);
diff --git a/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode2.c b/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode2.c
new file mode 100644
index 0000000..77c969f
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode2.c
@@ -0,0 +1,11 @@
+
+#include "ProductionCode2.h"
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction)
+{
+ (void)Poor;
+ (void)LittleFunction;
+ //Since There Are No Tests Yet, This Function Could Be Empty For All We Know.
+ // Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget
+ return (char*)0;
+}
diff --git a/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode2.h b/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode2.h
new file mode 100644
index 0000000..34ae980
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/src/ProductionCode2.h
@@ -0,0 +1,2 @@
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction);
diff --git a/vendor/Unity-2.4.3/examples/example_3/target_gcc_32.yml b/vendor/Unity-2.4.3/examples/example_3/target_gcc_32.yml
new file mode 100644
index 0000000..f155508
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/target_gcc_32.yml
@@ -0,0 +1,46 @@
+# Copied from ~Unity/targets/gcc_32.yml
+unity_root: &unity_root '../..'
+compiler:
+ path: gcc
+ source_path: 'src/'
+ unit_tests_path: &unit_tests_path 'test/'
+ build_path: &build_path 'build/'
+ options:
+ - '-c'
+ - '-m32'
+ - '-Wall'
+ - '-Wno-address'
+ - '-std=c99'
+ - '-pedantic'
+ includes:
+ prefix: '-I'
+ items:
+ - 'src/'
+ - '../../src/'
+ - *unit_tests_path
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_INCLUDE_DOUBLE
+ - UNITY_SUPPORT_TEST_CASES
+ object_files:
+ prefix: '-o'
+ extension: '.o'
+ destination: *build_path
+linker:
+ path: gcc
+ options:
+ - -lm
+ - '-m32'
+ includes:
+ prefix: '-I'
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.exe'
+ destination: *build_path
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/examples/example_3/test/TestProductionCode.c b/vendor/Unity-2.4.3/examples/example_3/test/TestProductionCode.c
new file mode 100644
index 0000000..28a5581
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/test/TestProductionCode.c
@@ -0,0 +1,62 @@
+
+#include "ProductionCode.h"
+#include "unity.h"
+
+//sometimes you may want to get at local data in a module.
+//for example: If you plan to pass by reference, this could be useful
+//however, it should often be avoided
+extern int Counter;
+
+void setUp(void)
+{
+ //This is run before EACH TEST
+ Counter = 0x5a5a;
+}
+
+void tearDown(void)
+{
+}
+
+void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void)
+{
+ //All of these should pass
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999));
+ TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1));
+}
+
+void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void)
+{
+ // You should see this line fail in your test summary
+ TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34));
+
+ // Notice the rest of these didn't get a chance to run because the line above failed.
+ // Unit tests abort each test function on the first sign of trouble.
+ // Then NEXT test function runs as normal.
+ TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888));
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void)
+{
+ //This should be true because setUp set this up for us before this test
+ TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+
+ //This should be true because we can still change our answer
+ Counter = 0x1234;
+ TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void)
+{
+ //This should be true again because setup was rerun before this test (and after we changed it to 0x1234)
+ TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void)
+{
+ //Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell
+ // you what actually happened...which in this case was a failure to setup the initial condition.
+ TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
diff --git a/vendor/Unity-2.4.3/examples/example_3/test/TestProductionCode2.c b/vendor/Unity-2.4.3/examples/example_3/test/TestProductionCode2.c
new file mode 100644
index 0000000..e2119cc
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/example_3/test/TestProductionCode2.c
@@ -0,0 +1,31 @@
+
+#include "ProductionCode2.h"
+#include "unity.h"
+
+/* These should be ignored because they are commented out in various ways:
+#include "whatever.h"
+*/
+//#include "somethingelse.h"
+
+void setUp(void)
+{
+}
+
+void tearDown(void)
+{
+}
+
+void test_IgnoredTest(void)
+{
+ TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose");
+}
+
+void test_AnotherIgnoredTest(void)
+{
+ TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet");
+}
+
+void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void)
+{
+ TEST_IGNORE(); //Like This
+}
diff --git a/vendor/Unity-2.4.3/examples/unity_config.h b/vendor/Unity-2.4.3/examples/unity_config.h
new file mode 100644
index 0000000..da3c2af
--- /dev/null
+++ b/vendor/Unity-2.4.3/examples/unity_config.h
@@ -0,0 +1,239 @@
+/* Unity Configuration
+ * As of May 11th, 2016 at ThrowTheSwitch/Unity commit 837c529
+ * Update: December 29th, 2016
+ * See Also: Unity/docs/UnityConfigurationGuide.pdf
+ *
+ * Unity is designed to run on almost anything that is targeted by a C compiler.
+ * It would be awesome if this could be done with zero configuration. While
+ * there are some targets that come close to this dream, it is sadly not
+ * universal. It is likely that you are going to need at least a couple of the
+ * configuration options described in this document.
+ *
+ * All of Unity's configuration options are `#defines`. Most of these are simple
+ * definitions. A couple are macros with arguments. They live inside the
+ * unity_internals.h header file. We don't necessarily recommend opening that
+ * file unless you really need to. That file is proof that a cross-platform
+ * library is challenging to build. From a more positive perspective, it is also
+ * proof that a great deal of complexity can be centralized primarily to one
+ * place in order to provide a more consistent and simple experience elsewhere.
+ *
+ * Using These Options
+ * It doesn't matter if you're using a target-specific compiler and a simulator
+ * or a native compiler. In either case, you've got a couple choices for
+ * configuring these options:
+ *
+ * 1. Because these options are specified via C defines, you can pass most of
+ * these options to your compiler through command line compiler flags. Even
+ * if you're using an embedded target that forces you to use their
+ * overbearing IDE for all configuration, there will be a place somewhere in
+ * your project to configure defines for your compiler.
+ * 2. You can create a custom `unity_config.h` configuration file (present in
+ * your toolchain's search paths). In this file, you will list definitions
+ * and macros specific to your target. All you must do is define
+ * `UNITY_INCLUDE_CONFIG_H` and Unity will rely on `unity_config.h` for any
+ * further definitions it may need.
+ */
+
+#ifndef UNITY_CONFIG_H
+#define UNITY_CONFIG_H
+
+/* ************************* AUTOMATIC INTEGER TYPES ***************************
+ * C's concept of an integer varies from target to target. The C Standard has
+ * rules about the `int` matching the register size of the target
+ * microprocessor. It has rules about the `int` and how its size relates to
+ * other integer types. An `int` on one target might be 16 bits while on another
+ * target it might be 64. There are more specific types in compilers compliant
+ * with C99 or later, but that's certainly not every compiler you are likely to
+ * encounter. Therefore, Unity has a number of features for helping to adjust
+ * itself to match your required integer sizes. It starts off by trying to do it
+ * automatically.
+ **************************************************************************** */
+
+/* The first attempt to guess your types is to check `limits.h`. Some compilers
+ * that don't support `stdint.h` could include `limits.h`. If you don't
+ * want Unity to check this file, define this to make it skip the inclusion.
+ * Unity looks at UINT_MAX & ULONG_MAX, which were available since C89.
+ */
+/* #define UNITY_EXCLUDE_LIMITS_H */
+
+/* The second thing that Unity does to guess your types is check `stdint.h`.
+ * This file defines `UINTPTR_MAX`, since C99, that Unity can make use of to
+ * learn about your system. It's possible you don't want it to do this or it's
+ * possible that your system doesn't support `stdint.h`. If that's the case,
+ * you're going to want to define this. That way, Unity will know to skip the
+ * inclusion of this file and you won't be left with a compiler error.
+ */
+/* #define UNITY_EXCLUDE_STDINT_H */
+
+/* ********************** MANUAL INTEGER TYPE DEFINITION ***********************
+ * If you've disabled all of the automatic options above, you're going to have
+ * to do the configuration yourself. There are just a handful of defines that
+ * you are going to specify if you don't like the defaults.
+ **************************************************************************** */
+
+ /* Define this to be the number of bits an `int` takes up on your system. The
+ * default, if not auto-detected, is 32 bits.
+ *
+ * Example:
+ */
+/* #define UNITY_INT_WIDTH 16 */
+
+/* Define this to be the number of bits a `long` takes up on your system. The
+ * default, if not autodetected, is 32 bits. This is used to figure out what
+ * kind of 64-bit support your system can handle. Does it need to specify a
+ * `long` or a `long long` to get a 64-bit value. On 16-bit systems, this option
+ * is going to be ignored.
+ *
+ * Example:
+ */
+/* #define UNITY_LONG_WIDTH 16 */
+
+/* Define this to be the number of bits a pointer takes up on your system. The
+ * default, if not autodetected, is 32-bits. If you're getting ugly compiler
+ * warnings about casting from pointers, this is the one to look at.
+ *
+ * Example:
+ */
+/* #define UNITY_POINTER_WIDTH 64 */
+
+/* Unity will automatically include 64-bit support if it auto-detects it, or if
+ * your `int`, `long`, or pointer widths are greater than 32-bits. Define this
+ * to enable 64-bit support if none of the other options already did it for you.
+ * There can be a significant size and speed impact to enabling 64-bit support
+ * on small targets, so don't define it if you don't need it.
+ */
+/* #define UNITY_INCLUDE_64 */
+
+
+/* *************************** FLOATING POINT TYPES ****************************
+ * In the embedded world, it's not uncommon for targets to have no support for
+ * floating point operations at all or to have support that is limited to only
+ * single precision. We are able to guess integer sizes on the fly because
+ * integers are always available in at least one size. Floating point, on the
+ * other hand, is sometimes not available at all. Trying to include `float.h` on
+ * these platforms would result in an error. This leaves manual configuration as
+ * the only option.
+ **************************************************************************** */
+
+ /* By default, Unity guesses that you will want single precision floating point
+ * support, but not double precision. It's easy to change either of these using
+ * the include and exclude options here. You may include neither, just float,
+ * or both, as suits your needs.
+ */
+/* #define UNITY_EXCLUDE_FLOAT */
+/* #define UNITY_INCLUDE_DOUBLE */
+/* #define UNITY_EXCLUDE_DOUBLE */
+
+/* For features that are enabled, the following floating point options also
+ * become available.
+ */
+
+/* Unity aims for as small of a footprint as possible and avoids most standard
+ * library calls (some embedded platforms don't have a standard library!).
+ * Because of this, its routines for printing integer values are minimalist and
+ * hand-coded. To keep Unity universal, though, we eventually chose to develop
+ * our own floating point print routines. Still, the display of floating point
+ * values during a failure are optional. By default, Unity will print the
+ * actual results of floating point assertion failures. So a failed assertion
+ * will produce a message like "Expected 4.0 Was 4.25". If you would like less
+ * verbose failure messages for floating point assertions, use this option to
+ * give a failure message `"Values Not Within Delta"` and trim the binary size.
+ */
+/* #define UNITY_EXCLUDE_FLOAT_PRINT */
+
+/* If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C
+ * floats. If your compiler supports a specialty floating point type, you can
+ * always override this behavior by using this definition.
+ *
+ * Example:
+ */
+/* #define UNITY_FLOAT_TYPE float16_t */
+
+/* If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard
+ * C doubles. If you would like to change this, you can specify something else
+ * by using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long
+ * double` could enable gargantuan floating point types on your 64-bit processor
+ * instead of the standard `double`.
+ *
+ * Example:
+ */
+/* #define UNITY_DOUBLE_TYPE long double */
+
+/* If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as
+ * documented in the Unity Assertion Guide, you will learn that they are not
+ * really asserting that two values are equal but rather that two values are
+ * "close enough" to equal. "Close enough" is controlled by these precision
+ * configuration options. If you are working with 32-bit floats and/or 64-bit
+ * doubles (the normal on most processors), you should have no need to change
+ * these options. They are both set to give you approximately 1 significant bit
+ * in either direction. The float precision is 0.00001 while the double is
+ * 10^-12. For further details on how this works, see the appendix of the Unity
+ * Assertion Guide.
+ *
+ * Example:
+ */
+/* #define UNITY_FLOAT_PRECISION 0.001f */
+/* #define UNITY_DOUBLE_PRECISION 0.001f */
+
+
+/* *************************** TOOLSET CUSTOMIZATION ***************************
+ * In addition to the options listed above, there are a number of other options
+ * which will come in handy to customize Unity's behavior for your specific
+ * toolchain. It is possible that you may not need to touch any of these but
+ * certain platforms, particularly those running in simulators, may need to jump
+ * through extra hoops to operate properly. These macros will help in those
+ * situations.
+ **************************************************************************** */
+
+/* By default, Unity prints its results to `stdout` as it runs. This works
+ * perfectly fine in most situations where you are using a native compiler for
+ * testing. It works on some simulators as well so long as they have `stdout`
+ * routed back to the command line. There are times, however, where the
+ * simulator will lack support for dumping results or you will want to route
+ * results elsewhere for other reasons. In these cases, you should define the
+ * `UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time
+ * (as an `int`, since this is the parameter type of the standard C `putchar`
+ * function most commonly used). You may replace this with whatever function
+ * call you like.
+ *
+ * Example:
+ * Say you are forced to run your test suite on an embedded processor with no
+ * `stdout` option. You decide to route your test result output to a custom
+ * serial `RS232_putc()` function you wrote like thus:
+ */
+/* #define UNITY_OUTPUT_CHAR(a) RS232_putc(a) */
+/* #define UNITY_OUTPUT_CHAR_HEADER_DECLARATION RS232_putc(int) */
+/* #define UNITY_OUTPUT_FLUSH() RS232_flush() */
+/* #define UNITY_OUTPUT_FLUSH_HEADER_DECLARATION RS232_flush(void) */
+/* #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0) */
+/* #define UNITY_OUTPUT_COMPLETE() RS232_close() */
+
+/* For some targets, Unity can make the otherwise required `setUp()` and
+ * `tearDown()` functions optional. This is a nice convenience for test writers
+ * since `setUp` and `tearDown` don't often actually _do_ anything. If you're
+ * using gcc or clang, this option is automatically defined for you. Other
+ * compilers can also support this behavior, if they support a C feature called
+ * weak functions. A weak function is a function that is compiled into your
+ * executable _unless_ a non-weak version of the same function is defined
+ * elsewhere. If a non-weak version is found, the weak version is ignored as if
+ * it never existed. If your compiler supports this feature, you can let Unity
+ * know by defining `UNITY_SUPPORT_WEAK` as the function attributes that would
+ * need to be applied to identify a function as weak. If your compiler lacks
+ * support for weak functions, you will always need to define `setUp` and
+ * `tearDown` functions (though they can be and often will be just empty). The
+ * most common options for this feature are:
+ */
+/* #define UNITY_SUPPORT_WEAK weak */
+/* #define UNITY_SUPPORT_WEAK __attribute__((weak)) */
+/* #define UNITY_NO_WEAK */
+
+/* Some compilers require a custom attribute to be assigned to pointers, like
+ * `near` or `far`. In these cases, you can give Unity a safe default for these
+ * by defining this option with the attribute you would like.
+ *
+ * Example:
+ */
+/* #define UNITY_PTR_ATTRIBUTE __attribute__((far)) */
+/* #define UNITY_PTR_ATTRIBUTE near */
+
+#endif /* UNITY_CONFIG_H */
diff --git a/vendor/Unity-2.4.3/extras/eclipse/error_parsers.txt b/vendor/Unity-2.4.3/extras/eclipse/error_parsers.txt
new file mode 100644
index 0000000..94e34ff
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/eclipse/error_parsers.txt
@@ -0,0 +1,26 @@
+Eclipse error parsers
+=====================
+
+These are a godsend for extracting & quickly navigating to
+warnings & error messages from console output. Unforunately
+I don't know how to write an Eclipse plugin so you'll have
+to add them manually.
+
+To add a console parser to Eclipse, go to Window --> Preferences
+--> C/C++ --> Build --> Settings. Click on the 'Error Parsers'
+tab and then click the 'Add...' button. See the table below for
+the parser fields to add.
+
+Eclipse will only parse the console output during a build, so
+running your unit tests must be part of your build process.
+Either add this to your make/rakefile, or add it as a post-
+build step in your Eclipse project settings.
+
+
+Unity unit test error parsers
+-----------------------------
+Severity Pattern File Line Description
+-------------------------------------------------------------------------------
+Error (\.+)(.*?):(\d+):(.*?):FAIL: (.*) $2 $3 $5
+Warning (\.+)(.*?):(\d+):(.*?):IGNORE: (.*) $2 $3 $5
+Warning (\.+)(.*?):(\d+):(.*?):IGNORE\s*$ $2 $3 Ignored test
diff --git a/vendor/Unity-2.4.3/extras/fixture/rakefile.rb b/vendor/Unity-2.4.3/extras/fixture/rakefile.rb
new file mode 100644
index 0000000..7603e57
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/rakefile.rb
@@ -0,0 +1,48 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+HERE = File.expand_path(File.dirname(__FILE__)) + '/'
+
+require 'rake'
+require 'rake/clean'
+require 'rake/testtask'
+require HERE + 'rakefile_helper'
+
+TEMP_DIRS = [
+ File.join(HERE, 'build')
+].freeze
+
+TEMP_DIRS.each do |dir|
+ directory(dir)
+ CLOBBER.include(dir)
+end
+
+task prepare_for_tests: TEMP_DIRS
+
+include RakefileHelpers
+
+# Load default configuration, for now
+DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml'.freeze
+configure_toolchain(DEFAULT_CONFIG_FILE)
+
+task unit: [:prepare_for_tests] do
+ run_tests
+end
+
+desc 'Build and test Unity Framework'
+task all: %i(clean unit)
+task default: %i(clobber all)
+task ci: %i(no_color default)
+task cruise: %i(no_color default)
+
+desc 'Load configuration'
+task :config, :config_file do |_t, args|
+ configure_toolchain(args[:config_file])
+end
+
+task :no_color do
+ $colour_output = false
+end
diff --git a/vendor/Unity-2.4.3/extras/fixture/rakefile_helper.rb b/vendor/Unity-2.4.3/extras/fixture/rakefile_helper.rb
new file mode 100644
index 0000000..c45b239
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/rakefile_helper.rb
@@ -0,0 +1,178 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+require 'yaml'
+require 'fileutils'
+require HERE + '../../auto/unity_test_summary'
+require HERE + '../../auto/generate_test_runner'
+require HERE + '../../auto/colour_reporter'
+
+module RakefileHelpers
+ C_EXTENSION = '.c'.freeze
+
+ def load_configuration(config_file)
+ return if $configured
+
+ $cfg_file = HERE + "../../test/targets/#{config_file}" unless config_file =~ /[\\|\/]/
+ $cfg = YAML.load(File.read($cfg_file))
+ $colour_output = false unless $cfg['colour']
+ $configured = true if config_file != DEFAULT_CONFIG_FILE
+ end
+
+ def configure_clean
+ CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil?
+ end
+
+ def configure_toolchain(config_file = DEFAULT_CONFIG_FILE)
+ config_file += '.yml' unless config_file =~ /\.yml$/
+ config_file = config_file unless config_file =~ /[\\|\/]/
+ load_configuration(config_file)
+ configure_clean
+ end
+
+ def tackit(strings)
+ result = if strings.is_a?(Array)
+ "\"#{strings.join}\""
+ else
+ strings
+ end
+ result
+ end
+
+ def squash(prefix, items)
+ result = ''
+ items.each { |item| result += " #{prefix}#{tackit(item)}" }
+ result
+ end
+
+ def build_compiler_fields
+ command = tackit($cfg['compiler']['path'])
+ defines = if $cfg['compiler']['defines']['items'].nil?
+ ''
+ else
+ squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar'] + ['UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar\(int\)'])
+ end
+ options = squash('', $cfg['compiler']['options'])
+ includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
+ includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+
+ { command: command, defines: defines, options: options, includes: includes }
+ end
+
+ def compile(file, _defines = [])
+ compiler = build_compiler_fields
+ unity_include = $cfg['compiler']['includes']['prefix'] + '../../src'
+ cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{unity_include} #{file} " \
+ "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" \
+ "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}"
+
+ execute(cmd_str)
+ end
+
+ def build_linker_fields
+ command = tackit($cfg['linker']['path'])
+ options = if $cfg['linker']['options'].nil?
+ ''
+ else
+ squash('', $cfg['linker']['options'])
+ end
+ includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?
+ ''
+ else
+ squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items'])
+ end.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+
+ { command: command, options: options, includes: includes }
+ end
+
+ def link_it(exe_name, obj_list)
+ linker = build_linker_fields
+ cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " +
+ (obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join +
+ $cfg['linker']['bin_files']['prefix'] + ' ' +
+ $cfg['linker']['bin_files']['destination'] +
+ exe_name + $cfg['linker']['bin_files']['extension']
+ execute(cmd_str)
+ end
+
+ def build_simulator_fields
+ return nil if $cfg['simulator'].nil?
+ command = if $cfg['simulator']['path'].nil?
+ ''
+ else
+ (tackit($cfg['simulator']['path']) + ' ')
+ end
+ pre_support = if $cfg['simulator']['pre_support'].nil?
+ ''
+ else
+ squash('', $cfg['simulator']['pre_support'])
+ end
+ post_support = if $cfg['simulator']['post_support'].nil?
+ ''
+ else
+ squash('', $cfg['simulator']['post_support'])
+ end
+ { command: command, pre_support: pre_support, post_support: post_support }
+ end
+
+ def execute(command_string, verbose = true)
+ report command_string
+ output = `#{command_string}`.chomp
+ report(output) if verbose && !output.nil? && !output.empty?
+ raise "Command failed. (Returned #{$?.exitstatus})" if $?.exitstatus != 0
+ output
+ end
+
+ def report_summary
+ summary = UnityTestSummary.new
+ summary.root = HERE
+ results_glob = "#{$cfg['compiler']['build_path']}*.test*"
+ results_glob.tr!('\\', '/')
+ results = Dir[results_glob]
+ summary.targets = results
+ summary.run
+ end
+
+ def run_tests
+ report 'Running Unity system tests...'
+
+ # Tack on TEST define for compiling unit tests
+ load_configuration($cfg_file)
+ test_defines = ['TEST']
+ $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil?
+
+ # Get a list of all source files needed
+ src_files = Dir[HERE + 'src/*.c']
+ src_files += Dir[HERE + 'test/*.c']
+ src_files += Dir[HERE + 'test/main/*.c']
+ src_files << '../../src/unity.c'
+
+ # Build object files
+ src_files.each { |f| compile(f, test_defines) }
+ obj_list = src_files.map { |f| File.basename(f.ext($cfg['compiler']['object_files']['extension'])) }
+
+ # Link the test executable
+ test_base = 'framework_test'
+ link_it(test_base, obj_list)
+
+ # Execute unit test and generate results file
+ simulator = build_simulator_fields
+ executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension']
+ cmd_str = if simulator.nil?
+ executable + ' -v -r'
+ else
+ "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}"
+ end
+ output = execute(cmd_str)
+ test_results = $cfg['compiler']['build_path'] + test_base
+ test_results += if output.match(/OK$/m).nil?
+ '.testfail'
+ else
+ '.testpass'
+ end
+ File.open(test_results, 'w') { |f| f.print output }
+ end
+end
diff --git a/vendor/Unity-2.4.3/extras/fixture/readme.txt b/vendor/Unity-2.4.3/extras/fixture/readme.txt
new file mode 100644
index 0000000..6b9a78c
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/readme.txt
@@ -0,0 +1,9 @@
+Copyright (c) 2010 James Grenning and Contributed to Unity Project
+
+Unity Project - A Test Framework for C
+Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+[Released under MIT License. Please refer to license.txt for details]
+
+This Framework is an optional add-on to Unity. By including unity_framework.h in place of unity.h,
+you may now work with Unity in a manner similar to CppUTest. This framework adds the concepts of
+test groups and gives finer control of your tests over the command line. \ No newline at end of file
diff --git a/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture.c b/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture.c
new file mode 100644
index 0000000..3872bd8
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture.c
@@ -0,0 +1,432 @@
+/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
+ * ==========================================
+ * Unity Project - A Test Framework for C
+ * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ * [Released under MIT License. Please refer to license.txt for details]
+ * ========================================== */
+
+#include "unity_fixture.h"
+#include "unity_internals.h"
+#include <string.h>
+
+struct UNITY_FIXTURE_T UnityFixture;
+
+/* If you decide to use the function pointer approach.
+ * Build with -D UNITY_OUTPUT_CHAR=outputChar and include <stdio.h>
+ * int (*outputChar)(int) = putchar; */
+
+#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA)
+void setUp(void) { /*does nothing*/ }
+void tearDown(void) { /*does nothing*/ }
+#endif
+
+static void announceTestRun(unsigned int runNumber)
+{
+ UnityPrint("Unity test run ");
+ UnityPrintNumberUnsigned(runNumber+1);
+ UnityPrint(" of ");
+ UnityPrintNumberUnsigned(UnityFixture.RepeatCount);
+ UNITY_PRINT_EOL();
+}
+
+int UnityMain(int argc, const char* argv[], void (*runAllTests)(void))
+{
+ int result = UnityGetCommandLineOptions(argc, argv);
+ unsigned int r;
+ if (result != 0)
+ return result;
+
+ for (r = 0; r < UnityFixture.RepeatCount; r++)
+ {
+ UnityBegin(argv[0]);
+ announceTestRun(r);
+ runAllTests();
+ if (!UnityFixture.Verbose) UNITY_PRINT_EOL();
+ UnityEnd();
+ }
+
+ return (int)Unity.TestFailures;
+}
+
+static int selected(const char* filter, const char* name)
+{
+ if (filter == 0)
+ return 1;
+ return strstr(name, filter) ? 1 : 0;
+}
+
+static int testSelected(const char* test)
+{
+ return selected(UnityFixture.NameFilter, test);
+}
+
+static int groupSelected(const char* group)
+{
+ return selected(UnityFixture.GroupFilter, group);
+}
+
+void UnityTestRunner(unityfunction* setup,
+ unityfunction* testBody,
+ unityfunction* teardown,
+ const char* printableName,
+ const char* group,
+ const char* name,
+ const char* file,
+ unsigned int line)
+{
+ if (testSelected(name) && groupSelected(group))
+ {
+ Unity.TestFile = file;
+ Unity.CurrentTestName = printableName;
+ Unity.CurrentTestLineNumber = line;
+ if (!UnityFixture.Verbose)
+ UNITY_OUTPUT_CHAR('.');
+ else
+ {
+ UnityPrint(printableName);
+ #ifndef UNITY_REPEAT_TEST_NAME
+ Unity.CurrentTestName = NULL;
+ #endif
+ }
+
+ Unity.NumberOfTests++;
+ UnityMalloc_StartTest();
+ UnityPointer_Init();
+
+ if (TEST_PROTECT())
+ {
+ setup();
+ testBody();
+ }
+ if (TEST_PROTECT())
+ {
+ teardown();
+ }
+ if (TEST_PROTECT())
+ {
+ UnityPointer_UndoAllSets();
+ if (!Unity.CurrentTestFailed)
+ UnityMalloc_EndTest();
+ }
+ UnityConcludeFixtureTest();
+ }
+}
+
+void UnityIgnoreTest(const char* printableName, const char* group, const char* name)
+{
+ if (testSelected(name) && groupSelected(group))
+ {
+ Unity.NumberOfTests++;
+ Unity.TestIgnores++;
+ if (!UnityFixture.Verbose)
+ UNITY_OUTPUT_CHAR('!');
+ else
+ {
+ UnityPrint(printableName);
+ UNITY_PRINT_EOL();
+ }
+ }
+}
+
+
+/*------------------------------------------------- */
+/* Malloc and free stuff */
+#define MALLOC_DONT_FAIL -1
+static int malloc_count;
+static int malloc_fail_countdown = MALLOC_DONT_FAIL;
+
+void UnityMalloc_StartTest(void)
+{
+ malloc_count = 0;
+ malloc_fail_countdown = MALLOC_DONT_FAIL;
+}
+
+void UnityMalloc_EndTest(void)
+{
+ malloc_fail_countdown = MALLOC_DONT_FAIL;
+ if (malloc_count != 0)
+ {
+ UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "This test leaks!");
+ }
+}
+
+void UnityMalloc_MakeMallocFailAfterCount(int countdown)
+{
+ malloc_fail_countdown = countdown;
+}
+
+/* These definitions are always included from unity_fixture_malloc_overrides.h */
+/* We undef to use them or avoid conflict with <stdlib.h> per the C standard */
+#undef malloc
+#undef free
+#undef calloc
+#undef realloc
+
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES];
+static size_t heap_index;
+#else
+#include <stdlib.h>
+#endif
+
+typedef struct GuardBytes
+{
+ size_t size;
+ size_t guard_space;
+} Guard;
+
+
+static const char end[] = "END";
+
+void* unity_malloc(size_t size)
+{
+ char* mem;
+ Guard* guard;
+ size_t total_size = size + sizeof(Guard) + sizeof(end);
+
+ if (malloc_fail_countdown != MALLOC_DONT_FAIL)
+ {
+ if (malloc_fail_countdown == 0)
+ return NULL;
+ malloc_fail_countdown--;
+ }
+
+ if (size == 0) return NULL;
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+ if (heap_index + total_size > UNITY_INTERNAL_HEAP_SIZE_BYTES)
+ {
+ guard = NULL;
+ }
+ else
+ {
+ guard = (Guard*)&unity_heap[heap_index];
+ heap_index += total_size;
+ }
+#else
+ guard = (Guard*)UNITY_FIXTURE_MALLOC(total_size);
+#endif
+ if (guard == NULL) return NULL;
+ malloc_count++;
+ guard->size = size;
+ guard->guard_space = 0;
+ mem = (char*)&(guard[1]);
+ memcpy(&mem[size], end, sizeof(end));
+
+ return (void*)mem;
+}
+
+static int isOverrun(void* mem)
+{
+ Guard* guard = (Guard*)mem;
+ char* memAsChar = (char*)mem;
+ guard--;
+
+ return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0;
+}
+
+static void release_memory(void* mem)
+{
+ Guard* guard = (Guard*)mem;
+ guard--;
+
+ malloc_count--;
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+ if (mem == unity_heap + heap_index - guard->size - sizeof(end))
+ {
+ heap_index -= (guard->size + sizeof(Guard) + sizeof(end));
+ }
+#else
+ UNITY_FIXTURE_FREE(guard);
+#endif
+}
+
+void unity_free(void* mem)
+{
+ int overrun;
+
+ if (mem == NULL)
+ {
+ return;
+ }
+
+ overrun = isOverrun(mem);
+ release_memory(mem);
+ if (overrun)
+ {
+ UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()");
+ }
+}
+
+void* unity_calloc(size_t num, size_t size)
+{
+ void* mem = unity_malloc(num * size);
+ if (mem == NULL) return NULL;
+ memset(mem, 0, num * size);
+ return mem;
+}
+
+void* unity_realloc(void* oldMem, size_t size)
+{
+ Guard* guard = (Guard*)oldMem;
+ void* newMem;
+
+ if (oldMem == NULL) return unity_malloc(size);
+
+ guard--;
+ if (isOverrun(oldMem))
+ {
+ release_memory(oldMem);
+ UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during realloc()");
+ }
+
+ if (size == 0)
+ {
+ release_memory(oldMem);
+ return NULL;
+ }
+
+ if (guard->size >= size) return oldMem;
+
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC /* Optimization if memory is expandable */
+ if (oldMem == unity_heap + heap_index - guard->size - sizeof(end) &&
+ heap_index + size - guard->size <= UNITY_INTERNAL_HEAP_SIZE_BYTES)
+ {
+ release_memory(oldMem); /* Not thread-safe, like unity_heap generally */
+ return unity_malloc(size); /* No memcpy since data is in place */
+ }
+#endif
+ newMem = unity_malloc(size);
+ if (newMem == NULL) return NULL; /* Do not release old memory */
+ memcpy(newMem, oldMem, guard->size);
+ release_memory(oldMem);
+ return newMem;
+}
+
+
+/*-------------------------------------------------------- */
+/*Automatic pointer restoration functions */
+struct PointerPair
+{
+ void** pointer;
+ void* old_value;
+};
+
+static struct PointerPair pointer_store[UNITY_MAX_POINTERS];
+static int pointer_index = 0;
+
+void UnityPointer_Init(void)
+{
+ pointer_index = 0;
+}
+
+void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line)
+{
+ if (pointer_index >= UNITY_MAX_POINTERS)
+ {
+ UNITY_TEST_FAIL(line, "Too many pointers set");
+ }
+ else
+ {
+ pointer_store[pointer_index].pointer = pointer;
+ pointer_store[pointer_index].old_value = *pointer;
+ *pointer = newValue;
+ pointer_index++;
+ }
+}
+
+void UnityPointer_UndoAllSets(void)
+{
+ while (pointer_index > 0)
+ {
+ pointer_index--;
+ *(pointer_store[pointer_index].pointer) =
+ pointer_store[pointer_index].old_value;
+ }
+}
+
+int UnityGetCommandLineOptions(int argc, const char* argv[])
+{
+ int i;
+ UnityFixture.Verbose = 0;
+ UnityFixture.GroupFilter = 0;
+ UnityFixture.NameFilter = 0;
+ UnityFixture.RepeatCount = 1;
+
+ if (argc == 1)
+ return 0;
+
+ for (i = 1; i < argc; )
+ {
+ if (strcmp(argv[i], "-v") == 0)
+ {
+ UnityFixture.Verbose = 1;
+ i++;
+ }
+ else if (strcmp(argv[i], "-g") == 0)
+ {
+ i++;
+ if (i >= argc)
+ return 1;
+ UnityFixture.GroupFilter = argv[i];
+ i++;
+ }
+ else if (strcmp(argv[i], "-n") == 0)
+ {
+ i++;
+ if (i >= argc)
+ return 1;
+ UnityFixture.NameFilter = argv[i];
+ i++;
+ }
+ else if (strcmp(argv[i], "-r") == 0)
+ {
+ UnityFixture.RepeatCount = 2;
+ i++;
+ if (i < argc)
+ {
+ if (*(argv[i]) >= '0' && *(argv[i]) <= '9')
+ {
+ unsigned int digit = 0;
+ UnityFixture.RepeatCount = 0;
+ while (argv[i][digit] >= '0' && argv[i][digit] <= '9')
+ {
+ UnityFixture.RepeatCount *= 10;
+ UnityFixture.RepeatCount += (unsigned int)argv[i][digit++] - '0';
+ }
+ i++;
+ }
+ }
+ }
+ else
+ {
+ /* ignore unknown parameter */
+ i++;
+ }
+ }
+ return 0;
+}
+
+void UnityConcludeFixtureTest(void)
+{
+ if (Unity.CurrentTestIgnored)
+ {
+ Unity.TestIgnores++;
+ UNITY_PRINT_EOL();
+ }
+ else if (!Unity.CurrentTestFailed)
+ {
+ if (UnityFixture.Verbose)
+ {
+ UnityPrint(" PASS");
+ UNITY_PRINT_EOL();
+ }
+ }
+ else /* Unity.CurrentTestFailed */
+ {
+ Unity.TestFailures++;
+ UNITY_PRINT_EOL();
+ }
+
+ Unity.CurrentTestFailed = 0;
+ Unity.CurrentTestIgnored = 0;
+}
diff --git a/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture.h b/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture.h
new file mode 100644
index 0000000..6f8d623
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture.h
@@ -0,0 +1,83 @@
+/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
+ * ==========================================
+ * Unity Project - A Test Framework for C
+ * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ * [Released under MIT License. Please refer to license.txt for details]
+ * ========================================== */
+
+#ifndef UNITY_FIXTURE_H_
+#define UNITY_FIXTURE_H_
+
+#include "unity.h"
+#include "unity_internals.h"
+#include "unity_fixture_malloc_overrides.h"
+#include "unity_fixture_internals.h"
+
+int UnityMain(int argc, const char* argv[], void (*runAllTests)(void));
+
+
+#define TEST_GROUP(group)\
+ static const char* TEST_GROUP_##group = #group
+
+#define TEST_SETUP(group) void TEST_##group##_SETUP(void);\
+ void TEST_##group##_SETUP(void)
+
+#define TEST_TEAR_DOWN(group) void TEST_##group##_TEAR_DOWN(void);\
+ void TEST_##group##_TEAR_DOWN(void)
+
+
+#define TEST(group, name) \
+ void TEST_##group##_##name##_(void);\
+ void TEST_##group##_##name##_run(void);\
+ void TEST_##group##_##name##_run(void)\
+ {\
+ UnityTestRunner(TEST_##group##_SETUP,\
+ TEST_##group##_##name##_,\
+ TEST_##group##_TEAR_DOWN,\
+ "TEST(" #group ", " #name ")",\
+ TEST_GROUP_##group, #name,\
+ __FILE__, __LINE__);\
+ }\
+ void TEST_##group##_##name##_(void)
+
+#define IGNORE_TEST(group, name) \
+ void TEST_##group##_##name##_(void);\
+ void TEST_##group##_##name##_run(void);\
+ void TEST_##group##_##name##_run(void)\
+ {\
+ UnityIgnoreTest("IGNORE_TEST(" #group ", " #name ")", TEST_GROUP_##group, #name);\
+ }\
+ void TEST_##group##_##name##_(void)
+
+/* Call this for each test, insider the group runner */
+#define RUN_TEST_CASE(group, name) \
+ { void TEST_##group##_##name##_run(void);\
+ TEST_##group##_##name##_run(); }
+
+/* This goes at the bottom of each test file or in a separate c file */
+#define TEST_GROUP_RUNNER(group)\
+ void TEST_##group##_GROUP_RUNNER(void);\
+ void TEST_##group##_GROUP_RUNNER(void)
+
+/* Call this from main */
+#define RUN_TEST_GROUP(group)\
+ { void TEST_##group##_GROUP_RUNNER(void);\
+ TEST_##group##_GROUP_RUNNER(); }
+
+/* CppUTest Compatibility Macros */
+#ifndef UNITY_EXCLUDE_CPPUTEST_ASSERTS
+/* Sets a pointer and automatically restores it to its old value after teardown */
+#define UT_PTR_SET(ptr, newPointerValue) UnityPointer_Set((void**)&(ptr), (void*)(newPointerValue), __LINE__)
+#define TEST_ASSERT_POINTERS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_PTR((expected), (actual))
+#define TEST_ASSERT_BYTES_EQUAL(expected, actual) TEST_ASSERT_EQUAL_HEX8(0xff & (expected), 0xff & (actual))
+#define FAIL(message) TEST_FAIL_MESSAGE((message))
+#define CHECK(condition) TEST_ASSERT_TRUE((condition))
+#define LONGS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_INT((expected), (actual))
+#define STRCMP_EQUAL(expected, actual) TEST_ASSERT_EQUAL_STRING((expected), (actual))
+#define DOUBLES_EQUAL(expected, actual, delta) TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual))
+#endif
+
+/* You must compile with malloc replacement, as defined in unity_fixture_malloc_overrides.h */
+void UnityMalloc_MakeMallocFailAfterCount(int count);
+
+#endif /* UNITY_FIXTURE_H_ */
diff --git a/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture_internals.h b/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture_internals.h
new file mode 100644
index 0000000..aa0d9e7
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture_internals.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
+ * ==========================================
+ * Unity Project - A Test Framework for C
+ * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ * [Released under MIT License. Please refer to license.txt for details]
+ * ========================================== */
+
+#ifndef UNITY_FIXTURE_INTERNALS_H_
+#define UNITY_FIXTURE_INTERNALS_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+struct UNITY_FIXTURE_T
+{
+ int Verbose;
+ unsigned int RepeatCount;
+ const char* NameFilter;
+ const char* GroupFilter;
+};
+extern struct UNITY_FIXTURE_T UnityFixture;
+
+typedef void unityfunction(void);
+void UnityTestRunner(unityfunction* setup,
+ unityfunction* body,
+ unityfunction* teardown,
+ const char* printableName,
+ const char* group,
+ const char* name,
+ const char* file, unsigned int line);
+
+void UnityIgnoreTest(const char* printableName, const char* group, const char* name);
+void UnityMalloc_StartTest(void);
+void UnityMalloc_EndTest(void);
+int UnityGetCommandLineOptions(int argc, const char* argv[]);
+void UnityConcludeFixtureTest(void);
+
+void UnityPointer_Set(void** ptr, void* newValue, UNITY_LINE_TYPE line);
+void UnityPointer_UndoAllSets(void);
+void UnityPointer_Init(void);
+#ifndef UNITY_MAX_POINTERS
+#define UNITY_MAX_POINTERS 5
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UNITY_FIXTURE_INTERNALS_H_ */
diff --git a/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture_malloc_overrides.h b/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture_malloc_overrides.h
new file mode 100644
index 0000000..7daba50
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/src/unity_fixture_malloc_overrides.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
+ * ==========================================
+ * Unity Project - A Test Framework for C
+ * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ * [Released under MIT License. Please refer to license.txt for details]
+ * ========================================== */
+
+#ifndef UNITY_FIXTURE_MALLOC_OVERRIDES_H_
+#define UNITY_FIXTURE_MALLOC_OVERRIDES_H_
+
+#include <stddef.h>
+
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+/* Define this macro to remove the use of stdlib.h, malloc, and free.
+ * Many embedded systems do not have a heap or malloc/free by default.
+ * This internal unity_malloc() provides allocated memory deterministically from
+ * the end of an array only, unity_free() only releases from end-of-array,
+ * blocks are not coalesced, and memory not freed in LIFO order is stranded. */
+ #ifndef UNITY_INTERNAL_HEAP_SIZE_BYTES
+ #define UNITY_INTERNAL_HEAP_SIZE_BYTES 256
+ #endif
+#endif
+
+/* These functions are used by the Unity Fixture to allocate and release memory
+ * on the heap and can be overridden with platform-specific implementations.
+ * For example, when using FreeRTOS UNITY_FIXTURE_MALLOC becomes pvPortMalloc()
+ * and UNITY_FIXTURE_FREE becomes vPortFree(). */
+#if !defined(UNITY_FIXTURE_MALLOC) || !defined(UNITY_FIXTURE_FREE)
+ #include <stdlib.h>
+ #define UNITY_FIXTURE_MALLOC(size) malloc(size)
+ #define UNITY_FIXTURE_FREE(ptr) free(ptr)
+#else
+ extern void* UNITY_FIXTURE_MALLOC(size_t size);
+ extern void UNITY_FIXTURE_FREE(void* ptr);
+#endif
+
+#define malloc unity_malloc
+#define calloc unity_calloc
+#define realloc unity_realloc
+#define free unity_free
+
+void* unity_malloc(size_t size);
+void* unity_calloc(size_t num, size_t size);
+void* unity_realloc(void * oldMem, size_t size);
+void unity_free(void * mem);
+
+#endif /* UNITY_FIXTURE_MALLOC_OVERRIDES_H_ */
diff --git a/vendor/Unity-2.4.3/extras/fixture/test/Makefile b/vendor/Unity-2.4.3/extras/fixture/test/Makefile
new file mode 100644
index 0000000..e6c6255
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/test/Makefile
@@ -0,0 +1,75 @@
+CC = gcc
+ifeq ($(shell uname -s), Darwin)
+CC = clang
+endif
+#DEBUG = -O0 -g
+CFLAGS += -std=c99 -pedantic -Wall -Wextra -Werror
+CFLAGS += $(DEBUG)
+DEFINES = -D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar
+DEFINES += -D UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar\(int\)
+SRC = ../src/unity_fixture.c \
+ ../../../src/unity.c \
+ unity_fixture_Test.c \
+ unity_fixture_TestRunner.c \
+ unity_output_Spy.c \
+ main/AllTests.c
+
+INC_DIR = -I../src -I../../../src/
+BUILD_DIR = ../build
+TARGET = ../build/fixture_tests.exe
+
+all: default noStdlibMalloc 32bits
+
+default: $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_SUPPORT_64
+ @ echo "default build"
+ ./$(TARGET)
+
+32bits: $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -m32
+ @ echo "32bits build"
+ ./$(TARGET)
+
+noStdlibMalloc: $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_EXCLUDE_STDLIB_MALLOC
+ @ echo "build with noStdlibMalloc"
+ ./$(TARGET)
+
+C89: CFLAGS += -D UNITY_EXCLUDE_STDINT_H # C89 did not have type 'long long', <stdint.h>
+C89: $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -std=c89 && ./$(TARGET)
+ $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_EXCLUDE_STDLIB_MALLOC -std=c89
+ ./$(TARGET)
+
+$(BUILD_DIR):
+ mkdir -p $(BUILD_DIR)
+
+clean:
+ rm -f $(TARGET) $(BUILD_DIR)/*.gc*
+
+cov: $(BUILD_DIR)
+ cd $(BUILD_DIR) && \
+ $(CC) $(DEFINES) $(foreach i, $(SRC), ../test/$(i)) $(INC_DIR) -o $(TARGET) -fprofile-arcs -ftest-coverage
+ rm -f $(BUILD_DIR)/*.gcda
+ ./$(TARGET) > /dev/null ; ./$(TARGET) -v > /dev/null
+ cd $(BUILD_DIR) && \
+ gcov unity_fixture.c | head -3
+ grep '###' $(BUILD_DIR)/unity_fixture.c.gcov -C2 || true # Show uncovered lines
+
+# These extended flags DO get included before any target build runs
+CFLAGS += -Wbad-function-cast
+CFLAGS += -Wcast-qual
+CFLAGS += -Wconversion
+CFLAGS += -Wformat=2
+CFLAGS += -Wmissing-prototypes
+CFLAGS += -Wold-style-definition
+CFLAGS += -Wpointer-arith
+CFLAGS += -Wshadow
+CFLAGS += -Wstrict-overflow=5
+CFLAGS += -Wstrict-prototypes
+CFLAGS += -Wswitch-default
+CFLAGS += -Wundef
+CFLAGS += -Wno-error=undef # Warning only, this should not stop the build
+CFLAGS += -Wunreachable-code
+CFLAGS += -Wunused
+CFLAGS += -fstrict-aliasing
diff --git a/vendor/Unity-2.4.3/extras/fixture/test/main/AllTests.c b/vendor/Unity-2.4.3/extras/fixture/test/main/AllTests.c
new file mode 100644
index 0000000..e30dd85
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/test/main/AllTests.c
@@ -0,0 +1,22 @@
+/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
+ * ==========================================
+ * Unity Project - A Test Framework for C
+ * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ * [Released under MIT License. Please refer to license.txt for details]
+ * ========================================== */
+
+#include "unity_fixture.h"
+
+static void runAllTests(void)
+{
+ RUN_TEST_GROUP(UnityFixture);
+ RUN_TEST_GROUP(UnityCommandOptions);
+ RUN_TEST_GROUP(LeakDetection);
+ RUN_TEST_GROUP(InternalMalloc);
+}
+
+int main(int argc, const char* argv[])
+{
+ return UnityMain(argc, argv, runAllTests);
+}
+
diff --git a/vendor/Unity-2.4.3/extras/fixture/test/template_fixture_tests.c b/vendor/Unity-2.4.3/extras/fixture/test/template_fixture_tests.c
new file mode 100644
index 0000000..18bbb89
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/test/template_fixture_tests.c
@@ -0,0 +1,39 @@
+/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
+ * ==========================================
+ * Unity Project - A Test Framework for C
+ * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ * [Released under MIT License. Please refer to license.txt for details]
+ * ========================================== */
+
+#include "unity_fixture.h"
+
+static int data = -1;
+
+TEST_GROUP(mygroup);
+
+TEST_SETUP(mygroup)
+{
+ data = 0;
+}
+
+TEST_TEAR_DOWN(mygroup)
+{
+ data = -1;
+}
+
+TEST(mygroup, test1)
+{
+ TEST_ASSERT_EQUAL_INT(0, data);
+}
+
+TEST(mygroup, test2)
+{
+ TEST_ASSERT_EQUAL_INT(0, data);
+ data = 5;
+}
+
+TEST(mygroup, test3)
+{
+ data = 7;
+ TEST_ASSERT_EQUAL_INT(7, data);
+}
diff --git a/vendor/Unity-2.4.3/extras/fixture/test/unity_fixture_Test.c b/vendor/Unity-2.4.3/extras/fixture/test/unity_fixture_Test.c
new file mode 100644
index 0000000..a842b08
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/test/unity_fixture_Test.c
@@ -0,0 +1,543 @@
+/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
+ * ==========================================
+ * Unity Project - A Test Framework for C
+ * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ * [Released under MIT License. Please refer to license.txt for details]
+ * ========================================== */
+
+#include "unity_fixture.h"
+#include "unity_output_Spy.h"
+#include <stdlib.h>
+#include <string.h>
+
+TEST_GROUP(UnityFixture);
+
+TEST_SETUP(UnityFixture)
+{
+}
+
+TEST_TEAR_DOWN(UnityFixture)
+{
+}
+
+static int* pointer1 = 0;
+static int* pointer2 = (int*)2;
+static int* pointer3 = (int*)3;
+static int int1;
+static int int2;
+static int int3;
+static int int4;
+
+TEST(UnityFixture, PointerSetting)
+{
+ TEST_ASSERT_POINTERS_EQUAL(pointer1, 0);
+ UT_PTR_SET(pointer1, &int1);
+ UT_PTR_SET(pointer2, &int2);
+ UT_PTR_SET(pointer3, &int3);
+ TEST_ASSERT_POINTERS_EQUAL(pointer1, &int1);
+ TEST_ASSERT_POINTERS_EQUAL(pointer2, &int2);
+ TEST_ASSERT_POINTERS_EQUAL(pointer3, &int3);
+ UT_PTR_SET(pointer1, &int4);
+ UnityPointer_UndoAllSets();
+ TEST_ASSERT_POINTERS_EQUAL(pointer1, 0);
+ TEST_ASSERT_POINTERS_EQUAL(pointer2, (int*)2);
+ TEST_ASSERT_POINTERS_EQUAL(pointer3, (int*)3);
+}
+
+TEST(UnityFixture, ForceMallocFail)
+{
+ void* m;
+ void* mfails;
+ UnityMalloc_MakeMallocFailAfterCount(1);
+ m = malloc(10);
+ CHECK(m);
+ mfails = malloc(10);
+ TEST_ASSERT_POINTERS_EQUAL(0, mfails);
+ free(m);
+}
+
+TEST(UnityFixture, ReallocSmallerIsUnchanged)
+{
+ void* m1 = malloc(10);
+ void* m2 = realloc(m1, 5);
+ TEST_ASSERT_POINTERS_EQUAL(m1, m2);
+ free(m2);
+}
+
+TEST(UnityFixture, ReallocSameIsUnchanged)
+{
+ void* m1 = malloc(10);
+ void* m2 = realloc(m1, 10);
+ TEST_ASSERT_POINTERS_EQUAL(m1, m2);
+ free(m2);
+}
+
+TEST(UnityFixture, ReallocLargerNeeded)
+{
+ void* m1 = malloc(10);
+ void* m2;
+ CHECK(m1);
+ strcpy((char*)m1, "123456789");
+ m2 = realloc(m1, 15);
+ /* CHECK(m1 != m2); //Depends on implementation */
+ STRCMP_EQUAL("123456789", m2);
+ free(m2);
+}
+
+TEST(UnityFixture, ReallocNullPointerIsLikeMalloc)
+{
+ void* m = realloc(0, 15);
+ CHECK(m != 0);
+ free(m);
+}
+
+TEST(UnityFixture, ReallocSizeZeroFreesMemAndReturnsNullPointer)
+{
+ void* m1 = malloc(10);
+ void* m2 = realloc(m1, 0);
+ TEST_ASSERT_POINTERS_EQUAL(0, m2);
+}
+
+TEST(UnityFixture, CallocFillsWithZero)
+{
+ void* m = calloc(3, sizeof(char));
+ char* s = (char*)m;
+ CHECK(m);
+ TEST_ASSERT_BYTES_EQUAL(0, s[0]);
+ TEST_ASSERT_BYTES_EQUAL(0, s[1]);
+ TEST_ASSERT_BYTES_EQUAL(0, s[2]);
+ free(m);
+}
+
+static char *p1;
+static char *p2;
+
+TEST(UnityFixture, PointerSet)
+{
+ char c1;
+ char c2;
+ char newC1;
+ char newC2;
+ p1 = &c1;
+ p2 = &c2;
+
+ UnityPointer_Init();
+ UT_PTR_SET(p1, &newC1);
+ UT_PTR_SET(p2, &newC2);
+ TEST_ASSERT_POINTERS_EQUAL(&newC1, p1);
+ TEST_ASSERT_POINTERS_EQUAL(&newC2, p2);
+ UnityPointer_UndoAllSets();
+ TEST_ASSERT_POINTERS_EQUAL(&c1, p1);
+ TEST_ASSERT_POINTERS_EQUAL(&c2, p2);
+}
+
+TEST(UnityFixture, FreeNULLSafety)
+{
+ free(NULL);
+}
+
+TEST(UnityFixture, ConcludeTestIncrementsFailCount)
+{
+ UNITY_UINT savedFails = Unity.TestFailures;
+ UNITY_UINT savedIgnores = Unity.TestIgnores;
+ UnityOutputCharSpy_Enable(1);
+ Unity.CurrentTestFailed = 1;
+ UnityConcludeFixtureTest(); /* Resets TestFailed for this test to pass */
+ Unity.CurrentTestIgnored = 1;
+ UnityConcludeFixtureTest(); /* Resets TestIgnored */
+ UnityOutputCharSpy_Enable(0);
+ TEST_ASSERT_EQUAL(savedFails + 1, Unity.TestFailures);
+ TEST_ASSERT_EQUAL(savedIgnores + 1, Unity.TestIgnores);
+ Unity.TestFailures = savedFails;
+ Unity.TestIgnores = savedIgnores;
+}
+
+/*------------------------------------------------------------ */
+
+TEST_GROUP(UnityCommandOptions);
+
+static int savedVerbose;
+static unsigned int savedRepeat;
+static const char* savedName;
+static const char* savedGroup;
+
+TEST_SETUP(UnityCommandOptions)
+{
+ savedVerbose = UnityFixture.Verbose;
+ savedRepeat = UnityFixture.RepeatCount;
+ savedName = UnityFixture.NameFilter;
+ savedGroup = UnityFixture.GroupFilter;
+}
+
+TEST_TEAR_DOWN(UnityCommandOptions)
+{
+ UnityFixture.Verbose = savedVerbose;
+ UnityFixture.RepeatCount= savedRepeat;
+ UnityFixture.NameFilter = savedName;
+ UnityFixture.GroupFilter = savedGroup;
+}
+
+
+static const char* noOptions[] = {
+ "testrunner.exe"
+};
+
+TEST(UnityCommandOptions, DefaultOptions)
+{
+ UnityGetCommandLineOptions(1, noOptions);
+ TEST_ASSERT_EQUAL(0, UnityFixture.Verbose);
+ TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.GroupFilter);
+ TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.NameFilter);
+ TEST_ASSERT_EQUAL(1, UnityFixture.RepeatCount);
+}
+
+static const char* verbose[] = {
+ "testrunner.exe",
+ "-v"
+};
+
+TEST(UnityCommandOptions, OptionVerbose)
+{
+ TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, verbose));
+ TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
+}
+
+static const char* group[] = {
+ "testrunner.exe",
+ "-g", "groupname"
+};
+
+TEST(UnityCommandOptions, OptionSelectTestByGroup)
+{
+ TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, group));
+ STRCMP_EQUAL("groupname", UnityFixture.GroupFilter);
+}
+
+static const char* name[] = {
+ "testrunner.exe",
+ "-n", "testname"
+};
+
+TEST(UnityCommandOptions, OptionSelectTestByName)
+{
+ TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, name));
+ STRCMP_EQUAL("testname", UnityFixture.NameFilter);
+}
+
+static const char* repeat[] = {
+ "testrunner.exe",
+ "-r", "99"
+};
+
+TEST(UnityCommandOptions, OptionSelectRepeatTestsDefaultCount)
+{
+ TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, repeat));
+ TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount);
+}
+
+TEST(UnityCommandOptions, OptionSelectRepeatTestsSpecificCount)
+{
+ TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, repeat));
+ TEST_ASSERT_EQUAL(99, UnityFixture.RepeatCount);
+}
+
+static const char* multiple[] = {
+ "testrunner.exe",
+ "-v",
+ "-g", "groupname",
+ "-n", "testname",
+ "-r", "98"
+};
+
+TEST(UnityCommandOptions, MultipleOptions)
+{
+ TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(8, multiple));
+ TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
+ STRCMP_EQUAL("groupname", UnityFixture.GroupFilter);
+ STRCMP_EQUAL("testname", UnityFixture.NameFilter);
+ TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount);
+}
+
+static const char* dashRNotLast[] = {
+ "testrunner.exe",
+ "-v",
+ "-g", "gggg",
+ "-r",
+ "-n", "tttt",
+};
+
+TEST(UnityCommandOptions, MultipleOptionsDashRNotLastAndNoValueSpecified)
+{
+ TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(7, dashRNotLast));
+ TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
+ STRCMP_EQUAL("gggg", UnityFixture.GroupFilter);
+ STRCMP_EQUAL("tttt", UnityFixture.NameFilter);
+ TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount);
+}
+
+static const char* unknownCommand[] = {
+ "testrunner.exe",
+ "-v",
+ "-g", "groupname",
+ "-n", "testname",
+ "-r", "98",
+ "-z"
+};
+TEST(UnityCommandOptions, UnknownCommandIsIgnored)
+{
+ TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(9, unknownCommand));
+ TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
+ STRCMP_EQUAL("groupname", UnityFixture.GroupFilter);
+ STRCMP_EQUAL("testname", UnityFixture.NameFilter);
+ TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount);
+}
+
+TEST(UnityCommandOptions, GroupOrNameFilterWithoutStringFails)
+{
+ TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(3, unknownCommand));
+ TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(5, unknownCommand));
+ TEST_ASSERT_EQUAL(1, UnityMain(3, unknownCommand, NULL));
+}
+
+TEST(UnityCommandOptions, GroupFilterReallyFilters)
+{
+ UNITY_UINT saved = Unity.NumberOfTests;
+ TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(4, unknownCommand));
+ UnityIgnoreTest(NULL, "non-matching", NULL);
+ TEST_ASSERT_EQUAL(saved, Unity.NumberOfTests);
+}
+
+IGNORE_TEST(UnityCommandOptions, TestShouldBeIgnored)
+{
+ TEST_FAIL_MESSAGE("This test should not run!");
+}
+
+/*------------------------------------------------------------ */
+
+TEST_GROUP(LeakDetection);
+
+TEST_SETUP(LeakDetection)
+{
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+ UnityOutputCharSpy_Create(200);
+#else
+ UnityOutputCharSpy_Create(1000);
+#endif
+}
+
+TEST_TEAR_DOWN(LeakDetection)
+{
+ UnityOutputCharSpy_Destroy();
+}
+
+#define EXPECT_ABORT_BEGIN \
+ { \
+ jmp_buf TestAbortFrame; \
+ memcpy(TestAbortFrame, Unity.AbortFrame, sizeof(jmp_buf)); \
+ if (TEST_PROTECT()) \
+ {
+
+#define EXPECT_ABORT_END \
+ } \
+ memcpy(Unity.AbortFrame, TestAbortFrame, sizeof(jmp_buf)); \
+ }
+
+/* This tricky set of defines lets us see if we are using the Spy, returns 1 if true */
+#ifdef __STDC_VERSION__
+
+#if __STDC_VERSION__ >= 199901L
+#define USING_SPY_AS(a) EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0)
+#define ASSIGN_VALUE(a) VAL_##a
+#define VAL_UnityOutputCharSpy_OutputChar 0, 1
+#define EXPAND_AND_USE_2ND(a, b) SECOND_PARAM(a, b, throwaway)
+#define SECOND_PARAM(a, b, ...) b
+#if USING_SPY_AS(UNITY_OUTPUT_CHAR)
+ #define USING_OUTPUT_SPY /* UNITY_OUTPUT_CHAR = UnityOutputCharSpy_OutputChar */
+#endif
+#endif /* >= 199901 */
+
+#else /* __STDC_VERSION__ else */
+#define UnityOutputCharSpy_OutputChar 42
+#if UNITY_OUTPUT_CHAR == UnityOutputCharSpy_OutputChar /* Works if no -Wundef -Werror */
+ #define USING_OUTPUT_SPY
+#endif
+#undef UnityOutputCharSpy_OutputChar
+#endif /* __STDC_VERSION__ */
+
+TEST(LeakDetection, DetectsLeak)
+{
+#ifndef USING_OUTPUT_SPY
+ TEST_IGNORE_MESSAGE("Build with '-D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar' to enable tests");
+#else
+ void* m = malloc(10);
+ TEST_ASSERT_NOT_NULL(m);
+ UnityOutputCharSpy_Enable(1);
+ EXPECT_ABORT_BEGIN
+ UnityMalloc_EndTest();
+ EXPECT_ABORT_END
+ UnityOutputCharSpy_Enable(0);
+ Unity.CurrentTestFailed = 0;
+ CHECK(strstr(UnityOutputCharSpy_Get(), "This test leaks!"));
+ free(m);
+#endif
+}
+
+TEST(LeakDetection, BufferOverrunFoundDuringFree)
+{
+#ifndef USING_OUTPUT_SPY
+ TEST_IGNORE();
+#else
+ void* m = malloc(10);
+ char* s = (char*)m;
+ TEST_ASSERT_NOT_NULL(m);
+ s[10] = (char)0xFF;
+ UnityOutputCharSpy_Enable(1);
+ EXPECT_ABORT_BEGIN
+ free(m);
+ EXPECT_ABORT_END
+ UnityOutputCharSpy_Enable(0);
+ Unity.CurrentTestFailed = 0;
+ CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
+#endif
+}
+
+TEST(LeakDetection, BufferOverrunFoundDuringRealloc)
+{
+#ifndef USING_OUTPUT_SPY
+ TEST_IGNORE();
+#else
+ void* m = malloc(10);
+ char* s = (char*)m;
+ TEST_ASSERT_NOT_NULL(m);
+ s[10] = (char)0xFF;
+ UnityOutputCharSpy_Enable(1);
+ EXPECT_ABORT_BEGIN
+ m = realloc(m, 100);
+ EXPECT_ABORT_END
+ UnityOutputCharSpy_Enable(0);
+ Unity.CurrentTestFailed = 0;
+ CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
+#endif
+}
+
+TEST(LeakDetection, BufferGuardWriteFoundDuringFree)
+{
+#ifndef USING_OUTPUT_SPY
+ TEST_IGNORE();
+#else
+ void* m = malloc(10);
+ char* s = (char*)m;
+ TEST_ASSERT_NOT_NULL(m);
+ s[-1] = (char)0x00; /* Will not detect 0 */
+ s[-2] = (char)0x01;
+ UnityOutputCharSpy_Enable(1);
+ EXPECT_ABORT_BEGIN
+ free(m);
+ EXPECT_ABORT_END
+ UnityOutputCharSpy_Enable(0);
+ Unity.CurrentTestFailed = 0;
+ CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
+#endif
+}
+
+TEST(LeakDetection, BufferGuardWriteFoundDuringRealloc)
+{
+#ifndef USING_OUTPUT_SPY
+ TEST_IGNORE();
+#else
+ void* m = malloc(10);
+ char* s = (char*)m;
+ TEST_ASSERT_NOT_NULL(m);
+ s[-1] = (char)0x0A;
+ UnityOutputCharSpy_Enable(1);
+ EXPECT_ABORT_BEGIN
+ m = realloc(m, 100);
+ EXPECT_ABORT_END
+ UnityOutputCharSpy_Enable(0);
+ Unity.CurrentTestFailed = 0;
+ CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
+#endif
+}
+
+TEST(LeakDetection, PointerSettingMax)
+{
+#ifndef USING_OUTPUT_SPY
+ TEST_IGNORE();
+#else
+ int i;
+ for (i = 0; i < UNITY_MAX_POINTERS; i++) UT_PTR_SET(pointer1, &int1);
+ UnityOutputCharSpy_Enable(1);
+ EXPECT_ABORT_BEGIN
+ UT_PTR_SET(pointer1, &int1);
+ EXPECT_ABORT_END
+ UnityOutputCharSpy_Enable(0);
+ Unity.CurrentTestFailed = 0;
+ CHECK(strstr(UnityOutputCharSpy_Get(), "Too many pointers set"));
+#endif
+}
+
+/*------------------------------------------------------------ */
+
+TEST_GROUP(InternalMalloc);
+#define TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(first_mem_ptr, ptr) \
+ ptr = malloc(10); free(ptr); \
+ TEST_ASSERT_EQUAL_PTR_MESSAGE(first_mem_ptr, ptr, "Memory was stranded, free in LIFO order");
+
+
+TEST_SETUP(InternalMalloc) { }
+TEST_TEAR_DOWN(InternalMalloc) { }
+
+TEST(InternalMalloc, MallocPastBufferFails)
+{
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+ void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
+ void* n = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
+ free(m);
+ TEST_ASSERT_NOT_NULL(m);
+ TEST_ASSERT_NULL(n);
+ TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
+#endif
+}
+
+TEST(InternalMalloc, CallocPastBufferFails)
+{
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+ void* m = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
+ void* n = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
+ free(m);
+ TEST_ASSERT_NOT_NULL(m);
+ TEST_ASSERT_NULL(n);
+ TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
+#endif
+}
+
+TEST(InternalMalloc, MallocThenReallocGrowsMemoryInPlace)
+{
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+ void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
+ void* n = realloc(m, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 9);
+ free(n);
+ TEST_ASSERT_NOT_NULL(m);
+ TEST_ASSERT_EQUAL(m, n);
+ TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
+#endif
+}
+
+TEST(InternalMalloc, ReallocFailDoesNotFreeMem)
+{
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+ void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
+ void* n1 = malloc(10);
+ void* out_of_mem = realloc(n1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
+ void* n2 = malloc(10);
+
+ free(n2);
+ if (out_of_mem == NULL) free(n1);
+ free(m);
+
+ TEST_ASSERT_NOT_NULL(m); /* Got a real memory location */
+ TEST_ASSERT_NULL(out_of_mem); /* The realloc should have failed */
+ TEST_ASSERT_NOT_EQUAL(n2, n1); /* If n1 != n2 then realloc did not free n1 */
+ TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n2);
+#endif
+}
diff --git a/vendor/Unity-2.4.3/extras/fixture/test/unity_fixture_TestRunner.c b/vendor/Unity-2.4.3/extras/fixture/test/unity_fixture_TestRunner.c
new file mode 100644
index 0000000..e8713e1
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/test/unity_fixture_TestRunner.c
@@ -0,0 +1,57 @@
+/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
+ * ==========================================
+ * Unity Project - A Test Framework for C
+ * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ * [Released under MIT License. Please refer to license.txt for details]
+ * ========================================== */
+
+#include "unity_fixture.h"
+
+TEST_GROUP_RUNNER(UnityFixture)
+{
+ RUN_TEST_CASE(UnityFixture, PointerSetting);
+ RUN_TEST_CASE(UnityFixture, ForceMallocFail);
+ RUN_TEST_CASE(UnityFixture, ReallocSmallerIsUnchanged);
+ RUN_TEST_CASE(UnityFixture, ReallocSameIsUnchanged);
+ RUN_TEST_CASE(UnityFixture, ReallocLargerNeeded);
+ RUN_TEST_CASE(UnityFixture, ReallocNullPointerIsLikeMalloc);
+ RUN_TEST_CASE(UnityFixture, ReallocSizeZeroFreesMemAndReturnsNullPointer);
+ RUN_TEST_CASE(UnityFixture, CallocFillsWithZero);
+ RUN_TEST_CASE(UnityFixture, PointerSet);
+ RUN_TEST_CASE(UnityFixture, FreeNULLSafety);
+ RUN_TEST_CASE(UnityFixture, ConcludeTestIncrementsFailCount);
+}
+
+TEST_GROUP_RUNNER(UnityCommandOptions)
+{
+ RUN_TEST_CASE(UnityCommandOptions, DefaultOptions);
+ RUN_TEST_CASE(UnityCommandOptions, OptionVerbose);
+ RUN_TEST_CASE(UnityCommandOptions, OptionSelectTestByGroup);
+ RUN_TEST_CASE(UnityCommandOptions, OptionSelectTestByName);
+ RUN_TEST_CASE(UnityCommandOptions, OptionSelectRepeatTestsDefaultCount);
+ RUN_TEST_CASE(UnityCommandOptions, OptionSelectRepeatTestsSpecificCount);
+ RUN_TEST_CASE(UnityCommandOptions, MultipleOptions);
+ RUN_TEST_CASE(UnityCommandOptions, MultipleOptionsDashRNotLastAndNoValueSpecified);
+ RUN_TEST_CASE(UnityCommandOptions, UnknownCommandIsIgnored);
+ RUN_TEST_CASE(UnityCommandOptions, GroupOrNameFilterWithoutStringFails);
+ RUN_TEST_CASE(UnityCommandOptions, GroupFilterReallyFilters);
+ RUN_TEST_CASE(UnityCommandOptions, TestShouldBeIgnored);
+}
+
+TEST_GROUP_RUNNER(LeakDetection)
+{
+ RUN_TEST_CASE(LeakDetection, DetectsLeak);
+ RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringFree);
+ RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringRealloc);
+ RUN_TEST_CASE(LeakDetection, BufferGuardWriteFoundDuringFree);
+ RUN_TEST_CASE(LeakDetection, BufferGuardWriteFoundDuringRealloc);
+ RUN_TEST_CASE(LeakDetection, PointerSettingMax);
+}
+
+TEST_GROUP_RUNNER(InternalMalloc)
+{
+ RUN_TEST_CASE(InternalMalloc, MallocPastBufferFails);
+ RUN_TEST_CASE(InternalMalloc, CallocPastBufferFails);
+ RUN_TEST_CASE(InternalMalloc, MallocThenReallocGrowsMemoryInPlace);
+ RUN_TEST_CASE(InternalMalloc, ReallocFailDoesNotFreeMem);
+}
diff --git a/vendor/Unity-2.4.3/extras/fixture/test/unity_output_Spy.c b/vendor/Unity-2.4.3/extras/fixture/test/unity_output_Spy.c
new file mode 100644
index 0000000..be87bd5
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/test/unity_output_Spy.c
@@ -0,0 +1,57 @@
+/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
+ * ==========================================
+ * Unity Project - A Test Framework for C
+ * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ * [Released under MIT License. Please refer to license.txt for details]
+ * ========================================== */
+
+
+#include "unity_output_Spy.h"
+#include "unity_fixture.h"
+
+#include <stdio.h>
+#include <string.h>
+
+static int size;
+static int count;
+static char* buffer;
+static int spy_enable;
+
+void UnityOutputCharSpy_Create(int s)
+{
+ size = (s > 0) ? s : 0;
+ count = 0;
+ spy_enable = 0;
+ buffer = malloc((size_t)size);
+ TEST_ASSERT_NOT_NULL_MESSAGE(buffer, "Internal malloc failed in Spy Create():" __FILE__);
+ memset(buffer, 0, (size_t)size);
+}
+
+void UnityOutputCharSpy_Destroy(void)
+{
+ size = 0;
+ free(buffer);
+}
+
+void UnityOutputCharSpy_OutputChar(int c)
+{
+ if (spy_enable)
+ {
+ if (count < (size-1))
+ buffer[count++] = (char)c;
+ }
+ else
+ {
+ putchar(c);
+ }
+}
+
+const char * UnityOutputCharSpy_Get(void)
+{
+ return buffer;
+}
+
+void UnityOutputCharSpy_Enable(int enable)
+{
+ spy_enable = enable;
+}
diff --git a/vendor/Unity-2.4.3/extras/fixture/test/unity_output_Spy.h b/vendor/Unity-2.4.3/extras/fixture/test/unity_output_Spy.h
new file mode 100644
index 0000000..b30a7f1
--- /dev/null
+++ b/vendor/Unity-2.4.3/extras/fixture/test/unity_output_Spy.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
+ * ==========================================
+ * Unity Project - A Test Framework for C
+ * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ * [Released under MIT License. Please refer to license.txt for details]
+ * ========================================== */
+
+#ifndef D_unity_output_Spy_H
+#define D_unity_output_Spy_H
+
+void UnityOutputCharSpy_Create(int s);
+void UnityOutputCharSpy_Destroy(void);
+void UnityOutputCharSpy_OutputChar(int c);
+const char * UnityOutputCharSpy_Get(void);
+void UnityOutputCharSpy_Enable(int enable);
+
+#endif
diff --git a/vendor/Unity-2.4.3/release/build.info b/vendor/Unity-2.4.3/release/build.info
new file mode 100644
index 0000000..56d5912
--- /dev/null
+++ b/vendor/Unity-2.4.3/release/build.info
@@ -0,0 +1,2 @@
+122
+
diff --git a/vendor/Unity-2.4.3/release/version.info b/vendor/Unity-2.4.3/release/version.info
new file mode 100644
index 0000000..cf12b30
--- /dev/null
+++ b/vendor/Unity-2.4.3/release/version.info
@@ -0,0 +1,2 @@
+2.4.3
+
diff --git a/vendor/Unity-2.4.3/src/unity.c b/vendor/Unity-2.4.3/src/unity.c
new file mode 100644
index 0000000..0f2d2de
--- /dev/null
+++ b/vendor/Unity-2.4.3/src/unity.c
@@ -0,0 +1,1570 @@
+/* =========================================================================
+ Unity Project - A Test Framework for C
+ Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+============================================================================ */
+
+#define UNITY_INCLUDE_SETUP_STUBS
+#include "unity.h"
+#include <stddef.h>
+
+/* If omitted from header, declare overrideable prototypes here so they're ready for use */
+#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION
+void UNITY_OUTPUT_CHAR(int);
+#endif
+
+/* Helpful macros for us to use here in Assert functions */
+#define UNITY_FAIL_AND_BAIL { Unity.CurrentTestFailed = 1; TEST_ABORT(); }
+#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; TEST_ABORT(); }
+#define RETURN_IF_FAIL_OR_IGNORE if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) return
+
+struct UNITY_STORAGE_T Unity;
+
+#ifdef UNITY_OUTPUT_COLOR
+static const char UnityStrOk[] = "\033[42mOK\033[00m";
+static const char UnityStrPass[] = "\033[42mPASS\033[00m";
+static const char UnityStrFail[] = "\033[41mFAIL\033[00m";
+static const char UnityStrIgnore[] = "\033[43mIGNORE\033[00m";
+#else
+static const char UnityStrOk[] = "OK";
+static const char UnityStrPass[] = "PASS";
+static const char UnityStrFail[] = "FAIL";
+static const char UnityStrIgnore[] = "IGNORE";
+#endif
+static const char UnityStrNull[] = "NULL";
+static const char UnityStrSpacer[] = ". ";
+static const char UnityStrExpected[] = " Expected ";
+static const char UnityStrWas[] = " Was ";
+static const char UnityStrGt[] = " to be greater than ";
+static const char UnityStrLt[] = " to be less than ";
+static const char UnityStrOrEqual[] = "or equal to ";
+static const char UnityStrElement[] = " Element ";
+static const char UnityStrByte[] = " Byte ";
+static const char UnityStrMemory[] = " Memory Mismatch.";
+static const char UnityStrDelta[] = " Values Not Within Delta ";
+static const char UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless.";
+static const char UnityStrNullPointerForExpected[] = " Expected pointer to be NULL";
+static const char UnityStrNullPointerForActual[] = " Actual pointer was NULL";
+#ifndef UNITY_EXCLUDE_FLOAT
+static const char UnityStrNot[] = "Not ";
+static const char UnityStrInf[] = "Infinity";
+static const char UnityStrNegInf[] = "Negative Infinity";
+static const char UnityStrNaN[] = "NaN";
+static const char UnityStrDet[] = "Determinate";
+static const char UnityStrInvalidFloatTrait[] = "Invalid Float Trait";
+#endif
+const char UnityStrErrFloat[] = "Unity Floating Point Disabled";
+const char UnityStrErrDouble[] = "Unity Double Precision Disabled";
+const char UnityStrErr64[] = "Unity 64-bit Support Disabled";
+static const char UnityStrBreaker[] = "-----------------------";
+static const char UnityStrResultsTests[] = " Tests ";
+static const char UnityStrResultsFailures[] = " Failures ";
+static const char UnityStrResultsIgnored[] = " Ignored ";
+static const char UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " ";
+static const char UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " ";
+
+/*-----------------------------------------------
+ * Pretty Printers & Test Result Output Handlers
+ *-----------------------------------------------*/
+
+void UnityPrint(const char* string)
+{
+ const char* pch = string;
+
+ if (pch != NULL)
+ {
+ while (*pch)
+ {
+ /* printable characters plus CR & LF are printed */
+ if ((*pch <= 126) && (*pch >= 32))
+ {
+ UNITY_OUTPUT_CHAR(*pch);
+ }
+ /* write escaped carriage returns */
+ else if (*pch == 13)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('r');
+ }
+ /* write escaped line feeds */
+ else if (*pch == 10)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('n');
+ }
+#ifdef UNITY_OUTPUT_COLOR
+ /* print ANSI escape code */
+ else if (*pch == 27 && *(pch + 1) == '[')
+ {
+ while (*pch && *pch != 'm')
+ {
+ UNITY_OUTPUT_CHAR(*pch);
+ pch++;
+ }
+ UNITY_OUTPUT_CHAR('m');
+ }
+#endif
+ /* unprintable characters are shown as codes */
+ else
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)*pch, 2);
+ }
+ pch++;
+ }
+ }
+}
+
+void UnityPrintLen(const char* string, const UNITY_UINT32 length)
+{
+ const char* pch = string;
+
+ if (pch != NULL)
+ {
+ while (*pch && (UNITY_UINT32)(pch - string) < length)
+ {
+ /* printable characters plus CR & LF are printed */
+ if ((*pch <= 126) && (*pch >= 32))
+ {
+ UNITY_OUTPUT_CHAR(*pch);
+ }
+ /* write escaped carriage returns */
+ else if (*pch == 13)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('r');
+ }
+ /* write escaped line feeds */
+ else if (*pch == 10)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('n');
+ }
+ /* unprintable characters are shown as codes */
+ else
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)*pch, 2);
+ }
+ pch++;
+ }
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style)
+{
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ UnityPrintNumber(number);
+ }
+ else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT)
+ {
+ UnityPrintNumberUnsigned((UNITY_UINT)number);
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('0');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2));
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumber(const UNITY_INT number_to_print)
+{
+ UNITY_UINT number = (UNITY_UINT)number_to_print;
+
+ if (number_to_print < 0)
+ {
+ /* A negative number, including MIN negative */
+ UNITY_OUTPUT_CHAR('-');
+ number = (UNITY_UINT)(-number_to_print);
+ }
+ UnityPrintNumberUnsigned(number);
+}
+
+/*-----------------------------------------------
+ * basically do an itoa using as little ram as possible */
+void UnityPrintNumberUnsigned(const UNITY_UINT number)
+{
+ UNITY_UINT divisor = 1;
+
+ /* figure out initial divisor */
+ while (number / divisor > 9)
+ {
+ divisor *= 10;
+ }
+
+ /* now mod and print, then divide divisor */
+ do
+ {
+ UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10)));
+ divisor /= 10;
+ } while (divisor > 0);
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print)
+{
+ int nibble;
+ char nibbles = nibbles_to_print;
+ if ((unsigned)nibbles > (2 * sizeof(number)))
+ nibbles = 2 * sizeof(number);
+
+ while (nibbles > 0)
+ {
+ nibbles--;
+ nibble = (int)(number >> (nibbles * 4)) & 0x0F;
+ if (nibble <= 9)
+ {
+ UNITY_OUTPUT_CHAR((char)('0' + nibble));
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble));
+ }
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number)
+{
+ UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1);
+ UNITY_INT32 i;
+
+ for (i = 0; i < UNITY_INT_WIDTH; i++)
+ {
+ if (current_bit & mask)
+ {
+ if (current_bit & number)
+ {
+ UNITY_OUTPUT_CHAR('1');
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('0');
+ }
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('X');
+ }
+ current_bit = current_bit >> 1;
+ }
+}
+
+/*-----------------------------------------------*/
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+/* This function prints a floating-point value in a format similar to
+ * printf("%.6g"). It can work with either single- or double-precision,
+ * but for simplicity, it prints only 6 significant digits in either case.
+ * Printing more than 6 digits accurately is hard (at least in the single-
+ * precision case) and isn't attempted here. */
+void UnityPrintFloat(const UNITY_DOUBLE input_number)
+{
+ UNITY_DOUBLE number = input_number;
+
+ /* print minus sign (including for negative zero) */
+ if (number < 0.0f || (number == 0.0f && 1.0f / number < 0.0f))
+ {
+ UNITY_OUTPUT_CHAR('-');
+ number = -number;
+ }
+
+ /* handle zero, NaN, and +/- infinity */
+ if (number == 0.0f) UnityPrint("0");
+ else if (isnan(number)) UnityPrint("nan");
+ else if (isinf(number)) UnityPrint("inf");
+ else
+ {
+ int exponent = 0;
+ int decimals, digits;
+ UNITY_INT32 n;
+ char buf[16];
+
+ /* scale up or down by powers of 10 */
+ while (number < 100000.0f / 1e6f) { number *= 1e6f; exponent -= 6; }
+ while (number < 100000.0f) { number *= 10.0f; exponent--; }
+ while (number > 1000000.0f * 1e6f) { number /= 1e6f; exponent += 6; }
+ while (number > 1000000.0f) { number /= 10.0f; exponent++; }
+
+ /* round to nearest integer */
+ n = ((UNITY_INT32)(number + number) + 1) / 2;
+ if (n > 999999)
+ {
+ n = 100000;
+ exponent++;
+ }
+
+ /* determine where to place decimal point */
+ decimals = (exponent <= 0 && exponent >= -9) ? -exponent : 5;
+ exponent += decimals;
+
+ /* truncate trailing zeroes after decimal point */
+ while (decimals > 0 && n % 10 == 0)
+ {
+ n /= 10;
+ decimals--;
+ }
+
+ /* build up buffer in reverse order */
+ digits = 0;
+ while (n != 0 || digits < decimals + 1)
+ {
+ buf[digits++] = (char)('0' + n % 10);
+ n /= 10;
+ }
+ while (digits > 0)
+ {
+ if(digits == decimals) UNITY_OUTPUT_CHAR('.');
+ UNITY_OUTPUT_CHAR(buf[--digits]);
+ }
+
+ /* print exponent if needed */
+ if (exponent != 0)
+ {
+ UNITY_OUTPUT_CHAR('e');
+
+ if(exponent < 0)
+ {
+ UNITY_OUTPUT_CHAR('-');
+ exponent = -exponent;
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('+');
+ }
+
+ digits = 0;
+ while (exponent != 0 || digits < 2)
+ {
+ buf[digits++] = (char)('0' + exponent % 10);
+ exponent /= 10;
+ }
+ while (digits > 0)
+ {
+ UNITY_OUTPUT_CHAR(buf[--digits]);
+ }
+ }
+ }
+}
+#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */
+
+/*-----------------------------------------------*/
+static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line)
+{
+ UnityPrint(file);
+ UNITY_OUTPUT_CHAR(':');
+ UnityPrintNumber((UNITY_INT)line);
+ UNITY_OUTPUT_CHAR(':');
+ UnityPrint(Unity.CurrentTestName);
+ UNITY_OUTPUT_CHAR(':');
+}
+
+/*-----------------------------------------------*/
+static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line)
+{
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint(UnityStrFail);
+ UNITY_OUTPUT_CHAR(':');
+}
+
+/*-----------------------------------------------*/
+void UnityConcludeTest(void)
+{
+ if (Unity.CurrentTestIgnored)
+ {
+ Unity.TestIgnores++;
+ }
+ else if (!Unity.CurrentTestFailed)
+ {
+ UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber);
+ UnityPrint(UnityStrPass);
+ }
+ else
+ {
+ Unity.TestFailures++;
+ }
+
+ Unity.CurrentTestFailed = 0;
+ Unity.CurrentTestIgnored = 0;
+ UNITY_PRINT_EOL();
+ UNITY_FLUSH_CALL();
+}
+
+/*-----------------------------------------------*/
+static void UnityAddMsgIfSpecified(const char* msg)
+{
+ if (msg)
+ {
+ UnityPrint(UnityStrSpacer);
+#ifndef UNITY_EXCLUDE_DETAILS
+ if (Unity.CurrentDetail1)
+ {
+ UnityPrint(UnityStrDetail1Name);
+ UnityPrint(Unity.CurrentDetail1);
+ if (Unity.CurrentDetail2)
+ {
+ UnityPrint(UnityStrDetail2Name);
+ UnityPrint(Unity.CurrentDetail2);
+ }
+ UnityPrint(UnityStrSpacer);
+ }
+#endif
+ UnityPrint(msg);
+ }
+}
+
+/*-----------------------------------------------*/
+static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual)
+{
+ UnityPrint(UnityStrExpected);
+ if (expected != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrint(expected);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+ UnityPrint(UnityStrWas);
+ if (actual != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrint(actual);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+}
+
+/*-----------------------------------------------*/
+static void UnityPrintExpectedAndActualStringsLen(const char* expected,
+ const char* actual,
+ const UNITY_UINT32 length)
+{
+ UnityPrint(UnityStrExpected);
+ if (expected != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrintLen(expected, length);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+ UnityPrint(UnityStrWas);
+ if (actual != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrintLen(actual, length);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+}
+
+/*-----------------------------------------------
+ * Assertion & Control Helpers
+ *-----------------------------------------------*/
+
+static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_LINE_TYPE lineNumber,
+ const char* msg)
+{
+ if (expected == actual) return 0; /* Both are NULL or same pointer */
+
+ /* print and return true if just expected is NULL */
+ if (expected == NULL)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrNullPointerForExpected);
+ UnityAddMsgIfSpecified(msg);
+ return 1;
+ }
+
+ /* print and return true if just actual is NULL */
+ if (actual == NULL)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrNullPointerForActual);
+ UnityAddMsgIfSpecified(msg);
+ return 1;
+ }
+
+ return 0; /* return false if neither is NULL */
+}
+
+/*-----------------------------------------------
+ * Assertion Functions
+ *-----------------------------------------------*/
+
+void UnityAssertBits(const UNITY_INT mask,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if ((mask & expected) != (mask & actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected);
+ UnityPrint(UnityStrWas);
+ UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualNumber(const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (expected != actual)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(expected, style);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(actual, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold,
+ const UNITY_INT actual,
+ const UNITY_COMPARISON_T compare,
+ const char *msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style)
+{
+ int failed = 0;
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (threshold == actual && compare & UNITY_EQUAL_TO) return;
+ if (threshold == actual) failed = 1;
+
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ if (actual > threshold && compare & UNITY_SMALLER_THAN) failed = 1;
+ if (actual < threshold && compare & UNITY_GREATER_THAN) failed = 1;
+ }
+ else /* UINT or HEX */
+ {
+ if ((UNITY_UINT)actual > (UNITY_UINT)threshold && compare & UNITY_SMALLER_THAN) failed = 1;
+ if ((UNITY_UINT)actual < (UNITY_UINT)threshold && compare & UNITY_GREATER_THAN) failed = 1;
+ }
+
+ if (failed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(actual, style);
+ if (compare & UNITY_GREATER_THAN) UnityPrint(UnityStrGt);
+ if (compare & UNITY_SMALLER_THAN) UnityPrint(UnityStrLt);
+ if (compare & UNITY_EQUAL_TO) UnityPrint(UnityStrOrEqual);
+ UnityPrintNumberByStyle(threshold, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+#define UnityPrintPointlessAndBail() \
+{ \
+ UnityTestResultsFailBegin(lineNumber); \
+ UnityPrint(UnityStrPointless); \
+ UnityAddMsgIfSpecified(msg); \
+ UNITY_FAIL_AND_BAIL; }
+
+/*-----------------------------------------------*/
+void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 elements = num_elements;
+ unsigned int length = style & 0xF;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (num_elements == 0)
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual) return; /* Both are NULL or same pointer */
+ if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
+ UNITY_FAIL_AND_BAIL;
+
+ while (elements--)
+ {
+ UNITY_INT expect_val;
+ UNITY_INT actual_val;
+ switch (length)
+ {
+ case 1:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual;
+ break;
+ case 2:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual;
+ break;
+#ifdef UNITY_SUPPORT_64
+ case 8:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual;
+ break;
+#endif
+ default: /* length 4 bytes */
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual;
+ length = 4;
+ break;
+ }
+
+ if (expect_val != actual_val)
+ {
+ if (style & UNITY_DISPLAY_RANGE_UINT && length < sizeof(expect_val))
+ { /* For UINT, remove sign extension (padding 1's) from signed type casts above */
+ UNITY_INT mask = 1;
+ mask = (mask << 8 * length) - 1;
+ expect_val &= mask;
+ actual_val &= mask;
+ }
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(expect_val, style);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(actual_val, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ expected = (UNITY_INTERNAL_PTR)(length + (const char*)expected);
+ }
+ actual = (UNITY_INTERNAL_PTR)(length + (const char*)actual);
+ }
+}
+
+/*-----------------------------------------------*/
+#ifndef UNITY_EXCLUDE_FLOAT
+/* Wrap this define in a function with variable types as float or double */
+#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \
+ if (isinf(expected) && isinf(actual) && ((expected < 0) == (actual < 0))) return 1; \
+ if (UNITY_NAN_CHECK) return 1; \
+ diff = actual - expected; \
+ if (diff < 0) diff = -diff; \
+ if (delta < 0) delta = -delta; \
+ return !(isnan(diff) || isinf(diff) || (diff > delta))
+ /* This first part of this condition will catch any NaN or Infinite values */
+#ifndef UNITY_NAN_NOT_EQUAL_NAN
+ #define UNITY_NAN_CHECK isnan(expected) && isnan(actual)
+#else
+ #define UNITY_NAN_CHECK 0
+#endif
+
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+ #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \
+ { \
+ UnityPrint(UnityStrExpected); \
+ UnityPrintFloat(expected); \
+ UnityPrint(UnityStrWas); \
+ UnityPrintFloat(actual); }
+#else
+ #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \
+ UnityPrint(UnityStrDelta)
+#endif /* UNITY_EXCLUDE_FLOAT_PRINT */
+
+static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual)
+{
+ UNITY_FLOAT diff;
+ UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff);
+}
+
+void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 elements = num_elements;
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected;
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (elements == 0)
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual) return; /* Both are NULL or same pointer */
+ if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
+ UNITY_FAIL_AND_BAIL;
+
+ while (elements--)
+ {
+ if (!UnityFloatsWithin(*ptr_expected * UNITY_FLOAT_PRECISION, *ptr_expected, *ptr_actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ ptr_expected++;
+ }
+ ptr_actual++;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertFloatsWithin(const UNITY_FLOAT delta,
+ const UNITY_FLOAT expected,
+ const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+
+ if (!UnityFloatsWithin(delta, expected, actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style)
+{
+ const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet};
+ UNITY_INT should_be_trait = ((UNITY_INT)style & 1);
+ UNITY_INT is_trait = !should_be_trait;
+ UNITY_INT trait_index = (UNITY_INT)(style >> 1);
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ switch (style)
+ {
+ case UNITY_FLOAT_IS_INF:
+ case UNITY_FLOAT_IS_NOT_INF:
+ is_trait = isinf(actual) && (actual > 0);
+ break;
+ case UNITY_FLOAT_IS_NEG_INF:
+ case UNITY_FLOAT_IS_NOT_NEG_INF:
+ is_trait = isinf(actual) && (actual < 0);
+ break;
+
+ case UNITY_FLOAT_IS_NAN:
+ case UNITY_FLOAT_IS_NOT_NAN:
+ is_trait = isnan(actual) ? 1 : 0;
+ break;
+
+ case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */
+ case UNITY_FLOAT_IS_NOT_DET:
+ is_trait = !isinf(actual) && !isnan(actual);
+ break;
+
+ default:
+ trait_index = 0;
+ trait_names[0] = UnityStrInvalidFloatTrait;
+ break;
+ }
+
+ if (is_trait != should_be_trait)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ if (!should_be_trait)
+ UnityPrint(UnityStrNot);
+ UnityPrint(trait_names[trait_index]);
+ UnityPrint(UnityStrWas);
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+ UnityPrintFloat((UNITY_DOUBLE)actual);
+#else
+ if (should_be_trait)
+ UnityPrint(UnityStrNot);
+ UnityPrint(trait_names[trait_index]);
+#endif
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+#endif /* not UNITY_EXCLUDE_FLOAT */
+
+/*-----------------------------------------------*/
+#ifndef UNITY_EXCLUDE_DOUBLE
+static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual)
+{
+ UNITY_DOUBLE diff;
+ UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff);
+}
+
+void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 elements = num_elements;
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected;
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (elements == 0)
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual) return; /* Both are NULL or same pointer */
+ if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
+ UNITY_FAIL_AND_BAIL;
+
+ while (elements--)
+ {
+ if (!UnityDoublesWithin(*ptr_expected * UNITY_DOUBLE_PRECISION, *ptr_expected, *ptr_actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ ptr_expected++;
+ }
+ ptr_actual++;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertDoublesWithin(const UNITY_DOUBLE delta,
+ const UNITY_DOUBLE expected,
+ const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (!UnityDoublesWithin(delta, expected, actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+
+void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style)
+{
+ const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet};
+ UNITY_INT should_be_trait = ((UNITY_INT)style & 1);
+ UNITY_INT is_trait = !should_be_trait;
+ UNITY_INT trait_index = (UNITY_INT)(style >> 1);
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ switch (style)
+ {
+ case UNITY_FLOAT_IS_INF:
+ case UNITY_FLOAT_IS_NOT_INF:
+ is_trait = isinf(actual) && (actual > 0);
+ break;
+ case UNITY_FLOAT_IS_NEG_INF:
+ case UNITY_FLOAT_IS_NOT_NEG_INF:
+ is_trait = isinf(actual) && (actual < 0);
+ break;
+
+ case UNITY_FLOAT_IS_NAN:
+ case UNITY_FLOAT_IS_NOT_NAN:
+ is_trait = isnan(actual) ? 1 : 0;
+ break;
+
+ case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */
+ case UNITY_FLOAT_IS_NOT_DET:
+ is_trait = !isinf(actual) && !isnan(actual);
+ break;
+
+ default:
+ trait_index = 0;
+ trait_names[0] = UnityStrInvalidFloatTrait;
+ break;
+ }
+
+ if (is_trait != should_be_trait)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ if (!should_be_trait)
+ UnityPrint(UnityStrNot);
+ UnityPrint(trait_names[trait_index]);
+ UnityPrint(UnityStrWas);
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+ UnityPrintFloat(actual);
+#else
+ if (should_be_trait)
+ UnityPrint(UnityStrNot);
+ UnityPrint(trait_names[trait_index]);
+#endif
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+#endif /* not UNITY_EXCLUDE_DOUBLE */
+
+/*-----------------------------------------------*/
+void UnityAssertNumbersWithin(const UNITY_UINT delta,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ if (actual > expected)
+ Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta);
+ else
+ Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta);
+ }
+ else
+ {
+ if ((UNITY_UINT)actual > (UNITY_UINT)expected)
+ Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta);
+ else
+ Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta);
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrDelta);
+ UnityPrintNumberByStyle((UNITY_INT)delta, style);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(expected, style);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(actual, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualString(const char* expected,
+ const char* actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ UNITY_UINT32 i;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ /* if both pointers not null compare the strings */
+ if (expected && actual)
+ {
+ for (i = 0; expected[i] || actual[i]; i++)
+ {
+ if (expected[i] != actual[i])
+ {
+ Unity.CurrentTestFailed = 1;
+ break;
+ }
+ }
+ }
+ else
+ { /* handle case of one pointers being null (if both null, test should pass) */
+ if (expected != actual)
+ {
+ Unity.CurrentTestFailed = 1;
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrintExpectedAndActualStrings(expected, actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualStringLen(const char* expected,
+ const char* actual,
+ const UNITY_UINT32 length,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ UNITY_UINT32 i;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ /* if both pointers not null compare the strings */
+ if (expected && actual)
+ {
+ for (i = 0; (i < length) && (expected[i] || actual[i]); i++)
+ {
+ if (expected[i] != actual[i])
+ {
+ Unity.CurrentTestFailed = 1;
+ break;
+ }
+ }
+ }
+ else
+ { /* handle case of one pointers being null (if both null, test should pass) */
+ if (expected != actual)
+ {
+ Unity.CurrentTestFailed = 1;
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrintExpectedAndActualStringsLen(expected, actual, length);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected,
+ const char** actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 i = 0;
+ UNITY_UINT32 j = 0;
+ const char* expd = NULL;
+ const char* act = NULL;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ /* if no elements, it's an error */
+ if (num_elements == 0)
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if ((const void*)expected == (const void*)actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ if (flags != UNITY_ARRAY_TO_ARRAY)
+ {
+ expd = (const char*)expected;
+ }
+
+ do
+ {
+ act = actual[j];
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ expd = ((const char* const*)expected)[j];
+ }
+
+ /* if both pointers not null compare the strings */
+ if (expd && act)
+ {
+ for (i = 0; expd[i] || act[i]; i++)
+ {
+ if (expd[i] != act[i])
+ {
+ Unity.CurrentTestFailed = 1;
+ break;
+ }
+ }
+ }
+ else
+ { /* handle case of one pointers being null (if both null, test should pass) */
+ if (expd != act)
+ {
+ Unity.CurrentTestFailed = 1;
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ if (num_elements > 1)
+ {
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(j);
+ }
+ UnityPrintExpectedAndActualStrings(expd, act);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ } while (++j < num_elements);
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 length,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected;
+ UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual;
+ UNITY_UINT32 elements = num_elements;
+ UNITY_UINT32 bytes;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if ((elements == 0) || (length == 0))
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual) return; /* Both are NULL or same pointer */
+ if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
+ UNITY_FAIL_AND_BAIL;
+
+ while (elements--)
+ {
+ bytes = length;
+ while (bytes--)
+ {
+ if (*ptr_exp != *ptr_act)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrMemory);
+ if (num_elements > 1)
+ {
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ }
+ UnityPrint(UnityStrByte);
+ UnityPrintNumberUnsigned(length - bytes - 1);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ ptr_exp++;
+ ptr_act++;
+ }
+ if (flags == UNITY_ARRAY_TO_VAL)
+ {
+ ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected;
+ }
+ }
+}
+
+/*-----------------------------------------------*/
+
+static union
+{
+ UNITY_INT8 i8;
+ UNITY_INT16 i16;
+ UNITY_INT32 i32;
+#ifdef UNITY_SUPPORT_64
+ UNITY_INT64 i64;
+#endif
+#ifndef UNITY_EXCLUDE_FLOAT
+ float f;
+#endif
+#ifndef UNITY_EXCLUDE_DOUBLE
+ double d;
+#endif
+} UnityQuickCompare;
+
+UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size)
+{
+ switch(size)
+ {
+ case 1:
+ UnityQuickCompare.i8 = (UNITY_INT8)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8);
+
+ case 2:
+ UnityQuickCompare.i16 = (UNITY_INT16)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16);
+
+#ifdef UNITY_SUPPORT_64
+ case 8:
+ UnityQuickCompare.i64 = (UNITY_INT64)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64);
+#endif
+ default: /* 4 bytes */
+ UnityQuickCompare.i32 = (UNITY_INT32)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32);
+ }
+}
+
+#ifndef UNITY_EXCLUDE_FLOAT
+UNITY_INTERNAL_PTR UnityFloatToPtr(const float num)
+{
+ UnityQuickCompare.f = num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f);
+}
+#endif
+
+#ifndef UNITY_EXCLUDE_DOUBLE
+UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num)
+{
+ UnityQuickCompare.d = num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d);
+}
+#endif
+
+/*-----------------------------------------------
+ * Control Functions
+ *-----------------------------------------------*/
+
+void UnityFail(const char* msg, const UNITY_LINE_TYPE line)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint(UnityStrFail);
+ if (msg != NULL)
+ {
+ UNITY_OUTPUT_CHAR(':');
+
+#ifndef UNITY_EXCLUDE_DETAILS
+ if (Unity.CurrentDetail1)
+ {
+ UnityPrint(UnityStrDetail1Name);
+ UnityPrint(Unity.CurrentDetail1);
+ if (Unity.CurrentDetail2)
+ {
+ UnityPrint(UnityStrDetail2Name);
+ UnityPrint(Unity.CurrentDetail2);
+ }
+ UnityPrint(UnityStrSpacer);
+ }
+#endif
+ if (msg[0] != ' ')
+ {
+ UNITY_OUTPUT_CHAR(' ');
+ }
+ UnityPrint(msg);
+ }
+
+ UNITY_FAIL_AND_BAIL;
+}
+
+/*-----------------------------------------------*/
+void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint(UnityStrIgnore);
+ if (msg != NULL)
+ {
+ UNITY_OUTPUT_CHAR(':');
+ UNITY_OUTPUT_CHAR(' ');
+ UnityPrint(msg);
+ }
+ UNITY_IGNORE_AND_BAIL;
+}
+
+/*-----------------------------------------------*/
+void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum)
+{
+ Unity.CurrentTestName = FuncName;
+ Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum;
+ Unity.NumberOfTests++;
+ UNITY_CLR_DETAILS();
+ if (TEST_PROTECT())
+ {
+ setUp();
+ Func();
+ }
+ if (TEST_PROTECT())
+ {
+ tearDown();
+ }
+ UnityConcludeTest();
+}
+
+/*-----------------------------------------------*/
+void UnityBegin(const char* filename)
+{
+ Unity.TestFile = filename;
+ Unity.CurrentTestName = NULL;
+ Unity.CurrentTestLineNumber = 0;
+ Unity.NumberOfTests = 0;
+ Unity.TestFailures = 0;
+ Unity.TestIgnores = 0;
+ Unity.CurrentTestFailed = 0;
+ Unity.CurrentTestIgnored = 0;
+
+ UNITY_CLR_DETAILS();
+ UNITY_OUTPUT_START();
+}
+
+/*-----------------------------------------------*/
+int UnityEnd(void)
+{
+ UNITY_PRINT_EOL();
+ UnityPrint(UnityStrBreaker);
+ UNITY_PRINT_EOL();
+ UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests));
+ UnityPrint(UnityStrResultsTests);
+ UnityPrintNumber((UNITY_INT)(Unity.TestFailures));
+ UnityPrint(UnityStrResultsFailures);
+ UnityPrintNumber((UNITY_INT)(Unity.TestIgnores));
+ UnityPrint(UnityStrResultsIgnored);
+ UNITY_PRINT_EOL();
+ if (Unity.TestFailures == 0U)
+ {
+ UnityPrint(UnityStrOk);
+ }
+ else
+ {
+ UnityPrint(UnityStrFail);
+#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL
+ UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D');
+#endif
+ }
+ UNITY_PRINT_EOL();
+ UNITY_FLUSH_CALL();
+ UNITY_OUTPUT_COMPLETE();
+ return (int)(Unity.TestFailures);
+}
+
+/*-----------------------------------------------
+ * Command Line Argument Support
+ *-----------------------------------------------*/
+#ifdef UNITY_USE_COMMAND_LINE_ARGS
+
+char* UnityOptionIncludeNamed = NULL;
+char* UnityOptionExcludeNamed = NULL;
+int UnityVerbosity = 1;
+
+int UnityParseOptions(int argc, char** argv)
+{
+ UnityOptionIncludeNamed = NULL;
+ UnityOptionExcludeNamed = NULL;
+
+ for (int i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'l': /* list tests */
+ return -1;
+ case 'n': /* include tests with name including this string */
+ case 'f': /* an alias for -n */
+ if (argv[i][2] == '=')
+ UnityOptionIncludeNamed = &argv[i][3];
+ else if (++i < argc)
+ UnityOptionIncludeNamed = argv[i];
+ else
+ {
+ UnityPrint("ERROR: No Test String to Include Matches For");
+ UNITY_PRINT_EOL();
+ return 1;
+ }
+ break;
+ case 'q': /* quiet */
+ UnityVerbosity = 0;
+ break;
+ case 'v': /* verbose */
+ UnityVerbosity = 2;
+ break;
+ case 'x': /* exclude tests with name including this string */
+ if (argv[i][2] == '=')
+ UnityOptionExcludeNamed = &argv[i][3];
+ else if (++i < argc)
+ UnityOptionExcludeNamed = argv[i];
+ else
+ {
+ UnityPrint("ERROR: No Test String to Exclude Matches For");
+ UNITY_PRINT_EOL();
+ return 1;
+ }
+ break;
+ default:
+ UnityPrint("ERROR: Unknown Option ");
+ UNITY_OUTPUT_CHAR(argv[i][1]);
+ UNITY_PRINT_EOL();
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int IsStringInBiggerString(const char* longstring, const char* shortstring)
+{
+ const char* lptr = longstring;
+ const char* sptr = shortstring;
+ const char* lnext = lptr;
+
+ if (*sptr == '*')
+ return 1;
+
+ while (*lptr)
+ {
+ lnext = lptr + 1;
+
+ /* If they current bytes match, go on to the next bytes */
+ while (*lptr && *sptr && (*lptr == *sptr))
+ {
+ lptr++;
+ sptr++;
+
+ /* We're done if we match the entire string or up to a wildcard */
+ if (*sptr == '*')
+ return 1;
+ if (*sptr == ',')
+ return 1;
+ if (*sptr == '"')
+ return 1;
+ if (*sptr == '\'')
+ return 1;
+ if (*sptr == ':')
+ return 2;
+ if (*sptr == 0)
+ return 1;
+ }
+
+ /* Otherwise we start in the long pointer 1 character further and try again */
+ lptr = lnext;
+ sptr = shortstring;
+ }
+ return 0;
+}
+
+int UnityStringArgumentMatches(const char* str)
+{
+ int retval;
+ const char* ptr1;
+ const char* ptr2;
+ const char* ptrf;
+
+ /* Go through the options and get the substrings for matching one at a time */
+ ptr1 = str;
+ while (ptr1[0] != 0)
+ {
+ if ((ptr1[0] == '"') || (ptr1[0] == '\''))
+ ptr1++;
+
+ /* look for the start of the next partial */
+ ptr2 = ptr1;
+ ptrf = 0;
+ do
+ {
+ ptr2++;
+ if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ','))
+ ptrf = &ptr2[1];
+ } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ','));
+ while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ',')))
+ ptr2++;
+
+ /* done if complete filename match */
+ retval = IsStringInBiggerString(Unity.TestFile, ptr1);
+ if (retval == 1)
+ return retval;
+
+ /* done if testname match after filename partial match */
+ if ((retval == 2) && (ptrf != 0))
+ {
+ if (IsStringInBiggerString(Unity.CurrentTestName, ptrf))
+ return 1;
+ }
+
+ /* done if complete testname match */
+ if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1)
+ return 1;
+
+ ptr1 = ptr2;
+ }
+
+ /* we couldn't find a match for any substrings */
+ return 0;
+}
+
+int UnityTestMatches(void)
+{
+ /* Check if this test name matches the included test pattern */
+ int retval;
+ if (UnityOptionIncludeNamed)
+ {
+ retval = UnityStringArgumentMatches(UnityOptionIncludeNamed);
+ }
+ else
+ retval = 1;
+
+ /* Check if this test name matches the excluded test pattern */
+ if (UnityOptionExcludeNamed)
+ {
+ if (UnityStringArgumentMatches(UnityOptionExcludeNamed))
+ retval = 0;
+ }
+ return retval;
+}
+
+#endif /* UNITY_USE_COMMAND_LINE_ARGS */
+/*-----------------------------------------------*/
diff --git a/vendor/Unity-2.4.3/src/unity.h b/vendor/Unity-2.4.3/src/unity.h
new file mode 100644
index 0000000..32ff0e6
--- /dev/null
+++ b/vendor/Unity-2.4.3/src/unity.h
@@ -0,0 +1,503 @@
+/* ==========================================
+ Unity Project - A Test Framework for C
+ Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef UNITY_FRAMEWORK_H
+#define UNITY_FRAMEWORK_H
+#define UNITY
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "unity_internals.h"
+
+/*-------------------------------------------------------
+ * Test Setup / Teardown
+ *-------------------------------------------------------*/
+
+/* These functions are intended to be called before and after each test. */
+void setUp(void);
+void tearDown(void);
+
+/* These functions are intended to be called at the beginning and end of an
+ * entire test suite. suiteTearDown() is passed the number of tests that
+ * failed, and its return value becomes the exit code of main(). */
+void suiteSetUp(void);
+int suiteTearDown(int num_failures);
+
+/* If the compiler supports it, the following block provides stub
+ * implementations of the above functions as weak symbols. Note that on
+ * some platforms (MinGW for example), weak function implementations need
+ * to be in the same translation unit they are called from. This can be
+ * achieved by defining UNITY_INCLUDE_SETUP_STUBS before including unity.h. */
+#ifdef UNITY_INCLUDE_SETUP_STUBS
+ #ifdef UNITY_WEAK_ATTRIBUTE
+ UNITY_WEAK_ATTRIBUTE void setUp(void) { }
+ UNITY_WEAK_ATTRIBUTE void tearDown(void) { }
+ UNITY_WEAK_ATTRIBUTE void suiteSetUp(void) { }
+ UNITY_WEAK_ATTRIBUTE int suiteTearDown(int num_failures) { return num_failures; }
+ #elif defined(UNITY_WEAK_PRAGMA)
+ #pragma weak setUp
+ void setUp(void) { }
+ #pragma weak tearDown
+ void tearDown(void) { }
+ #pragma weak suiteSetUp
+ void suiteSetUp(void) { }
+ #pragma weak suiteTearDown
+ int suiteTearDown(int num_failures) { return num_failures; }
+ #endif
+#endif
+
+/*-------------------------------------------------------
+ * Configuration Options
+ *-------------------------------------------------------
+ * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above.
+
+ * Integers/longs/pointers
+ * - Unity attempts to automatically discover your integer sizes
+ * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in <stdint.h>
+ * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in <limits.h>
+ * - If you cannot use the automatic methods above, you can force Unity by using these options:
+ * - define UNITY_SUPPORT_64
+ * - set UNITY_INT_WIDTH
+ * - set UNITY_LONG_WIDTH
+ * - set UNITY_POINTER_WIDTH
+
+ * Floats
+ * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons
+ * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT
+ * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats
+ * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons
+ * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default)
+ * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE
+ * - define UNITY_DOUBLE_TYPE to specify something other than double
+ * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors
+
+ * Output
+ * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired
+ * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure
+
+ * Optimization
+ * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge
+ * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests.
+
+ * Test Cases
+ * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script
+
+ * Parameterized Tests
+ * - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing
+
+ * Tests with Arguments
+ * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity
+
+ *-------------------------------------------------------
+ * Basic Fail and Ignore
+ *-------------------------------------------------------*/
+
+#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message))
+#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL)
+#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message))
+#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL)
+#define TEST_ONLY()
+
+/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails.
+ * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */
+#define TEST_PASS() TEST_ABORT()
+
+/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out
+ * which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */
+#define TEST_FILE(a)
+
+/*-------------------------------------------------------
+ * Test Asserts (simple)
+ *-------------------------------------------------------*/
+
+/* Boolean */
+#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE")
+#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE")
+#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE")
+#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE")
+#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL")
+#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL")
+
+/* Integers (of all sizes) */
+#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
+#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, NULL)
+
+/* Integer Greater Than/ Less Than (of all sizes) */
+#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
+
+#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
+
+#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
+
+#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
+
+/* Integer Ranges (of all sizes) */
+#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+
+/* Structs and Strings */
+#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL)
+
+/* Arrays */
+#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL)
+
+/* Arrays Compared To Single Value */
+#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL)
+
+/* Floating Point (If Enabled) */
+#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
+
+/* Double (If Enabled) */
+#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
+
+/*-------------------------------------------------------
+ * Test Asserts (with additional messages)
+ *-------------------------------------------------------*/
+
+/* Boolean */
+#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
+#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
+#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
+#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
+#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message))
+#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message))
+
+/* Integers (of all sizes) */
+#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message))
+#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
+#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message))
+
+/* Integer Greater Than/ Less Than (of all sizes) */
+#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message))
+
+#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message))
+
+#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
+
+#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message))
+
+/* Integer Ranges (of all sizes) */
+#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+
+/* Structs and Strings */
+#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message))
+
+/* Arrays */
+#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message))
+
+/* Arrays Compared To Single Value*/
+#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message))
+
+/* Floating Point (If Enabled) */
+#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message))
+
+/* Double (If Enabled) */
+#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message))
+
+/* end of UNITY_FRAMEWORK_H */
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/vendor/Unity-2.4.3/src/unity_internals.h b/vendor/Unity-2.4.3/src/unity_internals.h
new file mode 100644
index 0000000..67e219b
--- /dev/null
+++ b/vendor/Unity-2.4.3/src/unity_internals.h
@@ -0,0 +1,872 @@
+/* ==========================================
+ Unity Project - A Test Framework for C
+ Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef UNITY_INTERNALS_H
+#define UNITY_INTERNALS_H
+
+#ifdef UNITY_INCLUDE_CONFIG_H
+#include "unity_config.h"
+#endif
+
+#ifndef UNITY_EXCLUDE_SETJMP_H
+#include <setjmp.h>
+#endif
+
+#ifndef UNITY_EXCLUDE_MATH_H
+#include <math.h>
+#endif
+
+/* Unity Attempts to Auto-Detect Integer Types
+ * Attempt 1: UINT_MAX, ULONG_MAX in <limits.h>, or default to 32 bits
+ * Attempt 2: UINTPTR_MAX in <stdint.h>, or default to same size as long
+ * The user may override any of these derived constants:
+ * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */
+#ifndef UNITY_EXCLUDE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifndef UNITY_EXCLUDE_LIMITS_H
+#include <limits.h>
+#endif
+
+/*-------------------------------------------------------
+ * Guess Widths If Not Specified
+ *-------------------------------------------------------*/
+
+/* Determine the size of an int, if not already specified.
+ * We cannot use sizeof(int), because it is not yet defined
+ * at this stage in the translation of the C program.
+ * Therefore, infer it from UINT_MAX if possible. */
+#ifndef UNITY_INT_WIDTH
+ #ifdef UINT_MAX
+ #if (UINT_MAX == 0xFFFF)
+ #define UNITY_INT_WIDTH (16)
+ #elif (UINT_MAX == 0xFFFFFFFF)
+ #define UNITY_INT_WIDTH (32)
+ #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF)
+ #define UNITY_INT_WIDTH (64)
+ #endif
+ #else /* Set to default */
+ #define UNITY_INT_WIDTH (32)
+ #endif /* UINT_MAX */
+#endif
+
+/* Determine the size of a long, if not already specified. */
+#ifndef UNITY_LONG_WIDTH
+ #ifdef ULONG_MAX
+ #if (ULONG_MAX == 0xFFFF)
+ #define UNITY_LONG_WIDTH (16)
+ #elif (ULONG_MAX == 0xFFFFFFFF)
+ #define UNITY_LONG_WIDTH (32)
+ #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF)
+ #define UNITY_LONG_WIDTH (64)
+ #endif
+ #else /* Set to default */
+ #define UNITY_LONG_WIDTH (32)
+ #endif /* ULONG_MAX */
+#endif
+
+/* Determine the size of a pointer, if not already specified. */
+#ifndef UNITY_POINTER_WIDTH
+ #ifdef UINTPTR_MAX
+ #if (UINTPTR_MAX <= 0xFFFF)
+ #define UNITY_POINTER_WIDTH (16)
+ #elif (UINTPTR_MAX <= 0xFFFFFFFF)
+ #define UNITY_POINTER_WIDTH (32)
+ #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF)
+ #define UNITY_POINTER_WIDTH (64)
+ #endif
+ #else /* Set to default */
+ #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH
+ #endif /* UINTPTR_MAX */
+#endif
+
+/*-------------------------------------------------------
+ * Int Support (Define types based on detected sizes)
+ *-------------------------------------------------------*/
+
+#if (UNITY_INT_WIDTH == 32)
+ typedef unsigned char UNITY_UINT8;
+ typedef unsigned short UNITY_UINT16;
+ typedef unsigned int UNITY_UINT32;
+ typedef signed char UNITY_INT8;
+ typedef signed short UNITY_INT16;
+ typedef signed int UNITY_INT32;
+#elif (UNITY_INT_WIDTH == 16)
+ typedef unsigned char UNITY_UINT8;
+ typedef unsigned int UNITY_UINT16;
+ typedef unsigned long UNITY_UINT32;
+ typedef signed char UNITY_INT8;
+ typedef signed int UNITY_INT16;
+ typedef signed long UNITY_INT32;
+#else
+ #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported)
+#endif
+
+/*-------------------------------------------------------
+ * 64-bit Support
+ *-------------------------------------------------------*/
+
+#ifndef UNITY_SUPPORT_64
+ #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64
+ #define UNITY_SUPPORT_64
+ #endif
+#endif
+
+#ifndef UNITY_SUPPORT_64
+ /* No 64-bit Support */
+ typedef UNITY_UINT32 UNITY_UINT;
+ typedef UNITY_INT32 UNITY_INT;
+#else
+
+ /* 64-bit Support */
+ #if (UNITY_LONG_WIDTH == 32)
+ typedef unsigned long long UNITY_UINT64;
+ typedef signed long long UNITY_INT64;
+ #elif (UNITY_LONG_WIDTH == 64)
+ typedef unsigned long UNITY_UINT64;
+ typedef signed long UNITY_INT64;
+ #else
+ #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported)
+ #endif
+ typedef UNITY_UINT64 UNITY_UINT;
+ typedef UNITY_INT64 UNITY_INT;
+
+#endif
+
+/*-------------------------------------------------------
+ * Pointer Support
+ *-------------------------------------------------------*/
+
+#if (UNITY_POINTER_WIDTH == 32)
+#define UNITY_PTR_TO_INT UNITY_INT32
+#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32
+#elif (UNITY_POINTER_WIDTH == 64)
+#define UNITY_PTR_TO_INT UNITY_INT64
+#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64
+#elif (UNITY_POINTER_WIDTH == 16)
+#define UNITY_PTR_TO_INT UNITY_INT16
+#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16
+#else
+ #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported)
+#endif
+
+#ifndef UNITY_PTR_ATTRIBUTE
+#define UNITY_PTR_ATTRIBUTE
+#endif
+
+#ifndef UNITY_INTERNAL_PTR
+#define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void*
+#endif
+
+/*-------------------------------------------------------
+ * Float Support
+ *-------------------------------------------------------*/
+
+#ifdef UNITY_EXCLUDE_FLOAT
+
+/* No Floating Point Support */
+#ifndef UNITY_EXCLUDE_DOUBLE
+#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */
+#endif
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+#define UNITY_EXCLUDE_FLOAT_PRINT
+#endif
+
+#else
+
+/* Floating Point Support */
+#ifndef UNITY_FLOAT_PRECISION
+#define UNITY_FLOAT_PRECISION (0.00001f)
+#endif
+#ifndef UNITY_FLOAT_TYPE
+#define UNITY_FLOAT_TYPE float
+#endif
+typedef UNITY_FLOAT_TYPE UNITY_FLOAT;
+
+/* isinf & isnan macros should be provided by math.h */
+#ifndef isinf
+/* The value of Inf - Inf is NaN */
+#define isinf(n) (isnan((n) - (n)) && !isnan(n))
+#endif
+
+#ifndef isnan
+/* NaN is the only floating point value that does NOT equal itself.
+ * Therefore if n != n, then it is NaN. */
+#define isnan(n) ((n != n) ? 1 : 0)
+#endif
+
+#endif
+
+/*-------------------------------------------------------
+ * Double Float Support
+ *-------------------------------------------------------*/
+
+/* unlike float, we DON'T include by default */
+#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE)
+
+ /* No Floating Point Support */
+ #ifndef UNITY_EXCLUDE_DOUBLE
+ #define UNITY_EXCLUDE_DOUBLE
+ #else
+ #undef UNITY_INCLUDE_DOUBLE
+ #endif
+
+ #ifndef UNITY_EXCLUDE_FLOAT
+ #ifndef UNITY_DOUBLE_TYPE
+ #define UNITY_DOUBLE_TYPE double
+ #endif
+ typedef UNITY_FLOAT UNITY_DOUBLE;
+ /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */
+ #endif
+
+#else
+
+ /* Double Floating Point Support */
+ #ifndef UNITY_DOUBLE_PRECISION
+ #define UNITY_DOUBLE_PRECISION (1e-12)
+ #endif
+
+ #ifndef UNITY_DOUBLE_TYPE
+ #define UNITY_DOUBLE_TYPE double
+ #endif
+ typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE;
+
+#endif
+
+/*-------------------------------------------------------
+ * Output Method: stdout (DEFAULT)
+ *-------------------------------------------------------*/
+#ifndef UNITY_OUTPUT_CHAR
+/* Default to using putchar, which is defined in stdio.h */
+#include <stdio.h>
+#define UNITY_OUTPUT_CHAR(a) (void)putchar(a)
+#else
+ /* If defined as something else, make sure we declare it here so it's ready for use */
+ #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION
+extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION;
+ #endif
+#endif
+
+#ifndef UNITY_OUTPUT_FLUSH
+#ifdef UNITY_USE_FLUSH_STDOUT
+/* We want to use the stdout flush utility */
+#include <stdio.h>
+#define UNITY_OUTPUT_FLUSH() (void)fflush(stdout)
+#else
+/* We've specified nothing, therefore flush should just be ignored */
+#define UNITY_OUTPUT_FLUSH()
+#endif
+#else
+/* We've defined flush as something else, so make sure we declare it here so it's ready for use */
+#ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION
+extern void UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION;
+#endif
+#endif
+
+#ifndef UNITY_OUTPUT_FLUSH
+#define UNITY_FLUSH_CALL()
+#else
+#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH()
+#endif
+
+#ifndef UNITY_PRINT_EOL
+#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n')
+#endif
+
+#ifndef UNITY_OUTPUT_START
+#define UNITY_OUTPUT_START()
+#endif
+
+#ifndef UNITY_OUTPUT_COMPLETE
+#define UNITY_OUTPUT_COMPLETE()
+#endif
+
+/*-------------------------------------------------------
+ * Footprint
+ *-------------------------------------------------------*/
+
+#ifndef UNITY_LINE_TYPE
+#define UNITY_LINE_TYPE UNITY_UINT
+#endif
+
+#ifndef UNITY_COUNTER_TYPE
+#define UNITY_COUNTER_TYPE UNITY_UINT
+#endif
+
+/*-------------------------------------------------------
+ * Language Features Available
+ *-------------------------------------------------------*/
+#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA)
+# if defined(__GNUC__) || defined(__ghs__) /* __GNUC__ includes clang */
+# if !(defined(__WIN32__) && defined(__clang__)) && !defined(__TMS470__)
+# define UNITY_WEAK_ATTRIBUTE __attribute__((weak))
+# endif
+# endif
+#endif
+
+#ifdef UNITY_NO_WEAK
+# undef UNITY_WEAK_ATTRIBUTE
+# undef UNITY_WEAK_PRAGMA
+#endif
+
+
+/*-------------------------------------------------------
+ * Internal Structs Needed
+ *-------------------------------------------------------*/
+
+typedef void (*UnityTestFunction)(void);
+
+#define UNITY_DISPLAY_RANGE_INT (0x10)
+#define UNITY_DISPLAY_RANGE_UINT (0x20)
+#define UNITY_DISPLAY_RANGE_HEX (0x40)
+
+typedef enum
+{
+UNITY_DISPLAY_STYLE_INT = sizeof(int)+ UNITY_DISPLAY_RANGE_INT,
+ UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT,
+ UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT,
+ UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT,
+#ifdef UNITY_SUPPORT_64
+ UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT,
+#endif
+
+UNITY_DISPLAY_STYLE_UINT = sizeof(unsigned) + UNITY_DISPLAY_RANGE_UINT,
+ UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT,
+ UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT,
+ UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT,
+#ifdef UNITY_SUPPORT_64
+ UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT,
+#endif
+
+ UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX,
+ UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX,
+ UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX,
+#ifdef UNITY_SUPPORT_64
+ UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX,
+#endif
+
+ UNITY_DISPLAY_STYLE_UNKNOWN
+} UNITY_DISPLAY_STYLE_T;
+
+typedef enum
+{
+ UNITY_EQUAL_TO = 1,
+ UNITY_GREATER_THAN = 2,
+ UNITY_GREATER_OR_EQUAL = 2 + UNITY_EQUAL_TO,
+ UNITY_SMALLER_THAN = 4,
+ UNITY_SMALLER_OR_EQUAL = 4 + UNITY_EQUAL_TO
+} UNITY_COMPARISON_T;
+
+#ifndef UNITY_EXCLUDE_FLOAT
+typedef enum UNITY_FLOAT_TRAIT
+{
+ UNITY_FLOAT_IS_NOT_INF = 0,
+ UNITY_FLOAT_IS_INF,
+ UNITY_FLOAT_IS_NOT_NEG_INF,
+ UNITY_FLOAT_IS_NEG_INF,
+ UNITY_FLOAT_IS_NOT_NAN,
+ UNITY_FLOAT_IS_NAN,
+ UNITY_FLOAT_IS_NOT_DET,
+ UNITY_FLOAT_IS_DET,
+ UNITY_FLOAT_INVALID_TRAIT
+} UNITY_FLOAT_TRAIT_T;
+#endif
+
+typedef enum
+{
+ UNITY_ARRAY_TO_VAL = 0,
+ UNITY_ARRAY_TO_ARRAY
+} UNITY_FLAGS_T;
+
+struct UNITY_STORAGE_T
+{
+ const char* TestFile;
+ const char* CurrentTestName;
+#ifndef UNITY_EXCLUDE_DETAILS
+ const char* CurrentDetail1;
+ const char* CurrentDetail2;
+#endif
+ UNITY_LINE_TYPE CurrentTestLineNumber;
+ UNITY_COUNTER_TYPE NumberOfTests;
+ UNITY_COUNTER_TYPE TestFailures;
+ UNITY_COUNTER_TYPE TestIgnores;
+ UNITY_COUNTER_TYPE CurrentTestFailed;
+ UNITY_COUNTER_TYPE CurrentTestIgnored;
+#ifndef UNITY_EXCLUDE_SETJMP_H
+ jmp_buf AbortFrame;
+#endif
+};
+
+extern struct UNITY_STORAGE_T Unity;
+
+/*-------------------------------------------------------
+ * Test Suite Management
+ *-------------------------------------------------------*/
+
+void UnityBegin(const char* filename);
+int UnityEnd(void);
+void UnityConcludeTest(void);
+void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum);
+
+/*-------------------------------------------------------
+ * Details Support
+ *-------------------------------------------------------*/
+
+#ifdef UNITY_EXCLUDE_DETAILS
+#define UNITY_CLR_DETAILS()
+#define UNITY_SET_DETAIL(d1)
+#define UNITY_SET_DETAILS(d1,d2)
+#else
+#define UNITY_CLR_DETAILS() { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; }
+#define UNITY_SET_DETAIL(d1) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = 0; }
+#define UNITY_SET_DETAILS(d1,d2) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = d2; }
+
+#ifndef UNITY_DETAIL1_NAME
+#define UNITY_DETAIL1_NAME "Function"
+#endif
+
+#ifndef UNITY_DETAIL2_NAME
+#define UNITY_DETAIL2_NAME "Argument"
+#endif
+#endif
+
+/*-------------------------------------------------------
+ * Test Output
+ *-------------------------------------------------------*/
+
+void UnityPrint(const char* string);
+void UnityPrintLen(const char* string, const UNITY_UINT32 length);
+void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number);
+void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style);
+void UnityPrintNumber(const UNITY_INT number);
+void UnityPrintNumberUnsigned(const UNITY_UINT number);
+void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles);
+
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+void UnityPrintFloat(const UNITY_DOUBLE input_number);
+#endif
+
+/*-------------------------------------------------------
+ * Test Assertion Functions
+ *-------------------------------------------------------
+ * Use the macros below this section instead of calling
+ * these directly. The macros have a consistent naming
+ * convention and will pull in file and line information
+ * for you. */
+
+void UnityAssertEqualNumber(const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style);
+
+void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold,
+ const UNITY_INT actual,
+ const UNITY_COMPARISON_T compare,
+ const char *msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style);
+
+void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertBits(const UNITY_INT mask,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualString(const char* expected,
+ const char* actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualStringLen(const char* expected,
+ const char* actual,
+ const UNITY_UINT32 length,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected,
+ const char** actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 length,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertNumbersWithin(const UNITY_UINT delta,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style);
+
+void UnityFail(const char* message, const UNITY_LINE_TYPE line);
+
+void UnityIgnore(const char* message, const UNITY_LINE_TYPE line);
+
+#ifndef UNITY_EXCLUDE_FLOAT
+void UnityAssertFloatsWithin(const UNITY_FLOAT delta,
+ const UNITY_FLOAT expected,
+ const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style);
+#endif
+
+#ifndef UNITY_EXCLUDE_DOUBLE
+void UnityAssertDoublesWithin(const UNITY_DOUBLE delta,
+ const UNITY_DOUBLE expected,
+ const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style);
+#endif
+
+/*-------------------------------------------------------
+ * Helpers
+ *-------------------------------------------------------*/
+
+UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size);
+#ifndef UNITY_EXCLUDE_FLOAT
+UNITY_INTERNAL_PTR UnityFloatToPtr(const float num);
+#endif
+#ifndef UNITY_EXCLUDE_DOUBLE
+UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num);
+#endif
+
+/*-------------------------------------------------------
+ * Error Strings We Might Need
+ *-------------------------------------------------------*/
+
+extern const char UnityStrErrFloat[];
+extern const char UnityStrErrDouble[];
+extern const char UnityStrErr64[];
+
+/*-------------------------------------------------------
+ * Test Running Macros
+ *-------------------------------------------------------*/
+
+#ifndef UNITY_EXCLUDE_SETJMP_H
+#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0)
+#define TEST_ABORT() longjmp(Unity.AbortFrame, 1)
+#else
+#define TEST_PROTECT() 1
+#define TEST_ABORT() return
+#endif
+
+/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */
+#ifndef RUN_TEST
+#ifdef __STDC_VERSION__
+#if __STDC_VERSION__ >= 199901L
+#define RUN_TEST(...) UnityDefaultTestRun(RUN_TEST_FIRST(__VA_ARGS__), RUN_TEST_SECOND(__VA_ARGS__))
+#define RUN_TEST_FIRST(...) RUN_TEST_FIRST_HELPER(__VA_ARGS__, throwaway)
+#define RUN_TEST_FIRST_HELPER(first, ...) (first), #first
+#define RUN_TEST_SECOND(...) RUN_TEST_SECOND_HELPER(__VA_ARGS__, __LINE__, throwaway)
+#define RUN_TEST_SECOND_HELPER(first, second, ...) (second)
+#endif
+#endif
+#endif
+
+/* If we can't do the tricky version, we'll just have to require them to always include the line number */
+#ifndef RUN_TEST
+#ifdef CMOCK
+#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num)
+#else
+#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__)
+#endif
+#endif
+
+#define TEST_LINE_NUM (Unity.CurrentTestLineNumber)
+#define TEST_IS_IGNORED (Unity.CurrentTestIgnored)
+#define UNITY_NEW_TEST(a) \
+ Unity.CurrentTestName = (a); \
+ Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \
+ Unity.NumberOfTests++;
+
+#ifndef UNITY_BEGIN
+#define UNITY_BEGIN() UnityBegin(__FILE__)
+#endif
+
+#ifndef UNITY_END
+#define UNITY_END() UnityEnd()
+#endif
+
+/*-----------------------------------------------
+ * Command Line Argument Support
+ *-----------------------------------------------*/
+
+#ifdef UNITY_USE_COMMAND_LINE_ARGS
+int UnityParseOptions(int argc, char** argv);
+int UnityTestMatches(void);
+#endif
+
+/*-------------------------------------------------------
+ * Basic Fail and Ignore
+ *-------------------------------------------------------*/
+
+#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line))
+
+/*-------------------------------------------------------
+ * Test Asserts
+ *-------------------------------------------------------*/
+
+#define UNITY_TEST_ASSERT(condition, line, message) if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message));}
+#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message))
+
+#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line))
+
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+
+#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+
+#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER)
+#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+
+#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) expected, sizeof(int)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) expected, sizeof(unsigned int)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) expected, sizeof(int*)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
+
+#ifdef UNITY_SUPPORT_64
+#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#else
+#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#endif
+
+#ifdef UNITY_EXCLUDE_FLOAT
+#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#else
+#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray(UnityFloatToPtr(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
+#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
+#endif
+
+#ifdef UNITY_EXCLUDE_DOUBLE
+#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#else
+#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)line)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual, (UNITY_LINE_TYPE)(line), message)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)line, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray(UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)line, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
+#endif
+
+/* End of UNITY_INTERNALS_H */
+#endif
diff --git a/vendor/Unity-2.4.3/test/.rubocop.yml b/vendor/Unity-2.4.3/test/.rubocop.yml
new file mode 100644
index 0000000..c074ca9
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/.rubocop.yml
@@ -0,0 +1,58 @@
+# This is the configuration used to check the rubocop source code.
+
+#inherit_from: .rubocop_todo.yml
+
+AllCops:
+ TargetRubyVersion: 2.1
+
+# These are areas where ThrowTheSwitch's coding style diverges from the Ruby standard
+Style/SpecialGlobalVars:
+ EnforcedStyle: use_perl_names
+Style/FormatString:
+ Enabled: false
+Style/GlobalVars:
+ Enabled: false
+Style/RegexpLiteral:
+ AllowInnerSlashes: true
+Style/HashSyntax:
+ EnforcedStyle: no_mixed_keys
+
+# This is disabled because it seems to get confused over nested hashes
+Style/AlignHash:
+ Enabled: false
+ EnforcedHashRocketStyle: table
+ EnforcedColonStyle: table
+
+# We purposefully use these insecure features because they're what makes Ruby awesome
+Security/Eval:
+ Enabled: false
+Security/YAMLLoad:
+ Enabled: false
+
+# At this point, we're not ready to enforce inline documentation requirements
+Style/Documentation:
+ Enabled: false
+Style/DocumentationMethod:
+ Enabled: false
+
+# At this point, we're not ready to enforce any metrics
+Metrics/AbcSize:
+ Enabled: false
+Metrics/BlockLength:
+ Enabled: false
+Metrics/BlockNesting:
+ Enabled: false
+Metrics/ClassLength:
+ Enabled: false
+Metrics/CyclomaticComplexity:
+ Enabled: false
+Metrics/LineLength:
+ Enabled: false
+Metrics/MethodLength:
+ Enabled: false
+Metrics/ModuleLength:
+ Enabled: false
+Metrics/ParameterLists:
+ Enabled: false
+Metrics/PerceivedComplexity:
+ Enabled: false
diff --git a/vendor/Unity-2.4.3/test/Makefile b/vendor/Unity-2.4.3/test/Makefile
new file mode 100644
index 0000000..c2710f1
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/Makefile
@@ -0,0 +1,66 @@
+CC = gcc
+ifeq ($(shell uname -s), Darwin)
+CC = clang
+endif
+ifeq ($(findstring clang, $(CC)), clang)
+E = -Weverything
+CFLAGS += $E -Wno-unknown-warning-option -Wno-missing-prototypes
+CFLAGS += -Wno-unused-macros -Wno-padded -Wno-missing-noreturn
+endif
+CFLAGS += -std=c99 -pedantic -Wall -Wextra -Wconversion -Werror
+CFLAGS += -Wno-switch-enum -Wno-double-promotion
+CFLAGS += -Wbad-function-cast -Wcast-qual -Wold-style-definition -Wshadow -Wstrict-overflow \
+ -Wstrict-prototypes -Wswitch-default -Wundef
+#DEBUG = -O0 -g
+CFLAGS += $(DEBUG)
+DEFINES = -D UNITY_OUTPUT_CHAR=putcharSpy
+DEFINES += -D UNITY_OUTPUT_CHAR_HEADER_DECLARATION=putcharSpy\(int\)
+DEFINES += $(UNITY_SUPPORT_64) $(UNITY_INCLUDE_DOUBLE)
+UNITY_SUPPORT_64 = -D UNITY_SUPPORT_64
+UNITY_INCLUDE_DOUBLE = -D UNITY_INCLUDE_DOUBLE
+SRC = ../src/unity.c tests/testunity.c build/testunityRunner.c
+INC_DIR = -I ../src
+COV_FLAGS = -fprofile-arcs -ftest-coverage -I ../../src
+BUILD_DIR = build
+TARGET = build/testunity-cov.exe
+
+# To generate coverage, call 'make -s', the default target runs.
+# For verbose output of all the tests, run 'make test'.
+default: coverage
+.PHONY: default coverage test clean
+coverage: DEFINES += -D UNITY_NO_WEAK
+coverage: $(BUILD_DIR)/testunityRunner.c
+ cd $(BUILD_DIR) && \
+ $(CC) $(CFLAGS) $(DEFINES) $(foreach i,$(SRC), ../$i) $(COV_FLAGS) -o ../$(TARGET)
+ rm -f $(BUILD_DIR)/*.gcda
+ ./$(TARGET) | grep 'Tests\|]]]' -A1
+ cd $(BUILD_DIR) && \
+ gcov unity.c | head -3
+ grep '###' $(BUILD_DIR)/unity.c.gcov -C2 || true
+
+test: $(BUILD_DIR)/testunityRunner.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INC_DIR) $(SRC) -o $(TARGET)
+ ./$(TARGET)
+
+# Compile only, for testing that preprocessor detection works
+UNITY_C_ONLY =-c ../src/unity.c -o $(BUILD_DIR)/unity.o
+intDetection:
+ $(CC) $(CFLAGS) $(INC_DIR) $(UNITY_C_ONLY) -D UNITY_EXCLUDE_STDINT_H
+ $(CC) $(CFLAGS) $(INC_DIR) $(UNITY_C_ONLY) -D UNITY_EXCLUDE_LIMITS_H
+
+$(BUILD_DIR)/testunityRunner.c: tests/testunity.c | $(BUILD_DIR)
+ awk $(AWK_SCRIPT) tests/testunity.c > $@
+
+AWK_SCRIPT=\
+ '/^void test/{ declarations[d++]=$$0; gsub(/\(?void\)? ?/,""); tests[t++]=$$0; line[u++]=NR } \
+ END{ print "\#include \"unity.h\" /* Autogenerated by awk in Makefile */" ; \
+ for (i=0; i<d; i++) { print declarations[i] ";" } \
+ print "int main(void)\n{\n UnityBegin(\"" FILENAME "\");" ; \
+ for (i=0; i<t; i++) { print " RUN_TEST(" tests[i] ", " line[i] ");" } \
+ print " return UNITY_END();\n}" }'
+
+$(BUILD_DIR):
+ mkdir -p $(BUILD_DIR)
+
+clean:
+ rm -f $(TARGET) $(BUILD_DIR)/*.gc* $(BUILD_DIR)/testunityRunner.c
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_cmd.c b/vendor/Unity-2.4.3/test/expectdata/testsample_cmd.c
new file mode 100644
index 0000000..7bcf8e1
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_cmd.c
@@ -0,0 +1,61 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ CEXCEPTION_T e; \
+ Try { \
+ setUp(); \
+ TestFunc(); \
+ } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/testsample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+ RUN_TEST(test_TheThirdThingToTest, 53);
+ RUN_TEST(test_TheFourthThingToTest, 58);
+
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_def.c b/vendor/Unity-2.4.3/test/expectdata/testsample_def.c
new file mode 100644
index 0000000..b8ad559
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_def.c
@@ -0,0 +1,57 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(); \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/testsample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+ RUN_TEST(test_TheThirdThingToTest, 53);
+ RUN_TEST(test_TheFourthThingToTest, 58);
+
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_head1.c b/vendor/Unity-2.4.3/test/expectdata/testsample_head1.c
new file mode 100644
index 0000000..1d01551
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_head1.c
@@ -0,0 +1,55 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(); \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "testsample_head1.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/testsample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+ RUN_TEST(test_TheThirdThingToTest, 53);
+ RUN_TEST(test_TheFourthThingToTest, 58);
+
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_head1.h b/vendor/Unity-2.4.3/test/expectdata/testsample_head1.h
new file mode 100644
index 0000000..da6b7ab
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_head1.h
@@ -0,0 +1,15 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+#ifndef _TESTSAMPLE_HEAD1_H
+#define _TESTSAMPLE_HEAD1_H
+
+#include "unity.h"
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+void test_TheFirstThingToTest(void);
+void test_TheSecondThingToTest(void);
+void test_TheThirdThingToTest(void);
+void test_TheFourthThingToTest(void);
+#endif
+
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_mock_cmd.c b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_cmd.c
new file mode 100644
index 0000000..45a09af
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_cmd.c
@@ -0,0 +1,80 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ CMock_Init(); \
+ UNITY_CLR_DETAILS(); \
+ if (TEST_PROTECT()) \
+ { \
+ CEXCEPTION_T e; \
+ Try { \
+ setUp(); \
+ TestFunc(); \
+ } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ CMock_Verify(); \
+ } \
+ CMock_Destroy(); \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+ Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+ Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+ Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ CMock_Verify();
+ CMock_Destroy();
+ tearDown();
+ CMock_Init();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/mocksample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+
+ CMock_Guts_MemFreeFinal();
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_mock_def.c b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_def.c
new file mode 100644
index 0000000..a7a2607
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_def.c
@@ -0,0 +1,76 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ CMock_Init(); \
+ UNITY_CLR_DETAILS(); \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(); \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ CMock_Verify(); \
+ } \
+ CMock_Destroy(); \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+ Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+ Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+ Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ CMock_Verify();
+ CMock_Destroy();
+ tearDown();
+ CMock_Init();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/mocksample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+
+ CMock_Guts_MemFreeFinal();
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_mock_head1.c b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_head1.c
new file mode 100644
index 0000000..45829fe
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_head1.c
@@ -0,0 +1,75 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ CMock_Init(); \
+ UNITY_CLR_DETAILS(); \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(); \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ CMock_Verify(); \
+ } \
+ CMock_Destroy(); \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "testsample_mock_head1.h"
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+ Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+ Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+ Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ CMock_Verify();
+ CMock_Destroy();
+ tearDown();
+ CMock_Init();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/mocksample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+
+ CMock_Guts_MemFreeFinal();
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_mock_head1.h b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_head1.h
new file mode 100644
index 0000000..30c509a
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_head1.h
@@ -0,0 +1,13 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+#ifndef _TESTSAMPLE_MOCK_HEAD1_H
+#define _TESTSAMPLE_MOCK_HEAD1_H
+
+#include "unity.h"
+#include "cmock.h"
+#include "funky.h"
+#include <setjmp.h>
+
+void test_TheFirstThingToTest(void);
+void test_TheSecondThingToTest(void);
+#endif
+
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_mock_new1.c b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_new1.c
new file mode 100644
index 0000000..0061822
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_new1.c
@@ -0,0 +1,89 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ CMock_Init(); \
+ UNITY_CLR_DETAILS(); \
+ if (TEST_PROTECT()) \
+ { \
+ CEXCEPTION_T e; \
+ Try { \
+ setUp(); \
+ TestFunc(); \
+ } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ CMock_Verify(); \
+ } \
+ CMock_Destroy(); \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "one.h"
+#include "two.h"
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+int GlobalExpectCount;
+int GlobalVerifyOrder;
+char* GlobalOrderError;
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+ GlobalExpectCount = 0;
+ GlobalVerifyOrder = 0;
+ GlobalOrderError = NULL;
+ Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+ Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+ Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ CMock_Verify();
+ CMock_Destroy();
+ tearDown();
+ CMock_Init();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/mocksample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+
+ CMock_Guts_MemFreeFinal();
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_mock_new2.c b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_new2.c
new file mode 100644
index 0000000..ee63cdc
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_new2.c
@@ -0,0 +1,89 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ CMock_Init(); \
+ UNITY_CLR_DETAILS(); \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(); \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ CMock_Verify(); \
+ } \
+ CMock_Destroy(); \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+ Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+ Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+ Mockstanky_Destroy();
+}
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_custom_setup();
+}
+
+/*=======Suite Teardown=====*/
+static int suite_teardown(int num_failures)
+{
+a_custom_teardown();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ CMock_Verify();
+ CMock_Destroy();
+ tearDown();
+ CMock_Init();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ suite_setup();
+ UnityBegin("testdata/mocksample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+
+ CMock_Guts_MemFreeFinal();
+ return suite_teardown(UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_mock_param.c b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_param.c
new file mode 100644
index 0000000..a42b7de
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_param.c
@@ -0,0 +1,77 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST_NO_ARGS
+#define RUN_TEST(TestFunc, TestLineNum, ...) \
+{ \
+ Unity.CurrentTestName = #TestFunc "(" #__VA_ARGS__ ")"; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ CMock_Init(); \
+ UNITY_CLR_DETAILS(); \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(__VA_ARGS__); \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ CMock_Verify(); \
+ } \
+ CMock_Destroy(); \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+ Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+ Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+ Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ CMock_Verify();
+ CMock_Destroy();
+ tearDown();
+ CMock_Init();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/mocksample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21, RUN_TEST_NO_ARGS);
+ RUN_TEST(test_TheSecondThingToTest, 43, RUN_TEST_NO_ARGS);
+
+ CMock_Guts_MemFreeFinal();
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_mock_run1.c b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_run1.c
new file mode 100644
index 0000000..0061822
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_run1.c
@@ -0,0 +1,89 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ CMock_Init(); \
+ UNITY_CLR_DETAILS(); \
+ if (TEST_PROTECT()) \
+ { \
+ CEXCEPTION_T e; \
+ Try { \
+ setUp(); \
+ TestFunc(); \
+ } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ CMock_Verify(); \
+ } \
+ CMock_Destroy(); \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "one.h"
+#include "two.h"
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+int GlobalExpectCount;
+int GlobalVerifyOrder;
+char* GlobalOrderError;
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+ GlobalExpectCount = 0;
+ GlobalVerifyOrder = 0;
+ GlobalOrderError = NULL;
+ Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+ Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+ Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ CMock_Verify();
+ CMock_Destroy();
+ tearDown();
+ CMock_Init();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/mocksample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+
+ CMock_Guts_MemFreeFinal();
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_mock_run2.c b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_run2.c
new file mode 100644
index 0000000..ee63cdc
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_run2.c
@@ -0,0 +1,89 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ CMock_Init(); \
+ UNITY_CLR_DETAILS(); \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(); \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ CMock_Verify(); \
+ } \
+ CMock_Destroy(); \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+ Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+ Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+ Mockstanky_Destroy();
+}
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_custom_setup();
+}
+
+/*=======Suite Teardown=====*/
+static int suite_teardown(int num_failures)
+{
+a_custom_teardown();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ CMock_Verify();
+ CMock_Destroy();
+ tearDown();
+ CMock_Init();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ suite_setup();
+ UnityBegin("testdata/mocksample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+
+ CMock_Guts_MemFreeFinal();
+ return suite_teardown(UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_mock_yaml.c b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_yaml.c
new file mode 100644
index 0000000..a24bb5a
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_mock_yaml.c
@@ -0,0 +1,90 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ CMock_Init(); \
+ UNITY_CLR_DETAILS(); \
+ if (TEST_PROTECT()) \
+ { \
+ CEXCEPTION_T e; \
+ Try { \
+ setUp(); \
+ TestFunc(); \
+ } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ CMock_Verify(); \
+ } \
+ CMock_Destroy(); \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "two.h"
+#include "three.h"
+#include <four.h>
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+ Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+ Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+ Mockstanky_Destroy();
+}
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_yaml_setup();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ CMock_Verify();
+ CMock_Destroy();
+ tearDown();
+ CMock_Init();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ suite_setup();
+ UnityBegin("testdata/mocksample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+
+ CMock_Guts_MemFreeFinal();
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_new1.c b/vendor/Unity-2.4.3/test/expectdata/testsample_new1.c
new file mode 100644
index 0000000..7dcd3fd
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_new1.c
@@ -0,0 +1,67 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ CEXCEPTION_T e; \
+ Try { \
+ setUp(); \
+ TestFunc(); \
+ } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "one.h"
+#include "two.h"
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+int GlobalExpectCount;
+int GlobalVerifyOrder;
+char* GlobalOrderError;
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/testsample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+ RUN_TEST(test_TheThirdThingToTest, 53);
+ RUN_TEST(test_TheFourthThingToTest, 58);
+
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_new2.c b/vendor/Unity-2.4.3/test/expectdata/testsample_new2.c
new file mode 100644
index 0000000..c98c697
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_new2.c
@@ -0,0 +1,70 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(); \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_custom_setup();
+}
+
+/*=======Suite Teardown=====*/
+static int suite_teardown(int num_failures)
+{
+a_custom_teardown();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ suite_setup();
+ UnityBegin("testdata/testsample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+ RUN_TEST(test_TheThirdThingToTest, 53);
+ RUN_TEST(test_TheFourthThingToTest, 58);
+
+ return suite_teardown(UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_param.c b/vendor/Unity-2.4.3/test/expectdata/testsample_param.c
new file mode 100644
index 0000000..adf6c26
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_param.c
@@ -0,0 +1,58 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST_NO_ARGS
+#define RUN_TEST(TestFunc, TestLineNum, ...) \
+{ \
+ Unity.CurrentTestName = #TestFunc "(" #__VA_ARGS__ ")"; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(__VA_ARGS__); \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/testsample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21, RUN_TEST_NO_ARGS);
+ RUN_TEST(test_TheSecondThingToTest, 43, RUN_TEST_NO_ARGS);
+ RUN_TEST(test_TheThirdThingToTest, 53, RUN_TEST_NO_ARGS);
+ RUN_TEST(test_TheFourthThingToTest, 58, RUN_TEST_NO_ARGS);
+
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_run1.c b/vendor/Unity-2.4.3/test/expectdata/testsample_run1.c
new file mode 100644
index 0000000..7dcd3fd
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_run1.c
@@ -0,0 +1,67 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ CEXCEPTION_T e; \
+ Try { \
+ setUp(); \
+ TestFunc(); \
+ } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "one.h"
+#include "two.h"
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+int GlobalExpectCount;
+int GlobalVerifyOrder;
+char* GlobalOrderError;
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ UnityBegin("testdata/testsample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+ RUN_TEST(test_TheThirdThingToTest, 53);
+ RUN_TEST(test_TheFourthThingToTest, 58);
+
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_run2.c b/vendor/Unity-2.4.3/test/expectdata/testsample_run2.c
new file mode 100644
index 0000000..c98c697
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_run2.c
@@ -0,0 +1,70 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(); \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_custom_setup();
+}
+
+/*=======Suite Teardown=====*/
+static int suite_teardown(int num_failures)
+{
+a_custom_teardown();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ suite_setup();
+ UnityBegin("testdata/testsample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+ RUN_TEST(test_TheThirdThingToTest, 53);
+ RUN_TEST(test_TheFourthThingToTest, 58);
+
+ return suite_teardown(UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/expectdata/testsample_yaml.c b/vendor/Unity-2.4.3/test/expectdata/testsample_yaml.c
new file mode 100644
index 0000000..3316024
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/expectdata/testsample_yaml.c
@@ -0,0 +1,71 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ CEXCEPTION_T e; \
+ Try { \
+ setUp(); \
+ TestFunc(); \
+ } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "two.h"
+#include "three.h"
+#include <four.h>
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_yaml_setup();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+ suite_setup();
+ UnityBegin("testdata/testsample.c");
+ RUN_TEST(test_TheFirstThingToTest, 21);
+ RUN_TEST(test_TheSecondThingToTest, 43);
+ RUN_TEST(test_TheThirdThingToTest, 53);
+ RUN_TEST(test_TheFourthThingToTest, 58);
+
+ return (UnityEnd());
+}
diff --git a/vendor/Unity-2.4.3/test/rakefile b/vendor/Unity-2.4.3/test/rakefile
new file mode 100644
index 0000000..4a2f3d2
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/rakefile
@@ -0,0 +1,125 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/'
+$verbose = false
+
+require 'rake'
+require 'rake/clean'
+require UNITY_ROOT + 'rakefile_helper'
+require 'rspec/core/rake_task'
+
+TEMP_DIRS = [
+ File.join(UNITY_ROOT, 'build'),
+ File.join(UNITY_ROOT, 'sandbox')
+]
+
+TEMP_DIRS.each do |dir|
+ directory(dir)
+ CLOBBER.include(dir)
+end
+
+task :prepare_for_tests => TEMP_DIRS
+
+include RakefileHelpers
+
+# Load proper GCC as defult configuration
+DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml'
+configure_toolchain(DEFAULT_CONFIG_FILE)
+
+desc "Test unity with its own unit tests"
+task :unit => [:prepare_for_tests] do
+ run_tests unit_test_files
+end
+
+desc "Test unity's helper scripts"
+task :scripts => [:prepare_for_tests] do
+ Dir['tests/test_*.rb'].each do |scriptfile|
+ require "./"+scriptfile
+ end
+end
+
+desc "Run all rspecs"
+RSpec::Core::RakeTask.new(:spec) do |t|
+ t.pattern = 'spec/**/*_spec.rb'
+end
+
+desc "Generate test summary"
+task :summary do
+ report_summary
+end
+
+desc "Build and test Unity"
+task :all => [:clean, :prepare_for_tests, :scripts, :unit, :style, :summary]
+task :default => [:clobber, :all]
+task :ci => [:no_color, :default]
+task :cruise => [:no_color, :default]
+
+desc "Load configuration"
+task :config, :config_file do |t, args|
+ configure_toolchain(args[:config_file])
+end
+
+task :no_color do
+ $colour_output = false
+end
+
+task :verbose do
+ $verbose = true
+end
+
+namespace :style do
+ desc "Check style"
+ task :check do
+ report "\nVERIFYING RUBY STYLE"
+ report execute("rubocop ../auto ../examples ../extras --config .rubocop.yml", true)
+ report "Styling Ruby:PASS"
+ end
+
+ namespace :check do
+ Dir['../**/*.rb'].each do |f|
+ filename = File.basename(f, '.rb')
+ desc "Check Style of #{filename}"
+ task filename.to_sym => ['style:clean'] do
+ report execute("rubocop #{f} --color --config .rubocop.yml", true)
+ report "Style Checked for #{f}"
+ end
+ end
+ end
+
+ desc "Fix Style of all C Code"
+ task :c do
+ run_astyle("../src/*.* ../extras/fixture/src/*.*")
+ end
+
+ namespace :c do
+ Dir['../{src,extras/**}/*.{c,h}'].each do |f|
+ filename = File.basename(f)[0..-3]
+ desc "Check Style of #{filename}"
+ task filename.to_sym do
+ run_astyle f
+ end
+ end
+ end
+
+ desc "Attempt to Autocorrect style"
+ task :auto => ['style:clean'] do
+ execute("rubocop ../auto ../examples ../extras --auto-correct --config .rubocop.yml")
+ report "Autocorrected What We Could."
+ end
+
+ desc "Update style todo list"
+ task :todo => ['style:clean'] do
+ execute("rubocop ../auto ../examples ../extras --auto-gen-config --config .rubocop.yml")
+ report "Updated Style TODO List."
+ end
+
+ task :clean do
+ File.delete(".rubocop_todo.yml") if File.exists?(".rubocop_todo.yml")
+ end
+end
+
+task :style => ['style:check']
diff --git a/vendor/Unity-2.4.3/test/rakefile_helper.rb b/vendor/Unity-2.4.3/test/rakefile_helper.rb
new file mode 100644
index 0000000..1fd60c5
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/rakefile_helper.rb
@@ -0,0 +1,260 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+require 'yaml'
+require 'fileutils'
+require UNITY_ROOT + '../auto/unity_test_summary'
+require UNITY_ROOT + '../auto/generate_test_runner'
+require UNITY_ROOT + '../auto/colour_reporter'
+
+module RakefileHelpers
+ C_EXTENSION = '.c'.freeze
+ def load_configuration(config_file)
+ return if $configured
+
+ $cfg_file = "targets/#{config_file}" unless config_file =~ /[\\|\/]/
+ $cfg = YAML.load(File.read($cfg_file))
+ $colour_output = false unless $cfg['colour']
+ $configured = true if config_file != DEFAULT_CONFIG_FILE
+ end
+
+ def configure_clean
+ CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil?
+ end
+
+ def configure_toolchain(config_file = DEFAULT_CONFIG_FILE)
+ config_file += '.yml' unless config_file =~ /\.yml$/
+ config_file = config_file unless config_file =~ /[\\|\/]/
+ load_configuration(config_file)
+ configure_clean
+ end
+
+ def unit_test_files
+ path = $cfg['compiler']['unit_tests_path'] + 'test*' + C_EXTENSION
+ path.tr!('\\', '/')
+ FileList.new(path)
+ end
+
+ def local_include_dirs
+ include_dirs = $cfg['compiler']['includes']['items'].dup
+ include_dirs.delete_if { |dir| dir.is_a?(Array) }
+ include_dirs
+ end
+
+ def extract_headers(filename)
+ includes = []
+ lines = File.readlines(filename)
+ lines.each do |line|
+ m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/)
+ includes << m[1] unless m.nil?
+ end
+ includes
+ end
+
+ def find_source_file(header, paths)
+ paths.each do |dir|
+ src_file = dir + header.ext(C_EXTENSION)
+ return src_file if File.exist?(src_file)
+ end
+ nil
+ end
+
+ def tackit(strings)
+ result = if strings.is_a?(Array)
+ "\"#{strings.join}\""
+ else
+ strings
+ end
+ result
+ end
+
+ def squash(prefix, items)
+ result = ''
+ items.each { |item| result += " #{prefix}#{tackit(item)}" }
+ result
+ end
+
+ def should(behave, &block)
+ if block
+ puts 'Should ' + behave
+ yield block
+ else
+ puts "UNIMPLEMENTED CASE: Should #{behave}"
+ end
+ end
+
+ def build_compiler_fields(inject_defines)
+ command = tackit($cfg['compiler']['path'])
+ defines = if $cfg['compiler']['defines']['items'].nil?
+ ''
+ else
+ squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=putcharSpy'] + ['UNITY_OUTPUT_CHAR_HEADER_DECLARATION=putcharSpy\(int\)'] + inject_defines)
+ end
+ options = squash('', $cfg['compiler']['options'])
+ includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
+ includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+
+ { :command => command, :defines => defines, :options => options, :includes => includes }
+ end
+
+ def compile(file, defines = [])
+ compiler = build_compiler_fields(defines)
+ cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " \
+ "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}"
+ obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}"
+ execute(cmd_str + obj_file)
+
+ obj_file
+ end
+
+ def build_linker_fields
+ command = tackit($cfg['linker']['path'])
+ options = if $cfg['linker']['options'].nil?
+ ''
+ else
+ squash('', $cfg['linker']['options'])
+ end
+ includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?
+ ''
+ else
+ squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items'])
+ end.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+
+ { :command => command, :options => options, :includes => includes }
+ end
+
+ def link_it(exe_name, obj_list)
+ linker = build_linker_fields
+ cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " +
+ (obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join +
+ $cfg['linker']['bin_files']['prefix'] + ' ' +
+ $cfg['linker']['bin_files']['destination'] +
+ exe_name + $cfg['linker']['bin_files']['extension']
+ execute(cmd_str)
+ end
+
+ def build_simulator_fields
+ return nil if $cfg['simulator'].nil?
+ command = if $cfg['simulator']['path'].nil?
+ ''
+ else
+ (tackit($cfg['simulator']['path']) + ' ')
+ end
+ pre_support = if $cfg['simulator']['pre_support'].nil?
+ ''
+ else
+ squash('', $cfg['simulator']['pre_support'])
+ end
+ post_support = if $cfg['simulator']['post_support'].nil?
+ ''
+ else
+ squash('', $cfg['simulator']['post_support'])
+ end
+
+ { :command => command, :pre_support => pre_support, :post_support => post_support }
+ end
+
+ def run_astyle(style_what)
+ report "Styling C Code..."
+ command = "AStyle " \
+ "--style=allman --indent=spaces=4 --indent-switches --indent-preproc-define --indent-preproc-block " \
+ "--pad-oper --pad-comma --unpad-paren --pad-header " \
+ "--align-pointer=type --align-reference=name " \
+ "--add-brackets --mode=c --suffix=none " \
+ "#{style_what}"
+ execute(command, false)
+ report "Styling C:PASS"
+ end
+
+ def execute(command_string, ok_to_fail = false)
+ report command_string if $verbose
+ output = `#{command_string}`.chomp
+ report(output) if $verbose && !output.nil? && !output.empty?
+ raise "Command failed. (Returned #{$?.exitstatus})" if !$?.exitstatus.zero? && !ok_to_fail
+ output
+ end
+
+ def report_summary
+ summary = UnityTestSummary.new
+ summary.root = UNITY_ROOT
+ results_glob = "#{$cfg['compiler']['build_path']}*.test*"
+ results_glob.tr!('\\', '/')
+ results = Dir[results_glob]
+ summary.targets = results
+ report summary.run
+ end
+
+ def run_tests(test_files)
+ report 'Running Unity system tests...'
+
+ # Tack on TEST define for compiling unit tests
+ load_configuration($cfg_file)
+ test_defines = ['TEST']
+ $cfg['compiler']['defines']['items'] ||= []
+ $cfg['compiler']['defines']['items'] << 'TEST'
+
+ include_dirs = local_include_dirs
+
+ # Build and execute each unit test
+ test_files.each do |test|
+ obj_list = []
+
+ unless $cfg['compiler']['aux_sources'].nil?
+ $cfg['compiler']['aux_sources'].each do |aux|
+ obj_list << compile(aux, test_defines)
+ end
+ end
+
+ # Detect dependencies and build required modules
+ extract_headers(test).each do |header|
+ # Compile corresponding source file if it exists
+ src_file = find_source_file(header, include_dirs)
+
+ obj_list << compile(src_file, test_defines) unless src_file.nil?
+ end
+
+ # Build the test runner (generate if configured to do so)
+ test_base = File.basename(test, C_EXTENSION)
+
+ runner_name = test_base + '_Runner.c'
+
+ runner_path = if $cfg['compiler']['runner_path'].nil?
+ $cfg['compiler']['build_path'] + runner_name
+ else
+ $cfg['compiler']['runner_path'] + runner_name
+ end
+
+ options = $cfg[:unity]
+ options[:use_param_tests] = test =~ /parameterized/ ? true : false
+ UnityTestRunnerGenerator.new(options).run(test, runner_path)
+ obj_list << compile(runner_path, test_defines)
+
+ # Build the test module
+ obj_list << compile(test, test_defines)
+
+ # Link the test executable
+ link_it(test_base, obj_list)
+
+ # Execute unit test and generate results file
+ simulator = build_simulator_fields
+ executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension']
+ cmd_str = if simulator.nil?
+ executable
+ else
+ "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}"
+ end
+ output = execute(cmd_str)
+ test_results = $cfg['compiler']['build_path'] + test_base
+ if output.match(/OK$/m).nil?
+ test_results += '.testfail'
+ else
+ report output unless $verbose # Verbose already prints this line, as does a failure
+ test_results += '.testpass'
+ end
+ File.open(test_results, 'w') { |f| f.print output }
+ end
+ end
+end
diff --git a/vendor/Unity-2.4.3/test/spec/generate_module_existing_file_spec.rb b/vendor/Unity-2.4.3/test/spec/generate_module_existing_file_spec.rb
new file mode 100644
index 0000000..74e7fc8
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/spec/generate_module_existing_file_spec.rb
@@ -0,0 +1,158 @@
+
+require '../auto/generate_module.rb'
+require 'fileutils'
+
+def touch_src(file)
+ FileUtils.touch "sandbox/src/#{file}"
+end
+
+def touch_test(file)
+ FileUtils.touch "sandbox/test/#{file}"
+end
+
+def create_src_with_known_content(file)
+ File.open("sandbox/src/#{file}", "w") {|f| f.write("the original #{file}")}
+end
+
+def create_test_with_known_content(file)
+ File.open("sandbox/test/#{file}", "w") {|f| f.write("the original #{file}")}
+end
+
+def expect_src_content_didnt_change(file)
+ expect(File.read("sandbox/src/#{file}")).to eq("the original #{file}")
+end
+
+def expect_test_content_didnt_change(file)
+ expect(File.read("sandbox/test/#{file}")).to eq("the original #{file}")
+end
+
+def expect_src_file_to_exist(file)
+ expect(File.exist?("sandbox/src/#{file}")).to be true
+end
+
+def expect_test_file_to_exist(file)
+ expect(File.exist?("sandbox/test/#{file}")).to be true
+end
+
+describe "UnityModuleGenerator" do
+
+ before do
+ # clean sandbox and setup our "project" folders
+ FileUtils.rm_rf "sandbox"
+ FileUtils.mkdir_p "sandbox"
+ FileUtils.mkdir_p "sandbox/src"
+ FileUtils.mkdir_p "sandbox/test"
+
+ @options = {
+ :path_src => "sandbox/src",
+ :path_tst => "sandbox/test",
+ }
+ end
+
+ context "with src pattern" do
+ before do
+ @options[:pattern] = "src"
+ end
+
+ it "fails when all files already exist" do
+ # create an existing triad of files
+ touch_src "meh.c"
+ touch_src "meh.h"
+ touch_test "Testmeh.c"
+ expect {
+ UnityModuleGenerator.new(@options).generate("meh")
+ }.to raise_error("ERROR: File meh already exists. Exiting.")
+ end
+
+ it "creates the test file if the source and header files exist" do
+ # Create the existing files.
+ touch_src "meh.c"
+ touch_src "meh.h"
+
+ UnityModuleGenerator.new(@options).generate("meh")
+
+ expect_test_file_to_exist "Testmeh.c"
+ end
+
+ it "does not alter existing files" do
+ # Create some files with known content.
+ create_src_with_known_content "meh.c"
+ create_src_with_known_content "meh.h"
+
+ UnityModuleGenerator.new(@options).generate("meh")
+
+ expect_src_content_didnt_change "meh.c"
+ expect_src_content_didnt_change "meh.c"
+ end
+
+ it "does not alter existing test files" do
+ # Create some files with known content.
+ create_test_with_known_content "Testmeh.c"
+
+ UnityModuleGenerator.new(@options).generate("meh")
+
+ expect_test_content_didnt_change "Testmeh.c"
+ end
+
+ end
+
+ context "with mch pattern" do
+ before do
+ @options[:pattern] = "mch"
+ end
+
+ it "fails when all files exist" do
+ touch_src "meh_model.c"
+ touch_src "meh_conductor.c"
+ touch_src "meh_hardware.c"
+ touch_src "meh_model.h"
+ touch_src "meh_conductor.h"
+ touch_src "meh_hardware.h"
+ touch_test "Testmeh_model.c"
+ touch_test "Testmeh_conductor.c"
+ touch_test "Testmeh_hardware.c"
+ expect {
+ UnityModuleGenerator.new(@options).generate("meh")
+ }.to raise_error("ERROR: File meh_model already exists. Exiting.")
+ end
+
+ it "creates files that don't exist" do
+ touch_src "meh_model.c"
+ touch_src "meh_conductor.c"
+ touch_src "meh_hardware.c"
+ touch_src "meh_model.h"
+ touch_src "meh_conductor.h"
+
+ UnityModuleGenerator.new(@options).generate("meh")
+
+ expect_src_file_to_exist "meh_hardware.h"
+ expect_test_file_to_exist "Testmeh_model.c"
+ expect_test_file_to_exist "Testmeh_conductor.c"
+ expect_test_file_to_exist "Testmeh_hardware.c"
+ end
+
+ it "does not alter existing source files" do
+ create_src_with_known_content "meh_model.c"
+ create_src_with_known_content "meh_model.c"
+ create_src_with_known_content "meh_model.c"
+ create_src_with_known_content "meh_model.h"
+ create_src_with_known_content "meh_model.c"
+
+ UnityModuleGenerator.new(@options).generate("meh")
+
+ expect_src_content_didnt_change "meh_model.c"
+ expect_src_content_didnt_change "meh_model.c"
+ expect_src_content_didnt_change "meh_model.c"
+ expect_src_content_didnt_change "meh_model.c"
+ end
+
+ it "does not alter existing test files" do
+ create_test_with_known_content "Testmeh_model.c"
+
+ UnityModuleGenerator.new(@options).generate("meh")
+
+ expect_test_content_didnt_change "Testmeh_model.c"
+ end
+
+ end
+end
diff --git a/vendor/Unity-2.4.3/test/targets/clang_file.yml b/vendor/Unity-2.4.3/test/targets/clang_file.yml
new file mode 100644
index 0000000..df1bd24
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/clang_file.yml
@@ -0,0 +1,78 @@
+---
+compiler:
+ path: clang
+ source_path: '../src/'
+ unit_tests_path: &unit_tests_path 'tests/'
+ build_path: &build_path 'build/'
+ options:
+ - '-c'
+ - '-Wall'
+ - '-Wextra'
+ - '-Werror'
+ - '-Wcast-qual'
+ - '-Wconversion'
+ - '-Wdisabled-optimization'
+ - '-Wformat=2'
+ - '-Winit-self'
+ - '-Winline'
+ - '-Winvalid-pch'
+ - '-Wmissing-include-dirs'
+ - '-Wnonnull'
+ - '-Wpacked'
+ - '-Wpointer-arith'
+ - '-Wswitch-default'
+ - '-Wstrict-aliasing'
+ - '-Wstrict-overflow=5'
+ - '-Wuninitialized'
+ - '-Wunused'
+# - '-Wunreachable-code'
+ - '-Wreturn-type'
+ - '-Wshadow'
+ - '-Wundef'
+ - '-Wwrite-strings'
+ - '-Wno-nested-externs'
+ - '-Wno-unused-parameter'
+ - '-Wno-variadic-macros'
+ - '-Wbad-function-cast'
+ - '-fms-extensions'
+ - '-fno-omit-frame-pointer'
+ - '-ffloat-store'
+ - '-fno-common'
+ - '-fstrict-aliasing'
+ - '-std=gnu99'
+ - '-pedantic'
+ - '-O0'
+ includes:
+ prefix: '-I'
+ items:
+ - 'src/'
+ - '../src/'
+ - 'testdata/'
+ - *unit_tests_path
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_INCLUDE_DOUBLE
+ - UNITY_SUPPORT_64
+ - UNITY_OUTPUT_RESULTS_FILE
+ object_files:
+ prefix: '-o'
+ extension: '.o'
+ destination: *build_path
+linker:
+ path: clang
+ options:
+ - -lm
+ - '-m64'
+ includes:
+ prefix: '-I'
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.exe'
+ destination: *build_path
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/clang_strict.yml b/vendor/Unity-2.4.3/test/targets/clang_strict.yml
new file mode 100644
index 0000000..ee05b2a
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/clang_strict.yml
@@ -0,0 +1,78 @@
+---
+compiler:
+ path: clang
+ source_path: '../src/'
+ unit_tests_path: &unit_tests_path 'tests/'
+ build_path: &build_path 'build/'
+ options:
+ - '-c'
+ - '-Wall'
+ - '-Wextra'
+ - '-Werror'
+ - '-Wcast-qual'
+ - '-Wconversion'
+ - '-Wdisabled-optimization'
+ - '-Wformat=2'
+ - '-Winit-self'
+ - '-Winline'
+ - '-Winvalid-pch'
+ - '-Wmissing-include-dirs'
+ - '-Wnonnull'
+ - '-Wpacked'
+ - '-Wpointer-arith'
+ - '-Wswitch-default'
+ - '-Wstrict-aliasing'
+ - '-Wstrict-overflow=5'
+ - '-Wuninitialized'
+ - '-Wunused'
+# - '-Wunreachable-code'
+ - '-Wreturn-type'
+ - '-Wshadow'
+ - '-Wundef'
+ - '-Wwrite-strings'
+ - '-Wno-nested-externs'
+ - '-Wno-unused-parameter'
+ - '-Wno-variadic-macros'
+ - '-Wbad-function-cast'
+ - '-fms-extensions'
+ - '-fno-omit-frame-pointer'
+ #- '-ffloat-store'
+ - '-fno-common'
+ - '-fstrict-aliasing'
+ - '-std=gnu99'
+ - '-pedantic'
+ - '-O0'
+ includes:
+ prefix: '-I'
+ items:
+ - 'src/'
+ - '../src/'
+ - 'testdata/'
+ - *unit_tests_path
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_INCLUDE_DOUBLE
+ - UNITY_SUPPORT_TEST_CASES
+ - UNITY_SUPPORT_64
+ object_files:
+ prefix: '-o'
+ extension: '.o'
+ destination: *build_path
+linker:
+ path: clang
+ options:
+ - -lm
+ - '-m64'
+ includes:
+ prefix: '-I'
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.exe'
+ destination: *build_path
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/gcc_32.yml b/vendor/Unity-2.4.3/test/targets/gcc_32.yml
new file mode 100644
index 0000000..ec1165d
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/gcc_32.yml
@@ -0,0 +1,49 @@
+compiler:
+ path: gcc
+ source_path: '../src/'
+ unit_tests_path: &unit_tests_path 'tests/'
+ build_path: &build_path 'build/'
+ options:
+ - '-c'
+ - '-m32'
+ - '-Wall'
+ - '-Wno-address'
+ - '-std=c99'
+ - '-pedantic'
+ includes:
+ prefix: '-I'
+ items:
+ - 'src/'
+ - '../src/'
+ - 'testdata/'
+ - *unit_tests_path
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_EXCLUDE_STDINT_H
+ - UNITY_EXCLUDE_LIMITS_H
+ - UNITY_INCLUDE_DOUBLE
+ - UNITY_SUPPORT_TEST_CASES
+ - UNITY_INT_WIDTH=32
+ - UNITY_LONG_WIDTH=32
+ object_files:
+ prefix: '-o'
+ extension: '.o'
+ destination: *build_path
+linker:
+ path: gcc
+ options:
+ - -lm
+ - '-m32'
+ includes:
+ prefix: '-I'
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.exe'
+ destination: *build_path
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/gcc_64.yml b/vendor/Unity-2.4.3/test/targets/gcc_64.yml
new file mode 100644
index 0000000..0e273de
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/gcc_64.yml
@@ -0,0 +1,50 @@
+compiler:
+ path: gcc
+ source_path: '../src/'
+ unit_tests_path: &unit_tests_path 'tests/'
+ build_path: &build_path 'build/'
+ options:
+ - '-c'
+ - '-m64'
+ - '-Wall'
+ - '-Wno-address'
+ - '-std=c99'
+ - '-pedantic'
+ includes:
+ prefix: '-I'
+ items:
+ - 'src/'
+ - '../src/'
+ - 'testdata/'
+ - *unit_tests_path
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_EXCLUDE_STDINT_H
+ - UNITY_EXCLUDE_LIMITS_H
+ - UNITY_INCLUDE_DOUBLE
+ - UNITY_SUPPORT_TEST_CASES
+ - UNITY_SUPPORT_64
+ - UNITY_INT_WIDTH=32
+ - UNITY_LONG_WIDTH=64
+ object_files:
+ prefix: '-o'
+ extension: '.o'
+ destination: *build_path
+linker:
+ path: gcc
+ options:
+ - -lm
+ - '-m64'
+ includes:
+ prefix: '-I'
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.exe'
+ destination: *build_path
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/gcc_auto_limits.yml b/vendor/Unity-2.4.3/test/targets/gcc_auto_limits.yml
new file mode 100644
index 0000000..40088ac
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/gcc_auto_limits.yml
@@ -0,0 +1,47 @@
+compiler:
+ path: gcc
+ source_path: '../src/'
+ unit_tests_path: &unit_tests_path 'tests/'
+ build_path: &build_path 'build/'
+ options:
+ - '-c'
+ - '-m64'
+ - '-Wall'
+ - '-Wno-address'
+ - '-std=c99'
+ - '-pedantic'
+ includes:
+ prefix: '-I'
+ items:
+ - 'src/'
+ - '../src/'
+ - 'testdata/'
+ - *unit_tests_path
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_EXCLUDE_STDINT_H
+ - UNITY_INCLUDE_DOUBLE
+ - UNITY_SUPPORT_TEST_CASES
+ - UNITY_SUPPORT_64
+ object_files:
+ prefix: '-o'
+ extension: '.o'
+ destination: *build_path
+linker:
+ path: gcc
+ options:
+ - -lm
+ - '-m64'
+ includes:
+ prefix: '-I'
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.exe'
+ destination: *build_path
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/gcc_auto_stdint.yml b/vendor/Unity-2.4.3/test/targets/gcc_auto_stdint.yml
new file mode 100644
index 0000000..f12165c
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/gcc_auto_stdint.yml
@@ -0,0 +1,59 @@
+compiler:
+ path: gcc
+ source_path: '../src/'
+ unit_tests_path: &unit_tests_path 'tests/'
+ build_path: &build_path 'build/'
+ options:
+ - '-c'
+ - '-m64'
+ - '-Wall'
+ - '-Wno-address'
+ - '-std=c99'
+ - '-pedantic'
+ - '-Wextra'
+ - '-Werror'
+ - '-Wpointer-arith'
+ - '-Wcast-align'
+ - '-Wwrite-strings'
+ - '-Wswitch-default'
+ - '-Wunreachable-code'
+ - '-Winit-self'
+ - '-Wmissing-field-initializers'
+ - '-Wno-unknown-pragmas'
+ - '-Wstrict-prototypes'
+ - '-Wundef'
+ - '-Wold-style-definition'
+ includes:
+ prefix: '-I'
+ items:
+ - 'src/'
+ - '../src/'
+ - 'testdata/'
+ - *unit_tests_path
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_INCLUDE_DOUBLE
+ - UNITY_SUPPORT_TEST_CASES
+ - UNITY_SUPPORT_64
+ object_files:
+ prefix: '-o'
+ extension: '.o'
+ destination: *build_path
+linker:
+ path: gcc
+ options:
+ - -lm
+ - '-m64'
+ includes:
+ prefix: '-I'
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.exe'
+ destination: *build_path
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/gcc_manual_math.yml b/vendor/Unity-2.4.3/test/targets/gcc_manual_math.yml
new file mode 100644
index 0000000..b379e3f
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/gcc_manual_math.yml
@@ -0,0 +1,47 @@
+compiler:
+ path: gcc
+ source_path: '../src/'
+ unit_tests_path: &unit_tests_path 'tests/'
+ build_path: &build_path 'build/'
+ options:
+ - '-c'
+ - '-m64'
+ - '-Wall'
+ - '-Wno-address'
+ - '-std=c99'
+ - '-pedantic'
+ includes:
+ prefix: '-I'
+ items:
+ - 'src/'
+ - '../src/'
+ - 'testdata/'
+ - *unit_tests_path
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_EXCLUDE_MATH_H
+ - UNITY_INCLUDE_DOUBLE
+ - UNITY_SUPPORT_TEST_CASES
+ - UNITY_SUPPORT_64
+ object_files:
+ prefix: '-o'
+ extension: '.o'
+ destination: *build_path
+linker:
+ path: gcc
+ options:
+ - -lm
+ - '-m64'
+ includes:
+ prefix: '-I'
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.exe'
+ destination: *build_path
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/hitech_picc18.yml b/vendor/Unity-2.4.3/test/targets/hitech_picc18.yml
new file mode 100644
index 0000000..2fd4aa3
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/hitech_picc18.yml
@@ -0,0 +1,101 @@
+# rumor has it that this yaml file works for the standard edition of the
+# hitech PICC18 compiler, but not the pro version.
+#
+compiler:
+ path: cd build && picc18
+ source_path: '..\src\'
+ unit_tests_path: &unit_tests_path 'tests\'
+ build_path: &build_path 'build\'
+ options:
+ - --chip=18F87J10
+ - --ide=hitide
+ - --q #quiet please
+ - --asmlist
+ - --codeoffset=0
+ - --emi=wordwrite # External memory interface protocol
+ - --warn=0 # allow all normal warning messages
+ - --errors=10 # Number of errors before aborting compile
+ - --char=unsigned
+ - -Bl # Large memory model
+ - -G # generate symbol file
+ - --cp=16 # 16-bit pointers
+ - --double=24
+ - -N255 # 255-char symbol names
+ - --opt=none # Do not use any compiler optimziations
+ - -c # compile only
+ - -M
+ includes:
+ prefix: '-I'
+ items:
+ - 'c:/Projects/NexGen/Prototypes/CMockTest/src/'
+ - 'c:/Projects/NexGen/Prototypes/CMockTest/mocks/'
+ - 'c:/CMock/src/'
+ - 'c:/CMock/examples/src/'
+ - 'c:/CMock/vendor/unity/src/'
+ - 'c:/CMock/vendor/unity/examples/helper/'
+ - *unit_tests_path
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_INT_WIDTH=16
+ - UNITY_POINTER_WIDTH=16
+ - CMOCK_MEM_STATIC
+ - CMOCK_MEM_SIZE=3000
+ - UNITY_SUPPORT_TEST_CASES
+ - _PICC18
+ object_files:
+ # prefix: '-O' # Hi-Tech doesn't want a prefix. They key off of filename .extensions, instead
+ extension: '.obj'
+ destination: *build_path
+
+linker:
+ path: cd build && picc18
+ options:
+ - --chip=18F87J10
+ - --ide=hitide
+ - --cp=24 # 24-bit pointers. Is this needed for linker??
+ - --double=24 # Is this needed for linker??
+ - -Lw # Scan the pic87*w.lib in the lib/ of the compiler installation directory
+ - --summary=mem,file # info listing
+ - --summary=+psect
+ - --summary=+hex
+ - --output=+intel
+ - --output=+mcof
+ - --runtime=+init # Directs startup code to copy idata, ibigdata and ifardata psects from ROM to RAM.
+ - --runtime=+clear # Directs startup code to clear bss, bigbss, rbss and farbss psects
+ - --runtime=+clib # link in the c-runtime
+ - --runtime=+keep # Keep the generated startup src after its obj is linked
+ - -G # Generate src-level symbol file
+ - -MIWasTheLastToBuild.map
+ - --warn=0 # allow all normal warning messages
+ - -Bl # Large memory model (probably not needed for linking)
+ includes:
+ prefix: '-I'
+ object_files:
+ path: *build_path
+ extension: '.obj'
+ bin_files:
+ prefix: '-O'
+ extension: '.hex'
+ destination: *build_path
+
+simulator:
+ path:
+ pre_support:
+ - 'java -client -jar ' # note space
+ - ['C:\Program Files\HI-TECH Software\HI-TIDE\3.15\lib\', 'simpic18.jar']
+ - 18F87J10
+ post_support:
+
+:cmock:
+ :plugins: []
+ :includes:
+ - Types.h
+ :suite_teardown: |
+ if (num_failures)
+ _FAILED_TEST();
+ else
+ _PASSED_TESTS();
+ return 0;
+
+colour: true
diff --git a/vendor/Unity-2.4.3/test/targets/iar_arm_v4.yml b/vendor/Unity-2.4.3/test/targets/iar_arm_v4.yml
new file mode 100644
index 0000000..2f9f881
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/iar_arm_v4.yml
@@ -0,0 +1,90 @@
+tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\'
+compiler:
+ path: [*tools_root, 'arm\bin\iccarm.exe']
+ source_path: '..\src\'
+ unit_tests_path: &unit_tests_path 'tests\'
+ build_path: &build_path 'build\'
+ options:
+ - --dlib_config
+ - [*tools_root, 'arm\lib\dl4tptinl8n.h']
+ - -z3
+ - --no_cse
+ - --no_unroll
+ - --no_inline
+ - --no_code_motion
+ - --no_tbaa
+ - --no_clustering
+ - --no_scheduling
+ - --debug
+ - --cpu_mode thumb
+ - --endian little
+ - --cpu ARM7TDMI
+ - --stack_align 4
+ - --interwork
+ - -e
+ - --silent
+ - --warnings_are_errors
+ - --fpu None
+ - --diag_suppress Pa050
+ includes:
+ prefix: '-I'
+ items:
+ - [*tools_root, 'arm\inc\']
+ - 'src\'
+ - '..\src\'
+ - 'testdata/'
+ - *unit_tests_path
+ - 'vendor\unity\src\'
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_SUPPORT_64
+ - 'UNITY_SUPPORT_TEST_CASES'
+ object_files:
+ prefix: '-o'
+ extension: '.r79'
+ destination: *build_path
+linker:
+ path: [*tools_root, 'common\bin\xlink.exe']
+ options:
+ - -rt
+ - [*tools_root, 'arm\lib\dl4tptinl8n.r79']
+ - -D_L_EXTMEM_START=0
+ - -D_L_EXTMEM_SIZE=0
+ - -D_L_HEAP_SIZE=120
+ - -D_L_STACK_SIZE=32
+ - -e_small_write=_formatted_write
+ - -s
+ - __program_start
+ - -f
+ - [*tools_root, '\arm\config\lnkarm.xcl']
+ includes:
+ prefix: '-I'
+ items:
+ - [*tools_root, 'arm\config\']
+ - [*tools_root, 'arm\lib\']
+ object_files:
+ path: *build_path
+ extension: '.r79'
+ bin_files:
+ prefix: '-o'
+ extension: '.d79'
+ destination: *build_path
+simulator:
+ path: [*tools_root, 'common\bin\CSpyBat.exe']
+ pre_support:
+ - --silent
+ - [*tools_root, 'arm\bin\armproc.dll']
+ - [*tools_root, 'arm\bin\armsim.dll']
+ post_support:
+ - --plugin
+ - [*tools_root, 'arm\bin\armbat.dll']
+ - --backend
+ - -B
+ - -p
+ - [*tools_root, 'arm\config\ioat91sam7X256.ddf']
+ - -d
+ - sim
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/iar_arm_v5.yml b/vendor/Unity-2.4.3/test/targets/iar_arm_v5.yml
new file mode 100644
index 0000000..223f1a6
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/iar_arm_v5.yml
@@ -0,0 +1,80 @@
+tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 5.3\'
+compiler:
+ path: [*tools_root, 'arm\bin\iccarm.exe']
+ source_path: '..\src\'
+ unit_tests_path: &unit_tests_path 'tests\'
+ build_path: &build_path 'build\'
+ options:
+ - --dlib_config
+ - [*tools_root, 'arm\inc\DLib_Config_Normal.h']
+ - --no_cse
+ - --no_unroll
+ - --no_inline
+ - --no_code_motion
+ - --no_tbaa
+ - --no_clustering
+ - --no_scheduling
+ - --debug
+ - --cpu_mode thumb
+ - --endian=little
+ - --cpu=ARM7TDMI
+ - --interwork
+ - --warnings_are_errors
+ - --fpu=None
+ - --diag_suppress=Pa050
+ - --diag_suppress=Pe111
+ - -e
+ - -On
+ includes:
+ prefix: '-I'
+ items:
+ - [*tools_root, 'arm\inc\']
+ - 'src\'
+ - '..\src\'
+ - 'testdata/'
+ - *unit_tests_path
+ - 'vendor\unity\src\'
+ - 'iar\iar_v5\incIAR\'
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_SUPPORT_64
+ - 'UNITY_SUPPORT_TEST_CASES'
+ object_files:
+ prefix: '-o'
+ extension: '.r79'
+ destination: *build_path
+linker:
+ path: [*tools_root, 'arm\bin\ilinkarm.exe']
+ options:
+ - --redirect _Printf=_PrintfLarge
+ - --redirect _Scanf=_ScanfSmall
+ - --semihosting
+ - --entry __iar_program_start
+ - --config
+ - [*tools_root, 'arm\config\generic.icf']
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.out'
+ destination: *build_path
+simulator:
+ path: [*tools_root, 'common\bin\CSpyBat.exe']
+ pre_support:
+ - --silent
+ - [*tools_root, 'arm\bin\armproc.dll']
+ - [*tools_root, 'arm\bin\armsim.dll']
+ post_support:
+ - --plugin
+ - [*tools_root, 'arm\bin\armbat.dll']
+ - --backend
+ - -B
+ - -p
+ - [*tools_root, 'arm\config\debugger\atmel\ioat91sam7X256.ddf']
+ - -d
+ - sim
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/iar_arm_v5_3.yml b/vendor/Unity-2.4.3/test/targets/iar_arm_v5_3.yml
new file mode 100644
index 0000000..223f1a6
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/iar_arm_v5_3.yml
@@ -0,0 +1,80 @@
+tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 5.3\'
+compiler:
+ path: [*tools_root, 'arm\bin\iccarm.exe']
+ source_path: '..\src\'
+ unit_tests_path: &unit_tests_path 'tests\'
+ build_path: &build_path 'build\'
+ options:
+ - --dlib_config
+ - [*tools_root, 'arm\inc\DLib_Config_Normal.h']
+ - --no_cse
+ - --no_unroll
+ - --no_inline
+ - --no_code_motion
+ - --no_tbaa
+ - --no_clustering
+ - --no_scheduling
+ - --debug
+ - --cpu_mode thumb
+ - --endian=little
+ - --cpu=ARM7TDMI
+ - --interwork
+ - --warnings_are_errors
+ - --fpu=None
+ - --diag_suppress=Pa050
+ - --diag_suppress=Pe111
+ - -e
+ - -On
+ includes:
+ prefix: '-I'
+ items:
+ - [*tools_root, 'arm\inc\']
+ - 'src\'
+ - '..\src\'
+ - 'testdata/'
+ - *unit_tests_path
+ - 'vendor\unity\src\'
+ - 'iar\iar_v5\incIAR\'
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_SUPPORT_64
+ - 'UNITY_SUPPORT_TEST_CASES'
+ object_files:
+ prefix: '-o'
+ extension: '.r79'
+ destination: *build_path
+linker:
+ path: [*tools_root, 'arm\bin\ilinkarm.exe']
+ options:
+ - --redirect _Printf=_PrintfLarge
+ - --redirect _Scanf=_ScanfSmall
+ - --semihosting
+ - --entry __iar_program_start
+ - --config
+ - [*tools_root, 'arm\config\generic.icf']
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.out'
+ destination: *build_path
+simulator:
+ path: [*tools_root, 'common\bin\CSpyBat.exe']
+ pre_support:
+ - --silent
+ - [*tools_root, 'arm\bin\armproc.dll']
+ - [*tools_root, 'arm\bin\armsim.dll']
+ post_support:
+ - --plugin
+ - [*tools_root, 'arm\bin\armbat.dll']
+ - --backend
+ - -B
+ - -p
+ - [*tools_root, 'arm\config\debugger\atmel\ioat91sam7X256.ddf']
+ - -d
+ - sim
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/iar_armcortex_LM3S9B92_v5_4.yml b/vendor/Unity-2.4.3/test/targets/iar_armcortex_LM3S9B92_v5_4.yml
new file mode 100644
index 0000000..c79bacf
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/iar_armcortex_LM3S9B92_v5_4.yml
@@ -0,0 +1,94 @@
+#Default tool path for IAR 5.4 on Windows XP 64bit
+tools_root: &tools_root 'C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\'
+compiler:
+ path: [*tools_root, 'arm\bin\iccarm.exe']
+ source_path: '..\src\'
+ unit_tests_path: &unit_tests_path 'tests\'
+ build_path: &build_path 'build\'
+ options:
+ - --diag_suppress=Pa050
+ #- --diag_suppress=Pe111
+ - --debug
+ - --endian=little
+ - --cpu=Cortex-M3
+ - --no_path_in_file_macros
+ - -e
+ - --fpu=None
+ - --dlib_config
+ - [*tools_root, 'arm\inc\DLib_Config_Normal.h']
+ #- --preinclude --preinclude C:\Vss\T2 Working\common\system.h
+ - --interwork
+ - --warnings_are_errors
+# - Ohz
+ - -Oh
+# - --no_cse
+# - --no_unroll
+# - --no_inline
+# - --no_code_motion
+# - --no_tbaa
+# - --no_clustering
+# - --no_scheduling
+
+ includes:
+ prefix: '-I'
+ items:
+ - [*tools_root, 'arm\inc\']
+ - 'src\'
+ - '..\src\'
+ - 'testdata/'
+ - *unit_tests_path
+ - 'vendor\unity\src\'
+ - 'iar\iar_v5\incIAR\'
+ defines:
+ prefix: '-D'
+ items:
+ - ewarm
+ - PART_LM3S9B92
+ - TARGET_IS_TEMPEST_RB1
+ - USE_ROM_DRIVERS
+ - UART_BUFFERED
+ - UNITY_SUPPORT_64
+ object_files:
+ prefix: '-o'
+ extension: '.r79'
+ destination: *build_path
+linker:
+ path: [*tools_root, 'arm\bin\ilinkarm.exe']
+ options:
+ - --redirect _Printf=_PrintfLarge
+ - --redirect _Scanf=_ScanfSmall
+ - --semihosting
+ - --entry __iar_program_start
+ - --config
+ - [*tools_root, 'arm\config\generic.icf']
+# - ['C:\Temp\lm3s9b92.icf']
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.out'
+ destination: *build_path
+simulator:
+ path: [*tools_root, 'common\bin\CSpyBat.exe']
+ pre_support:
+ #- --silent
+ - [*tools_root, 'arm\bin\armproc.dll']
+ - [*tools_root, 'arm\bin\armsim2.dll']
+ post_support:
+ - --plugin
+ - [*tools_root, 'arm\bin\armbat.dll']
+ - --backend
+ - -B
+ - --endian=little
+ - --cpu=Cortex-M3
+ - --fpu=None
+ - -p
+ - [*tools_root, 'arm\config\debugger\TexasInstruments\iolm3sxxxx.ddf']
+ - --semihosting
+ - --device=LM3SxBxx
+ #- -d
+ #- sim
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/iar_cortexm3_v5.yml b/vendor/Unity-2.4.3/test/targets/iar_cortexm3_v5.yml
new file mode 100644
index 0000000..973de94
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/iar_cortexm3_v5.yml
@@ -0,0 +1,84 @@
+# unit testing under iar compiler / simulator for STM32 Cortex-M3
+
+tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 5.4\'
+compiler:
+ path: [*tools_root, 'arm\bin\iccarm.exe']
+ source_path: '..\src\'
+ unit_tests_path: &unit_tests_path 'tests\'
+ build_path: &build_path 'build\'
+ options:
+ - --dlib_config
+ - [*tools_root, 'arm\inc\DLib_Config_Normal.h']
+ - --no_cse
+ - --no_unroll
+ - --no_inline
+ - --no_code_motion
+ - --no_tbaa
+ - --no_clustering
+ - --no_scheduling
+ - --debug
+ - --cpu_mode thumb
+ - --endian=little
+ - --cpu=Cortex-M3
+ - --interwork
+ - --warnings_are_errors
+ - --fpu=None
+ - --diag_suppress=Pa050
+ - --diag_suppress=Pe111
+ - -e
+ - -On
+ includes:
+ prefix: '-I'
+ items:
+ - [*tools_root, 'arm\inc\']
+ - 'src\'
+ - '..\src\'
+ - 'testdata/'
+ - *unit_tests_path
+ - 'vendor\unity\src\'
+ - 'iar\iar_v5\incIAR\'
+ defines:
+ prefix: '-D'
+ items:
+ - 'IAR'
+ - 'UNITY_SUPPORT_64'
+ - 'UNITY_SUPPORT_TEST_CASES'
+ object_files:
+ prefix: '-o'
+ extension: '.r79'
+ destination: *build_path
+linker:
+ path: [*tools_root, 'arm\bin\ilinkarm.exe']
+ options:
+ - --redirect _Printf=_PrintfLarge
+ - --redirect _Scanf=_ScanfSmall
+ - --semihosting
+ - --entry __iar_program_start
+ - --config
+ - [*tools_root, 'arm\config\generic_cortex.icf']
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.out'
+ destination: *build_path
+simulator:
+ path: [*tools_root, 'common\bin\CSpyBat.exe']
+ pre_support:
+ - --silent
+ - [*tools_root, 'arm\bin\armproc.dll']
+ - [*tools_root, 'arm\bin\armsim.dll']
+ post_support:
+ - --plugin
+ - [*tools_root, 'arm\bin\armbat.dll']
+ - --backend
+ - -B
+ - -p
+ - [*tools_root, 'arm\config\debugger\ST\iostm32f107xx.ddf']
+ - --cpu=Cortex-M3
+ - -d
+ - sim
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/iar_msp430.yml b/vendor/Unity-2.4.3/test/targets/iar_msp430.yml
new file mode 100644
index 0000000..4563af9
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/iar_msp430.yml
@@ -0,0 +1,95 @@
+tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 5.3 MSP430\'
+core_root: &core_root [*tools_root, '430\']
+core_bin: &core_bin [*core_root, 'bin\']
+core_config: &core_config [*core_root, 'config\']
+core_lib: &core_lib [*core_root, 'lib\']
+core_inc: &core_inc [*core_root, 'inc\']
+core_config: &core_config [*core_root, 'config\']
+
+compiler:
+ path: [*core_bin, 'icc430.exe']
+ source_path: '..\src\'
+ unit_tests_path: &unit_tests_path 'tests\'
+ build_path: &build_path 'build\'
+ options:
+ - --dlib_config
+ - [*core_lib, 'dlib\dl430fn.h']
+ - --no_cse
+ - --no_unroll
+ - --no_inline
+ - --no_code_motion
+ - --no_tbaa
+ - --debug
+ - -e
+ - -Ol
+ - --multiplier=16
+ - --double=32
+ - --diag_suppress Pa050
+ - --diag_suppress Pe111
+ includes:
+ prefix: '-I'
+ items:
+ - *core_inc
+ - [*core_inc, 'dlib']
+ - [*core_lib, 'dlib']
+ - 'src\'
+ - '../src/'
+ - 'testdata/'
+ - *unit_tests_path
+ - 'vendor\unity\src'
+ defines:
+ prefix: '-D'
+ items:
+ - '__MSP430F149__'
+ - 'INT_WIDTH=16'
+ - 'UNITY_EXCLUDE_FLOAT'
+ - 'UNITY_SUPPORT_TEST_CASES'
+ object_files:
+ prefix: '-o'
+ extension: '.r43'
+ destination: *build_path
+linker:
+ path: [*core_bin, 'xlink.exe']
+ options:
+ - -rt
+ - [*core_lib, 'dlib\dl430fn.r43']
+ - -e_PrintfTiny=_Printf
+ - -e_ScanfSmall=_Scanf
+ - -s __program_start
+ - -D_STACK_SIZE=50
+ - -D_DATA16_HEAP_SIZE=50
+ - -D_DATA20_HEAP_SIZE=50
+ - -f
+ - [*core_config, 'lnk430f5438.xcl']
+ - -f
+ - [*core_config, 'multiplier.xcl']
+ includes:
+ prefix: '-I'
+ items:
+ - *core_config
+ - *core_lib
+ - [*core_lib, 'dlib']
+ object_files:
+ path: *build_path
+ extension: '.r79'
+ bin_files:
+ prefix: '-o'
+ extension: '.d79'
+ destination: *build_path
+simulator:
+ path: [*tools_root, 'common\bin\CSpyBat.exe']
+ pre_support:
+ - --silent
+ - [*core_bin, '430proc.dll']
+ - [*core_bin, '430sim.dll']
+ post_support:
+ - --plugin
+ - [*core_bin, '430bat.dll']
+ - --backend -B
+ - --cpu MSP430F5438
+ - -p
+ - [*core_config, 'MSP430F5438.ddf']
+ - -d sim
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/targets/iar_sh2a_v6.yml b/vendor/Unity-2.4.3/test/targets/iar_sh2a_v6.yml
new file mode 100644
index 0000000..27e6bee
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/targets/iar_sh2a_v6.yml
@@ -0,0 +1,86 @@
+tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 6.0\'
+compiler:
+ path: [*tools_root, 'sh\bin\iccsh.exe']
+ source_path: '..\src\'
+ unit_tests_path: &unit_tests_path 'tests\'
+ build_path: &build_path 'build\'
+ options:
+ - -e
+ - --char_is_signed
+ - -Ol
+ - --no_cse
+ - --no_unroll
+ - --no_inline
+ - --no_code_motion
+ - --no_tbaa
+ - --no_scheduling
+ - --no_clustering
+ - --debug
+ - --dlib_config
+ - [*tools_root, 'sh\inc\DLib_Product.h']
+ - --double=32
+ - --code_model=huge
+ - --data_model=huge
+ - --core=sh2afpu
+ - --warnings_affect_exit_code
+ - --warnings_are_errors
+ - --mfc
+ - --use_unix_directory_separators
+ - --diag_suppress=Pe161
+ includes:
+ prefix: '-I'
+ items:
+ - [*tools_root, 'sh\inc\']
+ - [*tools_root, 'sh\inc\c']
+ - 'src\'
+ - '..\src\'
+ - 'testdata/'
+ - *unit_tests_path
+ - 'vendor\unity\src\'
+ defines:
+ prefix: '-D'
+ items:
+ - UNITY_SUPPORT_64
+ - 'UNITY_SUPPORT_TEST_CASES'
+ object_files:
+ prefix: '-o'
+ extension: '.o'
+ destination: *build_path
+linker:
+ path: [*tools_root, 'sh\bin\ilinksh.exe']
+ options:
+ - --redirect __Printf=__PrintfSmall
+ - --redirect __Scanf=__ScanfSmall
+ - --config
+ - [*tools_root, 'sh\config\generic.icf']
+ - --config_def _CSTACK_SIZE=0x800
+ - --config_def _HEAP_SIZE=0x800
+ - --config_def _INT_TABLE=0x10
+ - --entry __iar_program_start
+ - --debug_lib
+ object_files:
+ path: *build_path
+ extension: '.o'
+ bin_files:
+ prefix: '-o'
+ extension: '.out'
+ destination: *build_path
+simulator:
+ path: [*tools_root, 'common\bin\CSpyBat.exe']
+ pre_support:
+ - --silent
+ - [*tools_root, 'sh\bin\shproc.dll']
+ - [*tools_root, 'sh\bin\shsim.dll']
+ post_support:
+ - --plugin
+ - [*tools_root, 'sh\bin\shbat.dll']
+ - --backend
+ - -B
+ - --core sh2afpu
+ - -p
+ - [*tools_root, 'sh\config\debugger\io7264.ddf']
+ - -d
+ - sim
+colour: true
+:unity:
+ :plugins: []
diff --git a/vendor/Unity-2.4.3/test/testdata/CException.h b/vendor/Unity-2.4.3/test/testdata/CException.h
new file mode 100644
index 0000000..91ad3e1
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/testdata/CException.h
@@ -0,0 +1,11 @@
+#ifndef CEXCEPTION_H
+#define CEXCEPTION_H
+
+#define CEXCEPTION_BEING_USED 1
+
+#define CEXCEPTION_NONE 0
+#define CEXCEPTION_T int e = 1; (void)
+#define Try if (e)
+#define Catch(a) if (!a)
+
+#endif //CEXCEPTION_H
diff --git a/vendor/Unity-2.4.3/test/testdata/Defs.h b/vendor/Unity-2.4.3/test/testdata/Defs.h
new file mode 100644
index 0000000..d3a90c0
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/testdata/Defs.h
@@ -0,0 +1,8 @@
+#ifndef DEF_H
+#define DEF_H
+
+#define EXTERN_DECL
+
+extern int CounterSuiteSetup;
+
+#endif //DEF_H
diff --git a/vendor/Unity-2.4.3/test/testdata/cmock.h b/vendor/Unity-2.4.3/test/testdata/cmock.h
new file mode 100644
index 0000000..c6149be
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/testdata/cmock.h
@@ -0,0 +1,14 @@
+#ifndef CMOCK_H
+#define CMOCK_H
+
+int CMockMemFreeFinalCounter = 0;
+int mockMock_Init_Counter = 0;
+int mockMock_Verify_Counter = 0;
+int mockMock_Destroy_Counter = 0;
+
+void CMock_Guts_MemFreeFinal(void) { CMockMemFreeFinalCounter++; }
+void mockMock_Init(void) { mockMock_Init_Counter++; }
+void mockMock_Verify(void) { mockMock_Verify_Counter++; }
+void mockMock_Destroy(void) { mockMock_Destroy_Counter++; }
+
+#endif //CMOCK_H
diff --git a/vendor/Unity-2.4.3/test/testdata/mockMock.h b/vendor/Unity-2.4.3/test/testdata/mockMock.h
new file mode 100644
index 0000000..0a2c616
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/testdata/mockMock.h
@@ -0,0 +1,13 @@
+#ifndef MOCK_MOCK_H
+#define MOCK_MOCK_H
+
+extern int mockMock_Init_Counter;
+extern int mockMock_Verify_Counter;
+extern int mockMock_Destroy_Counter;
+extern int CMockMemFreeFinalCounter;
+
+void mockMock_Init(void);
+void mockMock_Verify(void);
+void mockMock_Destroy(void);
+
+#endif //MOCK_MOCK_H
diff --git a/vendor/Unity-2.4.3/test/testdata/testRunnerGenerator.c b/vendor/Unity-2.4.3/test/testdata/testRunnerGenerator.c
new file mode 100644
index 0000000..e036dd9
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/testdata/testRunnerGenerator.c
@@ -0,0 +1,183 @@
+/* This Test File Is Used To Verify Many Combinations Of Using the Generate Test Runner Script */
+
+#include <stdio.h>
+#include "unity.h"
+#include "Defs.h"
+
+#ifdef USE_CEXCEPTION
+#include "CException.h"
+#endif
+
+/* Notes about prefixes:
+ test - normal default prefix. these are "always run" tests for this procedure
+ spec - normal default prefix. required to run default setup/teardown calls.
+ should - normal default prefix.
+ qwiktest - custom prefix for when tests skip all setup/teardown calls.
+ custtest - custom prefix for when tests use custom setup/teardown calls.
+ paratest - custom prefix for when we want to verify parameterized tests.
+ extest - custom prefix only used during cexception
+ suitetest- custom prefix for when we want to use custom suite setup/teardown
+*/
+
+/* Support for Meta Test Rig */
+#define TEST_CASE(a)
+void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests
+
+/* Global Variables Used During These Tests */
+int CounterSetup = 0;
+int CounterTeardown = 0;
+int CounterSuiteSetup = 0;
+
+void setUp(void)
+{
+ CounterSetup = 1;
+}
+
+void tearDown(void)
+{
+ CounterTeardown = 1;
+}
+
+void custom_setup(void)
+{
+ CounterSetup = 2;
+}
+
+void custom_teardown(void)
+{
+ CounterTeardown = 2;
+}
+
+/*
+void test_OldSchoolCommentsShouldBeIgnored(void)
+{
+ TEST_ASSERT_FAIL("Old-School Comments Should Be Ignored");
+}
+*/
+
+void test_ThisTestAlwaysPasses(void)
+{
+ TEST_PASS();
+}
+
+void test_ThisTestAlwaysFails(void)
+{
+ TEST_FAIL_MESSAGE("This Test Should Fail");
+}
+
+void test_ThisTestAlwaysIgnored(void)
+{
+ TEST_IGNORE_MESSAGE("This Test Should Be Ignored");
+}
+
+void qwiktest_ThisTestPassesWhenNoSetupRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(0, CounterSetup, "Setup Was Unexpectedly Run");
+}
+
+void qwiktest_ThisTestPassesWhenNoTeardownRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(0, CounterTeardown, "Teardown Was Unexpectedly Run");
+}
+
+void spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(0, CounterSuiteSetup, "Suite Setup Was Unexpectedly Run");
+}
+
+void spec_ThisTestPassesWhenNormalSetupRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(1, CounterSetup, "Normal Setup Wasn't Run");
+}
+
+void spec_ThisTestPassesWhenNormalTeardownRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(1, CounterTeardown, "Normal Teardown Wasn't Run");
+}
+
+void custtest_ThisTestPassesWhenCustomSetupRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(2, CounterSetup, "Custom Setup Wasn't Run");
+}
+
+void custtest_ThisTestPassesWhenCustomTeardownRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(2, CounterTeardown, "Custom Teardown Wasn't Run");
+}
+
+//void test_NewStyleCommentsShouldBeIgnored(void)
+//{
+// TEST_ASSERT_FAIL("New Style Comments Should Be Ignored");
+//}
+
+void test_NotBeConfusedByLongComplicatedStrings(void)
+{
+ const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n";
+
+ TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are The Same");
+}
+
+void test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings(void)
+{
+ TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True");
+}
+
+void test_StillNotBeConfusedByLongComplicatedStrings(void)
+{
+ const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n";
+
+ TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are Still The Same");
+}
+
+void should_RunTestsStartingWithShouldByDefault(void)
+{
+ TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True");
+}
+
+TEST_CASE(25)
+TEST_CASE(125)
+TEST_CASE(5)
+void paratest_ShouldHandleParameterizedTests(int Num)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(0, (Num % 5), "All The Values Are Divisible By 5");
+}
+
+TEST_CASE(7)
+void paratest_ShouldHandleParameterizedTests2(int Num)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(7, Num, "The Only Call To This Passes");
+}
+
+void paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid(void)
+{
+ TEST_PASS();
+}
+
+TEST_CASE(17)
+void paratest_ShouldHandleParameterizedTestsThatFail(int Num)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(3, Num, "This call should fail");
+}
+
+#ifdef USE_CEXCEPTION
+void extest_ShouldHandleCExceptionInTest(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(1, CEXCEPTION_BEING_USED, "Should be pulling in CException");
+}
+#endif
+
+#ifdef USE_ANOTHER_MAIN
+int custom_main(void);
+
+int main(void)
+{
+ return custom_main();
+}
+#endif
+
+void suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(1, CounterSuiteSetup, "Suite Setup Should Have Run");
+}
+
+
diff --git a/vendor/Unity-2.4.3/test/testdata/testRunnerGeneratorSmall.c b/vendor/Unity-2.4.3/test/testdata/testRunnerGeneratorSmall.c
new file mode 100644
index 0000000..c683749
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/testdata/testRunnerGeneratorSmall.c
@@ -0,0 +1,67 @@
+/* This Test File Is Used To Verify Many Combinations Of Using the Generate Test Runner Script */
+
+#include <stdio.h>
+#include "unity.h"
+#include "Defs.h"
+
+TEST_FILE("some_file.c")
+
+/* Notes about prefixes:
+ test - normal default prefix. these are "always run" tests for this procedure
+ spec - normal default prefix. required to run default setup/teardown calls.
+*/
+
+/* Support for Meta Test Rig */
+#define TEST_CASE(a)
+void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests
+
+/* Global Variables Used During These Tests */
+int CounterSetup = 0;
+int CounterTeardown = 0;
+int CounterSuiteSetup = 0;
+
+void setUp(void)
+{
+ CounterSetup = 1;
+}
+
+void tearDown(void)
+{
+ CounterTeardown = 1;
+}
+
+void custom_setup(void)
+{
+ CounterSetup = 2;
+}
+
+void custom_teardown(void)
+{
+ CounterTeardown = 2;
+}
+
+void test_ThisTestAlwaysPasses(void)
+{
+ TEST_PASS();
+}
+
+void test_ThisTestAlwaysFails(void)
+{
+ TEST_FAIL_MESSAGE("This Test Should Fail");
+}
+
+void test_ThisTestAlwaysIgnored(void)
+{
+ TEST_IGNORE_MESSAGE("This Test Should Be Ignored");
+}
+
+void spec_ThisTestPassesWhenNormalSetupRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(1, CounterSetup, "Normal Setup Wasn't Run");
+}
+
+void spec_ThisTestPassesWhenNormalTeardownRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(1, CounterTeardown, "Normal Teardown Wasn't Run");
+}
+
diff --git a/vendor/Unity-2.4.3/test/testdata/testRunnerGeneratorWithMocks.c b/vendor/Unity-2.4.3/test/testdata/testRunnerGeneratorWithMocks.c
new file mode 100644
index 0000000..7eb0b67
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/testdata/testRunnerGeneratorWithMocks.c
@@ -0,0 +1,192 @@
+/* This Test File Is Used To Verify Many Combinations Of Using the Generate Test Runner Script */
+
+#include <stdio.h>
+#include "unity.h"
+#include "Defs.h"
+#include "mockMock.h"
+
+#ifdef USE_CEXCEPTION
+#include "CException.h"
+#endif
+
+/* Notes about prefixes:
+ test - normal default prefix. these are "always run" tests for this procedure
+ spec - normal default prefix. required to run default setup/teardown calls.
+ should - normal default prefix.
+ qwiktest - custom prefix for when tests skip all setup/teardown calls.
+ custtest - custom prefix for when tests use custom setup/teardown calls.
+ paratest - custom prefix for when we want to verify parameterized tests.
+ extest - custom prefix only used during cexception
+ suitetest- custom prefix for when we want to use custom suite setup/teardown
+*/
+
+/* Support for Meta Test Rig */
+#define TEST_CASE(a)
+void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests
+
+/* Global Variables Used During These Tests */
+int CounterSetup = 0;
+int CounterTeardown = 0;
+int CounterSuiteSetup = 0;
+
+void setUp(void)
+{
+ CounterSetup = 1;
+}
+
+void tearDown(void)
+{
+ CounterTeardown = 1;
+}
+
+void custom_setup(void)
+{
+ CounterSetup = 2;
+}
+
+void custom_teardown(void)
+{
+ CounterTeardown = 2;
+}
+
+/*
+void test_OldSchoolCommentsShouldBeIgnored(void)
+{
+ TEST_ASSERT_FAIL("Old-School Comments Should Be Ignored");
+}
+*/
+
+void test_ThisTestAlwaysPasses(void)
+{
+ TEST_PASS();
+}
+
+void test_ThisTestAlwaysFails(void)
+{
+ TEST_FAIL_MESSAGE("This Test Should Fail");
+}
+
+void test_ThisTestAlwaysIgnored(void)
+{
+ TEST_IGNORE_MESSAGE("This Test Should Be Ignored");
+}
+
+void qwiktest_ThisTestPassesWhenNoSetupRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(0, CounterSetup, "Setup Was Unexpectedly Run");
+}
+
+void qwiktest_ThisTestPassesWhenNoTeardownRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(0, CounterTeardown, "Teardown Was Unexpectedly Run");
+}
+
+void spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(0, CounterSuiteSetup, "Suite Setup Was Unexpectedly Run");
+}
+
+void spec_ThisTestPassesWhenNormalSetupRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(1, CounterSetup, "Normal Setup Wasn't Run");
+}
+
+void spec_ThisTestPassesWhenNormalTeardownRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(1, CounterTeardown, "Normal Teardown Wasn't Run");
+}
+
+void custtest_ThisTestPassesWhenCustomSetupRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(2, CounterSetup, "Custom Setup Wasn't Run");
+}
+
+void custtest_ThisTestPassesWhenCustomTeardownRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(2, CounterTeardown, "Custom Teardown Wasn't Run");
+}
+
+//void test_NewStyleCommentsShouldBeIgnored(void)
+//{
+// TEST_ASSERT_FAIL("New Style Comments Should Be Ignored");
+//}
+
+void test_NotBeConfusedByLongComplicatedStrings(void)
+{
+ const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n";
+
+ TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are The Same");
+}
+
+void test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings(void)
+{
+ TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True");
+}
+
+void test_StillNotBeConfusedByLongComplicatedStrings(void)
+{
+ const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n";
+
+ TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are Still The Same");
+}
+
+void should_RunTestsStartingWithShouldByDefault(void)
+{
+ TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True");
+}
+
+TEST_CASE(25)
+TEST_CASE(125)
+TEST_CASE(5)
+void paratest_ShouldHandleParameterizedTests(int Num)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(0, (Num % 5), "All The Values Are Divisible By 5");
+}
+
+TEST_CASE(7)
+void paratest_ShouldHandleParameterizedTests2(int Num)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(7, Num, "The Only Call To This Passes");
+}
+
+void paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid(void)
+{
+ TEST_PASS();
+}
+
+TEST_CASE(17)
+void paratest_ShouldHandleParameterizedTestsThatFail(int Num)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(3, Num, "This call should fail");
+}
+
+#ifdef USE_CEXCEPTION
+void extest_ShouldHandleCExceptionInTest(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(1, CEXCEPTION_BEING_USED, "Should be pulling in CException");
+}
+#endif
+
+#ifdef USE_ANOTHER_MAIN
+int custom_main(void);
+
+int main(void)
+{
+ return custom_main();
+}
+#endif
+
+void suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan(void)
+{
+ TEST_ASSERT_EQUAL_MESSAGE(1, CounterSuiteSetup, "Suite Setup Should Have Run");
+}
+
+void test_ShouldCallMockInitAndVerifyFunctionsForEachTest(void)
+{
+ int passesOrIgnores = (int)(Unity.NumberOfTests - Unity.TestFailures);
+ TEST_ASSERT_EQUAL_MESSAGE(Unity.NumberOfTests, mockMock_Init_Counter, "Mock Init Should Be Called Once Per Test Started");
+ TEST_ASSERT_EQUAL_MESSAGE(passesOrIgnores, mockMock_Verify_Counter, "Mock Verify Should Be Called Once Per Test Passed");
+ TEST_ASSERT_EQUAL_MESSAGE(Unity.NumberOfTests - 1, mockMock_Destroy_Counter, "Mock Destroy Should Be Called Once Per Test Completed");
+ TEST_ASSERT_EQUAL_MESSAGE(0, CMockMemFreeFinalCounter, "Mock MemFreeFinal Should Not Be Called Until End");
+}
+
diff --git a/vendor/Unity-2.4.3/test/tests/test_generate_test_runner.rb b/vendor/Unity-2.4.3/test/tests/test_generate_test_runner.rb
new file mode 100644
index 0000000..a3536d3
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/tests/test_generate_test_runner.rb
@@ -0,0 +1,1252 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+require '../auto/generate_test_runner.rb'
+
+$generate_test_runner_tests = 0
+$generate_test_runner_failures = 0
+
+OUT_FILE = 'build/testsample_'
+
+RUNNER_TESTS = [
+ { :name => 'DefaultsThroughOptions',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :options => nil, #defaults
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'DefaultsThroughCommandLine',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :cmdline => "", #defaults
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'DefaultsThroughYAMLFile',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :cmdline => "", #defaults
+ :yaml => {}, #defaults
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ShorterFilterOfJustTest',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :test_prefix => "test",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ShorterFilterOfJustShould',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :test_prefix => "should",
+ },
+ :expected => {
+ :to_pass => [ 'should_RunTestsStartingWithShouldByDefault' ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ShorterFilterOfJustSpec',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :test_prefix => "spec",
+ },
+ :expected => {
+ :to_pass => [ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'InjectIncludes',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :includes => ['Defs.h'],
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ParameterizedThroughOptions',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :test_prefix => "paratest",
+ :use_param_tests => true,
+ },
+ :expected => {
+ :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)',
+ 'paratest_ShouldHandleParameterizedTests\(125\)',
+ 'paratest_ShouldHandleParameterizedTests\(5\)',
+ 'paratest_ShouldHandleParameterizedTests2\(7\)',
+ 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)',
+ ],
+ :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ParameterizedThroughCommandLine',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :cmdline => " --test_prefix=\"paratest\" --use_param_tests=1",
+ :expected => {
+ :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)',
+ 'paratest_ShouldHandleParameterizedTests\(125\)',
+ 'paratest_ShouldHandleParameterizedTests\(5\)',
+ 'paratest_ShouldHandleParameterizedTests2\(7\)',
+ 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)',
+ ],
+ :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ParameterizedThroughCommandLineAndYaml',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :cmdline => "--use_param_tests=1",
+ :yaml => {
+ :test_prefix => "paratest"
+ },
+ :expected => {
+ :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)',
+ 'paratest_ShouldHandleParameterizedTests\(125\)',
+ 'paratest_ShouldHandleParameterizedTests\(5\)',
+ 'paratest_ShouldHandleParameterizedTests2\(7\)',
+ 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)',
+ ],
+ :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'CException',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'USE_CEXCEPTION'],
+ :options => {
+ :test_prefix => "extest",
+ :plugins => [ :cexception ],
+ },
+ :expected => {
+ :to_pass => [ 'extest_ShouldHandleCExceptionInTest' ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'CustomSetupAndTeardownThroughOptions',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :test_prefix => "custtest|test",
+ :setup_name => "custom_setup",
+ :teardown_name => "custom_teardown",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'custtest_ThisTestPassesWhenCustomSetupRan',
+ 'custtest_ThisTestPassesWhenCustomTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'CustomSetupAndTeardownThroughCommandLine',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :cmdline => " --test_prefix=\"custtest|test\" --setup_name=\"custom_setup\" --teardown_name=\"custom_teardown\"",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'custtest_ThisTestPassesWhenCustomSetupRan',
+ 'custtest_ThisTestPassesWhenCustomTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'CustomSetupAndTeardownThroughYaml',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :cmdline => " --test_prefix=\"custtest|test\"",
+ :yaml => {
+ :setup_name => "custom_setup",
+ :teardown_name => "custom_teardown",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'custtest_ThisTestPassesWhenCustomSetupRan',
+ 'custtest_ThisTestPassesWhenCustomTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'CustomMain',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', "USE_ANOTHER_MAIN"],
+ :options => {
+ :main_name => "custom_main",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'CustomSuiteSetupAndTeardown',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :includes => ['Defs.h'],
+ :options => {
+ :test_prefix => "suitetest|test",
+ :suite_setup => " CounterSuiteSetup = 1;",
+ :suite_teardown => " return num_failures;",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'MainExternDeclaration',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST'],
+ :includes => ['Defs.h'],
+ :options => {
+ :main_export_decl => "EXTERN_DECL",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+
+ #### WITH MOCKS ##########################################
+
+ { :name => 'DefaultsThroughOptions',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :options => nil, #defaults
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'DefaultsThroughCommandLine',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :cmdline => "", #defaults
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'DefaultsThroughYAMLFile',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :cmdline => "", #defaults
+ :yaml => {}, #defaults
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ShorterFilterOfJustTest',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :test_prefix => "test",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ShorterFilterOfJustShould',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :test_prefix => "should",
+ },
+ :expected => {
+ :to_pass => [ 'should_RunTestsStartingWithShouldByDefault' ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ShorterFilterOfJustSpec',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :test_prefix => "spec",
+ },
+ :expected => {
+ :to_pass => [ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'InjectIncludes',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :includes => ['Defs.h'],
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ParameterizedThroughOptions',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :test_prefix => "paratest",
+ :use_param_tests => true,
+ },
+ :expected => {
+ :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)',
+ 'paratest_ShouldHandleParameterizedTests\(125\)',
+ 'paratest_ShouldHandleParameterizedTests\(5\)',
+ 'paratest_ShouldHandleParameterizedTests2\(7\)',
+ 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)',
+ ],
+ :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ParameterizedThroughCommandLine',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :cmdline => " --test_prefix=\"paratest\" --use_param_tests=1",
+ :expected => {
+ :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)',
+ 'paratest_ShouldHandleParameterizedTests\(125\)',
+ 'paratest_ShouldHandleParameterizedTests\(5\)',
+ 'paratest_ShouldHandleParameterizedTests2\(7\)',
+ 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)',
+ ],
+ :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ParameterizedThroughCommandLineAndYaml',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :cmdline => "--use_param_tests=1",
+ :yaml => {
+ :test_prefix => "paratest"
+ },
+ :expected => {
+ :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)',
+ 'paratest_ShouldHandleParameterizedTests\(125\)',
+ 'paratest_ShouldHandleParameterizedTests\(5\)',
+ 'paratest_ShouldHandleParameterizedTests2\(7\)',
+ 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)',
+ ],
+ :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'CException',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST', 'USE_CEXCEPTION'],
+ :options => {
+ :test_prefix => "extest",
+ :plugins => [ :cexception ],
+ },
+ :expected => {
+ :to_pass => [ 'extest_ShouldHandleCExceptionInTest' ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'CustomSetupAndTeardownThroughOptions',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :options => {
+ :test_prefix => "custtest|test",
+ :setup_name => "custom_setup",
+ :teardown_name => "custom_teardown",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'custtest_ThisTestPassesWhenCustomSetupRan',
+ 'custtest_ThisTestPassesWhenCustomTeardownRan',
+ 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'CustomSetupAndTeardownThroughCommandLine',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :cmdline => " --test_prefix=\"custtest|test\" --setup_name=\"custom_setup\" --teardown_name=\"custom_teardown\"",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'custtest_ThisTestPassesWhenCustomSetupRan',
+ 'custtest_ThisTestPassesWhenCustomTeardownRan',
+ 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'CustomSetupAndTeardownThroughYaml',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :cmdline => " --test_prefix=\"custtest|test\"",
+ :yaml => {
+ :setup_name => "custom_setup",
+ :teardown_name => "custom_teardown",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'custtest_ThisTestPassesWhenCustomSetupRan',
+ 'custtest_ThisTestPassesWhenCustomTeardownRan',
+ 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'CustomMain',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST', "USE_ANOTHER_MAIN"],
+ :options => {
+ :main_name => "custom_main",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'CustomSuiteSetupAndTeardown',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :includes => ['Defs.h'],
+ :options => {
+ :test_prefix => "suitetest|test",
+ :suite_setup => " CounterSuiteSetup = 1;",
+ :suite_teardown => " return num_failures;",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan',
+ 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'MainExternDeclaration',
+ :testfile => 'testdata/testRunnerGeneratorWithMocks.c',
+ :testdefines => ['TEST'],
+ :includes => ['Defs.h'],
+ :options => {
+ :main_export_decl => "EXTERN_DECL",
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+
+
+ #### WITH ARGS ##########################################
+
+ { :name => 'ArgsThroughOptions',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ArgsThroughCommandLine',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :cmdline => "--cmdline_args=1",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ArgsThroughYAMLFile',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :cmdline => "",
+ :yaml => {
+ :cmdline_args => true,
+ },
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ArgsNameFilterJustTest',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n test_",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ArgsNameFilterJustShould',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n should_",
+ :expected => {
+ :to_pass => [ 'should_RunTestsStartingWithShouldByDefault' ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsNameFilterTestAndShould',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n should_,test_",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault' ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ArgsNameFilterWithWildcardOnFile',
+ :testfile => 'testdata/testRunnerGeneratorSmall.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n testRunnerGeneratorSma*",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan' ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ArgsNameFilterWithWildcardAsName',
+ :testfile => 'testdata/testRunnerGeneratorSmall.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n testRunnerGeneratorSmall:*",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan' ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ArgsNameFilterWithWildcardOnName',
+ :testfile => 'testdata/testRunnerGeneratorSmall.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n testRunnerGeneratorSmall:test_*",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses' ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ArgsNameFilterWithWildcardAndShortName',
+ :testfile => 'testdata/testRunnerGeneratorSmall.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n testRunnerGeneratorSmall:te*",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses' ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ArgsNameFilterWithWildcardOnBoth',
+ :testfile => 'testdata/testRunnerGeneratorSmall.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n testRunnerGeneratorSm*:*",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan' ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ArgsExcludeFilterJustTest',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-x test_",
+ :expected => {
+ :to_pass => [ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ 'should_RunTestsStartingWithShouldByDefault',
+ ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsIncludeAndExcludeFilter',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ :includes => ['Defs.h'],
+ },
+ :cmdline_args => "-n test_ -x Ignored",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsIncludeSingleTest',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n ThisTestAlwaysPasses",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses' ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsIncludeSingleTestInSpecificFile',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n testRunnerGenerator:ThisTestAlwaysPasses",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses' ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsIncludeTestFileWithExtension',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n testRunnerGenerator.c:ThisTestAlwaysPasses",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses' ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsIncludeDoubleQuotes',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n \"testRunnerGenerator:ThisTestAlwaysPasses,test_ThisTestAlwaysFails\"",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses' ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsIncludeSingleQuotes',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n 'testRunnerGenerator:ThisTestAlwaysPasses,test_ThisTestAlwaysFails'",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses' ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsIncludeAValidTestForADifferentFile',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n AnotherFile:ThisTestDoesNotExist",
+ :expected => {
+ :to_pass => [ ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsIncludeNoTests',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n ThisTestDoesNotExist",
+ :expected => {
+ :to_pass => [ ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsExcludeAllTests',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-x _",
+ :expected => {
+ :to_pass => [ ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsIncludeFullFile',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n testRunnerGenerator",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses',
+ 'spec_ThisTestPassesWhenNormalSetupRan',
+ 'spec_ThisTestPassesWhenNormalTeardownRan',
+ 'test_NotBeConfusedByLongComplicatedStrings',
+ 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings',
+ 'test_StillNotBeConfusedByLongComplicatedStrings',
+ 'should_RunTestsStartingWithShouldByDefault',
+ 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan',
+ ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ 'test_ThisTestAlwaysIgnored' ],
+ }
+ },
+
+ { :name => 'ArgsIncludeWithAlternateFlag',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-f=\"testRunnerGenerator:ThisTestAlwaysPasses,test_ThisTestAlwaysFails\"",
+ :expected => {
+ :to_pass => [ 'test_ThisTestAlwaysPasses' ],
+ :to_fail => [ 'test_ThisTestAlwaysFails' ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsIncludeWithParameterized',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :cmdline => "--use_param_tests=1",
+ :yaml => {
+ :cmdline_args => true,
+ :test_prefix => "paratest"
+ },
+ :cmdline_args => "-n ShouldHandleParameterizedTests",
+ :expected => {
+ :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)',
+ 'paratest_ShouldHandleParameterizedTests\(125\)',
+ 'paratest_ShouldHandleParameterizedTests\(5\)',
+ 'paratest_ShouldHandleParameterizedTests2\(7\)',
+ ],
+ :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ],
+ :to_ignore => [ ],
+ }
+ },
+
+ { :name => 'ArgsList',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-l",
+ :expected => {
+ :to_pass => [ ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ :text => [ "testRunnerGenerator",
+ "test_ThisTestAlwaysPasses",
+ "test_ThisTestAlwaysFails",
+ "test_ThisTestAlwaysIgnored",
+ "spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan",
+ "spec_ThisTestPassesWhenNormalSetupRan",
+ "spec_ThisTestPassesWhenNormalTeardownRan",
+ "test_NotBeConfusedByLongComplicatedStrings",
+ "test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings",
+ "test_StillNotBeConfusedByLongComplicatedStrings",
+ "should_RunTestsStartingWithShouldByDefault"
+ ]
+ }
+ },
+
+ { :name => 'ArgsListParameterized',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :test_prefix => "paratest",
+ :use_param_tests => true,
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-l",
+ :expected => {
+ :to_pass => [ ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ :text => [ "testRunnerGenerator",
+ 'paratest_ShouldHandleParameterizedTests\(25\)',
+ 'paratest_ShouldHandleParameterizedTests\(125\)',
+ 'paratest_ShouldHandleParameterizedTests\(5\)',
+ 'paratest_ShouldHandleParameterizedTests2\(7\)',
+ 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)',
+ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)'
+ ],
+ }
+ },
+
+ { :name => 'ArgsIncompleteIncludeFlags',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-n",
+ :expected => {
+ :to_pass => [ ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ :text => [ "ERROR: No Test String to Include Matches For" ],
+ }
+ },
+
+ { :name => 'ArgsIncompleteExcludeFlags',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-x",
+ :expected => {
+ :to_pass => [ ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ :text => [ "ERROR: No Test String to Exclude Matches For" ],
+ }
+ },
+
+ { :name => 'ArgsIllegalFlags',
+ :testfile => 'testdata/testRunnerGenerator.c',
+ :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'],
+ :options => {
+ :cmdline_args => true,
+ },
+ :cmdline_args => "-z",
+ :expected => {
+ :to_pass => [ ],
+ :to_fail => [ ],
+ :to_ignore => [ ],
+ :text => [ "ERROR: Unknown Option z" ],
+ }
+ },
+]
+
+def runner_test(test, runner, expected, test_defines, cmdline_args)
+ # Tack on TEST define for compiling unit tests
+ load_configuration($cfg_file)
+
+ #compile objects
+ obj_list = [
+ compile(runner, test_defines),
+ compile(test, test_defines),
+ compile('../src/unity.c', test_defines),
+ ]
+
+ # Link the test executable
+ test_base = File.basename(test, C_EXTENSION)
+ link_it(test_base, obj_list)
+
+ # Execute unit test and generate results file
+ simulator = build_simulator_fields
+ cmdline_args ||= ""
+ executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] + " #{cmdline_args}"
+ cmd_str = if simulator.nil?
+ executable
+ else
+ "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}"
+ end
+ output = execute(cmd_str, true)
+
+ #compare to the expected pass/fail
+ allgood = expected[:to_pass].inject(true) {|s,v| s && verify_match(/#{v}:PASS/, output) }
+ allgood = expected[:to_fail].inject(allgood) {|s,v| s && verify_match(/#{v}:FAIL/, output) }
+ allgood = expected[:to_ignore].inject(allgood) {|s,v| s && verify_match(/#{v}:IGNORE/, output) }
+
+ #verify there weren't more pass/fail/etc than expected
+ allgood &&= verify_number( expected[:to_pass], /(:PASS)/, output)
+ allgood &&= verify_number( expected[:to_fail], /(:FAIL)/, output)
+ allgood &&= verify_number( expected[:to_ignore], /(:IGNORE)/, output)
+
+ #if we care about any other text, check that too
+ if (expected[:text])
+ allgood = expected[:text].inject(allgood) {|s,v| s && verify_match(/#{v}/, output) }
+ allgood &&= verify_number( expected[:text], /.+/, output )
+ end
+
+ report output if (!allgood && !$verbose) #report failures if not already reporting everything
+ return allgood
+end
+
+def verify_match(expression, output)
+ if (expression =~ output)
+ return true
+ else
+ report " FAIL: No Match For /#{expression.to_s}/"
+ return false
+ end
+end
+
+def verify_number(expected, expression, output)
+ exp = expected.length
+ act = output.scan(expression).length
+ if (exp == act)
+ return true
+ else
+ report " FAIL: Expected #{exp} Matches For /#{expression.to_s}/. Was #{act}"
+ return false
+ end
+end
+
+RUNNER_TESTS.each do |testset|
+ basename = File.basename(testset[:testfile], C_EXTENSION)
+ testset_name = "Runner_#{basename}_#{testset[:name]}"
+ should testset_name do
+ runner_name = OUT_FILE + testset[:name] + '_runner.c'
+
+ #create a yaml file first if required
+ yaml_option = ""
+ if (testset[:yaml])
+ File.open("build/runner_options.yml",'w') {|f| f << { :unity => testset[:yaml] }.to_yaml }
+ yaml_option = "build/runner_options.yml"
+ end
+
+ #run script via command line or through hash function call, as requested
+ if (testset[:cmdline])
+ cmdstr = "ruby ../auto/generate_test_runner.rb #{yaml_option} #{testset[:cmdline]} \"#{testset[:testfile]}\" \"#{runner_name}\""
+ `#{cmdstr}`
+ else
+ UnityTestRunnerGenerator.new(testset[:options]).run(testset[:testfile], runner_name)
+ end
+
+ #test the script against the specified test file and check results
+ if (runner_test(testset[:testfile], runner_name, testset[:expected], testset[:testdefines], testset[:cmdline_args]))
+ report "#{testset_name}:PASS"
+ else
+ report "#{testset_name}:FAIL"
+ $generate_test_runner_failures += 1
+ end
+ $generate_test_runner_tests += 1
+ end
+end
+
+raise "There were #{$generate_test_runner_failures.to_s} failures while testing generate_test_runner.rb" if ($generate_test_runner_failures > 0)
diff --git a/vendor/Unity-2.4.3/test/tests/testparameterized.c b/vendor/Unity-2.4.3/test/tests/testparameterized.c
new file mode 100644
index 0000000..aa6d173
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/tests/testparameterized.c
@@ -0,0 +1,110 @@
+/* ==========================================
+ Unity Project - A Test Framework for C
+ Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#include <setjmp.h>
+#include <stdio.h>
+#include "unity.h"
+
+void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests
+
+#define TEST_CASE(...)
+
+#define EXPECT_ABORT_BEGIN \
+ if (TEST_PROTECT()) \
+ {
+
+#define VERIFY_FAILS_END \
+ } \
+ Unity.CurrentTestFailed = (Unity.CurrentTestFailed != 0) ? 0 : 1; \
+ if (Unity.CurrentTestFailed == 1) { \
+ SetToOneMeanWeAlreadyCheckedThisGuy = 1; \
+ UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \
+ UNITY_OUTPUT_CHAR(':'); \
+ UnityPrint(Unity.CurrentTestName); \
+ UnityPrint(":FAIL: [[[[ Test Should Have Failed But Did Not ]]]]"); \
+ UNITY_OUTPUT_CHAR('\n'); \
+ }
+
+#define VERIFY_IGNORES_END \
+ } \
+ Unity.CurrentTestFailed = (Unity.CurrentTestIgnored != 0) ? 0 : 1; \
+ Unity.CurrentTestIgnored = 0; \
+ if (Unity.CurrentTestFailed == 1) { \
+ SetToOneMeanWeAlreadyCheckedThisGuy = 1; \
+ UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \
+ UNITY_OUTPUT_CHAR(':'); \
+ UnityPrint(Unity.CurrentTestName); \
+ UnityPrint(":FAIL: [[[[ Test Should Have Ignored But Did Not ]]]]"); \
+ UNITY_OUTPUT_CHAR('\n'); \
+ }
+
+int SetToOneToFailInTearDown;
+int SetToOneMeanWeAlreadyCheckedThisGuy;
+
+void setUp(void)
+{
+ SetToOneToFailInTearDown = 0;
+ SetToOneMeanWeAlreadyCheckedThisGuy = 0;
+}
+
+void tearDown(void)
+{
+ if (SetToOneToFailInTearDown == 1)
+ TEST_FAIL_MESSAGE("<= Failed in tearDown");
+ if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0))
+ {
+ UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]");
+ UNITY_OUTPUT_CHAR('\n');
+ }
+}
+
+TEST_CASE(0)
+TEST_CASE(44)
+TEST_CASE((90)+9)
+void test_TheseShouldAllPass(int Num)
+{
+ TEST_ASSERT_TRUE(Num < 100);
+}
+
+TEST_CASE(3)
+TEST_CASE(77)
+TEST_CASE( (99) + 1 - (1))
+void test_TheseShouldAllFail(int Num)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_TRUE(Num > 100);
+ VERIFY_FAILS_END
+}
+
+TEST_CASE(1)
+TEST_CASE(44)
+TEST_CASE(99)
+TEST_CASE(98)
+void test_TheseAreEveryOther(int Num)
+{
+ if (Num & 1)
+ {
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_TRUE(Num > 100);
+ VERIFY_FAILS_END
+ }
+ else
+ {
+ TEST_ASSERT_TRUE(Num < 100);
+ }
+}
+
+void test_NormalPassesStillWork(void)
+{
+ TEST_ASSERT_TRUE(1);
+}
+
+void test_NormalFailsStillWork(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_TRUE(0);
+ VERIFY_FAILS_END
+}
diff --git a/vendor/Unity-2.4.3/test/tests/testunity.c b/vendor/Unity-2.4.3/test/tests/testunity.c
new file mode 100644
index 0000000..af06647
--- /dev/null
+++ b/vendor/Unity-2.4.3/test/tests/testunity.c
@@ -0,0 +1,5337 @@
+/* ==========================================
+ Unity Project - A Test Framework for C
+ Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#include "unity.h"
+#include <string.h>
+#include <stdint.h>
+
+// Dividing by these constants produces +/- infinity.
+// The rationale is given in UnityAssertFloatIsInf's body.
+#ifndef UNITY_EXCLUDE_FLOAT
+static const UNITY_FLOAT f_zero = 0.0f;
+#endif
+
+#ifndef UNITY_EXCLUDE_DOUBLE
+static const UNITY_DOUBLE d_zero = 0.0;
+#endif
+
+#define EXPECT_ABORT_BEGIN \
+ startPutcharSpy(); \
+ if (TEST_PROTECT()) \
+ {
+
+#define VERIFY_FAILS_END \
+ } \
+ endPutcharSpy(); /* start/end Spy to suppress output of failure message */ \
+ Unity.CurrentTestFailed = (Unity.CurrentTestFailed == 1) ? 0 : 1; \
+ if (Unity.CurrentTestFailed == 1) { \
+ SetToOneMeanWeAlreadyCheckedThisGuy = 1; \
+ UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \
+ UNITY_OUTPUT_CHAR(':'); \
+ UnityPrint(Unity.CurrentTestName); \
+ UnityPrint(":FAIL: [[[[ Test Should Have Failed But Did Not ]]]]"); \
+ UNITY_OUTPUT_CHAR('\n'); \
+ }
+
+#define VERIFY_IGNORES_END \
+ } \
+ endPutcharSpy(); /* start/end Spy to suppress output of ignore message */ \
+ Unity.CurrentTestFailed = (Unity.CurrentTestIgnored == 1) ? 0 : 1; \
+ Unity.CurrentTestIgnored = 0; \
+ if (Unity.CurrentTestFailed == 1) { \
+ SetToOneMeanWeAlreadyCheckedThisGuy = 1; \
+ UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \
+ UNITY_OUTPUT_CHAR(':'); \
+ UnityPrint(Unity.CurrentTestName); \
+ UnityPrint(":FAIL: [[[[ Test Should Have Ignored But Did Not ]]]]"); \
+ UNITY_OUTPUT_CHAR('\n'); \
+ }
+
+void startPutcharSpy(void);
+void endPutcharSpy(void);
+char* getBufferPutcharSpy(void);
+
+static int SetToOneToFailInTearDown;
+static int SetToOneMeanWeAlreadyCheckedThisGuy;
+
+void setUp(void)
+{
+ SetToOneToFailInTearDown = 0;
+ SetToOneMeanWeAlreadyCheckedThisGuy = 0;
+}
+
+void tearDown(void)
+{
+ endPutcharSpy(); /* Stop suppressing test output */
+ if (SetToOneToFailInTearDown == 1)
+ {
+ /* These will be skipped internally if already failed/ignored */
+ TEST_FAIL_MESSAGE("<= Failed in tearDown");
+ TEST_IGNORE_MESSAGE("<= Ignored in tearDown");
+ }
+ if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0))
+ {
+ UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]");
+ UNITY_OUTPUT_CHAR('\n');
+ }
+}
+
+void testUnitySizeInitializationReminder(void)
+{
+ /* This test ensures that sizeof(struct UNITY_STORAGE_T) doesn't change. If this
+ * test breaks, go look at the initialization of the Unity global variable
+ * in unity.c and make sure we're filling in the proper fields. */
+ const char* message = "Unexpected size for UNITY_STORAGE_T struct. Please check that "
+ "the initialization of the Unity symbol in unity.c is "
+ "still correct.";
+
+ /* Define a structure with all the same fields as `struct UNITY_STORAGE_T`. */
+#ifdef UNITY_EXCLUDE_DETAILS
+ struct {
+ const char* TestFile;
+ const char* CurrentTestName;
+ UNITY_LINE_TYPE CurrentTestLineNumber;
+ UNITY_COUNTER_TYPE NumberOfTests;
+ UNITY_COUNTER_TYPE TestFailures;
+ UNITY_COUNTER_TYPE TestIgnores;
+ UNITY_COUNTER_TYPE CurrentTestFailed;
+ UNITY_COUNTER_TYPE CurrentTestIgnored;
+#ifndef UNITY_EXCLUDE_SETJMP_H
+ jmp_buf AbortFrame;
+#endif
+ } _Expected_Unity;
+#else
+ struct {
+ const char* TestFile;
+ const char* CurrentTestName;
+ const char* CurrentDetails1;
+ const char* CurrentDetails2;
+ UNITY_LINE_TYPE CurrentTestLineNumber;
+ UNITY_COUNTER_TYPE NumberOfTests;
+ UNITY_COUNTER_TYPE TestFailures;
+ UNITY_COUNTER_TYPE TestIgnores;
+ UNITY_COUNTER_TYPE CurrentTestFailed;
+ UNITY_COUNTER_TYPE CurrentTestIgnored;
+#ifndef UNITY_EXCLUDE_SETJMP_H
+ jmp_buf AbortFrame;
+#endif
+ } _Expected_Unity;
+#endif
+
+ /* Compare our fake structure's size to the actual structure's size. They
+ * should be the same.
+ *
+ * This accounts for alignment, padding, and packing issues that might come
+ * up between different architectures. */
+ TEST_ASSERT_EQUAL_MESSAGE(sizeof(_Expected_Unity), sizeof(Unity), message);
+}
+
+void testPassShouldEndImmediatelyWithPass(void)
+{
+ TEST_PASS();
+ TEST_FAIL_MESSAGE("We should have passed already and finished this test");
+}
+
+void testTrue(void)
+{
+ TEST_ASSERT(1);
+
+ TEST_ASSERT_TRUE(1);
+}
+
+void testFalse(void)
+{
+ TEST_ASSERT_FALSE(0);
+
+ TEST_ASSERT_UNLESS(0);
+}
+
+void testPreviousPass(void)
+{
+ TEST_ASSERT_EQUAL_INT(0U, Unity.TestFailures);
+}
+
+void testNotVanilla(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT(0);
+ VERIFY_FAILS_END
+}
+
+void testNotTrue(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_TRUE(0);
+ VERIFY_FAILS_END
+}
+
+void testNotFalse(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FALSE(1);
+ VERIFY_FAILS_END
+}
+
+void testNotUnless(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UNLESS(1);
+ VERIFY_FAILS_END
+}
+
+void testNotNotEqual(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_NOT_EQUAL(10, 10);
+ VERIFY_FAILS_END
+}
+
+void testFail(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_FAIL_MESSAGE("Expected for testing");
+ VERIFY_FAILS_END
+}
+
+void testIsNull(void)
+{
+ char* ptr1 = NULL;
+ const char* ptr2 = "hello";
+
+ TEST_ASSERT_NULL(ptr1);
+ TEST_ASSERT_NOT_NULL(ptr2);
+}
+
+void testIsNullShouldFailIfNot(void)
+{
+ const char* ptr1 = "hello";
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_NULL(ptr1);
+ VERIFY_FAILS_END
+}
+
+void testNotNullShouldFailIfNULL(void)
+{
+ char* ptr1 = NULL;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_NOT_NULL(ptr1);
+ VERIFY_FAILS_END
+}
+
+void testIgnore(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_IGNORE();
+ TEST_FAIL_MESSAGE("This should not be reached");
+ VERIFY_IGNORES_END
+}
+
+void testIgnoreMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_IGNORE_MESSAGE("This is an expected TEST_IGNORE_MESSAGE string!");
+ TEST_FAIL_MESSAGE("This should not be reached");
+ VERIFY_IGNORES_END
+}
+
+void testNotEqualInts(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT(3982, 3983);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualInt8s(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT8(-127, -126);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualInt16s(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT16(-16383, -16382);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualInt32s(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT32(-2147483647, -2147483648); //use largest 32 bit negative to test printability
+ VERIFY_FAILS_END
+}
+
+void testNotEqualBits(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_BITS(0xFF00, 0x5555, 0x5A55);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUInts(void)
+{
+ UNITY_UINT16 v0, v1;
+
+ v0 = 9000;
+ v1 = 9001;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT(v0, v1);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUInt8s(void)
+{
+ UNITY_UINT8 v0, v1;
+
+ v0 = 254;
+ v1 = 255;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT8(v0, v1);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUInt16s(void)
+{
+ UNITY_UINT16 v0, v1;
+
+ v0 = 65535;
+ v1 = 65534;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT16(v0, v1);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUInt32s(void)
+{
+ UNITY_UINT32 v0, v1;
+
+ v0 = 4294967295;
+ v1 = 4294967294;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT32(v0, v1);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHex8s(void)
+{
+ UNITY_UINT8 v0, v1;
+
+ v0 = 0x23;
+ v1 = 0x22;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX8(v0, v1);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHex8sIfSigned(void)
+{
+ UNITY_INT8 v0, v1;
+
+ v0 = -2;
+ v1 = 2;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX8(v0, v1);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHex16s(void)
+{
+ UNITY_UINT16 v0, v1;
+
+ v0 = 0x1234;
+ v1 = 0x1235;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX16(v0, v1);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHex16sIfSigned(void)
+{
+ UNITY_INT16 v0, v1;
+
+ v0 = -1024;
+ v1 = -1028;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX16(v0, v1);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHex32s(void)
+{
+ UNITY_UINT32 v0, v1;
+
+ v0 = 900000;
+ v1 = 900001;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX32(v0, v1);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHex32sIfSigned(void)
+{
+ UNITY_INT32 v0, v1;
+
+ v0 = -900000;
+ v1 = 900001;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX32(v0, v1);
+ VERIFY_FAILS_END
+}
+
+void testEqualInts(void)
+{
+ int v0, v1;
+ int *p0, *p1;
+
+ v0 = 19467;
+ v1 = 19467;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_INT(1837, 1837);
+ TEST_ASSERT_EQUAL_INT(-27365, -27365);
+ TEST_ASSERT_EQUAL_INT(v0, v1);
+ TEST_ASSERT_EQUAL_INT(19467, v1);
+ TEST_ASSERT_EQUAL_INT(v0, 19467);
+ TEST_ASSERT_EQUAL_INT(*p0, v1);
+ TEST_ASSERT_EQUAL_INT(*p0, *p1);
+ TEST_ASSERT_EQUAL_INT(*p0, 19467);
+}
+
+void testEqualInt8s(void)
+{
+ UNITY_INT8 v0, v1;
+ UNITY_INT8 *p0, *p1;
+
+ v0 = 0x22;
+ v1 = 0x22;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_INT8(0x22, 0x22);
+ TEST_ASSERT_EQUAL_INT8(v0, v1);
+ TEST_ASSERT_EQUAL_INT8(0x22, v1);
+ TEST_ASSERT_EQUAL_INT8(v0, 0x22);
+ TEST_ASSERT_EQUAL_INT8(*p0, v1);
+ TEST_ASSERT_EQUAL_INT8(*p0, *p1);
+ TEST_ASSERT_EQUAL_INT8(*p0, 0x22);
+}
+
+void testEqualInt8sWhenThereAreDifferencesOutside8Bits(void)
+{
+ TEST_ASSERT_EQUAL_INT8(0x321,0x421);
+ TEST_ASSERT_EQUAL_INT8(0xFF21,0x0021);
+}
+
+void testEqualInt16s(void)
+{
+ UNITY_INT16 v0, v1;
+ UNITY_INT16 *p0, *p1;
+
+ v0 = 0x7876;
+ v1 = 0x7876;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_INT16(0x7876, 0x7876);
+ TEST_ASSERT_EQUAL_INT16(v0, v1);
+ TEST_ASSERT_EQUAL_INT16(0x7876, v1);
+ TEST_ASSERT_EQUAL_INT16(v0, 0x7876);
+ TEST_ASSERT_EQUAL_INT16(*p0, v1);
+ TEST_ASSERT_EQUAL_INT16(*p0, *p1);
+ TEST_ASSERT_EQUAL_INT16(*p0, 0x7876);
+}
+
+void testEqualInt16sNegatives(void)
+{
+ UNITY_INT16 v0, v1;
+ UNITY_INT16 *p0, *p1;
+
+ v0 = -7876;
+ v1 = -7876;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_INT16(-7876, -7876);
+ TEST_ASSERT_EQUAL_INT16(v0, v1);
+ TEST_ASSERT_EQUAL_INT16(-7876, v1);
+ TEST_ASSERT_EQUAL_INT16(v0, -7876);
+ TEST_ASSERT_EQUAL_INT16(*p0, v1);
+ TEST_ASSERT_EQUAL_INT16(*p0, *p1);
+ TEST_ASSERT_EQUAL_INT16(*p0, -7876);
+}
+
+void testEqualInt16sWhenThereAreDifferencesOutside16Bits(void)
+{
+ TEST_ASSERT_EQUAL_INT16(0x54321,0x64321);
+ TEST_ASSERT_EQUAL_INT16(0xFFFF4321,0x00004321);
+}
+
+void testEqualInt32s(void)
+{
+ UNITY_INT32 v0, v1;
+ UNITY_INT32 *p0, *p1;
+
+ v0 = 0x78760000;
+ v1 = 0x78760000;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_INT32(0x78760000, 0x78760000);
+ TEST_ASSERT_EQUAL_INT32(v0, v1);
+ TEST_ASSERT_EQUAL_INT32(0x78760000, v1);
+ TEST_ASSERT_EQUAL_INT32(v0, 0x78760000);
+ TEST_ASSERT_EQUAL_INT32(*p0, v1);
+ TEST_ASSERT_EQUAL_INT32(*p0, *p1);
+ TEST_ASSERT_EQUAL_INT32(*p0, 0x78760000);
+}
+
+void testEqualInt32sNegatives(void)
+{
+ UNITY_INT32 v0, v1;
+ UNITY_INT32 *p0, *p1;
+
+ v0 = -123456789;
+ v1 = -123456789;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_INT32(-123456789, -123456789);
+ TEST_ASSERT_EQUAL_INT32(v0, v1);
+ TEST_ASSERT_EQUAL_INT32(-123456789, v1);
+ TEST_ASSERT_EQUAL_INT32(v0, -123456789);
+ TEST_ASSERT_EQUAL_INT32(*p0, v1);
+ TEST_ASSERT_EQUAL_INT32(*p0, *p1);
+ TEST_ASSERT_EQUAL_INT32(*p0, -123456789);
+}
+
+
+void testEqualUints(void)
+{
+ unsigned int v0, v1;
+ unsigned int *p0, *p1;
+
+ v0 = 19467;
+ v1 = 19467;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_UINT(1837, 1837);
+ TEST_ASSERT_EQUAL_UINT(v0, v1);
+ TEST_ASSERT_EQUAL_UINT(19467, v1);
+ TEST_ASSERT_EQUAL_UINT(v0, 19467);
+ TEST_ASSERT_EQUAL_UINT(*p0, v1);
+ TEST_ASSERT_EQUAL_UINT(*p0, *p1);
+ TEST_ASSERT_EQUAL_UINT(*p0, 19467);
+ TEST_ASSERT_EQUAL_UINT(60872u, 60872u);
+}
+
+
+void testEqualUint8s(void)
+{
+ UNITY_UINT8 v0, v1;
+ UNITY_UINT8 *p0, *p1;
+
+ v0 = 0x22;
+ v1 = 0x22;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_UINT8(0x22, 0x22);
+ TEST_ASSERT_EQUAL_UINT8(v0, v1);
+ TEST_ASSERT_EQUAL_UINT8(0x22, v1);
+ TEST_ASSERT_EQUAL_UINT8(v0, 0x22);
+ TEST_ASSERT_EQUAL_UINT8(*p0, v1);
+ TEST_ASSERT_EQUAL_UINT8(*p0, *p1);
+ TEST_ASSERT_EQUAL_UINT8(*p0, 0x22);
+}
+
+void testEqualUint8sWhenThereAreDifferencesOutside8Bits(void)
+{
+ TEST_ASSERT_EQUAL_UINT8(0x321,0x421);
+ TEST_ASSERT_EQUAL_UINT8(0xFF21,0x0021);
+}
+
+void testEqualUint16s(void)
+{
+ UNITY_UINT16 v0, v1;
+ UNITY_UINT16 *p0, *p1;
+
+ v0 = 0x9876;
+ v1 = 0x9876;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_UINT16(0x9876, 0x9876);
+ TEST_ASSERT_EQUAL_UINT16(v0, v1);
+ TEST_ASSERT_EQUAL_UINT16(0x9876, v1);
+ TEST_ASSERT_EQUAL_UINT16(v0, 0x9876);
+ TEST_ASSERT_EQUAL_UINT16(*p0, v1);
+ TEST_ASSERT_EQUAL_UINT16(*p0, *p1);
+ TEST_ASSERT_EQUAL_UINT16(*p0, 0x9876);
+}
+
+void testEqualUint16sWhenThereAreDifferencesOutside16Bits(void)
+{
+ TEST_ASSERT_EQUAL_UINT16(0x54321,0x64321);
+ TEST_ASSERT_EQUAL_UINT16(0xFFFF4321,0x00004321);
+}
+
+void testEqualUint32s(void)
+{
+ UNITY_UINT32 v0, v1;
+ UNITY_UINT32 *p0, *p1;
+
+ v0 = 0x98760000;
+ v1 = 0x98760000;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_UINT32(0x98760000, 0x98760000);
+ TEST_ASSERT_EQUAL_UINT32(v0, v1);
+ TEST_ASSERT_EQUAL_UINT32(0x98760000, v1);
+ TEST_ASSERT_EQUAL_UINT32(v0, 0x98760000);
+ TEST_ASSERT_EQUAL_UINT32(*p0, v1);
+ TEST_ASSERT_EQUAL_UINT32(*p0, *p1);
+ TEST_ASSERT_EQUAL_UINT32(*p0, 0x98760000);
+}
+
+void testNotEqual(void)
+{
+ TEST_ASSERT_NOT_EQUAL(0, 1);
+ TEST_ASSERT_NOT_EQUAL(1, 0);
+ TEST_ASSERT_NOT_EQUAL(100, 101);
+ TEST_ASSERT_NOT_EQUAL(0, -1);
+ TEST_ASSERT_NOT_EQUAL(65535, -65535);
+ TEST_ASSERT_NOT_EQUAL(75, 900);
+ TEST_ASSERT_NOT_EQUAL(-100, -101);
+}
+
+void testEqualHex8s(void)
+{
+ UNITY_UINT8 v0, v1;
+ UNITY_UINT8 *p0, *p1;
+
+ v0 = 0x22;
+ v1 = 0x22;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_HEX8(0x22, 0x22);
+ TEST_ASSERT_EQUAL_HEX8(v0, v1);
+ TEST_ASSERT_EQUAL_HEX8(0x22, v1);
+ TEST_ASSERT_EQUAL_HEX8(v0, 0x22);
+ TEST_ASSERT_EQUAL_HEX8(*p0, v1);
+ TEST_ASSERT_EQUAL_HEX8(*p0, *p1);
+ TEST_ASSERT_EQUAL_HEX8(*p0, 0x22);
+}
+
+void testEqualHex8sWhenThereAreDifferencesOutside8Bits(void)
+{
+ TEST_ASSERT_EQUAL_HEX8(0x321,0x421);
+ TEST_ASSERT_EQUAL_HEX8(0xFF21,0x0021);
+}
+
+void testEqualHex8sNegatives(void)
+{
+ UNITY_UINT8 v0, v1;
+ UNITY_UINT8 *p0, *p1;
+
+ v0 = 0xDD;
+ v1 = 0xDD;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_HEX8(0xDD, 0xDD);
+ TEST_ASSERT_EQUAL_HEX8(v0, v1);
+ TEST_ASSERT_EQUAL_HEX8(0xDD, v1);
+ TEST_ASSERT_EQUAL_HEX8(v0, 0xDD);
+ TEST_ASSERT_EQUAL_HEX8(*p0, v1);
+ TEST_ASSERT_EQUAL_HEX8(*p0, *p1);
+ TEST_ASSERT_EQUAL_HEX8(*p0, 0xDD);
+}
+
+void testEqualHex16s(void)
+{
+ UNITY_UINT16 v0, v1;
+ UNITY_UINT16 *p0, *p1;
+
+ v0 = 0x9876;
+ v1 = 0x9876;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_HEX16(0x9876, 0x9876);
+ TEST_ASSERT_EQUAL_HEX16(v0, v1);
+ TEST_ASSERT_EQUAL_HEX16(0x9876, v1);
+ TEST_ASSERT_EQUAL_HEX16(v0, 0x9876);
+ TEST_ASSERT_EQUAL_HEX16(*p0, v1);
+ TEST_ASSERT_EQUAL_HEX16(*p0, *p1);
+ TEST_ASSERT_EQUAL_HEX16(*p0, 0x9876);
+}
+
+void testEqualHex16sWhenThereAreDifferencesOutside16Bits(void)
+{
+ TEST_ASSERT_EQUAL_HEX16(0x54321,0x64321);
+ TEST_ASSERT_EQUAL_HEX16(0xFFFF4321,0x00004321);
+}
+
+void testEqualHex32s(void)
+{
+ UNITY_UINT32 v0, v1;
+ UNITY_UINT32 *p0, *p1;
+
+ v0 = 0x98765432ul;
+ v1 = 0x98765432ul;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_HEX32(0x98765432ul, 0x98765432ul);
+ TEST_ASSERT_EQUAL_HEX32(v0, v1);
+ TEST_ASSERT_EQUAL_HEX32(0x98765432ul, v1);
+ TEST_ASSERT_EQUAL_HEX32(v0, 0x98765432ul);
+ TEST_ASSERT_EQUAL_HEX32(*p0, v1);
+ TEST_ASSERT_EQUAL_HEX32(*p0, *p1);
+ TEST_ASSERT_EQUAL_HEX32(*p0, 0x98765432ul);
+}
+
+void testEqualBits(void)
+{
+ UNITY_UINT32 v0 = 0xFF55AA00;
+ UNITY_UINT32 v1 = 0x55550000;
+
+ TEST_ASSERT_BITS(v1, v0, 0x55550000);
+ TEST_ASSERT_BITS(v1, v0, 0xFF55CC00);
+ TEST_ASSERT_BITS(0xFFFFFFFF, v0, 0xFF55AA00);
+ TEST_ASSERT_BITS(0xFFFFFFFF, v0, v0);
+ TEST_ASSERT_BITS(0xF0F0F0F0, v0, 0xFC5DAE0F);
+ TEST_ASSERT_BITS_HIGH(v1, v0);
+ TEST_ASSERT_BITS_LOW(0x000055FF, v0);
+ TEST_ASSERT_BIT_HIGH(30, v0);
+ TEST_ASSERT_BIT_LOW(5, v0);
+}
+
+void testNotEqualBitHigh(void)
+{
+ UNITY_UINT32 v0 = 0x7F55AA00;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_BIT_HIGH(31, v0);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualBitLow(void)
+{
+ UNITY_UINT32 v0 = 0xFF55AA00;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_BIT_LOW(30, v0);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualBitsHigh(void)
+{
+ UNITY_UINT32 v0 = 0xFF55AA00;
+ UNITY_UINT32 v1 = 0x55550000;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_BITS_HIGH(v0, v1);
+ VERIFY_FAILS_END
+
+}
+
+void testNotEqualBitsLow(void)
+{
+ UNITY_UINT32 v0 = 0xFF55AA00;
+ UNITY_UINT32 v1 = 0x55550000;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_BITS_LOW(v0, v1);
+ VERIFY_FAILS_END
+}
+
+
+void testEqualShorts(void)
+{
+ short v0, v1;
+ short *p0, *p1;
+
+ v0 = 19467;
+ v1 = 19467;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_INT(1837, 1837);
+ TEST_ASSERT_EQUAL_INT(-2987, -2987);
+ TEST_ASSERT_EQUAL_INT(v0, v1);
+ TEST_ASSERT_EQUAL_INT(19467, v1);
+ TEST_ASSERT_EQUAL_INT(v0, 19467);
+ TEST_ASSERT_EQUAL_INT(*p0, v1);
+ TEST_ASSERT_EQUAL_INT(*p0, *p1);
+ TEST_ASSERT_EQUAL_INT(*p0, 19467);
+}
+
+void testEqualUShorts(void)
+{
+ unsigned short v0, v1;
+ unsigned short *p0, *p1;
+
+ v0 = 19467;
+ v1 = 19467;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_UINT(1837, 1837);
+ TEST_ASSERT_EQUAL_UINT(2987, 2987);
+ TEST_ASSERT_EQUAL_UINT(v0, v1);
+ TEST_ASSERT_EQUAL_UINT(19467, v1);
+ TEST_ASSERT_EQUAL_UINT(v0, 19467);
+ TEST_ASSERT_EQUAL_UINT(*p0, v1);
+ TEST_ASSERT_EQUAL_UINT(*p0, *p1);
+ TEST_ASSERT_EQUAL_UINT(*p0, 19467);
+}
+
+void testEqualChars(void)
+{
+ signed char v0, v1;
+ signed char *p0, *p1;
+
+ v0 = 109;
+ v1 = 109;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_INT(42, 42);
+ TEST_ASSERT_EQUAL_INT(-116, -116);
+ TEST_ASSERT_EQUAL_INT(v0, v1);
+ TEST_ASSERT_EQUAL_INT(109, v1);
+ TEST_ASSERT_EQUAL_INT(v0, 109);
+ TEST_ASSERT_EQUAL_INT(*p0, v1);
+ TEST_ASSERT_EQUAL_INT(*p0, *p1);
+ TEST_ASSERT_EQUAL_INT(*p0, 109);
+}
+
+void testEqualUChars(void)
+{
+ unsigned char v0, v1;
+ unsigned char *p0, *p1;
+
+ v0 = 251;
+ v1 = 251;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_INT(42, 42);
+ TEST_ASSERT_EQUAL_INT(v0, v1);
+ TEST_ASSERT_EQUAL_INT(251, v1);
+ TEST_ASSERT_EQUAL_INT(v0, 251);
+ TEST_ASSERT_EQUAL_INT(*p0, v1);
+ TEST_ASSERT_EQUAL_INT(*p0, *p1);
+ TEST_ASSERT_EQUAL_INT(*p0, 251);
+}
+
+void testEqualPointers(void)
+{
+ int v0, v1;
+ int *p0, *p1, *p2;
+
+ v0 = 19467;
+ v1 = 18271;
+ p0 = &v0;
+ p1 = &v1;
+ p2 = &v1;
+
+ TEST_ASSERT_EQUAL_PTR(p0, &v0);
+ TEST_ASSERT_EQUAL_PTR(&v1, p1);
+ TEST_ASSERT_EQUAL_PTR(p2, p1);
+ TEST_ASSERT_EQUAL_PTR(&v0, &v0);
+}
+
+void testNotEqualPointers(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_PTR(0x12345678, 0x12345677);
+ VERIFY_FAILS_END
+}
+
+void testIntsWithinDelta(void)
+{
+ TEST_ASSERT_INT_WITHIN(1, 5000, 5001);
+ TEST_ASSERT_INT_WITHIN(5, 5000, 4996);
+ TEST_ASSERT_INT_WITHIN(5, 5000, 5005);
+ TEST_ASSERT_INT_WITHIN(500, 50, -440);
+
+ TEST_ASSERT_INT_WITHIN(2, -1, -1);
+ TEST_ASSERT_INT_WITHIN(5, 1, -1);
+ TEST_ASSERT_INT_WITHIN(5, -1, 1);
+}
+
+void testIntsWithinDeltaAndCustomMessage(void)
+{
+ TEST_ASSERT_INT_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+ TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+ TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+ TEST_ASSERT_INT_WITHIN_MESSAGE(500, 50, -440, "Custom Message.");
+
+ TEST_ASSERT_INT_WITHIN_MESSAGE(2, -1, -1, "Custom Message.");
+ TEST_ASSERT_INT_WITHIN_MESSAGE(5, 1, -1, "Custom Message.");
+ TEST_ASSERT_INT_WITHIN_MESSAGE(5, -1, 1, "Custom Message.");
+}
+
+void testIntsNotWithinDelta(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_INT_WITHIN(5, 5000, 5006);
+ VERIFY_FAILS_END
+}
+
+void testIntsNotWithinDeltaAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 5006, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testUIntsWithinDelta(void)
+{
+ TEST_ASSERT_UINT_WITHIN(1, 5000, 5001);
+ TEST_ASSERT_UINT_WITHIN(5, 5000, 4996);
+ TEST_ASSERT_UINT_WITHIN(5, 5000, 5005);
+}
+
+void testUIntsWithinDeltaAndCustomMessage(void)
+{
+ TEST_ASSERT_UINT_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+ TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+ TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+}
+
+void testUIntsNotWithinDelta(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT_WITHIN(1, 2147483647u, 2147483649u);
+ VERIFY_FAILS_END
+}
+
+void testUIntsNotWithinDeltaAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassSmallFirst(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT_WITHIN(5, 1, -1);
+ VERIFY_FAILS_END
+}
+
+void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassSmallFirstAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 1, -1, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassBigFirst(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT_WITHIN(5, -1, 1);
+ VERIFY_FAILS_END
+}
+
+void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassBigFirstAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT_WITHIN_MESSAGE(5, -1, 1, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testHEX32sWithinDelta(void)
+{
+ TEST_ASSERT_HEX32_WITHIN(1, 5000, 5001);
+ TEST_ASSERT_HEX32_WITHIN(5, 5000, 4996);
+ TEST_ASSERT_HEX32_WITHIN(5, 5000, 5005);
+}
+
+void testHEX32sWithinDeltaAndCustomMessage(void)
+{
+ TEST_ASSERT_HEX32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+ TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+ TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+}
+
+void testHEX32sNotWithinDelta(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_HEX32_WITHIN(1, 2147483647u, 2147483649u);
+ VERIFY_FAILS_END
+}
+
+void testHEX32sNotWithinDeltaAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_HEX32_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testHEX32sNotWithinDeltaEvenThoughASignedIntWouldPass(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_HEX32_WITHIN(5, 1, -1);
+ VERIFY_FAILS_END
+}
+
+void testHEX32sNotWithinDeltaEvenThoughASignedIntWouldPassAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 1, -1, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testHEX16sWithinDelta(void)
+{
+ TEST_ASSERT_HEX16_WITHIN(1, 5000, 5001);
+ TEST_ASSERT_HEX16_WITHIN(5, 5000, 4996);
+ TEST_ASSERT_HEX16_WITHIN(5, 5000, 5005);
+}
+
+void testHEX16sWithinDeltaAndCustomMessage(void)
+{
+ TEST_ASSERT_HEX16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+ TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+ TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+}
+
+void testHEX16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void)
+{
+ TEST_ASSERT_HEX16_WITHIN(5, 0x54321, 0x44321);
+}
+
+void testHEX16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void)
+{
+ TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message.");
+}
+
+void testHEX16sNotWithinDelta(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_HEX16_WITHIN(2, 65535, 0);
+ VERIFY_FAILS_END
+}
+
+void testHEX16sNotWithinDeltaAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_HEX16_WITHIN_MESSAGE(2, 65535, 0, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testHEX8sWithinDelta(void)
+{
+ TEST_ASSERT_HEX8_WITHIN(1, 254, 255);
+ TEST_ASSERT_HEX8_WITHIN(5, 251, 255);
+ TEST_ASSERT_HEX8_WITHIN(5, 1, 4);
+}
+
+void testHEX8sWithinDeltaAndCustomMessage(void)
+{
+ TEST_ASSERT_HEX8_WITHIN_MESSAGE(1, 254, 255, "Custom Message.");
+ TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 251, 255, "Custom Message.");
+ TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 1, 4, "Custom Message.");
+}
+
+void testHEX8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void)
+{
+ TEST_ASSERT_HEX8_WITHIN(5, 0x123, 0xF23);
+}
+
+void testHEX8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void)
+{
+ TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message.");
+}
+
+void testHEX8sNotWithinDelta(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_HEX8_WITHIN(2, 255, 0);
+ VERIFY_FAILS_END
+}
+
+void testHEX8sNotWithinDeltaAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_HEX8_WITHIN_MESSAGE(2, 255, 0, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+//-----------------
+
+void testUINT32sWithinDelta(void)
+{
+ TEST_ASSERT_UINT32_WITHIN(1, 5000, 5001);
+ TEST_ASSERT_UINT32_WITHIN(5, 5000, 4996);
+ TEST_ASSERT_UINT32_WITHIN(5, 5000, 5005);
+}
+
+void testUINT32sWithinDeltaAndCustomMessage(void)
+{
+ TEST_ASSERT_UINT32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+ TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+ TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+}
+
+void testUINT32sNotWithinDelta(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT32_WITHIN(1, 2147483647u, 2147483649u);
+ VERIFY_FAILS_END
+}
+
+void testUINT32sNotWithinDeltaAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT32_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testUINT32sNotWithinDeltaEvenThoughASignedIntWouldPass(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT32_WITHIN(5, 1, -1);
+ VERIFY_FAILS_END
+}
+
+void testUINT32sNotWithinDeltaEvenThoughASignedIntWouldPassAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 1, -1, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testUINT16sWithinDelta(void)
+{
+ TEST_ASSERT_UINT16_WITHIN(1, 5000, 5001);
+ TEST_ASSERT_UINT16_WITHIN(5, 5000, 4996);
+ TEST_ASSERT_UINT16_WITHIN(5, 5000, 5005);
+}
+
+void testUINT16sWithinDeltaAndCustomMessage(void)
+{
+ TEST_ASSERT_UINT16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+ TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+ TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+}
+
+void testUINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void)
+{
+ TEST_ASSERT_UINT16_WITHIN(5, 0x54321, 0x44321);
+}
+
+void testUINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void)
+{
+ TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message.");
+}
+
+void testUINT16sNotWithinDelta(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT16_WITHIN(2, 65535, 0);
+ VERIFY_FAILS_END
+}
+
+void testUINT16sNotWithinDeltaAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT16_WITHIN_MESSAGE(2, 65535, 0, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testUINT8sWithinDelta(void)
+{
+ TEST_ASSERT_UINT8_WITHIN(1, 254, 255);
+ TEST_ASSERT_UINT8_WITHIN(5, 251, 255);
+ TEST_ASSERT_UINT8_WITHIN(5, 1, 4);
+}
+
+void testUINT8sWithinDeltaAndCustomMessage(void)
+{
+ TEST_ASSERT_UINT8_WITHIN_MESSAGE(1, 254, 255, "Custom Message.");
+ TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 251, 255, "Custom Message.");
+ TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 1, 4, "Custom Message.");
+}
+
+void testUINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void)
+{
+ TEST_ASSERT_UINT8_WITHIN(5, 0x123, 0xF23);
+}
+
+void testUINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void)
+{
+ TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message.");
+}
+
+void testUINT8sNotWithinDelta(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT8_WITHIN(2, 255, 0);
+ VERIFY_FAILS_END
+}
+
+void testUINT8sNotWithinDeltaAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT8_WITHIN_MESSAGE(2, 255, 0, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testINT32sWithinDelta(void)
+{
+ TEST_ASSERT_INT32_WITHIN(1, 5000, 5001);
+ TEST_ASSERT_INT32_WITHIN(5, 1, -2);
+ TEST_ASSERT_INT32_WITHIN(5, -2, 1);
+}
+
+void testINT32sWithinDeltaAndCustomMessage(void)
+{
+ TEST_ASSERT_INT32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+}
+
+void testINT32sNotWithinDelta(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_INT32_WITHIN(1, -3, 1);
+ VERIFY_FAILS_END
+}
+
+void testINT32sNotWithinDeltaAndDifferenceOverflows(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_INT32_WITHIN(1, -1, 0x7FFFFFFF);
+ VERIFY_FAILS_END
+}
+void testINT32sNotWithinDeltaAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_INT32_WITHIN_MESSAGE(1, -2, 1, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testINT16sWithinDelta(void)
+{
+ TEST_ASSERT_INT16_WITHIN(1, 5000, 5001);
+ TEST_ASSERT_INT16_WITHIN(5, 2, -2);
+ TEST_ASSERT_INT16_WITHIN(5, -2, 2);
+}
+
+void testINT16sWithinDeltaAndCustomMessage(void)
+{
+ TEST_ASSERT_INT16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+}
+
+void testINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void)
+{
+ TEST_ASSERT_INT16_WITHIN(5, 0x54321, 0x44321);
+}
+
+void testINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void)
+{
+ TEST_ASSERT_INT16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message.");
+}
+
+void testINT16sNotWithinDelta(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_INT16_WITHIN(2, 4, -2);
+ VERIFY_FAILS_END
+}
+
+void testINT16sNotWithinDeltaAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_INT16_WITHIN_MESSAGE(2, 3, 0, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+void testINT8sWithinDelta(void)
+{
+ TEST_ASSERT_INT8_WITHIN(1, 127, 126);
+ TEST_ASSERT_INT8_WITHIN(5, -2, 2);
+ TEST_ASSERT_INT8_WITHIN(5, 2, -2);
+}
+
+void testINT8sWithinDeltaAndCustomMessage(void)
+{
+ TEST_ASSERT_INT8_WITHIN_MESSAGE(5, 1, 4, "Custom Message.");
+}
+
+void testINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void)
+{
+ TEST_ASSERT_INT8_WITHIN(5, 0x123, 0xF23);
+}
+
+void testINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void)
+{
+ TEST_ASSERT_INT8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message.");
+}
+
+void testINT8sNotWithinDelta(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_INT8_WITHIN(2, -3, 0);
+ VERIFY_FAILS_END
+}
+
+void testINT8sNotWithinDeltaAndCustomMessage(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_INT8_WITHIN_MESSAGE(2, -4, 0, "Custom Message.");
+ VERIFY_FAILS_END
+}
+
+
+//-----------------
+void testGreaterThan(void)
+{
+ UNITY_INT v0, v1;
+ UNITY_INT *p0, *p1;
+
+ v0 = 0;
+ v1 = 1;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN(v0, v1);
+ TEST_ASSERT_GREATER_THAN(*p0, v1);
+ TEST_ASSERT_GREATER_THAN(v0, *p1);
+ TEST_ASSERT_GREATER_THAN(*p0, *p1);
+}
+
+void testGreaterThanINT(void)
+{
+ UNITY_INT v0, v1;
+ UNITY_INT *p0, *p1;
+
+ v0 = 302;
+ v1 = 3334;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN_INT(v0, v1);
+ TEST_ASSERT_GREATER_THAN_INT(*p0, v1);
+ TEST_ASSERT_GREATER_THAN_INT(v0, *p1);
+ TEST_ASSERT_GREATER_THAN_INT(*p0, *p1);
+}
+
+
+void testGreaterThanINT8(void)
+{
+ UNITY_INT8 v0, v1;
+ UNITY_INT8 *p0, *p1;
+
+ v0 = -128;
+ v1 = 127;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN_INT8(v0, v1);
+ TEST_ASSERT_GREATER_THAN_INT8(*p0, v1);
+ TEST_ASSERT_GREATER_THAN_INT8(v0, *p1);
+ TEST_ASSERT_GREATER_THAN_INT8(*p0, *p1);
+}
+
+void testGreaterThanINT16(void)
+{
+ UNITY_INT16 v0, v1;
+ UNITY_INT16 *p0, *p1;
+
+ v0 = -32768;
+ v1 = 32767;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN_INT16(v0, v1);
+ TEST_ASSERT_GREATER_THAN_INT16(*p0, v1);
+ TEST_ASSERT_GREATER_THAN_INT16(v0, *p1);
+ TEST_ASSERT_GREATER_THAN_INT16(*p0, *p1);
+}
+
+void testGreaterThanINT32(void)
+{
+ UNITY_INT32 v0, v1;
+ UNITY_INT32 *p0, *p1;
+
+ v0 = -214783648;
+ v1 = 214783647;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN_INT32(v0, v1);
+ TEST_ASSERT_GREATER_THAN_INT32(*p0, v1);
+ TEST_ASSERT_GREATER_THAN_INT32(v0, *p1);
+ TEST_ASSERT_GREATER_THAN_INT32(*p0, *p1);
+}
+
+void testGreaterThanUINT(void)
+{
+ UNITY_UINT v0, v1;
+ UNITY_UINT *p0, *p1;
+
+ v0 = 0;
+ v1 = 1;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN_UINT(v0, v1);
+ TEST_ASSERT_GREATER_THAN_UINT(*p0, v1);
+ TEST_ASSERT_GREATER_THAN_UINT(v0, *p1);
+ TEST_ASSERT_GREATER_THAN_UINT(*p0, *p1);
+}
+
+
+void testGreaterThanUINT8(void)
+{
+ UNITY_UINT8 v0, v1;
+ UNITY_UINT8 *p0, *p1;
+
+ v0 = 0;
+ v1 = 255;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN_UINT8(v0, v1);
+ TEST_ASSERT_GREATER_THAN_UINT8(*p0, v1);
+ TEST_ASSERT_GREATER_THAN_UINT8(v0, *p1);
+ TEST_ASSERT_GREATER_THAN_UINT8(*p0, *p1);
+}
+
+void testGreaterThanUINT16(void)
+{
+ UNITY_UINT16 v0, v1;
+ UNITY_UINT16 *p0, *p1;
+
+ v0 = 0;
+ v1 = 65535;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN_UINT16(v0, v1);
+ TEST_ASSERT_GREATER_THAN_UINT16(*p0, v1);
+ TEST_ASSERT_GREATER_THAN_UINT16(v0, *p1);
+ TEST_ASSERT_GREATER_THAN_UINT16(*p0, *p1);
+}
+
+void testGreaterThanUINT32(void)
+{
+ UNITY_UINT32 v0, v1;
+ UNITY_UINT32 *p0, *p1;
+
+ v0 = 0;
+ v1 = 4294967295;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN_UINT32(v0, v1);
+ TEST_ASSERT_GREATER_THAN_UINT32(*p0, v1);
+ TEST_ASSERT_GREATER_THAN_UINT32(v0, *p1);
+ TEST_ASSERT_GREATER_THAN_UINT32(*p0, *p1);
+}
+
+void testGreaterThanHEX8(void)
+{
+ UNITY_UINT8 v0, v1;
+ UNITY_UINT8 *p0, *p1;
+
+ v0 = 0x00;
+ v1 = 0xFF;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN_HEX8(v0, v1);
+ TEST_ASSERT_GREATER_THAN_HEX8(*p0, v1);
+ TEST_ASSERT_GREATER_THAN_HEX8(v0, *p1);
+ TEST_ASSERT_GREATER_THAN_HEX8(*p0, *p1);
+}
+
+void testGreaterThanHEX16(void)
+{
+ UNITY_UINT16 v0, v1;
+ UNITY_UINT16 *p0, *p1;
+
+ v0 = 0x0000;
+ v1 = 0xFFFF;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN_HEX16(v0, v1);
+ TEST_ASSERT_GREATER_THAN_HEX16(*p0, v1);
+ TEST_ASSERT_GREATER_THAN_HEX16(v0, *p1);
+ TEST_ASSERT_GREATER_THAN_HEX16(*p0, *p1);
+}
+
+void testGreaterThanHEX32(void)
+{
+ UNITY_UINT32 v0, v1;
+ UNITY_UINT32 *p0, *p1;
+
+ v0 = 0x00000000;
+ v1 = 0xFFFFFFFF;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_GREATER_THAN_HEX32(v0, v1);
+ TEST_ASSERT_GREATER_THAN_HEX32(*p0, v1);
+ TEST_ASSERT_GREATER_THAN_HEX32(v0, *p1);
+ TEST_ASSERT_GREATER_THAN_HEX32(*p0, *p1);
+}
+
+
+void testNotGreaterThan(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_GREATER_THAN(0, -1);
+ VERIFY_FAILS_END
+}
+
+void testLessThan(void)
+{
+ UNITY_INT v0, v1;
+ UNITY_INT *p0, *p1;
+
+ v0 = 0;
+ v1 = -1;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN(v0, v1);
+ TEST_ASSERT_LESS_THAN(*p0, v1);
+ TEST_ASSERT_LESS_THAN(v0, *p1);
+ TEST_ASSERT_LESS_THAN(*p0, *p1);
+}
+
+void testLessThanINT(void)
+{
+ UNITY_INT v0, v1;
+ UNITY_INT *p0, *p1;
+
+ v0 = 3334;
+ v1 = 302;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN_INT(v0, v1);
+ TEST_ASSERT_LESS_THAN_INT(*p0, v1);
+ TEST_ASSERT_LESS_THAN_INT(v0, *p1);
+ TEST_ASSERT_LESS_THAN_INT(*p0, *p1);
+}
+
+
+void testLessThanINT8(void)
+{
+ UNITY_INT8 v0, v1;
+ UNITY_INT8 *p0, *p1;
+
+ v0 = 127;
+ v1 = -128;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN_INT8(v0, v1);
+ TEST_ASSERT_LESS_THAN_INT8(*p0, v1);
+ TEST_ASSERT_LESS_THAN_INT8(v0, *p1);
+ TEST_ASSERT_LESS_THAN_INT8(*p0, *p1);
+}
+
+void testLessThanINT16(void)
+{
+ UNITY_INT16 v0, v1;
+ UNITY_INT16 *p0, *p1;
+
+ v0 = 32767;
+ v1 = -32768;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN_INT16(v0, v1);
+ TEST_ASSERT_LESS_THAN_INT16(*p0, v1);
+ TEST_ASSERT_LESS_THAN_INT16(v0, *p1);
+ TEST_ASSERT_LESS_THAN_INT16(*p0, *p1);
+}
+
+void testLessThanINT32(void)
+{
+ UNITY_INT32 v0, v1;
+ UNITY_INT32 *p0, *p1;
+
+ v0 = 214783647;
+ v1 = -214783648;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN_INT32(v0, v1);
+ TEST_ASSERT_LESS_THAN_INT32(*p0, v1);
+ TEST_ASSERT_LESS_THAN_INT32(v0, *p1);
+ TEST_ASSERT_LESS_THAN_INT32(*p0, *p1);
+}
+
+void testLessThanUINT(void)
+{
+ UNITY_UINT v0, v1;
+ UNITY_UINT *p0, *p1;
+
+ v0 = 1;
+ v1 = 0;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN_UINT(v0, v1);
+ TEST_ASSERT_LESS_THAN_UINT(*p0, v1);
+ TEST_ASSERT_LESS_THAN_UINT(v0, *p1);
+ TEST_ASSERT_LESS_THAN_UINT(*p0, *p1);
+}
+
+
+void testLessThanUINT8(void)
+{
+ UNITY_UINT8 v0, v1;
+ UNITY_UINT8 *p0, *p1;
+
+ v0 = 255;
+ v1 = 0;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN_UINT8(v0, v1);
+ TEST_ASSERT_LESS_THAN_UINT8(*p0, v1);
+ TEST_ASSERT_LESS_THAN_UINT8(v0, *p1);
+ TEST_ASSERT_LESS_THAN_UINT8(*p0, *p1);
+}
+
+void testLessThanUINT16(void)
+{
+ UNITY_UINT16 v0, v1;
+ UNITY_UINT16 *p0, *p1;
+
+ v0 = 65535;
+ v1 = 0;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN_UINT16(v0, v1);
+ TEST_ASSERT_LESS_THAN_UINT16(*p0, v1);
+ TEST_ASSERT_LESS_THAN_UINT16(v0, *p1);
+ TEST_ASSERT_LESS_THAN_UINT16(*p0, *p1);
+}
+
+void testLessThanUINT32(void)
+{
+ UNITY_UINT32 v0, v1;
+ UNITY_UINT32 *p0, *p1;
+
+ v0 = 4294967295;
+ v1 = 0;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN_UINT32(v0, v1);
+ TEST_ASSERT_LESS_THAN_UINT32(*p0, v1);
+ TEST_ASSERT_LESS_THAN_UINT32(v0, *p1);
+ TEST_ASSERT_LESS_THAN_UINT32(*p0, *p1);
+}
+
+void testLessThanHEX8(void)
+{
+ UNITY_UINT8 v0, v1;
+ UNITY_UINT8 *p0, *p1;
+
+ v0 = 0xFF;
+ v1 = 0x00;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN_HEX8(v0, v1);
+ TEST_ASSERT_LESS_THAN_HEX8(*p0, v1);
+ TEST_ASSERT_LESS_THAN_HEX8(v0, *p1);
+ TEST_ASSERT_LESS_THAN_HEX8(*p0, *p1);
+}
+
+void testLessThanHEX16(void)
+{
+ UNITY_UINT16 v0, v1;
+ UNITY_UINT16 *p0, *p1;
+
+ v0 = 0xFFFF;
+ v1 = 0x0000;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN_HEX16(v0, v1);
+ TEST_ASSERT_LESS_THAN_HEX16(*p0, v1);
+ TEST_ASSERT_LESS_THAN_HEX16(v0, *p1);
+ TEST_ASSERT_LESS_THAN_HEX16(*p0, *p1);
+}
+
+void testLessThanHEX32(void)
+{
+ UNITY_UINT32 v0, v1;
+ UNITY_UINT32 *p0, *p1;
+
+ v0 = 0xFFFFFFFF;
+ v1 = 0x00000000;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_LESS_THAN_HEX32(v0, v1);
+ TEST_ASSERT_LESS_THAN_HEX32(*p0, v1);
+ TEST_ASSERT_LESS_THAN_HEX32(v0, *p1);
+ TEST_ASSERT_LESS_THAN_HEX32(*p0, *p1);
+}
+
+
+void testNotLessThan(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_LESS_THAN(0, 1);
+ VERIFY_FAILS_END
+}
+
+
+
+//-----------------
+void testEqualStrings(void)
+{
+ const char *testString = "foo";
+
+ TEST_ASSERT_EQUAL_STRING(testString, testString);
+ TEST_ASSERT_EQUAL_STRING_MESSAGE("foo", "foo", "foo isn't foo");
+ TEST_ASSERT_EQUAL_STRING("foo", testString);
+ TEST_ASSERT_EQUAL_STRING(testString, "foo");
+ TEST_ASSERT_EQUAL_STRING("", "");
+}
+
+void testEqualStringsLen(void)
+{
+ const char *testString = "foobar";
+ TEST_ASSERT_EQUAL_STRING_LEN(testString, testString, strlen(testString));
+ TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE("foobar", "foobaz", 5, "fooba isn't fooba");
+ TEST_ASSERT_EQUAL_STRING_LEN("foo", testString, 3);
+ TEST_ASSERT_EQUAL_STRING_LEN(testString, "foo", 3);
+ TEST_ASSERT_EQUAL_STRING_LEN("", "", 3);
+}
+
+void testEqualStringsWithCarriageReturnsAndLineFeeds(void)
+{
+ const char *testString = "foo\r\nbar";
+
+ TEST_ASSERT_EQUAL_STRING(testString, testString);
+ TEST_ASSERT_EQUAL_STRING("foo\r\nbar", "foo\r\nbar");
+ TEST_ASSERT_EQUAL_STRING("foo\r\nbar", testString);
+ TEST_ASSERT_EQUAL_STRING(testString, "foo\r\nbar");
+ TEST_ASSERT_EQUAL_STRING("", "");
+}
+
+void testNotEqualString1(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING("foo", "bar");
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen1(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_LEN("foobar", "foobaz", 6);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualString2(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING("foo", "");
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen2(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_LEN("foo", "", 3);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualString3(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING("", "bar");
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen3(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_LEN("", "bar", 3);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualString4(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING("bar\r", "bar\n");
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen4(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_LEN("ba\r\x16", "ba\r\n", 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualString5(void)
+{
+ const char str1[] = { 0x41, 0x42, 0x03, 0x00 };
+ const char str2[] = { 0x41, 0x42, 0x04, 0x00 };
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING(str1, str2);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualString_ExpectedStringIsNull(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING(NULL, "bar");
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen_ExpectedStringIsNull(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_LEN(NULL, "bar", 1);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualString_ActualStringIsNull(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING("foo", NULL);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen_ActualStringIsNull(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_LEN("foo", NULL, 1);
+ VERIFY_FAILS_END
+}
+
+void testEqualStringArrays(void)
+{
+ const char *testStrings[] = { "foo", "boo", "woo", "moo" };
+ const char *expStrings[] = { "foo", "boo", "woo", "zoo" };
+
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, expStrings, 3);
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 3);
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 2);
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 1);
+}
+
+void testNotEqualStringArray1(void)
+{
+ const char *testStrings[] = { "foo", "boo", "woo", "moo" };
+ const char *expStrings[] = { "foo", "boo", "woo", "zoo" };
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringArray2(void)
+{
+ const char *testStrings[] = { "zoo", "boo", "woo", "moo" };
+ const char *expStrings[] = { "foo", "boo", "woo", "moo" };
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringArray3(void)
+{
+ const char *testStrings[] = { "foo", "boo", "woo", NULL };
+ const char *expStrings[] = { "foo", "boo", "woo", "zoo" };
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringArray4(void)
+{
+ const char *testStrings[] = { "foo", "boo", "woo", "moo" };
+ const char *expStrings[] = { "foo", NULL, "woo", "moo" };
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringArray5(void)
+{
+ const char **testStrings = NULL;
+ const char *expStrings[] = { "foo", "boo", "woo", "zoo" };
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringArray6(void)
+{
+ const char *testStrings[] = { "foo", "boo", "woo", "zoo" };
+ const char **expStrings = NULL;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualStringArrayIfBothNulls(void)
+{
+ const char **testStrings = NULL;
+ const char **expStrings = NULL;
+
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+}
+
+void testNotEqualStringArrayLengthZero(void)
+{
+ const char *testStrings[] = {NULL};
+ const char **expStrings = NULL;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 0);
+ VERIFY_FAILS_END
+}
+
+void testEqualStringEachEqual(void)
+{
+ const char *testStrings1[] = { "foo", "foo", "foo", "foo" };
+ const char *testStrings2[] = { "boo", "boo", "boo", "zoo" };
+ const char *testStrings3[] = { "", "", "", "" };
+
+ TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings1, 4);
+ TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings1, 1);
+ TEST_ASSERT_EACH_EQUAL_STRING("boo", testStrings2, 3);
+ TEST_ASSERT_EACH_EQUAL_STRING("", testStrings3, 4);
+}
+
+void testNotEqualStringEachEqual1(void)
+{
+ const char *testStrings[] = { "foo", "foo", "foo", "moo" };
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringEachEqual2(void)
+{
+ const char *testStrings[] = { "boo", "foo", "foo", "foo" };
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringEachEqual3(void)
+{
+ const char *testStrings[] = { "foo", "foo", "foo", NULL };
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringEachEqual4(void)
+{
+ const char *testStrings[] = { "foo", "foo", "woo", "foo" };
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualStringEachEqual5(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_STRING("foo", NULL, 1);
+ VERIFY_FAILS_END
+}
+
+void testEqualMemory(void)
+{
+ const char *testString = "whatever";
+
+ TEST_ASSERT_EQUAL_MEMORY(testString, testString, 8);
+ TEST_ASSERT_EQUAL_MEMORY("whatever", "whatever", 8);
+ TEST_ASSERT_EQUAL_MEMORY("whatever", testString, 8);
+ TEST_ASSERT_EQUAL_MEMORY(testString, "whatever", 8);
+ TEST_ASSERT_EQUAL_MEMORY(testString, "whatever", 2);
+ TEST_ASSERT_EQUAL_MEMORY(NULL, NULL, 1);
+}
+
+void testNotEqualMemory1(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_MEMORY("foo", "bar", 3);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemory2(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_MEMORY("fool", "food", 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemory3(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_MEMORY(NULL, "food", 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemory4(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_MEMORY("fool", NULL, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryLengthZero(void)
+{
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_MEMORY(NULL, NULL, 0);
+ VERIFY_FAILS_END
+}
+
+void testEqualIntArrays(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {1, 8, 987, -2};
+ int p2[] = {1, 8, 987, 2};
+ int p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EQUAL_INT_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_INT_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_INT_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_INT_ARRAY(p0, p3, 1);
+ TEST_ASSERT_EQUAL_INT_ARRAY(NULL, NULL, 1);
+}
+
+void testNotEqualIntArraysNullExpected(void)
+{
+ int* p0 = NULL;
+ int p1[] = {1, 8, 987, 2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualIntArraysNullActual(void)
+{
+ int* p1 = NULL;
+ int p0[] = {1, 8, 987, 2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualIntArrays1(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {1, 8, 987, 2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualIntArrays2(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {2, 8, 987, -2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualIntArrays3(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {1, 8, 986, -2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualIntArraysLengthZero(void)
+{
+ UNITY_UINT32 p0[1] = {1};
+ UNITY_UINT32 p1[1] = {1};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 0);
+ VERIFY_FAILS_END
+}
+
+void testEqualIntEachEqual(void)
+{
+ int p0[] = {1, 1, 1, 1};
+ int p1[] = {987, 987, 987, 987};
+ int p2[] = {-2, -2, -2, -3};
+ int p3[] = {1, 5, 600, 700};
+
+ TEST_ASSERT_EACH_EQUAL_INT(1, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_INT(1, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_INT(987, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_INT(-2, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_INT(1, p3, 1);
+}
+
+void testNotEqualIntEachEqualNullActual(void)
+{
+ int* p1 = NULL;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_INT(1, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualIntEachEqual1(void)
+{
+ int p0[] = {1, 1, 1, -2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_INT(1, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualIntEachEqual2(void)
+{
+ int p0[] = {-5, -5, -1, -5};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_INT(-5, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualIntEachEqual3(void)
+{
+ int p0[] = {1, 88, 88, 88};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_INT(88, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualEachEqualLengthZero(void)
+{
+ UNITY_UINT32 p0[1] = {1};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_INT(0, p0, 0);
+ VERIFY_FAILS_END
+}
+
+void testEqualPtrArrays(void)
+{
+ char A = 1;
+ char B = 2;
+ char C = 3;
+ char* p0[] = {&A, &B, &C};
+ char* p1[] = {&A, &B, &C, &A};
+ char* p2[] = {&A, &B};
+ char* p3[] = {&A};
+
+ TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p0, 3);
+ TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 3);
+ TEST_ASSERT_EQUAL_PTR_ARRAY(p1, p2, 2);
+ TEST_ASSERT_EQUAL_PTR_ARRAY(p3, p0, 1);
+}
+
+void testNotEqualPtrArraysNullExpected(void)
+{
+ char A = 1;
+ char B = 2;
+ char** p0 = NULL;
+ char* p1[] = {&A, &B};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 2);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualPtrArraysNullActual(void)
+{
+ char A = 1;
+ char B = 2;
+ char** p0 = NULL;
+ char* p1[] = {&A, &B};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_PTR_ARRAY(p1, p0, 2);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualPtrArrays1(void)
+{
+ char A = 1;
+ char B = 2;
+ char C = 3;
+ char* p0[] = {&A, &B, &C, &B};
+ char* p1[] = {&A, &B, &C, &A};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualPtrArrays2(void)
+{
+ char A = 1;
+ char B = 2;
+ char C = 3;
+ char* p0[] = {&B, &B, &C, &A};
+ char* p1[] = {&A, &B, &C, &A};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualPtrArrays3(void)
+{
+ char A = 1;
+ char B = 2;
+ char C = 3;
+ char* p0[] = {&A, &B, &B, &A};
+ char* p1[] = {&A, &B, &C, &A};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualPtrEachEqual(void)
+{
+ char A = 1;
+ char B = 2;
+ char C = 3;
+ char* p0[] = {&A, &A, &A};
+ char* p1[] = {&A, &B, &C, &A};
+ char* p2[] = {&B, &B};
+ char* p3[] = {&C};
+
+ TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 3);
+ TEST_ASSERT_EACH_EQUAL_PTR(&A, p1, 1);
+ TEST_ASSERT_EACH_EQUAL_PTR(&B, p2, 2);
+ TEST_ASSERT_EACH_EQUAL_PTR(&C, p3, 1);
+}
+
+void testNotEqualPtrEachEqualNullExpected(void)
+{
+ char A = 1;
+ char B = 1;
+ char* p0[] = {&A, &B};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 2);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualPtrEachEqualNullActual(void)
+{
+ char A = 1;
+ char** p0 = NULL;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 2);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualPtrEachEqual1(void)
+{
+ char A = 1;
+ char B = 1;
+ char* p0[] = {&A, &A, &A, &B};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualPtrEachEqual2(void)
+{
+ char A = 1;
+ char B = 1;
+ char* p0[] = {&B, &B, &A, &B};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_PTR(&B, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualPtrEachEqual3(void)
+{
+ char A = 1;
+ char B = 1;
+ char* p0[] = {&A, &B, &B, &B};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_PTR(&B, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualInt8Arrays(void)
+{
+ UNITY_INT8 p0[] = {1, 8, 117, -2};
+ UNITY_INT8 p1[] = {1, 8, 117, -2};
+ UNITY_INT8 p2[] = {1, 8, 117, 2};
+ UNITY_INT8 p3[] = {1, 50, 60, 70};
+
+ TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualInt8Arrays(void)
+{
+ UNITY_INT8 p0[] = {1, 8, 36, -2};
+ UNITY_INT8 p1[] = {1, 8, 36, 2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualInt8EachEqual(void)
+{
+ UNITY_INT8 p0[] = {1, 1, 1, 1};
+ UNITY_INT8 p1[] = {117, 117, 117, -2};
+ UNITY_INT8 p2[] = {-1, -1, 117, 2};
+ UNITY_INT8 p3[] = {1, 50, 60, 70};
+
+ TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_INT8(117, p1, 3);
+ TEST_ASSERT_EACH_EQUAL_INT8(-1, p2, 2);
+ TEST_ASSERT_EACH_EQUAL_INT8(1, p3, 1);
+}
+
+void testNotEqualInt8EachEqual(void)
+{
+ UNITY_INT8 p0[] = {1, 8, 36, -2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 2);
+ VERIFY_FAILS_END
+}
+
+void testEqualUIntArrays(void)
+{
+ unsigned int p0[] = {1, 8, 987, 65132u};
+ unsigned int p1[] = {1, 8, 987, 65132u};
+ unsigned int p2[] = {1, 8, 987, 2};
+ unsigned int p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualUIntArrays1(void)
+{
+ unsigned int p0[] = {1, 8, 987, 65132u};
+ unsigned int p1[] = {1, 8, 987, 65131u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUIntArrays2(void)
+{
+ unsigned int p0[] = {1, 8, 987, 65132u};
+ unsigned int p1[] = {2, 8, 987, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUIntArrays3(void)
+{
+ unsigned int p0[] = {1, 8, 987, 65132u};
+ unsigned int p1[] = {1, 8, 986, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualUIntEachEqual(void)
+{
+ unsigned int p0[] = {1, 1, 1, 1};
+ unsigned int p1[] = {65132u, 65132u, 65132u, 65132u};
+ unsigned int p2[] = {8, 8, 987, 2};
+ unsigned int p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_UINT(65132u, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_UINT(8, p2, 2);
+ TEST_ASSERT_EACH_EQUAL_UINT(1, p3, 1);
+}
+
+void testNotEqualUIntEachEqual1(void)
+{
+ unsigned int p0[] = {1, 65132u, 65132u, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT(65132u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUIntEachEqual2(void)
+{
+ unsigned int p0[] = {987, 8, 987, 987};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT(987, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUIntEachEqual3(void)
+{
+ unsigned int p0[] = {1, 1, 1, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualInt16Arrays(void)
+{
+ UNITY_INT16 p0[] = {1, 8, 117, 3};
+ UNITY_INT16 p1[] = {1, 8, 117, 3};
+ UNITY_INT16 p2[] = {1, 8, 117, 2};
+ UNITY_INT16 p3[] = {1, 50, 60, 70};
+
+ TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualInt16Arrays(void)
+{
+ UNITY_INT16 p0[] = {1, 8, 127, 3};
+ UNITY_INT16 p1[] = {1, 8, 127, 2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualInt16EachEqual(void)
+{
+ UNITY_INT16 p0[] = {1, 1, 1, 1};
+ UNITY_INT16 p1[] = {32111, 32111, 32111, 3};
+ UNITY_INT16 p2[] = {-1, -1, -1, 2};
+ UNITY_INT16 p3[] = {1, 50, 60, 70};
+
+ TEST_ASSERT_EACH_EQUAL_INT16(1, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_INT16(1, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_INT16(32111, p1, 3);
+ TEST_ASSERT_EACH_EQUAL_INT16(-1, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_INT16(1, p3, 1);
+}
+
+void testNotEqualInt16EachEqual(void)
+{
+ UNITY_INT16 p0[] = {127, 127, 127, 3};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_INT16(127, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualInt32Arrays(void)
+{
+ UNITY_INT32 p0[] = {1, 8, 117, 3};
+ UNITY_INT32 p1[] = {1, 8, 117, 3};
+ UNITY_INT32 p2[] = {1, 8, 117, 2};
+ UNITY_INT32 p3[] = {1, 50, 60, 70};
+
+ TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualInt32Arrays(void)
+{
+ UNITY_INT32 p0[] = {1, 8, 127, 3};
+ UNITY_INT32 p1[] = {1, 8, 127, 2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualInt32EachEqual(void)
+{
+ UNITY_INT32 p0[] = {8, 8, 8, 8};
+ UNITY_INT32 p1[] = {65537, 65537, 65537, 65537};
+ UNITY_INT32 p2[] = {-3, -3, -3, 2};
+ UNITY_INT32 p3[] = {1, 50, 60, 70};
+
+ TEST_ASSERT_EACH_EQUAL_INT32(8, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_INT32(8, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_INT32(65537, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_INT32(-3, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_INT32(1, p3, 1);
+}
+
+void testNotEqualInt32EachEqual(void)
+{
+ UNITY_INT32 p0[] = {127, 8, 127, 127};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_INT32(127, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualUINT8Arrays(void)
+{
+ UNITY_UINT8 p0[] = {1, 8, 100, 127};
+ UNITY_UINT8 p1[] = {1, 8, 100, 127};
+ UNITY_UINT8 p2[] = {1, 8, 100, 2};
+ UNITY_UINT8 p3[] = {1, 50, 60, 70};
+
+ TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualUINT8Arrays1(void)
+{
+ unsigned char p0[] = {1, 8, 100, 127u};
+ unsigned char p1[] = {1, 8, 100, 255u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT8Arrays2(void)
+{
+ unsigned char p0[] = {1, 8, 100, 127u};
+ unsigned char p1[] = {1, 8, 100, 255u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT8Arrays3(void)
+{
+ unsigned char p0[] = {1, 8, 100, 127u};
+ unsigned char p1[] = {1, 8, 100, 255u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+
+void testEqualUINT16Arrays(void)
+{
+ unsigned short p0[] = {1, 8, 987, 65132u};
+ unsigned short p1[] = {1, 8, 987, 65132u};
+ unsigned short p2[] = {1, 8, 987, 2};
+ unsigned short p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualUINT16Arrays1(void)
+{
+ unsigned short p0[] = {1, 8, 987, 65132u};
+ unsigned short p1[] = {1, 8, 987, 65131u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT16Arrays2(void)
+{
+ unsigned short p0[] = {1, 8, 987, 65132u};
+ unsigned short p1[] = {2, 8, 987, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT16Arrays3(void)
+{
+ unsigned short p0[] = {1, 8, 987, 65132u};
+ unsigned short p1[] = {1, 8, 986, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualUINT32Arrays(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p2[] = {1, 8, 987, 2};
+ UNITY_UINT32 p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualUINT32Arrays1(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {1, 8, 987, 65131u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT32Arrays2(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {2, 8, 987, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT32Arrays3(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {1, 8, 986, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualHEXArrays(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p2[] = {1, 8, 987, 2};
+ UNITY_UINT32 p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualHEXArrays1(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {1, 8, 987, 65131u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEXArrays2(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {2, 8, 987, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEXArrays3(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {1, 8, 986, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualHEX32Arrays(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p2[] = {1, 8, 987, 2};
+ UNITY_UINT32 p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualHEX32Arrays1(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {1, 8, 987, 65131u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX32Arrays2(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {2, 8, 987, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX32Arrays3(void)
+{
+ UNITY_UINT32 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT32 p1[] = {1, 8, 986, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualHEX16Arrays(void)
+{
+ unsigned short p0[] = {1, 8, 987, 65132u};
+ unsigned short p1[] = {1, 8, 987, 65132u};
+ unsigned short p2[] = {1, 8, 987, 2};
+ unsigned short p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualHEX16Arrays1(void)
+{
+ unsigned short p0[] = {1, 8, 987, 65132u};
+ unsigned short p1[] = {1, 8, 987, 65131u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX16Arrays2(void)
+{
+ unsigned short p0[] = {1, 8, 987, 65132u};
+ unsigned short p1[] = {2, 8, 987, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX16Arrays3(void)
+{
+ unsigned short p0[] = {1, 8, 987, 65132u};
+ unsigned short p1[] = {1, 8, 986, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualHEX8Arrays(void)
+{
+ unsigned char p0[] = {1, 8, 254u, 123};
+ unsigned char p1[] = {1, 8, 254u, 123};
+ unsigned char p2[] = {1, 8, 254u, 2};
+ unsigned char p3[] = {1, 23, 25, 26};
+
+ TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualHEX8Arrays1(void)
+{
+ unsigned char p0[] = {1, 8, 254u, 253u};
+ unsigned char p1[] = {1, 8, 254u, 252u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX8Arrays2(void)
+{
+ unsigned char p0[] = {1, 8, 254u, 253u};
+ unsigned char p1[] = {2, 8, 254u, 253u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX8Arrays3(void)
+{
+ unsigned char p0[] = {1, 8, 254u, 253u};
+ unsigned char p1[] = {1, 8, 255u, 253u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualUINT8EachEqual(void)
+{
+ UNITY_UINT8 p0[] = {127u, 127u, 127u, 127u};
+ UNITY_UINT8 p1[] = {1u, 1u, 1u, 1u};
+ UNITY_UINT8 p2[] = {128u, 128u, 128u, 2u};
+ UNITY_UINT8 p3[] = {1u, 50u, 60u, 70u};
+
+ TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_UINT8(1u, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_UINT8(128u, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_UINT8(1u, p3, 1);
+}
+
+void testNotEqualUINT8EachEqual1(void)
+{
+ unsigned char p0[] = {127u, 127u, 128u, 127u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT8EachEqual2(void)
+{
+ unsigned char p0[] = {1, 1, 1, 127u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT8(1, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT8EachEqual3(void)
+{
+ unsigned char p0[] = {54u, 55u, 55u, 55u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT8(55u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualUINT16EachEqual(void)
+{
+ unsigned short p0[] = {65132u, 65132u, 65132u, 65132u};
+ unsigned short p1[] = {987, 987, 987, 987};
+ unsigned short p2[] = {1, 1, 1, 2};
+ unsigned short p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_UINT16(987, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_UINT16(1, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_UINT16(1, p3, 1);
+}
+
+void testNotEqualUINT16EachEqual1(void)
+{
+ unsigned short p0[] = {1, 65132u, 65132u, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT16EachEqual2(void)
+{
+ unsigned short p0[] = {65132u, 65132u, 987, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT16EachEqual3(void)
+{
+ unsigned short p0[] = {65132u, 65132u, 65132u, 65133u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualUINT32EachEqual(void)
+{
+ UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u};
+ UNITY_UINT32 p1[] = {987, 987, 987, 987};
+ UNITY_UINT32 p2[] = {8, 8, 8, 2};
+ UNITY_UINT32 p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_UINT32(987, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_UINT32(8, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_UINT32(1, p3, 1);
+}
+
+void testNotEqualUINT32EachEqual1(void)
+{
+ UNITY_UINT32 p0[] = {65132u, 65132u, 987, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT32EachEqual2(void)
+{
+ UNITY_UINT32 p0[] = {1, 987, 987, 987};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT32(987, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualUINT32EachEqual3(void)
+{
+ UNITY_UINT32 p0[] = {1, 1, 1, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_UINT32(1, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualHEXEachEqual(void)
+{
+ UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u};
+ UNITY_UINT32 p1[] = {987, 987, 987, 987};
+ UNITY_UINT32 p2[] = {8, 8, 8, 2};
+ UNITY_UINT32 p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EACH_EQUAL_HEX(65132u, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_HEX(65132u, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_HEX(987, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_HEX(8, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_HEX(1, p3, 1);
+}
+
+void testNotEqualHEXEachEqual1(void)
+{
+ UNITY_UINT32 p0[] = {1, 65132u, 65132u, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEXEachEqual2(void)
+{
+ UNITY_UINT32 p0[] = {987, 987, 987, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX32(987, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEXEachEqual3(void)
+{
+ UNITY_UINT32 p0[] = {8, 8, 987, 8};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX(8, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualHEX32EachEqual(void)
+{
+ UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u};
+ UNITY_UINT32 p1[] = {987, 987, 987, 987};
+ UNITY_UINT32 p2[] = {8, 8, 8, 2};
+ UNITY_UINT32 p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_HEX32(987, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_HEX32(8, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_HEX32(1, p3, 1);
+}
+
+void testNotEqualHEX32EachEqual1(void)
+{
+ UNITY_UINT32 p0[] = {65132u, 8, 65132u, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX32EachEqual2(void)
+{
+ UNITY_UINT32 p0[] = {1, 987, 987, 987};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX32(987, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX32EachEqual3(void)
+{
+ UNITY_UINT32 p0[] = {8, 8, 8, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX32(8, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualHEX16EachEqual(void)
+{
+ UNITY_UINT16 p0[] = {65132u, 65132u, 65132u, 65132u};
+ UNITY_UINT16 p1[] = {987, 987, 987, 987};
+ UNITY_UINT16 p2[] = {8, 8, 8, 2};
+ UNITY_UINT16 p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_HEX16(987, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_HEX16(8, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_HEX16(1, p3, 1);
+}
+
+void testNotEqualHEX16EachEqual1(void)
+{
+ unsigned short p0[] = {65132u, 65132u, 987, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX16EachEqual2(void)
+{
+ unsigned short p0[] = {1, 987, 987, 987};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX16(987, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX16EachEqual3(void)
+{
+ unsigned short p0[] = {8, 8, 8, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX16(8, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualHEX8EachEqual(void)
+{
+ unsigned char p0[] = {254u, 254u, 254u, 254u};
+ unsigned char p1[] = {123, 123, 123, 123};
+ unsigned char p2[] = {8, 8, 8, 2};
+ unsigned char p3[] = {1, 23, 25, 26};
+
+ TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_HEX8(123, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_HEX8(8, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_HEX8(1, p3, 1);
+}
+
+void testNotEqualHEX8EachEqual1(void)
+{
+ unsigned char p0[] = {253u, 253u, 254u, 253u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX8(253u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX8EachEqual2(void)
+{
+ unsigned char p0[] = {254u, 254u, 254u, 253u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualHEX8EachEqual3(void)
+{
+ unsigned char p0[] = {1, 8, 8, 8};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_HEX8(8, p0, 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualMemoryArrays(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {1, 8, 987, -2};
+ int p2[] = {1, 8, 987, 2};
+ int p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p0, sizeof(int), 1);
+ TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p0, sizeof(int), 4);
+ TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+ TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p2, sizeof(int), 3);
+ TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p3, sizeof(int), 1);
+}
+
+void testNotEqualMemoryArraysExpectedNull(void)
+{
+ int* p0 = NULL;
+ int p1[] = {1, 8, 987, 2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryArraysActualNull(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int* p1 = NULL;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryArrays1(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {1, 8, 987, 2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryArrays2(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {2, 8, 987, -2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryArrays3(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {1, 8, 986, -2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+ VERIFY_FAILS_END
+}
+
+void testEqualMemoryEachEqual(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {1, 8, 987, -2, 1, 8, 987, -2};
+ int p2[] = {8, 8, 8, 2};
+ int p3[] = {8, 500, 600, 700};
+ int v = 8;
+
+ TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p0, sizeof(int)*4, 1);
+ TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 2);
+ TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 1);
+ TEST_ASSERT_EACH_EQUAL_MEMORY(&v, p2, sizeof(int), 3);
+ TEST_ASSERT_EACH_EQUAL_MEMORY(&v, p3, sizeof(int), 1);
+}
+
+void testNotEqualMemoryEachEqualExpectedNull(void)
+{
+ int* p0 = NULL;
+ int p1[] = {1, 8, 987, 2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int), 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryEachEqualActualNull(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int* p1 = NULL;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int), 4);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryEachEqual1(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {9, 8, 987, -2, 1, 8, 987, -2, 1, 8, 987, -2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 3);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryEachEqual2(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {1, 8, 987, -2, 1, 8, 987, -2, 1, 8, 987, 9};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 3);
+ VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryEachEqual3(void)
+{
+ int p0[] = {1, 8, 987, -2};
+ int p1[] = {1, 8, 987, -2, 1, 9, 987, -2, 1, 8, 987, -2};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 3);
+ VERIFY_FAILS_END
+}
+
+void testProtection(void)
+{
+ volatile int mask = 0;
+
+ if (TEST_PROTECT())
+ {
+ mask |= 1;
+ TEST_ABORT();
+ }
+ else
+ {
+ Unity.CurrentTestFailed = 0;
+ mask |= 2;
+ }
+
+ TEST_ASSERT_EQUAL(3, mask);
+}
+
+void testIgnoredAndThenFailInTearDown(void)
+{
+ SetToOneToFailInTearDown = 1;
+ TEST_IGNORE();
+}
+
+// Tricky series of macros to set USING_OUTPUT_SPY
+#define USING_SPY_AS(a) EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0)
+#define ASSIGN_VALUE(a) VAL_##a
+#define VAL_putcharSpy 0, 1
+#define EXPAND_AND_USE_2ND(a, b) SECOND_PARAM(a, b, throwaway)
+#define SECOND_PARAM(a, b, ...) b
+#if USING_SPY_AS(UNITY_OUTPUT_CHAR)
+ #define USING_OUTPUT_SPY // true only if UNITY_OUTPUT_CHAR = putcharSpy
+#endif
+
+#ifdef USING_OUTPUT_SPY
+#include <stdio.h>
+#define SPY_BUFFER_MAX 40
+static char putcharSpyBuffer[SPY_BUFFER_MAX];
+#endif
+static int indexSpyBuffer;
+static int putcharSpyEnabled;
+
+void startPutcharSpy(void) {indexSpyBuffer = 0; putcharSpyEnabled = 1;}
+
+void endPutcharSpy(void) {putcharSpyEnabled = 0;}
+
+char* getBufferPutcharSpy(void)
+{
+#ifdef USING_OUTPUT_SPY
+ putcharSpyBuffer[indexSpyBuffer] = '\0';
+ return putcharSpyBuffer;
+#else
+ return NULL;
+#endif
+}
+
+void putcharSpy(int c)
+{
+#ifdef USING_OUTPUT_SPY
+ if (putcharSpyEnabled)
+ {
+ if (indexSpyBuffer < SPY_BUFFER_MAX - 1)
+ putcharSpyBuffer[indexSpyBuffer++] = (char)c;
+ } else
+ putchar((char)c);
+#endif
+}
+
+void testFailureCountIncrementsAndIsReturnedAtEnd(void)
+{
+ UNITY_UINT savedFailures = Unity.TestFailures;
+ Unity.CurrentTestFailed = 1;
+ startPutcharSpy(); // Suppress output
+ UnityConcludeTest();
+ endPutcharSpy();
+ TEST_ASSERT_EQUAL(savedFailures + 1, Unity.TestFailures);
+
+ startPutcharSpy(); // Suppress output
+ int failures = UnityEnd();
+ Unity.TestFailures--;
+ endPutcharSpy();
+ TEST_ASSERT_EQUAL(savedFailures + 1, failures);
+}
+
+void testCstringsEscapeSequence(void)
+{
+#ifndef USING_OUTPUT_SPY
+ TEST_IGNORE();
+#else
+ startPutcharSpy();
+ UnityPrint("\x16\x10");
+ endPutcharSpy();
+ TEST_ASSERT_EQUAL_STRING("\\x16\\x10", getBufferPutcharSpy());
+#endif
+}
+
+void testHexPrintsUpToMaxNumberOfNibbles(void)
+{
+#ifndef USING_OUTPUT_SPY
+ TEST_IGNORE();
+#else
+ startPutcharSpy();
+ UnityPrintNumberHex(0xBEE, 21);
+ endPutcharSpy();
+ TEST_ASSERT_EQUAL_INT(sizeof(UNITY_INT)*2, strlen(getBufferPutcharSpy()));
+#endif
+}
+
+#define TEST_ASSERT_EQUAL_PRINT_NUMBERS(expected, actual) { \
+ startPutcharSpy(); UnityPrintNumber((actual)); endPutcharSpy(); \
+ TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \
+ }
+
+#define TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS(expected, actual) { \
+ startPutcharSpy(); UnityPrintNumberUnsigned((actual)); endPutcharSpy(); \
+ TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \
+ }
+
+void testPrintNumbers32(void)
+{
+#ifndef USING_OUTPUT_SPY
+ TEST_IGNORE_MESSAGE("Compile with '-D UNITY_OUTPUT_CHAR=putcharSpy' to enable print testing");
+#else
+ TEST_ASSERT_EQUAL_PRINT_NUMBERS("0", 0);
+ TEST_ASSERT_EQUAL_PRINT_NUMBERS("1", 1);
+ TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1", -1);
+ TEST_ASSERT_EQUAL_PRINT_NUMBERS("2000000000", 2000000000);
+ TEST_ASSERT_EQUAL_PRINT_NUMBERS("-2147483648", (UNITY_INT32)0x80000000);
+ TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1", (UNITY_INT32)0xFFFFFFFF);
+#endif
+}
+
+void testPrintNumbersUnsigned32(void)
+{
+#ifndef USING_OUTPUT_SPY
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("0", 0);
+ TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("1", 1);
+ TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("1500000000", 1500000000);
+ TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("2147483648", (UNITY_UINT32)0x80000000);
+ TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("4294967295", (UNITY_UINT32)0xFFFFFFFF);
+#endif
+}
+
+// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES 64 BIT SUPPORT ==================
+
+void testPrintNumbersInt64(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ #ifndef USING_OUTPUT_SPY
+ TEST_IGNORE();
+ #else
+ TEST_ASSERT_EQUAL_PRINT_NUMBERS("0", 0);
+ TEST_ASSERT_EQUAL_PRINT_NUMBERS("10000000000", 10000000000);
+ TEST_ASSERT_EQUAL_PRINT_NUMBERS("-9223372036854775808", (UNITY_INT)0x8000000000000000);
+ TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1", (UNITY_INT)0xFFFFFFFFFFFFFFFF);
+ #endif
+#endif
+}
+
+void testPrintNumbersUInt64(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ #ifndef USING_OUTPUT_SPY
+ TEST_IGNORE();
+ #else
+ TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("0", 0);
+ TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("70000000000", 70000000000);
+ TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("9223372036854775808", (UNITY_UINT)0x8000000000000000);
+ TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("18446744073709551615", (UNITY_UINT)0xFFFFFFFFFFFFFFFF);
+ #endif
+#endif
+}
+
+void testEqualHex64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_UINT64 v0, v1;
+ UNITY_UINT64 *p0, *p1;
+
+ v0 = 0x9876543201234567;
+ v1 = 0x9876543201234567;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_HEX64(0x9876543201234567, 0x9876543201234567);
+ TEST_ASSERT_EQUAL_HEX64(v0, v1);
+ TEST_ASSERT_EQUAL_HEX64(0x9876543201234567, v1);
+ TEST_ASSERT_EQUAL_HEX64(v0, 0x9876543201234567);
+ TEST_ASSERT_EQUAL_HEX64(*p0, v1);
+ TEST_ASSERT_EQUAL_HEX64(*p0, *p1);
+ TEST_ASSERT_EQUAL_HEX64(*p0, 0x9876543201234567);
+#endif
+}
+
+void testEqualUint64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_UINT64 v0, v1;
+ UNITY_UINT64 *p0, *p1;
+
+ v0 = 0x9876543201234567;
+ v1 = 0x9876543201234567;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_UINT64(0x9876543201234567, 0x9876543201234567);
+ TEST_ASSERT_EQUAL_UINT64(v0, v1);
+ TEST_ASSERT_EQUAL_UINT64(0x9876543201234567, v1);
+ TEST_ASSERT_EQUAL_UINT64(v0, 0x9876543201234567);
+ TEST_ASSERT_EQUAL_UINT64(*p0, v1);
+ TEST_ASSERT_EQUAL_UINT64(*p0, *p1);
+ TEST_ASSERT_EQUAL_UINT64(*p0, 0x9876543201234567);
+#endif
+}
+
+void testEqualInt64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_INT64 v0, v1;
+ UNITY_INT64 *p0, *p1;
+
+ v0 = (UNITY_INT64)0x9876543201234567;
+ v1 = (UNITY_INT64)0x9876543201234567;
+ p0 = &v0;
+ p1 = &v1;
+
+ TEST_ASSERT_EQUAL_INT64(0x9876543201234567, 0x9876543201234567);
+ TEST_ASSERT_EQUAL_INT64(v0, v1);
+ TEST_ASSERT_EQUAL_INT64(0x9876543201234567, v1);
+ TEST_ASSERT_EQUAL_INT64(v0, 0x9876543201234567);
+ TEST_ASSERT_EQUAL_INT64(*p0, v1);
+ TEST_ASSERT_EQUAL_INT64(*p0, *p1);
+ TEST_ASSERT_EQUAL_INT64(*p0, 0x9876543201234567);
+#endif
+}
+
+
+void testNotEqualHex64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_UINT64 v0, v1;
+
+ v0 = 9000000000;
+ v1 = 9100000000;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX64(v0, v1);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualUint64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_UINT64 v0, v1;
+
+ v0 = 9000000000;
+ v1 = 9100000000;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT64(v0, v1);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualInt64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_INT64 v0, v1;
+
+ v0 = -9000000000;
+ v1 = 9100000000;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT64(v0, v1);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualHex64sIfSigned(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_INT64 v0, v1;
+
+ v0 = -9000000000;
+ v1 = 9000000000;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX64(v0, v1);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testHEX64sWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_HEX64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE);
+ TEST_ASSERT_HEX64_WITHIN(5, 5000, 4996);
+ TEST_ASSERT_HEX64_WITHIN(5, 5000, 5005);
+#endif
+}
+
+void testHEX64sNotWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_HEX64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testHEX64sNotWithinDeltaEvenThoughASignedIntWouldPass(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_HEX64_WITHIN(5, 1, -1);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testUINT64sWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_UINT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE);
+ TEST_ASSERT_UINT64_WITHIN(5, 5000, 4996);
+ TEST_ASSERT_UINT64_WITHIN(5, 5000, 5005);
+#endif
+}
+
+void testUINT64sNotWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testUINT64sNotWithinDeltaEvenThoughASignedIntWouldPass(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_UINT64_WITHIN(5, 1, -1);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testINT64sWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_INT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE);
+ TEST_ASSERT_INT64_WITHIN(5, 5000, 4996);
+ TEST_ASSERT_INT64_WITHIN(5, 5000, 5005);
+#endif
+}
+
+void testINT64sNotWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_INT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testINT64sNotWithinDeltaAndDifferenceOverflows(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_INT64_WITHIN(1, 0x8000000000000000, 0x7FFFFFFFFFFFFFFF);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testEqualHEX64Arrays(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_UINT64 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT64 p1[] = {1, 8, 987, 65132u};
+ UNITY_UINT64 p2[] = {1, 8, 987, 2};
+ UNITY_UINT64 p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p3, 1);
+#endif
+}
+
+void testEqualUint64Arrays(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_UINT64 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT64 p1[] = {1, 8, 987, 65132u};
+ UNITY_UINT64 p2[] = {1, 8, 987, 2};
+ UNITY_UINT64 p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p3, 1);
+#endif
+}
+
+void testEqualInt64Arrays(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_INT64 p0[] = {1, 8, 987, -65132};
+ UNITY_INT64 p1[] = {1, 8, 987, -65132};
+ UNITY_INT64 p2[] = {1, 8, 987, -2};
+ UNITY_INT64 p3[] = {1, 500, 600, 700};
+
+ TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p3, 1);
+#endif
+}
+
+
+void testNotEqualHEX64Arrays1(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_UINT64 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT64 p1[] = {1, 8, 987, 65131u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualHEX64Arrays2(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_UINT64 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT64 p1[] = {2, 8, 987, 65132u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualUint64Arrays(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_UINT64 p0[] = {1, 8, 987, 65132u};
+ UNITY_UINT64 p1[] = {1, 8, 987, 65131u};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualInt64Arrays(void)
+{
+#ifndef UNITY_SUPPORT_64
+ TEST_IGNORE();
+#else
+ UNITY_INT64 p0[] = {1, 8, 987, -65132};
+ UNITY_INT64 p1[] = {1, 8, 987, -65131};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES FLOAT SUPPORT ==================
+
+void testFloatsWithinDelta(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_FLOAT_WITHIN(0.00003f, 187245.03485f, 187245.03488f);
+ TEST_ASSERT_FLOAT_WITHIN(1.0f, 187245.0f, 187246.0f);
+ TEST_ASSERT_FLOAT_WITHIN(0.05f, 9273.2549f, 9273.2049f);
+ TEST_ASSERT_FLOAT_WITHIN(0.007f, -726.93724f, -726.94424f);
+#endif
+}
+
+void testFloatsNotWithinDelta(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FLOAT_WITHIN(0.05f, 9273.2649f, 9273.2049f);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsEqual(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_EQUAL_FLOAT(187245.0f, 187246.0f);
+ TEST_ASSERT_EQUAL_FLOAT(18724.5f, 18724.6f);
+ TEST_ASSERT_EQUAL_FLOAT(9273.2549f, 9273.2599f);
+ TEST_ASSERT_EQUAL_FLOAT(-726.93724f, -726.9374f);
+#endif
+}
+
+void testFloatsNotEqual(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT(9273.9649f, 9273.0049f);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualNegative1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT(-9273.9649f, -9273.0049f);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualNegative2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT(-9273.0049f, -9273.9649f);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualActualNaN(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT(85.963f, 0.0f / f_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualExpectedNaN(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 85.963f);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsEqualBothNaN(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 0.0f / f_zero);
+#endif
+}
+
+void testFloatsNotEqualInfNaN(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 0.0f / f_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualNaNInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 1.0f / f_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualActualInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT(321.642f, 1.0f / f_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualExpectedInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 321.642f);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsEqualBothInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 1.0f / f_zero);
+#endif
+}
+
+void testFloatsNotEqualPlusMinusInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, -1.0f / f_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsPosInf1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_FLOAT_IS_INF(2.0f / f_zero);
+#endif
+}
+
+void testFloatIsPosInf2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FLOAT_IS_NOT_INF(2.0f / f_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNegInf1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_FLOAT_IS_NEG_INF(-3.0f / f_zero);
+#endif
+}
+
+void testFloatIsNegInf2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(-3.0f / f_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNotPosInf1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FLOAT_IS_INF(2.0f);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNotPosInf2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_FLOAT_IS_NOT_INF(2.0f);
+#endif
+}
+
+void testFloatIsNotNegInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FLOAT_IS_NEG_INF(-999.876f);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNan1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_FLOAT_IS_NAN(0.0f / f_zero);
+#endif
+}
+
+void testFloatIsNan2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FLOAT_IS_NOT_NAN(0.0f / f_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNotNan1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FLOAT_IS_NAN(234.9f);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNotNan2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_FLOAT_IS_NOT_NAN(234.9f);
+#endif
+}
+
+void testFloatInfIsNotNan(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FLOAT_IS_NAN(1.0f / f_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatNanIsNotInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FLOAT_IS_INF(0.0f / f_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsDeterminate1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_FLOAT_IS_DETERMINATE(0.0f);
+ TEST_ASSERT_FLOAT_IS_DETERMINATE(123.3f);
+ TEST_ASSERT_FLOAT_IS_DETERMINATE(-88.3f);
+#endif
+}
+
+void testFloatIsDeterminate2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(-88.3f);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNotDeterminate1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(1.0f / f_zero);
+ TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(-1.0f / f_zero);
+ TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(0.0f / f_zero);
+#endif
+}
+
+void testFloatIsNotDeterminate2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_FLOAT_IS_DETERMINATE(-1.0f / f_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testFloatTraitFailsOnInvalidTrait(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ UnityAssertFloatSpecial(1.0f, NULL, __LINE__, UNITY_FLOAT_INVALID_TRAIT);
+ VERIFY_FAILS_END
+#endif
+}
+
+
+void testEqualFloatArrays(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {1.0f, -8.0f, 25.4f, -0.123f};
+ float p1[] = {1.0f, -8.0f, 25.4f, -0.123f};
+ float p2[] = {1.0f, -8.0f, 25.4f, -0.2f};
+ float p3[] = {1.0f, -23.0f, 25.0f, -0.26f};
+
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p3, 1);
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(NULL, NULL, 1);
+#endif
+}
+
+void testNotEqualFloatArraysExpectedNull(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float* p0 = NULL;
+ float p1[] = {1.0f, 8.0f, 25.4f, 0.252f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArraysActualNull(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {1.0f, 8.0f, 25.4f, 0.253f};
+ float* p1 = NULL;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArrays1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {1.0f, 8.0f, 25.4f, 0.253f};
+ float p1[] = {1.0f, 8.0f, 25.4f, 0.252f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArrays2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {1.0f, 8.0f, 25.4f, 0.253f};
+ float p1[] = {2.0f, 8.0f, 25.4f, 0.253f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArrays3(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {1.0f, 8.0f, 25.4f, 0.253f};
+ float p1[] = {1.0f, 8.0f, 25.5f, 0.253f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArraysNegative1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f};
+ float p1[] = {-1.0f, -8.0f, -25.4f, -0.252f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArraysNegative2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f};
+ float p1[] = {-2.0f, -8.0f, -25.4f, -0.253f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArraysNegative3(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f};
+ float p1[] = {-1.0f, -8.0f, -25.5f, -0.253f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testEqualFloatArraysNaN(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {1.0f, 0.0f / f_zero, 25.4f, 0.253f};
+ float p1[] = {1.0f, 0.0f / f_zero, 25.4f, 0.253f};
+
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+#endif
+}
+
+void testEqualFloatArraysInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {1.0f, 1.0f / f_zero, 25.4f, 0.253f};
+ float p1[] = {1.0f, 1.0f / f_zero, 25.4f, 0.253f};
+
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+#endif
+}
+
+void testNotEqualFloatArraysLengthZero(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[1] = {0.0f};
+ float p1[1] = {0.0f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 0);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testEqualFloatEachEqual(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {1.0f, 1.0f, 1.0f, 1.0f};
+ float p1[] = {-0.123f, -0.123f, -0.123f, -0.123f};
+ float p2[] = {25.4f, 25.4f, 25.4f, -0.2f};
+ float p3[] = {1.0f, -23.0f, 25.0f, -0.26f};
+
+ TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_FLOAT(-0.123f, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_FLOAT(25.4f, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p3, 1);
+#endif
+}
+
+void testNotEqualFloatEachEqualActualNull(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float* p0 = NULL;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_FLOAT(5, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatEachEqual1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {0.253f, 8.0f, 0.253f, 0.253f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_FLOAT(0.253f, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatEachEqual2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {8.0f, 8.0f, 8.0f, 0.253f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_FLOAT(8.0f, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatEachEqual3(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {1.0f, 1.0f, 1.0f, 0.253f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatEachEqualNegative1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {-1.0f, -0.253f, -0.253f, -0.253f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_FLOAT(-0.253f, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatEachEqualNegative2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {-25.4f, -8.0f, -25.4f, -25.4f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_FLOAT(-25.4f, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatEachEqualNegative3(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {-8.0f, -8.0f, -8.0f, -0.253f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_FLOAT(-8.0f, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testEqualFloatEachEqualNaN(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {0.0f / f_zero, 0.0f / f_zero, 0.0f / f_zero, 0.0f / f_zero};
+
+ TEST_ASSERT_EACH_EQUAL_FLOAT(0.0f / f_zero, p0, 4);
+#endif
+}
+
+void testEqualFloatEachEqualInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[] = {1.0f / f_zero, 1.0f / f_zero, 25.4f, 0.253f};
+
+ TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f / f_zero, p0, 2);
+#endif
+}
+
+void testNotEqualFloatEachEqualLengthZero(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+ TEST_IGNORE();
+#else
+ float p0[1] = {0.0f};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_FLOAT(0.0f, p0, 0);
+ VERIFY_FAILS_END
+#endif
+}
+
+#define TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, actual) { \
+ startPutcharSpy(); UnityPrintFloat((actual)); endPutcharSpy(); \
+ TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \
+ }
+
+void testFloatPrinting(void)
+{
+#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY)
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("0", 0.0f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("4.99e-07", 0.000000499f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("5e-07", 0.00000050000005f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.100469499f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 0.9999995f); /*Rounding to int place*/
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 1.0f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("1.25", 1.25f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("7.99999", 7.99999f); /*Not rounding*/
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0002", 16.0002f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0004", 16.0004f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0006", 16.0006f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("999999", 999999.0f); /*Last full print integer*/
+
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-0", -0.0f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.99e-07", -0.000000499f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-5e-07", -0.00000050000005f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.100469499f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -0.9999995f); /*Rounding to int place*/
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -1.0f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.25", -1.25f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.99999", -7.99999f); /*Not rounding*/
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0002", -16.0002f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0004", -16.0004f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0006", -16.0006f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-999999", -999999.0f); /*Last full print integer*/
+
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967296.0f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("5e+09", 5000000000.0f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("8e+09", 8.0e+09f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("8.31e+09", 8309999104.0f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 1.0e+10f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 10000000000.0f);
+ /* Some compilers have trouble with inexact float constants, a float cast works generally */
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00005e+10", (float)1.000054e+10f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("1.1e+38", (float)1.10000005e+38f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("1.6353e+10", 1.63529943e+10f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("3.40282e+38", 3.40282346638e38f);
+
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-1e+10", -1.0e+10f);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-3.40282e+38", -3.40282346638e38f);
+#endif
+}
+
+void testFloatPrintingInfinityAndNaN(void)
+{
+#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY)
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("inf", 1.0f / f_zero);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-inf", -1.0f / f_zero);
+
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("nan", 0.0f / f_zero);
+#endif
+}
+
+#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY)
+static void printFloatValue(float f)
+{
+ char expected[18];
+ char expected_lower[18];
+ char expected_higher[18];
+
+ startPutcharSpy();
+
+ UnityPrintFloat(f);
+
+ sprintf(expected, "%.6g", f);
+
+ /* We print all NaN's as "nan", not "-nan" */
+ if(strcmp(expected, "-nan") == 0) strcpy(expected, "nan");
+
+ /* Allow for rounding differences in last digit */
+ double lower = (double)f * 0.9999995;
+ double higher = (double)f * 1.0000005;
+
+ if (isfinite(lower)) sprintf(expected_lower, "%.6g", lower); else strcpy(expected_lower, expected);
+ if (isfinite(higher)) sprintf(expected_higher, "%.6g", higher); else strcpy(expected_higher, expected);
+
+ if (strcmp(expected, getBufferPutcharSpy()) != 0 &&
+ strcmp(expected_lower, getBufferPutcharSpy()) != 0 &&
+ strcmp(expected_higher, getBufferPutcharSpy()) != 0)
+ {
+ /* Fail with diagnostic printing */
+ TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, f);
+ }
+}
+#endif
+
+void testFloatPrintingRandomSamples(void)
+{
+#if !defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) || !defined(USING_OUTPUT_SPY)
+ TEST_IGNORE();
+#else
+ union { float f_value; uint32_t int_value; } u;
+
+ /* These values are not covered by the MINSTD generator */
+ u.int_value = 0x00000000; printFloatValue(u.f_value);
+ u.int_value = 0x80000000; printFloatValue(u.f_value);
+ u.int_value = 0x7fffffff; printFloatValue(u.f_value);
+ u.int_value = 0xffffffff; printFloatValue(u.f_value);
+
+ uint32_t a = 1;
+ for(int num_tested = 0; num_tested < 1000000; num_tested++)
+ {
+ /* MINSTD pseudo-random number generator */
+ a = (uint32_t)(((uint64_t)a * 48271u) % 2147483647u);
+
+ /* MINSTD does not set the highest bit; test both possibilities */
+ u.int_value = a; printFloatValue(u.f_value);
+ u.int_value = a | 0x80000000; printFloatValue(u.f_value);
+ }
+#endif
+}
+
+// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DOUBLE SUPPORT ==================
+
+void testDoublesWithinDelta(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_DOUBLE_WITHIN(0.00003, 187245.03485, 187245.03488);
+ TEST_ASSERT_DOUBLE_WITHIN(1.0, 187245.0, 187246.0);
+ TEST_ASSERT_DOUBLE_WITHIN(0.05, 9273.2549, 9273.2049);
+ TEST_ASSERT_DOUBLE_WITHIN(0.007, -726.93725, -726.94424);
+#endif
+}
+
+void testDoublesNotWithinDelta(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_DOUBLE_WITHIN(0.05, 9273.2649, 9273.2049);
+ VERIFY_FAILS_END
+#endif
+}
+
+
+void testDoublesEqual(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_EQUAL_DOUBLE(187245123456.0, 187245123456.0);
+ TEST_ASSERT_EQUAL_DOUBLE(187241234567.5, 187241234567.6);
+ TEST_ASSERT_EQUAL_DOUBLE(9273.2512345649, 9273.25123455699);
+ TEST_ASSERT_EQUAL_DOUBLE(-726.12345693724, -726.1234569374);
+#endif
+}
+
+void testDoublesNotEqual(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE(9273.9649, 9273.0049);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualNegative1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE(-9273.9649, -9273.0049);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualNegative2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE(-9273.0049, -9273.9649);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualActualNaN(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE(85.963, 0.0 / d_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualExpectedNaN(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 85.963);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesEqualBothNaN(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 0.0 / d_zero);
+#endif
+}
+
+void testDoublesNotEqualInfNaN(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 0.0 / d_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualNaNInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 1.0 / d_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualActualInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE(321.642, 1.0 / d_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualExpectedInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 321.642);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesEqualBothInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 1.0 / d_zero);
+#endif
+}
+
+void testDoublesNotEqualPlusMinusInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, -1.0 / d_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsPosInf1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_DOUBLE_IS_INF(2.0 / d_zero);
+#endif
+}
+
+void testDoubleIsPosInf2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_DOUBLE_IS_NOT_INF(2.0 / d_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNegInf1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_DOUBLE_IS_NEG_INF(-3.0 / d_zero);
+#endif
+}
+
+void testDoubleIsNegInf2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(-3.0 / d_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNotPosInf1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_DOUBLE_IS_INF(2.0);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNotPosInf2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_DOUBLE_IS_NOT_INF(2.0);
+#endif
+}
+
+void testDoubleIsNotNegInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_DOUBLE_IS_NEG_INF(-999.876);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNan1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_DOUBLE_IS_NAN(0.0 / d_zero);
+#endif
+}
+
+void testDoubleIsNan2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_DOUBLE_IS_NOT_NAN(0.0 / d_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNotNan1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_DOUBLE_IS_NAN(234.9);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNotNan2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_DOUBLE_IS_NOT_NAN(234.9);
+#endif
+}
+
+void testDoubleInfIsNotNan(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_DOUBLE_IS_NAN(1.0 / d_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleNanIsNotInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_DOUBLE_IS_INF(0.0 / d_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsDeterminate1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_DOUBLE_IS_DETERMINATE(0.0);
+ TEST_ASSERT_DOUBLE_IS_DETERMINATE(123.3);
+ TEST_ASSERT_DOUBLE_IS_DETERMINATE(-88.3);
+#endif
+}
+
+void testDoubleIsDeterminate2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(-88.3);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNotDeterminate1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(1.0 / d_zero);
+ TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(-1.0 / d_zero);
+ TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(0.0 / d_zero);
+#endif
+}
+
+void testDoubleIsNotDeterminate2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_DOUBLE_IS_DETERMINATE(-1.0 / d_zero);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleTraitFailsOnInvalidTrait(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ EXPECT_ABORT_BEGIN
+ UnityAssertDoubleSpecial(1.0, NULL, __LINE__, UNITY_FLOAT_INVALID_TRAIT);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testEqualDoubleArrays(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {1.0, -8.0, 25.4, -0.123};
+ double p1[] = {1.0, -8.0, 25.4, -0.123};
+ double p2[] = {1.0, -8.0, 25.4, -0.2};
+ double p3[] = {1.0, -23.0, 25.0, -0.26};
+
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p0, 1);
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p0, 4);
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p2, 3);
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p3, 1);
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(NULL, NULL, 1);
+#endif
+}
+
+void testNotEqualDoubleArraysExpectedNull(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double* p0 = NULL;
+ double p1[] = {1.0, 8.0, 25.4, 0.252};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArraysActualNull(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {1.0, 8.0, 25.4, 0.253};
+ double* p1 = NULL;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArrays1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {1.0, 8.0, 25.4, 0.25666666667};
+ double p1[] = {1.0, 8.0, 25.4, 0.25666666666};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArrays2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {1.0, 8.0, 25.4, 0.253};
+ double p1[] = {2.0, 8.0, 25.4, 0.253};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArrays3(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {1.0, 8.0, 25.4, 0.253};
+ double p1[] = {1.0, 8.0, 25.5, 0.253};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArraysNegative1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {-1.0, -8.0, -25.4, -0.2566666667};
+ double p1[] = {-1.0, -8.0, -25.4, -0.2566666666};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArraysNegative2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {-1.0, -8.0, -25.4, -0.253};
+ double p1[] = {-2.0, -8.0, -25.4, -0.253};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArraysNegative3(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {-1.0, -8.0, -25.4, -0.253};
+ double p1[] = {-1.0, -8.0, -25.5, -0.253};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testEqualDoubleArraysNaN(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {1.0, 0.0 / d_zero, 25.4, 0.253};
+ double p1[] = {1.0, 0.0 / d_zero, 25.4, 0.253};
+
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+#endif
+}
+
+void testEqualDoubleArraysInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {1.0, 1.0 / d_zero, 25.4, 0.253};
+ double p1[] = {1.0, 1.0 / d_zero, 25.4, 0.253};
+
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+#endif
+}
+
+void testNotEqualDoubleArraysLengthZero(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[1] = {0.0};
+ double p1[1] = {0.0};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 0);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testEqualDoubleEachEqual(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {1.0, 1.0, 1.0, 1.0};
+ double p1[] = {-0.123, -0.123, -0.123, -0.123};
+ double p2[] = {25.4, 25.4, 25.4, -0.2};
+ double p3[] = {1.0, -23.0, 25.0, -0.26};
+
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 1);
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 4);
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(-0.123, p1, 4);
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(25.4, p2, 3);
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p3, 1);
+#endif
+}
+
+void testNotEqualDoubleEachEqualActualNull(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double* p0 = NULL;
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(5, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleEachEqual1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {0.253, 8.0, 0.253, 0.253};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(0.253, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleEachEqual2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {8.0, 8.0, 8.0, 0.253};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(8.0, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleEachEqual3(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {1.0, 1.0, 1.0, 0.253};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleEachEqualNegative1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {-1.0, -0.253, -0.253, -0.253};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(-0.253, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleEachEqualNegative2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {-25.4, -8.0, -25.4, -25.4};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(-25.4, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleEachEqualNegative3(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {-8.0, -8.0, -8.0, -0.253};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(-8.0, p0, 4);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testEqualDoubleEachEqualNaN(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {0.0 / d_zero, 0.0 / d_zero, 0.0 / d_zero, 0.0 / d_zero};
+
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(0.0 / d_zero, p0, 4);
+#endif
+}
+
+void testEqualDoubleEachEqualInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[] = {1.0 / d_zero, 1.0 / d_zero, 25.4, 0.253};
+
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0 / d_zero, p0, 2);
+#endif
+}
+
+void testNotEqualDoubleEachEqualLengthZero(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+ TEST_IGNORE();
+#else
+ double p0[1] = {0.0};
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EACH_EQUAL_DOUBLE(0.0, p0, 0);
+ VERIFY_FAILS_END
+#endif
+}
+
+void testDoublePrinting(void)
+{
+#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY)
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.10046949999999999);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967295.999999);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967295.9999995);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967296.0);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 9999999995.0);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("9.0072e+15", 9007199254740990.0);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("7e+100", 7.0e+100);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("3e+200", 3.0e+200);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("9.23457e+300", 9.23456789e+300);
+
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.10046949999999999);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.29497e+09", -4294967295.999999);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.29497e+09", -4294967295.9999995);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-7e+100", -7.0e+100);
+#endif
+}
+
+void testDoublePrintingInfinityAndNaN(void)
+{
+#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY)
+ TEST_IGNORE();
+#else
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("inf", 1.0 / d_zero);
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("-inf", -1.0 / d_zero);
+
+ TEST_ASSERT_EQUAL_PRINT_FLOATING("nan", 0.0 / d_zero);
+#endif
+}
+
+// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DETAIL SUPPORT ==================
+
+void testThatDetailsCanBeHandleOneDetail(void)
+{
+#ifdef UNITY_EXCLUDE_DETAILS
+ TEST_IGNORE();
+#else
+ UNITY_SET_DETAIL("Detail1");
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_INT_MESSAGE(5, 6, "Should Fail And Say Detail1");
+ VERIFY_FAILS_END
+#endif
+}
+
+void testThatDetailsCanHandleTestFail(void)
+{
+#ifdef UNITY_EXCLUDE_DETAILS
+ TEST_IGNORE();
+#else
+ UNITY_SET_DETAILS("Detail1","Detail2");
+
+ EXPECT_ABORT_BEGIN
+ TEST_FAIL_MESSAGE("Should Fail And Say Detail1 and Detail2");
+ VERIFY_FAILS_END
+#endif
+}
+
+void testThatDetailsCanBeHandleTwoDetails(void)
+{
+#ifdef UNITY_EXCLUDE_DETAILS
+ TEST_IGNORE();
+#else
+ UNITY_SET_DETAILS("Detail1","Detail2");
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_HEX8_MESSAGE(7, 8, "Should Fail And Say Detail1 and Detail2");
+ VERIFY_FAILS_END
+#endif
+}
+
+void testThatDetailsCanBeHandleSingleDetailClearingTwoDetails(void)
+{
+#ifdef UNITY_EXCLUDE_DETAILS
+ TEST_IGNORE();
+#else
+ UNITY_SET_DETAILS("Detail1","Detail2");
+ UNITY_SET_DETAIL("DetailNew");
+
+ EXPECT_ABORT_BEGIN
+ TEST_ASSERT_EQUAL_STRING_MESSAGE("MEH", "GUH", "Should Fail And Say DetailNew");
+ VERIFY_FAILS_END
+#endif
+}
diff --git a/vendor/parson/.gitignore b/vendor/parson/.gitignore
new file mode 100644
index 0000000..8743bfc
--- /dev/null
+++ b/vendor/parson/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+test
+*.o
diff --git a/vendor/parson/CMakeLists.txt b/vendor/parson/CMakeLists.txt
new file mode 100644
index 0000000..1959af8
--- /dev/null
+++ b/vendor/parson/CMakeLists.txt
@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 3.5)
+project(parson C)
+
+add_library(parson parson.c)
+target_include_directories(parson PUBLIC $<INSTALL_INTERFACE:include>)
+
+set_target_properties(parson PROPERTIES PUBLIC_HEADER "parson.h")
+
+install(
+ TARGETS parson
+ EXPORT parsonTargets
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
+ PUBLIC_HEADER DESTINATION include
+)
+
+install(
+ EXPORT parsonTargets
+ FILE parsonConfig.cmake
+ NAMESPACE parson::
+ DESTINATION cmake
+)
+
diff --git a/vendor/parson/LICENSE b/vendor/parson/LICENSE
new file mode 100644
index 0000000..12cbc1b
--- /dev/null
+++ b/vendor/parson/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2012 - 2019 Krzysztof Gabis
+
+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.
diff --git a/vendor/parson/Makefile b/vendor/parson/Makefile
new file mode 100644
index 0000000..98654de
--- /dev/null
+++ b/vendor/parson/Makefile
@@ -0,0 +1,20 @@
+CC = gcc
+CFLAGS = -O0 -g -Wall -Wextra -std=c89 -pedantic-errors
+
+CPPC = g++
+CPPFLAGS = -O0 -g -Wall -Wextra
+
+all: test testcpp
+
+.PHONY: test testcpp
+test: tests.c parson.c
+ $(CC) $(CFLAGS) -o $@ tests.c parson.c
+ ./$@
+
+testcpp: tests.c parson.c
+ $(CPPC) $(CPPFLAGS) -o $@ tests.c parson.c
+ ./$@
+
+clean:
+ rm -f test *.o
+
diff --git a/vendor/parson/README.md b/vendor/parson/README.md
new file mode 100644
index 0000000..56d2de3
--- /dev/null
+++ b/vendor/parson/README.md
@@ -0,0 +1,149 @@
+## About
+Parson is a lighweight [json](http://json.org) library written in C.
+
+## Features
+* Full JSON support
+* Lightweight (only 2 files)
+* Simple API
+* Addressing json values with dot notation (similar to C structs or objects in most OO languages, e.g. "objectA.objectB.value")
+* C89 compatible
+* Test suites
+
+## Installation
+Run:
+```
+git clone https://github.com/kgabis/parson.git
+```
+and copy parson.h and parson.c to you source code tree.
+
+Run ```make test``` to compile and run tests.
+
+## Examples
+### Parsing JSON
+Here is a function, which prints basic commit info (date, sha and author) from a github repository.
+```c
+void print_commits_info(const char *username, const char *repo) {
+ JSON_Value *root_value;
+ JSON_Array *commits;
+ JSON_Object *commit;
+ size_t i;
+
+ char curl_command[512];
+ char cleanup_command[256];
+ char output_filename[] = "commits.json";
+
+ /* it ain't pretty, but it's not a libcurl tutorial */
+ sprintf(curl_command,
+ "curl -s \"https://api.github.com/repos/%s/%s/commits\" > %s",
+ username, repo, output_filename);
+ sprintf(cleanup_command, "rm -f %s", output_filename);
+ system(curl_command);
+
+ /* parsing json and validating output */
+ root_value = json_parse_file(output_filename);
+ if (json_value_get_type(root_value) != JSONArray) {
+ system(cleanup_command);
+ return;
+ }
+
+ /* getting array from root value and printing commit info */
+ commits = json_value_get_array(root_value);
+ printf("%-10.10s %-10.10s %s\n", "Date", "SHA", "Author");
+ for (i = 0; i < json_array_get_count(commits); i++) {
+ commit = json_array_get_object(commits, i);
+ printf("%.10s %.10s %s\n",
+ json_object_dotget_string(commit, "commit.author.date"),
+ json_object_get_string(commit, "sha"),
+ json_object_dotget_string(commit, "commit.author.name"));
+ }
+
+ /* cleanup code */
+ json_value_free(root_value);
+ system(cleanup_command);
+}
+
+```
+Calling ```print_commits_info("torvalds", "linux");``` prints:
+```
+Date SHA Author
+2012-10-15 dd8e8c4a2c David Rientjes
+2012-10-15 3ce9e53e78 Michal Marek
+2012-10-14 29bb4cc5e0 Randy Dunlap
+2012-10-15 325adeb55e Ralf Baechle
+2012-10-14 68687c842c Russell King
+2012-10-14 ddffeb8c4d Linus Torvalds
+...
+```
+
+### Persistence
+In this example I'm using parson to save user information to a file and then load it and validate later.
+```c
+void persistence_example(void) {
+ JSON_Value *schema = json_parse_string("{\"name\":\"\"}");
+ JSON_Value *user_data = json_parse_file("user_data.json");
+ char buf[256];
+ const char *name = NULL;
+ if (user_data == NULL || json_validate(schema, user_data) != JSONSuccess) {
+ puts("Enter your name:");
+ scanf("%s", buf);
+ user_data = json_value_init_object();
+ json_object_set_string(json_object(user_data), "name", buf);
+ json_serialize_to_file(user_data, "user_data.json");
+ }
+ name = json_object_get_string(json_object(user_data), "name");
+ printf("Hello, %s.", name);
+ json_value_free(schema);
+ json_value_free(user_data);
+ return;
+}
+```
+
+### Serialization
+Creating JSON values is very simple thanks to the dot notation.
+Object hierarchy is automatically created when addressing specific fields.
+In the following example I create a simple JSON value containing basic information about a person.
+```c
+void serialization_example(void) {
+ JSON_Value *root_value = json_value_init_object();
+ JSON_Object *root_object = json_value_get_object(root_value);
+ char *serialized_string = NULL;
+ json_object_set_string(root_object, "name", "John Smith");
+ json_object_set_number(root_object, "age", 25);
+ json_object_dotset_string(root_object, "address.city", "Cupertino");
+ json_object_dotset_value(root_object, "contact.emails", json_parse_string("[\"email@example.com\",\"email2@example.com\"]"));
+ serialized_string = json_serialize_to_string_pretty(root_value);
+ puts(serialized_string);
+ json_free_serialized_string(serialized_string);
+ json_value_free(root_value);
+}
+
+```
+
+Output:
+```
+{
+ "name": "John Smith",
+ "age": 25,
+ "address": {
+ "city": "Cupertino"
+ },
+ "contact": {
+ "emails": [
+ "email@example.com",
+ "email2@example.com"
+ ]
+ }
+}
+```
+
+## Contributing
+
+I will always merge *working* bug fixes. However, if you want to add something new to the API, please create an "issue" on github for this first so we can discuss if it should end up in the library before you start implementing it.
+Remember to follow parson's code style and write appropriate tests.
+
+## My other projects
+* [kgflags](https://github.com/kgabis/kgflags) - easy to use command-line flag parsing library
+* [agnes](https://github.com/kgabis/agnes) - header-only NES emulation library
+
+## License
+[The MIT License (MIT)](http://opensource.org/licenses/mit-license.php)
diff --git a/vendor/parson/package.json b/vendor/parson/package.json
new file mode 100644
index 0000000..76f80da
--- /dev/null
+++ b/vendor/parson/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "parson",
+ "version": "0.0.0",
+ "repo": "kgabis/parson",
+ "description": "Small json parser and reader",
+ "keywords": [ "json", "parser" ],
+ "license": "MIT",
+ "src": [
+ "parson.c",
+ "parson.h"
+ ]
+}
diff --git a/vendor/parson/parson.c b/vendor/parson/parson.c
new file mode 100644
index 0000000..95d97ea
--- /dev/null
+++ b/vendor/parson/parson.c
@@ -0,0 +1,2060 @@
+/*
+ SPDX-License-Identifier: MIT
+
+ Parson ( http://kgabis.github.com/parson/ )
+ Copyright (c) 2012 - 2019 Krzysztof Gabis
+
+ 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.
+*/
+#ifdef _MSC_VER
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif /* _CRT_SECURE_NO_WARNINGS */
+#endif /* _MSC_VER */
+
+#include "parson.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <errno.h>
+
+/* Apparently sscanf is not implemented in some "standard" libraries, so don't use it, if you
+ * don't have to. */
+#define sscanf THINK_TWICE_ABOUT_USING_SSCANF
+
+#define STARTING_CAPACITY 16
+#define MAX_NESTING 2048
+
+#define FLOAT_FORMAT "%1.17g" /* do not increase precision without incresing NUM_BUF_SIZE */
+#define NUM_BUF_SIZE 64 /* double printed with "%1.17g" shouldn't be longer than 25 bytes so let's be paranoid and use 64 */
+
+#define SIZEOF_TOKEN(a) (sizeof(a) - 1)
+#define SKIP_CHAR(str) ((*str)++)
+#define SKIP_WHITESPACES(str) while (isspace((unsigned char)(**str))) { SKIP_CHAR(str); }
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#undef malloc
+#undef free
+
+#if defined(isnan) && defined(isinf)
+#define IS_NUMBER_INVALID(x) (isnan((x)) || isinf((x)))
+#else
+#define IS_NUMBER_INVALID(x) (((x) * 0.0) != 0.0)
+#endif
+
+static JSON_Malloc_Function parson_malloc = malloc;
+static JSON_Free_Function parson_free = free;
+
+static int parson_escape_slashes = 1;
+
+#define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */
+
+/* Type definitions */
+typedef union json_value_value {
+ char *string;
+ double number;
+ JSON_Object *object;
+ JSON_Array *array;
+ int boolean;
+ int null;
+} JSON_Value_Value;
+
+struct json_value_t {
+ JSON_Value *parent;
+ JSON_Value_Type type;
+ JSON_Value_Value value;
+};
+
+struct json_object_t {
+ JSON_Value *wrapping_value;
+ char **names;
+ JSON_Value **values;
+ size_t count;
+ size_t capacity;
+};
+
+struct json_array_t {
+ JSON_Value *wrapping_value;
+ JSON_Value **items;
+ size_t count;
+ size_t capacity;
+};
+
+/* Various */
+static char * read_file(const char *filename);
+static void remove_comments(char *string, const char *start_token, const char *end_token);
+static char * parson_strndup(const char *string, size_t n);
+static char * parson_strdup(const char *string);
+static int hex_char_to_int(char c);
+static int parse_utf16_hex(const char *string, unsigned int *result);
+static int num_bytes_in_utf8_sequence(unsigned char c);
+static int verify_utf8_sequence(const unsigned char *string, int *len);
+static int is_valid_utf8(const char *string, size_t string_len);
+static int is_decimal(const char *string, size_t length);
+
+/* JSON Object */
+static JSON_Object * json_object_init(JSON_Value *wrapping_value);
+static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value);
+static JSON_Status json_object_addn(JSON_Object *object, const char *name, size_t name_len, JSON_Value *value);
+static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity);
+static JSON_Value * json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len);
+static JSON_Status json_object_remove_internal(JSON_Object *object, const char *name, int free_value);
+static JSON_Status json_object_dotremove_internal(JSON_Object *object, const char *name, int free_value);
+static void json_object_free(JSON_Object *object);
+
+/* JSON Array */
+static JSON_Array * json_array_init(JSON_Value *wrapping_value);
+static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value);
+static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity);
+static void json_array_free(JSON_Array *array);
+
+/* JSON Value */
+static JSON_Value * json_value_init_string_no_copy(char *string);
+
+/* Parser */
+static JSON_Status skip_quotes(const char **string);
+static int parse_utf16(const char **unprocessed, char **processed);
+static char * process_string(const char *input, size_t len);
+static char * get_quoted_string(const char **string);
+static JSON_Value * parse_object_value(const char **string, size_t nesting);
+static JSON_Value * parse_array_value(const char **string, size_t nesting);
+static JSON_Value * parse_string_value(const char **string);
+static JSON_Value * parse_boolean_value(const char **string);
+static JSON_Value * parse_number_value(const char **string);
+static JSON_Value * parse_null_value(const char **string);
+static JSON_Value * parse_value(const char **string, size_t nesting);
+
+/* Serialization */
+static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf);
+static int json_serialize_string(const char *string, char *buf);
+static int append_indent(char *buf, int level);
+static int append_string(char *buf, const char *string);
+
+/* Various */
+static char * parson_strndup(const char *string, size_t n) {
+ char *output_string = (char*)parson_malloc(n + 1);
+ if (!output_string) {
+ return NULL;
+ }
+ output_string[n] = '\0';
+ strncpy(output_string, string, n);
+ return output_string;
+}
+
+static char * parson_strdup(const char *string) {
+ return parson_strndup(string, strlen(string));
+}
+
+static int hex_char_to_int(char c) {
+ if (c >= '0' && c <= '9') {
+ return c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ return c - 'a' + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ return c - 'A' + 10;
+ }
+ return -1;
+}
+
+static int parse_utf16_hex(const char *s, unsigned int *result) {
+ int x1, x2, x3, x4;
+ if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0' || s[3] == '\0') {
+ return 0;
+ }
+ x1 = hex_char_to_int(s[0]);
+ x2 = hex_char_to_int(s[1]);
+ x3 = hex_char_to_int(s[2]);
+ x4 = hex_char_to_int(s[3]);
+ if (x1 == -1 || x2 == -1 || x3 == -1 || x4 == -1) {
+ return 0;
+ }
+ *result = (unsigned int)((x1 << 12) | (x2 << 8) | (x3 << 4) | x4);
+ return 1;
+}
+
+static int num_bytes_in_utf8_sequence(unsigned char c) {
+ if (c == 0xC0 || c == 0xC1 || c > 0xF4 || IS_CONT(c)) {
+ return 0;
+ } else if ((c & 0x80) == 0) { /* 0xxxxxxx */
+ return 1;
+ } else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */
+ return 2;
+ } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */
+ return 3;
+ } else if ((c & 0xF8) == 0xF0) { /* 11110xxx */
+ return 4;
+ }
+ return 0; /* won't happen */
+}
+
+static int verify_utf8_sequence(const unsigned char *string, int *len) {
+ unsigned int cp = 0;
+ *len = num_bytes_in_utf8_sequence(string[0]);
+
+ if (*len == 1) {
+ cp = string[0];
+ } else if (*len == 2 && IS_CONT(string[1])) {
+ cp = string[0] & 0x1F;
+ cp = (cp << 6) | (string[1] & 0x3F);
+ } else if (*len == 3 && IS_CONT(string[1]) && IS_CONT(string[2])) {
+ cp = ((unsigned char)string[0]) & 0xF;
+ cp = (cp << 6) | (string[1] & 0x3F);
+ cp = (cp << 6) | (string[2] & 0x3F);
+ } else if (*len == 4 && IS_CONT(string[1]) && IS_CONT(string[2]) && IS_CONT(string[3])) {
+ cp = string[0] & 0x7;
+ cp = (cp << 6) | (string[1] & 0x3F);
+ cp = (cp << 6) | (string[2] & 0x3F);
+ cp = (cp << 6) | (string[3] & 0x3F);
+ } else {
+ return 0;
+ }
+
+ /* overlong encodings */
+ if ((cp < 0x80 && *len > 1) ||
+ (cp < 0x800 && *len > 2) ||
+ (cp < 0x10000 && *len > 3)) {
+ return 0;
+ }
+
+ /* invalid unicode */
+ if (cp > 0x10FFFF) {
+ return 0;
+ }
+
+ /* surrogate halves */
+ if (cp >= 0xD800 && cp <= 0xDFFF) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int is_valid_utf8(const char *string, size_t string_len) {
+ int len = 0;
+ const char *string_end = string + string_len;
+ while (string < string_end) {
+ if (!verify_utf8_sequence((const unsigned char*)string, &len)) {
+ return 0;
+ }
+ string += len;
+ }
+ return 1;
+}
+
+static int is_decimal(const char *string, size_t length) {
+ if (length > 1 && string[0] == '0' && string[1] != '.') {
+ return 0;
+ }
+ if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') {
+ return 0;
+ }
+ while (length--) {
+ if (strchr("xX", string[length])) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static char * read_file(const char * filename) {
+ FILE *fp = fopen(filename, "r");
+ size_t size_to_read = 0;
+ size_t size_read = 0;
+ long pos;
+ char *file_contents;
+ if (!fp) {
+ return NULL;
+ }
+ fseek(fp, 0L, SEEK_END);
+ pos = ftell(fp);
+ if (pos < 0) {
+ fclose(fp);
+ return NULL;
+ }
+ size_to_read = pos;
+ rewind(fp);
+ file_contents = (char*)parson_malloc(sizeof(char) * (size_to_read + 1));
+ if (!file_contents) {
+ fclose(fp);
+ return NULL;
+ }
+ size_read = fread(file_contents, 1, size_to_read, fp);
+ if (size_read == 0 || ferror(fp)) {
+ fclose(fp);
+ parson_free(file_contents);
+ return NULL;
+ }
+ fclose(fp);
+ file_contents[size_read] = '\0';
+ return file_contents;
+}
+
+static void remove_comments(char *string, const char *start_token, const char *end_token) {
+ int in_string = 0, escaped = 0;
+ size_t i;
+ char *ptr = NULL, current_char;
+ size_t start_token_len = strlen(start_token);
+ size_t end_token_len = strlen(end_token);
+ if (start_token_len == 0 || end_token_len == 0) {
+ return;
+ }
+ while ((current_char = *string) != '\0') {
+ if (current_char == '\\' && !escaped) {
+ escaped = 1;
+ string++;
+ continue;
+ } else if (current_char == '\"' && !escaped) {
+ in_string = !in_string;
+ } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) {
+ for(i = 0; i < start_token_len; i++) {
+ string[i] = ' ';
+ }
+ string = string + start_token_len;
+ ptr = strstr(string, end_token);
+ if (!ptr) {
+ return;
+ }
+ for (i = 0; i < (ptr - string) + end_token_len; i++) {
+ string[i] = ' ';
+ }
+ string = ptr + end_token_len - 1;
+ }
+ escaped = 0;
+ string++;
+ }
+}
+
+/* JSON Object */
+static JSON_Object * json_object_init(JSON_Value *wrapping_value) {
+ JSON_Object *new_obj = (JSON_Object*)parson_malloc(sizeof(JSON_Object));
+ if (new_obj == NULL) {
+ return NULL;
+ }
+ new_obj->wrapping_value = wrapping_value;
+ new_obj->names = (char**)NULL;
+ new_obj->values = (JSON_Value**)NULL;
+ new_obj->capacity = 0;
+ new_obj->count = 0;
+ return new_obj;
+}
+
+static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value) {
+ if (name == NULL) {
+ return JSONFailure;
+ }
+ return json_object_addn(object, name, strlen(name), value);
+}
+
+static JSON_Status json_object_addn(JSON_Object *object, const char *name, size_t name_len, JSON_Value *value) {
+ size_t index = 0;
+ if (object == NULL || name == NULL || value == NULL) {
+ return JSONFailure;
+ }
+ if (json_object_getn_value(object, name, name_len) != NULL) {
+ return JSONFailure;
+ }
+ if (object->count >= object->capacity) {
+ size_t new_capacity = MAX(object->capacity * 2, STARTING_CAPACITY);
+ if (json_object_resize(object, new_capacity) == JSONFailure) {
+ return JSONFailure;
+ }
+ }
+ index = object->count;
+ object->names[index] = parson_strndup(name, name_len);
+ if (object->names[index] == NULL) {
+ return JSONFailure;
+ }
+ value->parent = json_object_get_wrapping_value(object);
+ object->values[index] = value;
+ object->count++;
+ return JSONSuccess;
+}
+
+static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity) {
+ char **temp_names = NULL;
+ JSON_Value **temp_values = NULL;
+
+ if ((object->names == NULL && object->values != NULL) ||
+ (object->names != NULL && object->values == NULL) ||
+ new_capacity == 0) {
+ return JSONFailure; /* Shouldn't happen */
+ }
+ temp_names = (char**)parson_malloc(new_capacity * sizeof(char*));
+ if (temp_names == NULL) {
+ return JSONFailure;
+ }
+ temp_values = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*));
+ if (temp_values == NULL) {
+ parson_free(temp_names);
+ return JSONFailure;
+ }
+ if (object->names != NULL && object->values != NULL && object->count > 0) {
+ memcpy(temp_names, object->names, object->count * sizeof(char*));
+ memcpy(temp_values, object->values, object->count * sizeof(JSON_Value*));
+ }
+ parson_free(object->names);
+ parson_free(object->values);
+ object->names = temp_names;
+ object->values = temp_values;
+ object->capacity = new_capacity;
+ return JSONSuccess;
+}
+
+static JSON_Value * json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len) {
+ size_t i, name_length;
+ for (i = 0; i < json_object_get_count(object); i++) {
+ name_length = strlen(object->names[i]);
+ if (name_length != name_len) {
+ continue;
+ }
+ if (strncmp(object->names[i], name, name_len) == 0) {
+ return object->values[i];
+ }
+ }
+ return NULL;
+}
+
+static JSON_Status json_object_remove_internal(JSON_Object *object, const char *name, int free_value) {
+ size_t i = 0, last_item_index = 0;
+ if (object == NULL || json_object_get_value(object, name) == NULL) {
+ return JSONFailure;
+ }
+ last_item_index = json_object_get_count(object) - 1;
+ for (i = 0; i < json_object_get_count(object); i++) {
+ if (strcmp(object->names[i], name) == 0) {
+ parson_free(object->names[i]);
+ if (free_value) {
+ json_value_free(object->values[i]);
+ }
+ if (i != last_item_index) { /* Replace key value pair with one from the end */
+ object->names[i] = object->names[last_item_index];
+ object->values[i] = object->values[last_item_index];
+ }
+ object->count -= 1;
+ return JSONSuccess;
+ }
+ }
+ return JSONFailure; /* No execution path should end here */
+}
+
+static JSON_Status json_object_dotremove_internal(JSON_Object *object, const char *name, int free_value) {
+ JSON_Value *temp_value = NULL;
+ JSON_Object *temp_object = NULL;
+ const char *dot_pos = strchr(name, '.');
+ if (dot_pos == NULL) {
+ return json_object_remove_internal(object, name, free_value);
+ }
+ temp_value = json_object_getn_value(object, name, dot_pos - name);
+ if (json_value_get_type(temp_value) != JSONObject) {
+ return JSONFailure;
+ }
+ temp_object = json_value_get_object(temp_value);
+ return json_object_dotremove_internal(temp_object, dot_pos + 1, free_value);
+}
+
+static void json_object_free(JSON_Object *object) {
+ size_t i;
+ for (i = 0; i < object->count; i++) {
+ parson_free(object->names[i]);
+ json_value_free(object->values[i]);
+ }
+ parson_free(object->names);
+ parson_free(object->values);
+ parson_free(object);
+}
+
+/* JSON Array */
+static JSON_Array * json_array_init(JSON_Value *wrapping_value) {
+ JSON_Array *new_array = (JSON_Array*)parson_malloc(sizeof(JSON_Array));
+ if (new_array == NULL) {
+ return NULL;
+ }
+ new_array->wrapping_value = wrapping_value;
+ new_array->items = (JSON_Value**)NULL;
+ new_array->capacity = 0;
+ new_array->count = 0;
+ return new_array;
+}
+
+static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value) {
+ if (array->count >= array->capacity) {
+ size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY);
+ if (json_array_resize(array, new_capacity) == JSONFailure) {
+ return JSONFailure;
+ }
+ }
+ value->parent = json_array_get_wrapping_value(array);
+ array->items[array->count] = value;
+ array->count++;
+ return JSONSuccess;
+}
+
+static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity) {
+ JSON_Value **new_items = NULL;
+ if (new_capacity == 0) {
+ return JSONFailure;
+ }
+ new_items = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*));
+ if (new_items == NULL) {
+ return JSONFailure;
+ }
+ if (array->items != NULL && array->count > 0) {
+ memcpy(new_items, array->items, array->count * sizeof(JSON_Value*));
+ }
+ parson_free(array->items);
+ array->items = new_items;
+ array->capacity = new_capacity;
+ return JSONSuccess;
+}
+
+static void json_array_free(JSON_Array *array) {
+ size_t i;
+ for (i = 0; i < array->count; i++) {
+ json_value_free(array->items[i]);
+ }
+ parson_free(array->items);
+ parson_free(array);
+}
+
+/* JSON Value */
+static JSON_Value * json_value_init_string_no_copy(char *string) {
+ JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (!new_value) {
+ return NULL;
+ }
+ new_value->parent = NULL;
+ new_value->type = JSONString;
+ new_value->value.string = string;
+ return new_value;
+}
+
+/* Parser */
+static JSON_Status skip_quotes(const char **string) {
+ if (**string != '\"') {
+ return JSONFailure;
+ }
+ SKIP_CHAR(string);
+ while (**string != '\"') {
+ if (**string == '\0') {
+ return JSONFailure;
+ } else if (**string == '\\') {
+ SKIP_CHAR(string);
+ if (**string == '\0') {
+ return JSONFailure;
+ }
+ }
+ SKIP_CHAR(string);
+ }
+ SKIP_CHAR(string);
+ return JSONSuccess;
+}
+
+static int parse_utf16(const char **unprocessed, char **processed) {
+ unsigned int cp, lead, trail;
+ int parse_succeeded = 0;
+ char *processed_ptr = *processed;
+ const char *unprocessed_ptr = *unprocessed;
+ unprocessed_ptr++; /* skips u */
+ parse_succeeded = parse_utf16_hex(unprocessed_ptr, &cp);
+ if (!parse_succeeded) {
+ return JSONFailure;
+ }
+ if (cp < 0x80) {
+ processed_ptr[0] = (char)cp; /* 0xxxxxxx */
+ } else if (cp < 0x800) {
+ processed_ptr[0] = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */
+ processed_ptr[1] = ((cp) & 0x3F) | 0x80; /* 10xxxxxx */
+ processed_ptr += 1;
+ } else if (cp < 0xD800 || cp > 0xDFFF) {
+ processed_ptr[0] = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */
+ processed_ptr[1] = ((cp >> 6) & 0x3F) | 0x80; /* 10xxxxxx */
+ processed_ptr[2] = ((cp) & 0x3F) | 0x80; /* 10xxxxxx */
+ processed_ptr += 2;
+ } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */
+ lead = cp;
+ unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */
+ if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u') {
+ return JSONFailure;
+ }
+ parse_succeeded = parse_utf16_hex(unprocessed_ptr, &trail);
+ if (!parse_succeeded || trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */
+ return JSONFailure;
+ }
+ cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000;
+ processed_ptr[0] = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */
+ processed_ptr[1] = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */
+ processed_ptr[2] = (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */
+ processed_ptr[3] = (((cp) & 0x3F) | 0x80); /* 10xxxxxx */
+ processed_ptr += 3;
+ } else { /* trail surrogate before lead surrogate */
+ return JSONFailure;
+ }
+ unprocessed_ptr += 3;
+ *processed = processed_ptr;
+ *unprocessed = unprocessed_ptr;
+ return JSONSuccess;
+}
+
+
+/* Copies and processes passed string up to supplied length.
+Example: "\u006Corem ipsum" -> lorem ipsum */
+static char* process_string(const char *input, size_t len) {
+ const char *input_ptr = input;
+ size_t initial_size = (len + 1) * sizeof(char);
+ size_t final_size = 0;
+ char *output = NULL, *output_ptr = NULL, *resized_output = NULL;
+ output = (char*)parson_malloc(initial_size);
+ if (output == NULL) {
+ goto error;
+ }
+ output_ptr = output;
+ while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < len) {
+ if (*input_ptr == '\\') {
+ input_ptr++;
+ switch (*input_ptr) {
+ case '\"': *output_ptr = '\"'; break;
+ case '\\': *output_ptr = '\\'; break;
+ case '/': *output_ptr = '/'; break;
+ case 'b': *output_ptr = '\b'; break;
+ case 'f': *output_ptr = '\f'; break;
+ case 'n': *output_ptr = '\n'; break;
+ case 'r': *output_ptr = '\r'; break;
+ case 't': *output_ptr = '\t'; break;
+ case 'u':
+ if (parse_utf16(&input_ptr, &output_ptr) == JSONFailure) {
+ goto error;
+ }
+ break;
+ default:
+ goto error;
+ }
+ } else if ((unsigned char)*input_ptr < 0x20) {
+ goto error; /* 0x00-0x19 are invalid characters for json string (http://www.ietf.org/rfc/rfc4627.txt) */
+ } else {
+ *output_ptr = *input_ptr;
+ }
+ output_ptr++;
+ input_ptr++;
+ }
+ *output_ptr = '\0';
+ /* resize to new length */
+ final_size = (size_t)(output_ptr-output) + 1;
+ /* todo: don't resize if final_size == initial_size */
+ resized_output = (char*)parson_malloc(final_size);
+ if (resized_output == NULL) {
+ goto error;
+ }
+ memcpy(resized_output, output, final_size);
+ parson_free(output);
+ return resized_output;
+error:
+ parson_free(output);
+ return NULL;
+}
+
+/* Return processed contents of a string between quotes and
+ skips passed argument to a matching quote. */
+static char * get_quoted_string(const char **string) {
+ const char *string_start = *string;
+ size_t string_len = 0;
+ JSON_Status status = skip_quotes(string);
+ if (status != JSONSuccess) {
+ return NULL;
+ }
+ string_len = *string - string_start - 2; /* length without quotes */
+ return process_string(string_start + 1, string_len);
+}
+
+static JSON_Value * parse_value(const char **string, size_t nesting) {
+ if (nesting > MAX_NESTING) {
+ return NULL;
+ }
+ SKIP_WHITESPACES(string);
+ switch (**string) {
+ case '{':
+ return parse_object_value(string, nesting + 1);
+ case '[':
+ return parse_array_value(string, nesting + 1);
+ case '\"':
+ return parse_string_value(string);
+ case 'f': case 't':
+ return parse_boolean_value(string);
+ case '-':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ return parse_number_value(string);
+ case 'n':
+ return parse_null_value(string);
+ default:
+ return NULL;
+ }
+}
+
+static JSON_Value * parse_object_value(const char **string, size_t nesting) {
+ JSON_Value *output_value = NULL, *new_value = NULL;
+ JSON_Object *output_object = NULL;
+ char *new_key = NULL;
+ output_value = json_value_init_object();
+ if (output_value == NULL) {
+ return NULL;
+ }
+ if (**string != '{') {
+ json_value_free(output_value);
+ return NULL;
+ }
+ output_object = json_value_get_object(output_value);
+ SKIP_CHAR(string);
+ SKIP_WHITESPACES(string);
+ if (**string == '}') { /* empty object */
+ SKIP_CHAR(string);
+ return output_value;
+ }
+ while (**string != '\0') {
+ new_key = get_quoted_string(string);
+ if (new_key == NULL) {
+ json_value_free(output_value);
+ return NULL;
+ }
+ SKIP_WHITESPACES(string);
+ if (**string != ':') {
+ parson_free(new_key);
+ json_value_free(output_value);
+ return NULL;
+ }
+ SKIP_CHAR(string);
+ new_value = parse_value(string, nesting);
+ if (new_value == NULL) {
+ parson_free(new_key);
+ json_value_free(output_value);
+ return NULL;
+ }
+ if (json_object_add(output_object, new_key, new_value) == JSONFailure) {
+ parson_free(new_key);
+ json_value_free(new_value);
+ json_value_free(output_value);
+ return NULL;
+ }
+ parson_free(new_key);
+ SKIP_WHITESPACES(string);
+ if (**string != ',') {
+ break;
+ }
+ SKIP_CHAR(string);
+ SKIP_WHITESPACES(string);
+ }
+ SKIP_WHITESPACES(string);
+ if (**string != '}' || /* Trim object after parsing is over */
+ json_object_resize(output_object, json_object_get_count(output_object)) == JSONFailure) {
+ json_value_free(output_value);
+ return NULL;
+ }
+ SKIP_CHAR(string);
+ return output_value;
+}
+
+static JSON_Value * parse_array_value(const char **string, size_t nesting) {
+ JSON_Value *output_value = NULL, *new_array_value = NULL;
+ JSON_Array *output_array = NULL;
+ output_value = json_value_init_array();
+ if (output_value == NULL) {
+ return NULL;
+ }
+ if (**string != '[') {
+ json_value_free(output_value);
+ return NULL;
+ }
+ output_array = json_value_get_array(output_value);
+ SKIP_CHAR(string);
+ SKIP_WHITESPACES(string);
+ if (**string == ']') { /* empty array */
+ SKIP_CHAR(string);
+ return output_value;
+ }
+ while (**string != '\0') {
+ new_array_value = parse_value(string, nesting);
+ if (new_array_value == NULL) {
+ json_value_free(output_value);
+ return NULL;
+ }
+ if (json_array_add(output_array, new_array_value) == JSONFailure) {
+ json_value_free(new_array_value);
+ json_value_free(output_value);
+ return NULL;
+ }
+ SKIP_WHITESPACES(string);
+ if (**string != ',') {
+ break;
+ }
+ SKIP_CHAR(string);
+ SKIP_WHITESPACES(string);
+ }
+ SKIP_WHITESPACES(string);
+ if (**string != ']' || /* Trim array after parsing is over */
+ json_array_resize(output_array, json_array_get_count(output_array)) == JSONFailure) {
+ json_value_free(output_value);
+ return NULL;
+ }
+ SKIP_CHAR(string);
+ return output_value;
+}
+
+static JSON_Value * parse_string_value(const char **string) {
+ JSON_Value *value = NULL;
+ char *new_string = get_quoted_string(string);
+ if (new_string == NULL) {
+ return NULL;
+ }
+ value = json_value_init_string_no_copy(new_string);
+ if (value == NULL) {
+ parson_free(new_string);
+ return NULL;
+ }
+ return value;
+}
+
+static JSON_Value * parse_boolean_value(const char **string) {
+ size_t true_token_size = SIZEOF_TOKEN("true");
+ size_t false_token_size = SIZEOF_TOKEN("false");
+ if (strncmp("true", *string, true_token_size) == 0) {
+ *string += true_token_size;
+ return json_value_init_boolean(1);
+ } else if (strncmp("false", *string, false_token_size) == 0) {
+ *string += false_token_size;
+ return json_value_init_boolean(0);
+ }
+ return NULL;
+}
+
+static JSON_Value * parse_number_value(const char **string) {
+ char *end;
+ double number = 0;
+ errno = 0;
+ number = strtod(*string, &end);
+ if (errno || !is_decimal(*string, end - *string)) {
+ return NULL;
+ }
+ *string = end;
+ return json_value_init_number(number);
+}
+
+static JSON_Value * parse_null_value(const char **string) {
+ size_t token_size = SIZEOF_TOKEN("null");
+ if (strncmp("null", *string, token_size) == 0) {
+ *string += token_size;
+ return json_value_init_null();
+ }
+ return NULL;
+}
+
+/* Serialization */
+#define APPEND_STRING(str) do { written = append_string(buf, (str));\
+ if (written < 0) { return -1; }\
+ if (buf != NULL) { buf += written; }\
+ written_total += written; } while(0)
+
+#define APPEND_INDENT(level) do { written = append_indent(buf, (level));\
+ if (written < 0) { return -1; }\
+ if (buf != NULL) { buf += written; }\
+ written_total += written; } while(0)
+
+static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf)
+{
+ const char *key = NULL, *string = NULL;
+ JSON_Value *temp_value = NULL;
+ JSON_Array *array = NULL;
+ JSON_Object *object = NULL;
+ size_t i = 0, count = 0;
+ double num = 0.0;
+ int written = -1, written_total = 0;
+
+ switch (json_value_get_type(value)) {
+ case JSONArray:
+ array = json_value_get_array(value);
+ count = json_array_get_count(array);
+ APPEND_STRING("[");
+ if (count > 0 && is_pretty) {
+ APPEND_STRING("\n");
+ }
+ for (i = 0; i < count; i++) {
+ if (is_pretty) {
+ APPEND_INDENT(level+1);
+ }
+ temp_value = json_array_get_value(array, i);
+ written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf);
+ if (written < 0) {
+ return -1;
+ }
+ if (buf != NULL) {
+ buf += written;
+ }
+ written_total += written;
+ if (i < (count - 1)) {
+ APPEND_STRING(",");
+ }
+ if (is_pretty) {
+ APPEND_STRING("\n");
+ }
+ }
+ if (count > 0 && is_pretty) {
+ APPEND_INDENT(level);
+ }
+ APPEND_STRING("]");
+ return written_total;
+ case JSONObject:
+ object = json_value_get_object(value);
+ count = json_object_get_count(object);
+ APPEND_STRING("{");
+ if (count > 0 && is_pretty) {
+ APPEND_STRING("\n");
+ }
+ for (i = 0; i < count; i++) {
+ key = json_object_get_name(object, i);
+ if (key == NULL) {
+ return -1;
+ }
+ if (is_pretty) {
+ APPEND_INDENT(level+1);
+ }
+ written = json_serialize_string(key, buf);
+ if (written < 0) {
+ return -1;
+ }
+ if (buf != NULL) {
+ buf += written;
+ }
+ written_total += written;
+ APPEND_STRING(":");
+ if (is_pretty) {
+ APPEND_STRING(" ");
+ }
+ temp_value = json_object_get_value(object, key);
+ written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf);
+ if (written < 0) {
+ return -1;
+ }
+ if (buf != NULL) {
+ buf += written;
+ }
+ written_total += written;
+ if (i < (count - 1)) {
+ APPEND_STRING(",");
+ }
+ if (is_pretty) {
+ APPEND_STRING("\n");
+ }
+ }
+ if (count > 0 && is_pretty) {
+ APPEND_INDENT(level);
+ }
+ APPEND_STRING("}");
+ return written_total;
+ case JSONString:
+ string = json_value_get_string(value);
+ if (string == NULL) {
+ return -1;
+ }
+ written = json_serialize_string(string, buf);
+ if (written < 0) {
+ return -1;
+ }
+ if (buf != NULL) {
+ buf += written;
+ }
+ written_total += written;
+ return written_total;
+ case JSONBoolean:
+ if (json_value_get_boolean(value)) {
+ APPEND_STRING("true");
+ } else {
+ APPEND_STRING("false");
+ }
+ return written_total;
+ case JSONNumber:
+ num = json_value_get_number(value);
+ if (buf != NULL) {
+ num_buf = buf;
+ }
+ written = sprintf(num_buf, FLOAT_FORMAT, num);
+ if (written < 0) {
+ return -1;
+ }
+ if (buf != NULL) {
+ buf += written;
+ }
+ written_total += written;
+ return written_total;
+ case JSONNull:
+ APPEND_STRING("null");
+ return written_total;
+ case JSONError:
+ return -1;
+ default:
+ return -1;
+ }
+}
+
+static int json_serialize_string(const char *string, char *buf) {
+ size_t i = 0, len = strlen(string);
+ char c = '\0';
+ int written = -1, written_total = 0;
+ APPEND_STRING("\"");
+ for (i = 0; i < len; i++) {
+ c = string[i];
+ switch (c) {
+ case '\"': APPEND_STRING("\\\""); break;
+ case '\\': APPEND_STRING("\\\\"); break;
+ case '\b': APPEND_STRING("\\b"); break;
+ case '\f': APPEND_STRING("\\f"); break;
+ case '\n': APPEND_STRING("\\n"); break;
+ case '\r': APPEND_STRING("\\r"); break;
+ case '\t': APPEND_STRING("\\t"); break;
+ case '\x00': APPEND_STRING("\\u0000"); break;
+ case '\x01': APPEND_STRING("\\u0001"); break;
+ case '\x02': APPEND_STRING("\\u0002"); break;
+ case '\x03': APPEND_STRING("\\u0003"); break;
+ case '\x04': APPEND_STRING("\\u0004"); break;
+ case '\x05': APPEND_STRING("\\u0005"); break;
+ case '\x06': APPEND_STRING("\\u0006"); break;
+ case '\x07': APPEND_STRING("\\u0007"); break;
+ /* '\x08' duplicate: '\b' */
+ /* '\x09' duplicate: '\t' */
+ /* '\x0a' duplicate: '\n' */
+ case '\x0b': APPEND_STRING("\\u000b"); break;
+ /* '\x0c' duplicate: '\f' */
+ /* '\x0d' duplicate: '\r' */
+ case '\x0e': APPEND_STRING("\\u000e"); break;
+ case '\x0f': APPEND_STRING("\\u000f"); break;
+ case '\x10': APPEND_STRING("\\u0010"); break;
+ case '\x11': APPEND_STRING("\\u0011"); break;
+ case '\x12': APPEND_STRING("\\u0012"); break;
+ case '\x13': APPEND_STRING("\\u0013"); break;
+ case '\x14': APPEND_STRING("\\u0014"); break;
+ case '\x15': APPEND_STRING("\\u0015"); break;
+ case '\x16': APPEND_STRING("\\u0016"); break;
+ case '\x17': APPEND_STRING("\\u0017"); break;
+ case '\x18': APPEND_STRING("\\u0018"); break;
+ case '\x19': APPEND_STRING("\\u0019"); break;
+ case '\x1a': APPEND_STRING("\\u001a"); break;
+ case '\x1b': APPEND_STRING("\\u001b"); break;
+ case '\x1c': APPEND_STRING("\\u001c"); break;
+ case '\x1d': APPEND_STRING("\\u001d"); break;
+ case '\x1e': APPEND_STRING("\\u001e"); break;
+ case '\x1f': APPEND_STRING("\\u001f"); break;
+ case '/':
+ if (parson_escape_slashes) {
+ APPEND_STRING("\\/"); /* to make json embeddable in xml\/html */
+ } else {
+ APPEND_STRING("/");
+ }
+ break;
+ default:
+ if (buf != NULL) {
+ buf[0] = c;
+ buf += 1;
+ }
+ written_total += 1;
+ break;
+ }
+ }
+ APPEND_STRING("\"");
+ return written_total;
+}
+
+static int append_indent(char *buf, int level) {
+ int i;
+ int written = -1, written_total = 0;
+ for (i = 0; i < level; i++) {
+ APPEND_STRING(" ");
+ }
+ return written_total;
+}
+
+static int append_string(char *buf, const char *string) {
+ if (buf == NULL) {
+ return (int)strlen(string);
+ }
+ return sprintf(buf, "%s", string);
+}
+
+#undef APPEND_STRING
+#undef APPEND_INDENT
+
+/* Parser API */
+JSON_Value * json_parse_file(const char *filename) {
+ char *file_contents = read_file(filename);
+ JSON_Value *output_value = NULL;
+ if (file_contents == NULL) {
+ return NULL;
+ }
+ output_value = json_parse_string(file_contents);
+ parson_free(file_contents);
+ return output_value;
+}
+
+JSON_Value * json_parse_file_with_comments(const char *filename) {
+ char *file_contents = read_file(filename);
+ JSON_Value *output_value = NULL;
+ if (file_contents == NULL) {
+ return NULL;
+ }
+ output_value = json_parse_string_with_comments(file_contents);
+ parson_free(file_contents);
+ return output_value;
+}
+
+JSON_Value * json_parse_string(const char *string) {
+ if (string == NULL) {
+ return NULL;
+ }
+ if (string[0] == '\xEF' && string[1] == '\xBB' && string[2] == '\xBF') {
+ string = string + 3; /* Support for UTF-8 BOM */
+ }
+ return parse_value((const char**)&string, 0);
+}
+
+JSON_Value * json_parse_string_with_comments(const char *string) {
+ JSON_Value *result = NULL;
+ char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL;
+ string_mutable_copy = parson_strdup(string);
+ if (string_mutable_copy == NULL) {
+ return NULL;
+ }
+ remove_comments(string_mutable_copy, "/*", "*/");
+ remove_comments(string_mutable_copy, "//", "\n");
+ string_mutable_copy_ptr = string_mutable_copy;
+ result = parse_value((const char**)&string_mutable_copy_ptr, 0);
+ parson_free(string_mutable_copy);
+ return result;
+}
+
+/* JSON Object API */
+
+JSON_Value * json_object_get_value(const JSON_Object *object, const char *name) {
+ if (object == NULL || name == NULL) {
+ return NULL;
+ }
+ return json_object_getn_value(object, name, strlen(name));
+}
+
+const char * json_object_get_string(const JSON_Object *object, const char *name) {
+ return json_value_get_string(json_object_get_value(object, name));
+}
+
+double json_object_get_number(const JSON_Object *object, const char *name) {
+ return json_value_get_number(json_object_get_value(object, name));
+}
+
+JSON_Object * json_object_get_object(const JSON_Object *object, const char *name) {
+ return json_value_get_object(json_object_get_value(object, name));
+}
+
+JSON_Array * json_object_get_array(const JSON_Object *object, const char *name) {
+ return json_value_get_array(json_object_get_value(object, name));
+}
+
+int json_object_get_boolean(const JSON_Object *object, const char *name) {
+ return json_value_get_boolean(json_object_get_value(object, name));
+}
+
+JSON_Value * json_object_dotget_value(const JSON_Object *object, const char *name) {
+ const char *dot_position = strchr(name, '.');
+ if (!dot_position) {
+ return json_object_get_value(object, name);
+ }
+ object = json_value_get_object(json_object_getn_value(object, name, dot_position - name));
+ return json_object_dotget_value(object, dot_position + 1);
+}
+
+const char * json_object_dotget_string(const JSON_Object *object, const char *name) {
+ return json_value_get_string(json_object_dotget_value(object, name));
+}
+
+double json_object_dotget_number(const JSON_Object *object, const char *name) {
+ return json_value_get_number(json_object_dotget_value(object, name));
+}
+
+JSON_Object * json_object_dotget_object(const JSON_Object *object, const char *name) {
+ return json_value_get_object(json_object_dotget_value(object, name));
+}
+
+JSON_Array * json_object_dotget_array(const JSON_Object *object, const char *name) {
+ return json_value_get_array(json_object_dotget_value(object, name));
+}
+
+int json_object_dotget_boolean(const JSON_Object *object, const char *name) {
+ return json_value_get_boolean(json_object_dotget_value(object, name));
+}
+
+size_t json_object_get_count(const JSON_Object *object) {
+ return object ? object->count : 0;
+}
+
+const char * json_object_get_name(const JSON_Object *object, size_t index) {
+ if (object == NULL || index >= json_object_get_count(object)) {
+ return NULL;
+ }
+ return object->names[index];
+}
+
+JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index) {
+ if (object == NULL || index >= json_object_get_count(object)) {
+ return NULL;
+ }
+ return object->values[index];
+}
+
+JSON_Value *json_object_get_wrapping_value(const JSON_Object *object) {
+ return object->wrapping_value;
+}
+
+int json_object_has_value (const JSON_Object *object, const char *name) {
+ return json_object_get_value(object, name) != NULL;
+}
+
+int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) {
+ JSON_Value *val = json_object_get_value(object, name);
+ return val != NULL && json_value_get_type(val) == type;
+}
+
+int json_object_dothas_value (const JSON_Object *object, const char *name) {
+ return json_object_dotget_value(object, name) != NULL;
+}
+
+int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) {
+ JSON_Value *val = json_object_dotget_value(object, name);
+ return val != NULL && json_value_get_type(val) == type;
+}
+
+/* JSON Array API */
+JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) {
+ if (array == NULL || index >= json_array_get_count(array)) {
+ return NULL;
+ }
+ return array->items[index];
+}
+
+const char * json_array_get_string(const JSON_Array *array, size_t index) {
+ return json_value_get_string(json_array_get_value(array, index));
+}
+
+double json_array_get_number(const JSON_Array *array, size_t index) {
+ return json_value_get_number(json_array_get_value(array, index));
+}
+
+JSON_Object * json_array_get_object(const JSON_Array *array, size_t index) {
+ return json_value_get_object(json_array_get_value(array, index));
+}
+
+JSON_Array * json_array_get_array(const JSON_Array *array, size_t index) {
+ return json_value_get_array(json_array_get_value(array, index));
+}
+
+int json_array_get_boolean(const JSON_Array *array, size_t index) {
+ return json_value_get_boolean(json_array_get_value(array, index));
+}
+
+size_t json_array_get_count(const JSON_Array *array) {
+ return array ? array->count : 0;
+}
+
+JSON_Value * json_array_get_wrapping_value(const JSON_Array *array) {
+ return array->wrapping_value;
+}
+
+/* JSON Value API */
+JSON_Value_Type json_value_get_type(const JSON_Value *value) {
+ return value ? value->type : JSONError;
+}
+
+JSON_Object * json_value_get_object(const JSON_Value *value) {
+ return json_value_get_type(value) == JSONObject ? value->value.object : NULL;
+}
+
+JSON_Array * json_value_get_array(const JSON_Value *value) {
+ return json_value_get_type(value) == JSONArray ? value->value.array : NULL;
+}
+
+const char * json_value_get_string(const JSON_Value *value) {
+ return json_value_get_type(value) == JSONString ? value->value.string : NULL;
+}
+
+double json_value_get_number(const JSON_Value *value) {
+ return json_value_get_type(value) == JSONNumber ? value->value.number : 0;
+}
+
+int json_value_get_boolean(const JSON_Value *value) {
+ return json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1;
+}
+
+JSON_Value * json_value_get_parent (const JSON_Value *value) {
+ return value ? value->parent : NULL;
+}
+
+void json_value_free(JSON_Value *value) {
+ switch (json_value_get_type(value)) {
+ case JSONObject:
+ json_object_free(value->value.object);
+ break;
+ case JSONString:
+ parson_free(value->value.string);
+ break;
+ case JSONArray:
+ json_array_free(value->value.array);
+ break;
+ default:
+ break;
+ }
+ parson_free(value);
+}
+
+JSON_Value * json_value_init_object(void) {
+ JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (!new_value) {
+ return NULL;
+ }
+ new_value->parent = NULL;
+ new_value->type = JSONObject;
+ new_value->value.object = json_object_init(new_value);
+ if (!new_value->value.object) {
+ parson_free(new_value);
+ return NULL;
+ }
+ return new_value;
+}
+
+JSON_Value * json_value_init_array(void) {
+ JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (!new_value) {
+ return NULL;
+ }
+ new_value->parent = NULL;
+ new_value->type = JSONArray;
+ new_value->value.array = json_array_init(new_value);
+ if (!new_value->value.array) {
+ parson_free(new_value);
+ return NULL;
+ }
+ return new_value;
+}
+
+JSON_Value * json_value_init_string(const char *string) {
+ char *copy = NULL;
+ JSON_Value *value;
+ size_t string_len = 0;
+ if (string == NULL) {
+ return NULL;
+ }
+ string_len = strlen(string);
+ if (!is_valid_utf8(string, string_len)) {
+ return NULL;
+ }
+ copy = parson_strndup(string, string_len);
+ if (copy == NULL) {
+ return NULL;
+ }
+ value = json_value_init_string_no_copy(copy);
+ if (value == NULL) {
+ parson_free(copy);
+ }
+ return value;
+}
+
+JSON_Value * json_value_init_number(double number) {
+ JSON_Value *new_value = NULL;
+ if (IS_NUMBER_INVALID(number)) {
+ return NULL;
+ }
+ new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (new_value == NULL) {
+ return NULL;
+ }
+ new_value->parent = NULL;
+ new_value->type = JSONNumber;
+ new_value->value.number = number;
+ return new_value;
+}
+
+JSON_Value * json_value_init_boolean(int boolean) {
+ JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (!new_value) {
+ return NULL;
+ }
+ new_value->parent = NULL;
+ new_value->type = JSONBoolean;
+ new_value->value.boolean = boolean ? 1 : 0;
+ return new_value;
+}
+
+JSON_Value * json_value_init_null(void) {
+ JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (!new_value) {
+ return NULL;
+ }
+ new_value->parent = NULL;
+ new_value->type = JSONNull;
+ return new_value;
+}
+
+JSON_Value * json_value_deep_copy(const JSON_Value *value) {
+ size_t i = 0;
+ JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL;
+ const char *temp_string = NULL, *temp_key = NULL;
+ char *temp_string_copy = NULL;
+ JSON_Array *temp_array = NULL, *temp_array_copy = NULL;
+ JSON_Object *temp_object = NULL, *temp_object_copy = NULL;
+
+ switch (json_value_get_type(value)) {
+ case JSONArray:
+ temp_array = json_value_get_array(value);
+ return_value = json_value_init_array();
+ if (return_value == NULL) {
+ return NULL;
+ }
+ temp_array_copy = json_value_get_array(return_value);
+ for (i = 0; i < json_array_get_count(temp_array); i++) {
+ temp_value = json_array_get_value(temp_array, i);
+ temp_value_copy = json_value_deep_copy(temp_value);
+ if (temp_value_copy == NULL) {
+ json_value_free(return_value);
+ return NULL;
+ }
+ if (json_array_add(temp_array_copy, temp_value_copy) == JSONFailure) {
+ json_value_free(return_value);
+ json_value_free(temp_value_copy);
+ return NULL;
+ }
+ }
+ return return_value;
+ case JSONObject:
+ temp_object = json_value_get_object(value);
+ return_value = json_value_init_object();
+ if (return_value == NULL) {
+ return NULL;
+ }
+ temp_object_copy = json_value_get_object(return_value);
+ for (i = 0; i < json_object_get_count(temp_object); i++) {
+ temp_key = json_object_get_name(temp_object, i);
+ temp_value = json_object_get_value(temp_object, temp_key);
+ temp_value_copy = json_value_deep_copy(temp_value);
+ if (temp_value_copy == NULL) {
+ json_value_free(return_value);
+ return NULL;
+ }
+ if (json_object_add(temp_object_copy, temp_key, temp_value_copy) == JSONFailure) {
+ json_value_free(return_value);
+ json_value_free(temp_value_copy);
+ return NULL;
+ }
+ }
+ return return_value;
+ case JSONBoolean:
+ return json_value_init_boolean(json_value_get_boolean(value));
+ case JSONNumber:
+ return json_value_init_number(json_value_get_number(value));
+ case JSONString:
+ temp_string = json_value_get_string(value);
+ if (temp_string == NULL) {
+ return NULL;
+ }
+ temp_string_copy = parson_strdup(temp_string);
+ if (temp_string_copy == NULL) {
+ return NULL;
+ }
+ return_value = json_value_init_string_no_copy(temp_string_copy);
+ if (return_value == NULL) {
+ parson_free(temp_string_copy);
+ }
+ return return_value;
+ case JSONNull:
+ return json_value_init_null();
+ case JSONError:
+ return NULL;
+ default:
+ return NULL;
+ }
+}
+
+size_t json_serialization_size(const JSON_Value *value) {
+ char num_buf[NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */
+ int res = json_serialize_to_buffer_r(value, NULL, 0, 0, num_buf);
+ return res < 0 ? 0 : (size_t)(res + 1);
+}
+
+JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) {
+ int written = -1;
+ size_t needed_size_in_bytes = json_serialization_size(value);
+ if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) {
+ return JSONFailure;
+ }
+ written = json_serialize_to_buffer_r(value, buf, 0, 0, NULL);
+ if (written < 0) {
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename) {
+ JSON_Status return_code = JSONSuccess;
+ FILE *fp = NULL;
+ char *serialized_string = json_serialize_to_string(value);
+ if (serialized_string == NULL) {
+ return JSONFailure;
+ }
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ json_free_serialized_string(serialized_string);
+ return JSONFailure;
+ }
+ if (fputs(serialized_string, fp) == EOF) {
+ return_code = JSONFailure;
+ }
+ if (fclose(fp) == EOF) {
+ return_code = JSONFailure;
+ }
+ json_free_serialized_string(serialized_string);
+ return return_code;
+}
+
+char * json_serialize_to_string(const JSON_Value *value) {
+ JSON_Status serialization_result = JSONFailure;
+ size_t buf_size_bytes = json_serialization_size(value);
+ char *buf = NULL;
+ if (buf_size_bytes == 0) {
+ return NULL;
+ }
+ buf = (char*)parson_malloc(buf_size_bytes);
+ if (buf == NULL) {
+ return NULL;
+ }
+ serialization_result = json_serialize_to_buffer(value, buf, buf_size_bytes);
+ if (serialization_result == JSONFailure) {
+ json_free_serialized_string(buf);
+ return NULL;
+ }
+ return buf;
+}
+
+size_t json_serialization_size_pretty(const JSON_Value *value) {
+ char num_buf[NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */
+ int res = json_serialize_to_buffer_r(value, NULL, 0, 1, num_buf);
+ return res < 0 ? 0 : (size_t)(res + 1);
+}
+
+JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) {
+ int written = -1;
+ size_t needed_size_in_bytes = json_serialization_size_pretty(value);
+ if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) {
+ return JSONFailure;
+ }
+ written = json_serialize_to_buffer_r(value, buf, 0, 1, NULL);
+ if (written < 0) {
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename) {
+ JSON_Status return_code = JSONSuccess;
+ FILE *fp = NULL;
+ char *serialized_string = json_serialize_to_string_pretty(value);
+ if (serialized_string == NULL) {
+ return JSONFailure;
+ }
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ json_free_serialized_string(serialized_string);
+ return JSONFailure;
+ }
+ if (fputs(serialized_string, fp) == EOF) {
+ return_code = JSONFailure;
+ }
+ if (fclose(fp) == EOF) {
+ return_code = JSONFailure;
+ }
+ json_free_serialized_string(serialized_string);
+ return return_code;
+}
+
+char * json_serialize_to_string_pretty(const JSON_Value *value) {
+ JSON_Status serialization_result = JSONFailure;
+ size_t buf_size_bytes = json_serialization_size_pretty(value);
+ char *buf = NULL;
+ if (buf_size_bytes == 0) {
+ return NULL;
+ }
+ buf = (char*)parson_malloc(buf_size_bytes);
+ if (buf == NULL) {
+ return NULL;
+ }
+ serialization_result = json_serialize_to_buffer_pretty(value, buf, buf_size_bytes);
+ if (serialization_result == JSONFailure) {
+ json_free_serialized_string(buf);
+ return NULL;
+ }
+ return buf;
+}
+
+void json_free_serialized_string(char *string) {
+ parson_free(string);
+}
+
+JSON_Status json_array_remove(JSON_Array *array, size_t ix) {
+ size_t to_move_bytes = 0;
+ if (array == NULL || ix >= json_array_get_count(array)) {
+ return JSONFailure;
+ }
+ json_value_free(json_array_get_value(array, ix));
+ to_move_bytes = (json_array_get_count(array) - 1 - ix) * sizeof(JSON_Value*);
+ memmove(array->items + ix, array->items + ix + 1, to_move_bytes);
+ array->count -= 1;
+ return JSONSuccess;
+}
+
+JSON_Status json_array_replace_value(JSON_Array *array, size_t ix, JSON_Value *value) {
+ if (array == NULL || value == NULL || value->parent != NULL || ix >= json_array_get_count(array)) {
+ return JSONFailure;
+ }
+ json_value_free(json_array_get_value(array, ix));
+ value->parent = json_array_get_wrapping_value(array);
+ array->items[ix] = value;
+ return JSONSuccess;
+}
+
+JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string) {
+ JSON_Value *value = json_value_init_string(string);
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_array_replace_value(array, i, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number) {
+ JSON_Value *value = json_value_init_number(number);
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_array_replace_value(array, i, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean) {
+ JSON_Value *value = json_value_init_boolean(boolean);
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_array_replace_value(array, i, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_array_replace_null(JSON_Array *array, size_t i) {
+ JSON_Value *value = json_value_init_null();
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_array_replace_value(array, i, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_array_clear(JSON_Array *array) {
+ size_t i = 0;
+ if (array == NULL) {
+ return JSONFailure;
+ }
+ for (i = 0; i < json_array_get_count(array); i++) {
+ json_value_free(json_array_get_value(array, i));
+ }
+ array->count = 0;
+ return JSONSuccess;
+}
+
+JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value) {
+ if (array == NULL || value == NULL || value->parent != NULL) {
+ return JSONFailure;
+ }
+ return json_array_add(array, value);
+}
+
+JSON_Status json_array_append_string(JSON_Array *array, const char *string) {
+ JSON_Value *value = json_value_init_string(string);
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_array_append_value(array, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_array_append_number(JSON_Array *array, double number) {
+ JSON_Value *value = json_value_init_number(number);
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_array_append_value(array, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_array_append_boolean(JSON_Array *array, int boolean) {
+ JSON_Value *value = json_value_init_boolean(boolean);
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_array_append_value(array, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_array_append_null(JSON_Array *array) {
+ JSON_Value *value = json_value_init_null();
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_array_append_value(array, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value) {
+ size_t i = 0;
+ JSON_Value *old_value;
+ if (object == NULL || name == NULL || value == NULL || value->parent != NULL) {
+ return JSONFailure;
+ }
+ old_value = json_object_get_value(object, name);
+ if (old_value != NULL) { /* free and overwrite old value */
+ json_value_free(old_value);
+ for (i = 0; i < json_object_get_count(object); i++) {
+ if (strcmp(object->names[i], name) == 0) {
+ value->parent = json_object_get_wrapping_value(object);
+ object->values[i] = value;
+ return JSONSuccess;
+ }
+ }
+ }
+ /* add new key value pair */
+ return json_object_add(object, name, value);
+}
+
+JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string) {
+ return json_object_set_value(object, name, json_value_init_string(string));
+}
+
+JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number) {
+ return json_object_set_value(object, name, json_value_init_number(number));
+}
+
+JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean) {
+ return json_object_set_value(object, name, json_value_init_boolean(boolean));
+}
+
+JSON_Status json_object_set_null(JSON_Object *object, const char *name) {
+ return json_object_set_value(object, name, json_value_init_null());
+}
+
+JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value) {
+ const char *dot_pos = NULL;
+ JSON_Value *temp_value = NULL, *new_value = NULL;
+ JSON_Object *temp_object = NULL, *new_object = NULL;
+ JSON_Status status = JSONFailure;
+ size_t name_len = 0;
+ if (object == NULL || name == NULL || value == NULL) {
+ return JSONFailure;
+ }
+ dot_pos = strchr(name, '.');
+ if (dot_pos == NULL) {
+ return json_object_set_value(object, name, value);
+ }
+ name_len = dot_pos - name;
+ temp_value = json_object_getn_value(object, name, name_len);
+ if (temp_value) {
+ /* Don't overwrite existing non-object (unlike json_object_set_value, but it shouldn't be changed at this point) */
+ if (json_value_get_type(temp_value) != JSONObject) {
+ return JSONFailure;
+ }
+ temp_object = json_value_get_object(temp_value);
+ return json_object_dotset_value(temp_object, dot_pos + 1, value);
+ }
+ new_value = json_value_init_object();
+ if (new_value == NULL) {
+ return JSONFailure;
+ }
+ new_object = json_value_get_object(new_value);
+ status = json_object_dotset_value(new_object, dot_pos + 1, value);
+ if (status != JSONSuccess) {
+ json_value_free(new_value);
+ return JSONFailure;
+ }
+ status = json_object_addn(object, name, name_len, new_value);
+ if (status != JSONSuccess) {
+ json_object_dotremove_internal(new_object, dot_pos + 1, 0);
+ json_value_free(new_value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string) {
+ JSON_Value *value = json_value_init_string(string);
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_object_dotset_value(object, name, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number) {
+ JSON_Value *value = json_value_init_number(number);
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_object_dotset_value(object, name, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean) {
+ JSON_Value *value = json_value_init_boolean(boolean);
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_object_dotset_value(object, name, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_object_dotset_null(JSON_Object *object, const char *name) {
+ JSON_Value *value = json_value_init_null();
+ if (value == NULL) {
+ return JSONFailure;
+ }
+ if (json_object_dotset_value(object, name, value) == JSONFailure) {
+ json_value_free(value);
+ return JSONFailure;
+ }
+ return JSONSuccess;
+}
+
+JSON_Status json_object_remove(JSON_Object *object, const char *name) {
+ return json_object_remove_internal(object, name, 1);
+}
+
+JSON_Status json_object_dotremove(JSON_Object *object, const char *name) {
+ return json_object_dotremove_internal(object, name, 1);
+}
+
+JSON_Status json_object_clear(JSON_Object *object) {
+ size_t i = 0;
+ if (object == NULL) {
+ return JSONFailure;
+ }
+ for (i = 0; i < json_object_get_count(object); i++) {
+ parson_free(object->names[i]);
+ json_value_free(object->values[i]);
+ }
+ object->count = 0;
+ return JSONSuccess;
+}
+
+JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value) {
+ JSON_Value *temp_schema_value = NULL, *temp_value = NULL;
+ JSON_Array *schema_array = NULL, *value_array = NULL;
+ JSON_Object *schema_object = NULL, *value_object = NULL;
+ JSON_Value_Type schema_type = JSONError, value_type = JSONError;
+ const char *key = NULL;
+ size_t i = 0, count = 0;
+ if (schema == NULL || value == NULL) {
+ return JSONFailure;
+ }
+ schema_type = json_value_get_type(schema);
+ value_type = json_value_get_type(value);
+ if (schema_type != value_type && schema_type != JSONNull) { /* null represents all values */
+ return JSONFailure;
+ }
+ switch (schema_type) {
+ case JSONArray:
+ schema_array = json_value_get_array(schema);
+ value_array = json_value_get_array(value);
+ count = json_array_get_count(schema_array);
+ if (count == 0) {
+ return JSONSuccess; /* Empty array allows all types */
+ }
+ /* Get first value from array, rest is ignored */
+ temp_schema_value = json_array_get_value(schema_array, 0);
+ for (i = 0; i < json_array_get_count(value_array); i++) {
+ temp_value = json_array_get_value(value_array, i);
+ if (json_validate(temp_schema_value, temp_value) == JSONFailure) {
+ return JSONFailure;
+ }
+ }
+ return JSONSuccess;
+ case JSONObject:
+ schema_object = json_value_get_object(schema);
+ value_object = json_value_get_object(value);
+ count = json_object_get_count(schema_object);
+ if (count == 0) {
+ return JSONSuccess; /* Empty object allows all objects */
+ } else if (json_object_get_count(value_object) < count) {
+ return JSONFailure; /* Tested object mustn't have less name-value pairs than schema */
+ }
+ for (i = 0; i < count; i++) {
+ key = json_object_get_name(schema_object, i);
+ temp_schema_value = json_object_get_value(schema_object, key);
+ temp_value = json_object_get_value(value_object, key);
+ if (temp_value == NULL) {
+ return JSONFailure;
+ }
+ if (json_validate(temp_schema_value, temp_value) == JSONFailure) {
+ return JSONFailure;
+ }
+ }
+ return JSONSuccess;
+ case JSONString: case JSONNumber: case JSONBoolean: case JSONNull:
+ return JSONSuccess; /* equality already tested before switch */
+ case JSONError: default:
+ return JSONFailure;
+ }
+}
+
+int json_value_equals(const JSON_Value *a, const JSON_Value *b) {
+ JSON_Object *a_object = NULL, *b_object = NULL;
+ JSON_Array *a_array = NULL, *b_array = NULL;
+ const char *a_string = NULL, *b_string = NULL;
+ const char *key = NULL;
+ size_t a_count = 0, b_count = 0, i = 0;
+ JSON_Value_Type a_type, b_type;
+ a_type = json_value_get_type(a);
+ b_type = json_value_get_type(b);
+ if (a_type != b_type) {
+ return 0;
+ }
+ switch (a_type) {
+ case JSONArray:
+ a_array = json_value_get_array(a);
+ b_array = json_value_get_array(b);
+ a_count = json_array_get_count(a_array);
+ b_count = json_array_get_count(b_array);
+ if (a_count != b_count) {
+ return 0;
+ }
+ for (i = 0; i < a_count; i++) {
+ if (!json_value_equals(json_array_get_value(a_array, i),
+ json_array_get_value(b_array, i))) {
+ return 0;
+ }
+ }
+ return 1;
+ case JSONObject:
+ a_object = json_value_get_object(a);
+ b_object = json_value_get_object(b);
+ a_count = json_object_get_count(a_object);
+ b_count = json_object_get_count(b_object);
+ if (a_count != b_count) {
+ return 0;
+ }
+ for (i = 0; i < a_count; i++) {
+ key = json_object_get_name(a_object, i);
+ if (!json_value_equals(json_object_get_value(a_object, key),
+ json_object_get_value(b_object, key))) {
+ return 0;
+ }
+ }
+ return 1;
+ case JSONString:
+ a_string = json_value_get_string(a);
+ b_string = json_value_get_string(b);
+ if (a_string == NULL || b_string == NULL) {
+ return 0; /* shouldn't happen */
+ }
+ return strcmp(a_string, b_string) == 0;
+ case JSONBoolean:
+ return json_value_get_boolean(a) == json_value_get_boolean(b);
+ case JSONNumber:
+ return fabs(json_value_get_number(a) - json_value_get_number(b)) < 0.000001; /* EPSILON */
+ case JSONError:
+ return 1;
+ case JSONNull:
+ return 1;
+ default:
+ return 1;
+ }
+}
+
+JSON_Value_Type json_type(const JSON_Value *value) {
+ return json_value_get_type(value);
+}
+
+JSON_Object * json_object (const JSON_Value *value) {
+ return json_value_get_object(value);
+}
+
+JSON_Array * json_array (const JSON_Value *value) {
+ return json_value_get_array(value);
+}
+
+const char * json_string (const JSON_Value *value) {
+ return json_value_get_string(value);
+}
+
+double json_number (const JSON_Value *value) {
+ return json_value_get_number(value);
+}
+
+int json_boolean(const JSON_Value *value) {
+ return json_value_get_boolean(value);
+}
+
+void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun) {
+ parson_malloc = malloc_fun;
+ parson_free = free_fun;
+}
+
+void json_set_escape_slashes(int escape_slashes) {
+ parson_escape_slashes = escape_slashes;
+}
diff --git a/vendor/parson/parson.h b/vendor/parson/parson.h
new file mode 100644
index 0000000..186fcb0
--- /dev/null
+++ b/vendor/parson/parson.h
@@ -0,0 +1,240 @@
+/*
+ SPDX-License-Identifier: MIT
+
+ Parson ( http://kgabis.github.com/parson/ )
+ Copyright (c) 2012 - 2019 Krzysztof Gabis
+
+ 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 parson_parson_h
+#define parson_parson_h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stddef.h> /* size_t */
+
+/* Types and enums */
+typedef struct json_object_t JSON_Object;
+typedef struct json_array_t JSON_Array;
+typedef struct json_value_t JSON_Value;
+
+enum json_value_type {
+ JSONError = -1,
+ JSONNull = 1,
+ JSONString = 2,
+ JSONNumber = 3,
+ JSONObject = 4,
+ JSONArray = 5,
+ JSONBoolean = 6
+};
+typedef int JSON_Value_Type;
+
+enum json_result_t {
+ JSONSuccess = 0,
+ JSONFailure = -1
+};
+typedef int JSON_Status;
+
+typedef void * (*JSON_Malloc_Function)(size_t);
+typedef void (*JSON_Free_Function)(void *);
+
+/* Call only once, before calling any other function from parson API. If not called, malloc and free
+ from stdlib will be used for all allocations */
+void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun);
+
+/* Sets if slashes should be escaped or not when serializing JSON. By default slashes are escaped.
+ This function sets a global setting and is not thread safe. */
+void json_set_escape_slashes(int escape_slashes);
+
+/* Parses first JSON value in a file, returns NULL in case of error */
+JSON_Value * json_parse_file(const char *filename);
+
+/* Parses first JSON value in a file and ignores comments (/ * * / and //),
+ returns NULL in case of error */
+JSON_Value * json_parse_file_with_comments(const char *filename);
+
+/* Parses first JSON value in a string, returns NULL in case of error */
+JSON_Value * json_parse_string(const char *string);
+
+/* Parses first JSON value in a string and ignores comments (/ * * / and //),
+ returns NULL in case of error */
+JSON_Value * json_parse_string_with_comments(const char *string);
+
+/* Serialization */
+size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */
+JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
+JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename);
+char * json_serialize_to_string(const JSON_Value *value);
+
+/* Pretty serialization */
+size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */
+JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
+JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename);
+char * json_serialize_to_string_pretty(const JSON_Value *value);
+
+void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */
+
+/* Comparing */
+int json_value_equals(const JSON_Value *a, const JSON_Value *b);
+
+/* Validation
+ This is *NOT* JSON Schema. It validates json by checking if object have identically
+ named fields with matching types.
+ For example schema {"name":"", "age":0} will validate
+ {"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"},
+ but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}.
+ In case of arrays, only first value in schema is checked against all values in tested array.
+ Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays,
+ null validates values of every type.
+ */
+JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value);
+
+/*
+ * JSON Object
+ */
+JSON_Value * json_object_get_value (const JSON_Object *object, const char *name);
+const char * json_object_get_string (const JSON_Object *object, const char *name);
+JSON_Object * json_object_get_object (const JSON_Object *object, const char *name);
+JSON_Array * json_object_get_array (const JSON_Object *object, const char *name);
+double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
+int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
+
+/* dotget functions enable addressing values with dot notation in nested objects,
+ just like in structs or c++/java/c# objects (e.g. objectA.objectB.value).
+ Because valid names in JSON can contain dots, some values may be inaccessible
+ this way. */
+JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name);
+const char * json_object_dotget_string (const JSON_Object *object, const char *name);
+JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name);
+JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name);
+double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
+int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
+
+/* Functions to get available names */
+size_t json_object_get_count (const JSON_Object *object);
+const char * json_object_get_name (const JSON_Object *object, size_t index);
+JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index);
+JSON_Value * json_object_get_wrapping_value(const JSON_Object *object);
+
+/* Functions to check if object has a value with a specific name. Returned value is 1 if object has
+ * a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */
+int json_object_has_value (const JSON_Object *object, const char *name);
+int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
+
+int json_object_dothas_value (const JSON_Object *object, const char *name);
+int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
+
+/* Creates new name-value pair or frees and replaces old value with a new one.
+ * json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */
+JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value);
+JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string);
+JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number);
+JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean);
+JSON_Status json_object_set_null(JSON_Object *object, const char *name);
+
+/* Works like dotget functions, but creates whole hierarchy if necessary.
+ * json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */
+JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value);
+JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string);
+JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number);
+JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean);
+JSON_Status json_object_dotset_null(JSON_Object *object, const char *name);
+
+/* Frees and removes name-value pair */
+JSON_Status json_object_remove(JSON_Object *object, const char *name);
+
+/* Works like dotget function, but removes name-value pair only on exact match. */
+JSON_Status json_object_dotremove(JSON_Object *object, const char *key);
+
+/* Removes all name-value pairs in object */
+JSON_Status json_object_clear(JSON_Object *object);
+
+/*
+ *JSON Array
+ */
+JSON_Value * json_array_get_value (const JSON_Array *array, size_t index);
+const char * json_array_get_string (const JSON_Array *array, size_t index);
+JSON_Object * json_array_get_object (const JSON_Array *array, size_t index);
+JSON_Array * json_array_get_array (const JSON_Array *array, size_t index);
+double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */
+int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */
+size_t json_array_get_count (const JSON_Array *array);
+JSON_Value * json_array_get_wrapping_value(const JSON_Array *array);
+
+/* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
+ * Order of values in array may change during execution. */
+JSON_Status json_array_remove(JSON_Array *array, size_t i);
+
+/* Frees and removes from array value at given index and replaces it with given one.
+ * Does nothing and returns JSONFailure if index doesn't exist.
+ * json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */
+JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value);
+JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string);
+JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number);
+JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean);
+JSON_Status json_array_replace_null(JSON_Array *array, size_t i);
+
+/* Frees and removes all values from array */
+JSON_Status json_array_clear(JSON_Array *array);
+
+/* Appends new value at the end of array.
+ * json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */
+JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value);
+JSON_Status json_array_append_string(JSON_Array *array, const char *string);
+JSON_Status json_array_append_number(JSON_Array *array, double number);
+JSON_Status json_array_append_boolean(JSON_Array *array, int boolean);
+JSON_Status json_array_append_null(JSON_Array *array);
+
+/*
+ *JSON Value
+ */
+JSON_Value * json_value_init_object (void);
+JSON_Value * json_value_init_array (void);
+JSON_Value * json_value_init_string (const char *string); /* copies passed string */
+JSON_Value * json_value_init_number (double number);
+JSON_Value * json_value_init_boolean(int boolean);
+JSON_Value * json_value_init_null (void);
+JSON_Value * json_value_deep_copy (const JSON_Value *value);
+void json_value_free (JSON_Value *value);
+
+JSON_Value_Type json_value_get_type (const JSON_Value *value);
+JSON_Object * json_value_get_object (const JSON_Value *value);
+JSON_Array * json_value_get_array (const JSON_Value *value);
+const char * json_value_get_string (const JSON_Value *value);
+double json_value_get_number (const JSON_Value *value);
+int json_value_get_boolean(const JSON_Value *value);
+JSON_Value * json_value_get_parent (const JSON_Value *value);
+
+/* Same as above, but shorter */
+JSON_Value_Type json_type (const JSON_Value *value);
+JSON_Object * json_object (const JSON_Value *value);
+JSON_Array * json_array (const JSON_Value *value);
+const char * json_string (const JSON_Value *value);
+double json_number (const JSON_Value *value);
+int json_boolean(const JSON_Value *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vendor/parson/tests.c b/vendor/parson/tests.c
new file mode 100644
index 0000000..e24f88e
--- /dev/null
+++ b/vendor/parson/tests.c
@@ -0,0 +1,684 @@
+/*
+ SPDX-License-Identifier: MIT
+
+ Parson ( http://kgabis.github.com/parson/ )
+ Copyright (c) 2012 - 2019 Krzysztof Gabis
+
+ 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.
+*/
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "parson.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#define TEST(A) printf("%d %-72s-", __LINE__, #A);\
+ if(A){puts(" OK");tests_passed++;}\
+ else{puts(" FAIL");tests_failed++;}
+#define STREQ(A, B) ((A) && (B) ? strcmp((A), (B)) == 0 : 0)
+#define EPSILON 0.000001
+
+void test_suite_1(void); /* Test 3 files from json.org + serialization*/
+void test_suite_2(JSON_Value *value); /* Test correctness of parsed values */
+void test_suite_2_no_comments(void);
+void test_suite_2_with_comments(void);
+void test_suite_3(void); /* Test parsing valid and invalid strings */
+void test_suite_4(void); /* Test deep copy function */
+void test_suite_5(void); /* Test building json values from scratch */
+void test_suite_6(void); /* Test value comparing verification */
+void test_suite_7(void); /* Test schema validation */
+void test_suite_8(void); /* Test serialization */
+void test_suite_9(void); /* Test serialization (pretty) */
+void test_suite_10(void); /* Testing for memory leaks */
+void test_suite_11(void); /* Additional things that require testing */
+
+void print_commits_info(const char *username, const char *repo);
+void persistence_example(void);
+void serialization_example(void);
+
+static int malloc_count;
+static void *counted_malloc(size_t size);
+static void counted_free(void *ptr);
+
+static char * read_file(const char * filename);
+
+static int tests_passed;
+static int tests_failed;
+
+int main() {
+ /* Example functions from readme file: */
+ /* print_commits_info("torvalds", "linux"); */
+ /* serialization_example(); */
+ /* persistence_example(); */
+ json_set_allocation_functions(counted_malloc, counted_free);
+ test_suite_1();
+ test_suite_2_no_comments();
+ test_suite_2_with_comments();
+ test_suite_3();
+ test_suite_4();
+ test_suite_5();
+ test_suite_6();
+ test_suite_7();
+ test_suite_8();
+ test_suite_9();
+ test_suite_10();
+ test_suite_11();
+
+ printf("Tests failed: %d\n", tests_failed);
+ printf("Tests passed: %d\n", tests_passed);
+ return 0;
+}
+
+void test_suite_1(void) {
+ JSON_Value *val;
+ TEST((val = json_parse_file("tests/test_1_1.txt")) != NULL);
+ TEST(json_value_equals(json_parse_string(json_serialize_to_string(val)), val));
+ TEST(json_value_equals(json_parse_string(json_serialize_to_string_pretty(val)), val));
+ if (val) { json_value_free(val); }
+
+ TEST((val = json_parse_file("tests/test_1_2.txt")) == NULL); /* Over 2048 levels of nesting */
+ if (val) { json_value_free(val); }
+
+ TEST((val = json_parse_file("tests/test_1_3.txt")) != NULL);
+ TEST(json_value_equals(json_parse_string(json_serialize_to_string(val)), val));
+ TEST(json_value_equals(json_parse_string(json_serialize_to_string_pretty(val)), val));
+ if (val) { json_value_free(val); }
+
+ TEST((val = json_parse_file_with_comments("tests/test_1_1.txt")) != NULL);
+ TEST(json_value_equals(json_parse_string(json_serialize_to_string(val)), val));
+ TEST(json_value_equals(json_parse_string(json_serialize_to_string_pretty(val)), val));
+ if (val) { json_value_free(val); }
+
+ TEST((val = json_parse_file_with_comments("tests/test_1_2.txt")) == NULL); /* Over 2048 levels of nesting */
+ if (val) { json_value_free(val); }
+
+ TEST((val = json_parse_file_with_comments("tests/test_1_3.txt")) != NULL);
+ TEST(json_value_equals(json_parse_string(json_serialize_to_string(val)), val));
+ TEST(json_value_equals(json_parse_string(json_serialize_to_string_pretty(val)), val));
+ if (val) { json_value_free(val); }
+}
+
+void test_suite_2(JSON_Value *root_value) {
+ JSON_Object *root_object;
+ JSON_Array *array;
+ JSON_Value *array_value;
+ size_t i;
+ TEST(root_value);
+ TEST(json_value_get_type(root_value) == JSONObject);
+ root_object = json_value_get_object(root_value);
+
+ TEST(json_object_has_value(root_object, "string"));
+ TEST(!json_object_has_value(root_object, "_string"));
+ TEST(json_object_has_value_of_type(root_object, "object", JSONObject));
+ TEST(!json_object_has_value_of_type(root_object, "string array", JSONObject));
+ TEST(json_object_has_value_of_type(root_object, "string array", JSONArray));
+ TEST(!json_object_has_value_of_type(root_object, "object", JSONArray));
+ TEST(json_object_has_value_of_type(root_object, "string", JSONString));
+ TEST(!json_object_has_value_of_type(root_object, "positive one", JSONString));
+ TEST(json_object_has_value_of_type(root_object, "positive one", JSONNumber));
+ TEST(!json_object_has_value_of_type(root_object, "string", JSONNumber));
+ TEST(json_object_has_value_of_type(root_object, "boolean true", JSONBoolean));
+ TEST(!json_object_has_value_of_type(root_object, "positive one", JSONBoolean));
+ TEST(json_object_has_value_of_type(root_object, "null", JSONNull));
+ TEST(!json_object_has_value_of_type(root_object, "object", JSONNull));
+
+ TEST(json_object_dothas_value(root_object, "object.nested array"));
+ TEST(!json_object_dothas_value(root_object, "_object.nested array"));
+ TEST(json_object_dothas_value_of_type(root_object, "object.nested object", JSONObject));
+ TEST(!json_object_dothas_value_of_type(root_object, "object.nested array", JSONObject));
+ TEST(json_object_dothas_value_of_type(root_object, "object.nested array", JSONArray));
+ TEST(!json_object_dothas_value_of_type(root_object, "object.nested object", JSONArray));
+ TEST(json_object_dothas_value_of_type(root_object, "object.nested string", JSONString));
+ TEST(!json_object_dothas_value_of_type(root_object, "object.nested number", JSONString));
+ TEST(json_object_dothas_value_of_type(root_object, "object.nested number", JSONNumber));
+ TEST(!json_object_dothas_value_of_type(root_object, "_object.nested whatever", JSONNumber));
+ TEST(json_object_dothas_value_of_type(root_object, "object.nested true", JSONBoolean));
+ TEST(!json_object_dothas_value_of_type(root_object, "object.nested number", JSONBoolean));
+ TEST(json_object_dothas_value_of_type(root_object, "object.nested null", JSONNull));
+ TEST(!json_object_dothas_value_of_type(root_object, "object.nested object", JSONNull));
+
+ TEST(STREQ(json_object_get_string(root_object, "string"), "lorem ipsum"));
+ TEST(STREQ(json_object_get_string(root_object, "utf string"), "lorem ipsum"));
+ TEST(STREQ(json_object_get_string(root_object, "utf-8 string"), "あいうえお"));
+ TEST(STREQ(json_object_get_string(root_object, "surrogate string"), "lorem𝄞ipsum𝍧lorem"));
+
+ TEST(json_object_get_number(root_object, "positive one") == 1.0);
+ TEST(json_object_get_number(root_object, "negative one") == -1.0);
+ TEST(fabs(json_object_get_number(root_object, "hard to parse number") - (-0.000314)) < EPSILON);
+ TEST(json_object_get_boolean(root_object, "boolean true") == 1);
+ TEST(json_object_get_boolean(root_object, "boolean false") == 0);
+ TEST(json_value_get_type(json_object_get_value(root_object, "null")) == JSONNull);
+
+ array = json_object_get_array(root_object, "string array");
+ if (array != NULL && json_array_get_count(array) > 1) {
+ TEST(STREQ(json_array_get_string(array, 0), "lorem"));
+ TEST(STREQ(json_array_get_string(array, 1), "ipsum"));
+ } else {
+ tests_failed++;
+ }
+
+ array = json_object_get_array(root_object, "x^2 array");
+ if (array != NULL) {
+ for (i = 0; i < json_array_get_count(array); i++) {
+ TEST(json_array_get_number(array, i) == (i * i));
+ }
+ } else {
+ tests_failed++;
+ }
+
+ TEST(json_object_get_array(root_object, "non existent array") == NULL);
+ TEST(STREQ(json_object_dotget_string(root_object, "object.nested string"), "str"));
+ TEST(json_object_dotget_boolean(root_object, "object.nested true") == 1);
+ TEST(json_object_dotget_boolean(root_object, "object.nested false") == 0);
+ TEST(json_object_dotget_value(root_object, "object.nested null") != NULL);
+ TEST(json_object_dotget_number(root_object, "object.nested number") == 123);
+
+ TEST(json_object_dotget_value(root_object, "should.be.null") == NULL);
+ TEST(json_object_dotget_value(root_object, "should.be.null.") == NULL);
+ TEST(json_object_dotget_value(root_object, ".") == NULL);
+ TEST(json_object_dotget_value(root_object, "") == NULL);
+
+ array = json_object_dotget_array(root_object, "object.nested array");
+ TEST(array != NULL);
+ TEST(json_array_get_count(array) > 1);
+ if (array != NULL && json_array_get_count(array) > 1) {
+ TEST(STREQ(json_array_get_string(array, 0), "lorem"));
+ TEST(STREQ(json_array_get_string(array, 1), "ipsum"));
+ }
+ TEST(json_object_dotget_boolean(root_object, "object.nested true") == 1);
+
+ TEST(STREQ(json_object_get_string(root_object, "/**/"), "comment"));
+ TEST(STREQ(json_object_get_string(root_object, "//"), "comment"));
+ TEST(STREQ(json_object_get_string(root_object, "url"), "https://www.example.com/search?q=12345"));
+ TEST(STREQ(json_object_get_string(root_object, "escaped chars"), "\" \\ /"));
+
+ TEST(json_object_get_object(root_object, "empty object") != NULL);
+ TEST(json_object_get_array(root_object, "empty array") != NULL);
+
+ TEST(json_object_get_wrapping_value(root_object) == root_value);
+ array = json_object_get_array(root_object, "string array");
+ array_value = json_object_get_value(root_object, "string array");
+ TEST(json_array_get_wrapping_value(array) == array_value);
+ TEST(json_value_get_parent(array_value) == root_value);
+ TEST(json_value_get_parent(root_value) == NULL);
+}
+
+void test_suite_2_no_comments(void) {
+ const char *filename = "tests/test_2.txt";
+ JSON_Value *root_value = NULL;
+ root_value = json_parse_file(filename);
+ test_suite_2(root_value);
+ TEST(json_value_equals(root_value, json_parse_string(json_serialize_to_string(root_value))));
+ TEST(json_value_equals(root_value, json_parse_string(json_serialize_to_string_pretty(root_value))));
+ json_value_free(root_value);
+}
+
+void test_suite_2_with_comments(void) {
+ const char *filename = "tests/test_2_comments.txt";
+ JSON_Value *root_value = NULL;
+ root_value = json_parse_file_with_comments(filename);
+ test_suite_2(root_value);
+ TEST(json_value_equals(root_value, json_parse_string(json_serialize_to_string(root_value))));
+ TEST(json_value_equals(root_value, json_parse_string(json_serialize_to_string_pretty(root_value))));
+ json_value_free(root_value);
+}
+
+void test_suite_3(void) {
+ puts("Testing valid strings:");
+ TEST(json_parse_string("{\"lorem\":\"ipsum\"}") != NULL);
+ TEST(json_parse_string("[\"lorem\"]") != NULL);
+ TEST(json_parse_string("null") != NULL);
+ TEST(json_parse_string("true") != NULL);
+ TEST(json_parse_string("false") != NULL);
+ TEST(json_parse_string("\"string\"") != NULL);
+ TEST(json_parse_string("123") != NULL);
+
+ puts("Test UTF-16 parsing:");
+ TEST(STREQ(json_string(json_parse_string("\"\\u0024x\"")), "$x"));
+ TEST(STREQ(json_string(json_parse_string("\"\\u00A2x\"")), "¢x"));
+ TEST(STREQ(json_string(json_parse_string("\"\\u20ACx\"")), "€x"));
+ TEST(STREQ(json_string(json_parse_string("\"\\uD801\\uDC37x\"")), "𐐷x"));
+
+ puts("Testing invalid strings:");
+ malloc_count = 0;
+ TEST(json_parse_string(NULL) == NULL);
+ TEST(json_parse_string("") == NULL); /* empty string */
+ TEST(json_parse_string("[\"lorem\",]") == NULL);
+ TEST(json_parse_string("{\"lorem\":\"ipsum\",}") == NULL);
+ TEST(json_parse_string("{lorem:ipsum}") == NULL);
+ TEST(json_parse_string("[,]") == NULL);
+ TEST(json_parse_string("[,") == NULL);
+ TEST(json_parse_string("[") == NULL);
+ TEST(json_parse_string("]") == NULL);
+ TEST(json_parse_string("{\"a\":0,\"a\":0}") == NULL); /* duplicate keys */
+ TEST(json_parse_string("{:,}") == NULL);
+ TEST(json_parse_string("{,}") == NULL);
+ TEST(json_parse_string("{,") == NULL);
+ TEST(json_parse_string("{:") == NULL);
+ TEST(json_parse_string("{") == NULL);
+ TEST(json_parse_string("}") == NULL);
+ TEST(json_parse_string("x") == NULL);
+ TEST(json_parse_string("{:\"no name\"}") == NULL);
+ TEST(json_parse_string("[,\"no first value\"]") == NULL);
+ TEST(json_parse_string("{\"key\"\"value\"}") == NULL);
+ TEST(json_parse_string("{\"a\"}") == NULL);
+ TEST(json_parse_string("[\"\\u00zz\"]") == NULL); /* invalid utf value */
+ TEST(json_parse_string("[\"\\u00\"]") == NULL); /* invalid utf value */
+ TEST(json_parse_string("[\"\\u\"]") == NULL); /* invalid utf value */
+ TEST(json_parse_string("[\"\\\"]") == NULL); /* control character */
+ TEST(json_parse_string("[\"\"\"]") == NULL); /* control character */
+ TEST(json_parse_string("[\"\0\"]") == NULL); /* control character */
+ TEST(json_parse_string("[\"\a\"]") == NULL); /* control character */
+ TEST(json_parse_string("[\"\b\"]") == NULL); /* control character */
+ TEST(json_parse_string("[\"\t\"]") == NULL); /* control character */
+ TEST(json_parse_string("[\"\n\"]") == NULL); /* control character */
+ TEST(json_parse_string("[\"\f\"]") == NULL); /* control character */
+ TEST(json_parse_string("[\"\r\"]") == NULL); /* control character */
+ TEST(json_parse_string("[0x2]") == NULL); /* hex */
+ TEST(json_parse_string("[0X2]") == NULL); /* HEX */
+ TEST(json_parse_string("[07]") == NULL); /* octals */
+ TEST(json_parse_string("[0070]") == NULL);
+ TEST(json_parse_string("[07.0]") == NULL);
+ TEST(json_parse_string("[-07]") == NULL);
+ TEST(json_parse_string("[-007]") == NULL);
+ TEST(json_parse_string("[-07.0]") == NULL);
+ TEST(json_parse_string("[\"\\uDF67\\uD834\"]") == NULL); /* wrong order surrogate pair */
+ TEST(json_parse_string("[1.7976931348623157e309]") == NULL);
+ TEST(json_parse_string("[-1.7976931348623157e309]") == NULL);
+ TEST(malloc_count == 0);
+}
+
+void test_suite_4() {
+ const char *filename = "tests/test_2.txt";
+ JSON_Value *a = NULL, *a_copy = NULL;
+ printf("Testing %s:\n", filename);
+ a = json_parse_file(filename);
+ TEST(json_value_equals(a, a)); /* test equality test */
+ a_copy = json_value_deep_copy(a);
+ TEST(a_copy != NULL);
+ TEST(json_value_equals(a, a_copy));
+}
+
+void test_suite_5(void) {
+ double zero = 0.0; /* msvc is silly (workaround for error C2124) */
+
+ JSON_Value *val_from_file = json_parse_file("tests/test_5.txt");
+
+ JSON_Value *val = NULL, *val_parent;
+ JSON_Object *obj = NULL;
+ JSON_Array *interests_arr = NULL;
+
+ JSON_Value *remove_test_val = NULL;
+ JSON_Array *remove_test_arr = NULL;
+
+ val = json_value_init_object();
+ TEST(val != NULL);
+
+ obj = json_value_get_object(val);
+ TEST(obj != NULL);
+
+ TEST(json_object_set_string(obj, "first", "John") == JSONSuccess);
+ TEST(json_object_set_string(obj, "last", "Doe") == JSONSuccess);
+ TEST(json_object_set_number(obj, "age", 25) == JSONSuccess);
+ TEST(json_object_set_boolean(obj, "registered", 1) == JSONSuccess);
+
+ TEST(json_object_set_value(obj, "interests", json_value_init_array()) == JSONSuccess);
+ interests_arr = json_object_get_array(obj, "interests");
+ TEST(interests_arr != NULL);
+ TEST(json_array_append_string(interests_arr, "Writing") == JSONSuccess);
+ TEST(json_array_append_string(interests_arr, "Mountain Biking") == JSONSuccess);
+ TEST(json_array_replace_string(interests_arr, 0, "Reading") == JSONSuccess);
+
+ TEST(json_object_dotset_string(obj, "favorites.color", "blue") == JSONSuccess);
+ TEST(json_object_dotset_string(obj, "favorites.sport", "running") == JSONSuccess);
+ TEST(json_object_dotset_string(obj, "favorites.fruit", "apple") == JSONSuccess);
+ TEST(json_object_dotremove(obj, "favorites.fruit") == JSONSuccess);
+ TEST(json_object_set_string(obj, "utf string", "lorem ipsum") == JSONSuccess);
+ TEST(json_object_set_string(obj, "utf-8 string", "あいうえお") == JSONSuccess);
+ TEST(json_object_set_string(obj, "surrogate string", "lorem𝄞ipsum𝍧lorem") == JSONSuccess);
+ TEST(json_object_set_string(obj, "windows path", "C:\\Windows\\Path") == JSONSuccess);
+ TEST(json_value_equals(val_from_file, val));
+
+ TEST(json_object_set_string(obj, NULL, "") == JSONFailure);
+ TEST(json_object_set_string(obj, "last", NULL) == JSONFailure);
+ TEST(json_object_set_string(obj, NULL, NULL) == JSONFailure);
+ TEST(json_object_set_value(obj, NULL, NULL) == JSONFailure);
+
+ TEST(json_object_dotset_string(obj, NULL, "") == JSONFailure);
+ TEST(json_object_dotset_string(obj, "favorites.color", NULL) == JSONFailure);
+ TEST(json_object_dotset_string(obj, NULL, NULL) == JSONFailure);
+ TEST(json_object_dotset_value(obj, NULL, NULL) == JSONFailure);
+
+ TEST(json_array_append_string(NULL, "lorem") == JSONFailure);
+ TEST(json_array_append_value(interests_arr, NULL) == JSONFailure);
+ TEST(json_array_append_value(NULL, NULL) == JSONFailure);
+
+ TEST(json_array_remove(NULL, 0) == JSONFailure);
+ TEST(json_array_replace_value(interests_arr, 0, NULL) == JSONFailure);
+ TEST(json_array_replace_string(NULL, 0, "lorem") == JSONFailure);
+ TEST(json_array_replace_string(interests_arr, 100, "not existing") == JSONFailure);
+
+ TEST(json_array_append_string(json_object_get_array(obj, "interests"), NULL) == JSONFailure);
+
+ TEST(json_array_append_string(interests_arr, "Writing") == JSONSuccess);
+ TEST(json_array_remove(interests_arr, 0) == JSONSuccess);
+ TEST(json_array_remove(interests_arr, 1) == JSONSuccess);
+ TEST(json_array_remove(interests_arr, 0) == JSONSuccess);
+ TEST(json_array_remove(interests_arr, 0) == JSONFailure); /* should be empty by now */
+
+ val_parent = json_value_init_null();
+ TEST(json_object_set_value(obj, "x", val_parent) == JSONSuccess);
+ TEST(json_object_set_value(obj, "x", val_parent) == JSONFailure);
+
+ val_parent = json_value_init_null();
+ TEST(json_array_append_value(interests_arr, val_parent) == JSONSuccess);
+ TEST(json_array_append_value(interests_arr, val_parent) == JSONFailure);
+
+ val_parent = json_value_init_null();
+ TEST(json_array_replace_value(interests_arr, 0, val_parent) == JSONSuccess);
+ TEST(json_array_replace_value(interests_arr, 0, val_parent) == JSONFailure);
+
+ TEST(json_object_remove(obj, "interests") == JSONSuccess);
+
+ /* UTF-8 tests */
+ TEST(json_object_set_string(obj, "correct string", "κόσμε") == JSONSuccess);
+
+ TEST(json_object_set_string(obj, "boundary 1", "\xed\x9f\xbf") == JSONSuccess);
+ TEST(json_object_set_string(obj, "boundary 2", "\xee\x80\x80") == JSONSuccess);
+ TEST(json_object_set_string(obj, "boundary 3", "\xef\xbf\xbd") == JSONSuccess);
+ TEST(json_object_set_string(obj, "boundary 4", "\xf4\x8f\xbf\xbf") == JSONSuccess);
+
+ TEST(json_object_set_string(obj, "first continuation byte", "\x80") == JSONFailure);
+ TEST(json_object_set_string(obj, "last continuation byte", "\xbf") == JSONFailure);
+
+ TEST(json_object_set_string(obj, "impossible sequence 1", "\xfe") == JSONFailure);
+ TEST(json_object_set_string(obj, "impossible sequence 2", "\xff") == JSONFailure);
+ TEST(json_object_set_string(obj, "impossible sequence 3", "\xfe\xfe\xff\xff") == JSONFailure);
+
+ TEST(json_object_set_string(obj, "overlong 1", "\xc0\xaf") == JSONFailure);
+ TEST(json_object_set_string(obj, "overlong 2", "\xc1\xbf") == JSONFailure);
+ TEST(json_object_set_string(obj, "overlong 3", "\xe0\x80\xaf") == JSONFailure);
+ TEST(json_object_set_string(obj, "overlong 4", "\xe0\x9f\xbf") == JSONFailure);
+ TEST(json_object_set_string(obj, "overlong 5", "\xf0\x80\x80\xaf") == JSONFailure);
+ TEST(json_object_set_string(obj, "overlong 6", "\xf0\x8f\xbf\xbf") == JSONFailure);
+ TEST(json_object_set_string(obj, "overlong 7", "\xf0\x8f\xbf\xbf") == JSONFailure);
+
+ TEST(json_object_set_string(obj, "overlong null 1", "\xc0\x80") == JSONFailure);
+ TEST(json_object_set_string(obj, "overlong null 2", "\xe0\x80\x80") == JSONFailure);
+ TEST(json_object_set_string(obj, "overlong null 3", "\xf0\x80\x80\x80") == JSONFailure);
+ TEST(json_object_set_string(obj, "overlong null 4", "\xf8\x80\x80\x80\x80") == JSONFailure);
+ TEST(json_object_set_string(obj, "overlong null 5", "\xfc\x80\x80\x80\x80\x80") == JSONFailure);
+
+ TEST(json_object_set_string(obj, "single surrogate 1", "\xed\xa0\x80") == JSONFailure);
+ TEST(json_object_set_string(obj, "single surrogate 2", "\xed\xaf\xbf") == JSONFailure);
+ TEST(json_object_set_string(obj, "single surrogate 3", "\xed\xbf\xbf") == JSONFailure);
+
+ /* Testing removing values from array, order of the elements should be preserved */
+ remove_test_val = json_parse_string("[1, 2, 3, 4, 5]");
+ remove_test_arr = json_array(remove_test_val);
+ json_array_remove(remove_test_arr, 2);
+ TEST(json_value_equals(remove_test_val, json_parse_string("[1, 2, 4, 5]")));
+ json_array_remove(remove_test_arr, 0);
+ TEST(json_value_equals(remove_test_val, json_parse_string("[2, 4, 5]")));
+ json_array_remove(remove_test_arr, 2);
+ TEST(json_value_equals(remove_test_val, json_parse_string("[2, 4]")));
+
+ /* Testing nan and inf */
+ TEST(json_object_set_number(obj, "num", 0.0 / zero) == JSONFailure);
+ TEST(json_object_set_number(obj, "num", 1.0 / zero) == JSONFailure);
+}
+
+void test_suite_6(void) {
+ const char *filename = "tests/test_2.txt";
+ JSON_Value *a = NULL;
+ JSON_Value *b = NULL;
+ a = json_parse_file(filename);
+ b = json_parse_file(filename);
+ TEST(json_value_equals(a, b));
+ json_object_set_string(json_object(a), "string", "eki");
+ TEST(!json_value_equals(a, b));
+ a = json_value_deep_copy(b);
+ TEST(json_value_equals(a, b));
+ json_array_append_number(json_object_get_array(json_object(b), "string array"), 1337);
+ TEST(!json_value_equals(a, b));
+}
+
+void test_suite_7(void) {
+ JSON_Value *val_from_file = json_parse_file("tests/test_5.txt");
+ JSON_Value *schema = json_value_init_object();
+ JSON_Object *schema_obj = json_value_get_object(schema);
+ JSON_Array *interests_arr = NULL;
+ json_object_set_string(schema_obj, "first", "");
+ json_object_set_string(schema_obj, "last", "");
+ json_object_set_number(schema_obj, "age", 0);
+ json_object_set_value(schema_obj, "interests", json_value_init_array());
+ interests_arr = json_object_get_array(schema_obj, "interests");
+ json_array_append_string(interests_arr, "");
+ json_object_set_null(schema_obj, "favorites");
+ TEST(json_validate(schema, val_from_file) == JSONSuccess);
+ json_object_set_string(schema_obj, "age", "");
+ TEST(json_validate(schema, val_from_file) == JSONFailure);
+}
+
+void test_suite_8(void) {
+ const char *filename = "tests/test_2.txt";
+ const char *temp_filename = "tests/test_2_serialized.txt";
+ JSON_Value *a = NULL;
+ JSON_Value *b = NULL;
+ char *buf = NULL;
+ size_t serialization_size = 0;
+ a = json_parse_file(filename);
+ TEST(json_serialize_to_file(a, temp_filename) == JSONSuccess);
+ b = json_parse_file(temp_filename);
+ TEST(json_value_equals(a, b));
+ remove(temp_filename);
+ serialization_size = json_serialization_size(a);
+ buf = json_serialize_to_string(a);
+ TEST((strlen(buf)+1) == serialization_size);
+}
+
+void test_suite_9(void) {
+ const char *filename = "tests/test_2_pretty.txt";
+ const char *temp_filename = "tests/test_2_serialized_pretty.txt";
+ char *file_contents = NULL;
+ char *serialized = NULL;
+ JSON_Value *a = NULL;
+ JSON_Value *b = NULL;
+ size_t serialization_size = 0;
+ a = json_parse_file(filename);
+ TEST(json_serialize_to_file_pretty(a, temp_filename) == JSONSuccess);
+ b = json_parse_file(temp_filename);
+ TEST(json_value_equals(a, b));
+ remove(temp_filename);
+ serialization_size = json_serialization_size_pretty(a);
+ serialized = json_serialize_to_string_pretty(a);
+ TEST((strlen(serialized)+1) == serialization_size);
+
+ file_contents = read_file(filename);
+
+ TEST(STREQ(file_contents, serialized));
+}
+
+void test_suite_10(void) {
+ JSON_Value *val;
+ char *serialized;
+
+ malloc_count = 0;
+
+ val = json_parse_file("tests/test_1_1.txt");
+ json_value_free(val);
+
+ val = json_parse_file("tests/test_1_3.txt");
+ json_value_free(val);
+
+ val = json_parse_file("tests/test_2.txt");
+ serialized = json_serialize_to_string_pretty(val);
+ json_free_serialized_string(serialized);
+ json_value_free(val);
+
+ val = json_parse_file("tests/test_2_pretty.txt");
+ json_value_free(val);
+
+ TEST(malloc_count == 0);
+}
+
+void test_suite_11() {
+ const char * array_with_slashes = "[\"a/b/c\"]";
+ const char * array_with_escaped_slashes = "[\"a\\/b\\/c\"]";
+ char *serialized = NULL;
+ JSON_Value *value = json_parse_string(array_with_slashes);
+
+ serialized = json_serialize_to_string(value);
+ TEST(STREQ(array_with_escaped_slashes, serialized));
+
+ json_set_escape_slashes(0);
+ serialized = json_serialize_to_string(value);
+ TEST(STREQ(array_with_slashes, serialized));
+
+ json_set_escape_slashes(1);
+ serialized = json_serialize_to_string(value);
+ TEST(STREQ(array_with_escaped_slashes, serialized));
+}
+
+void print_commits_info(const char *username, const char *repo) {
+ JSON_Value *root_value;
+ JSON_Array *commits;
+ JSON_Object *commit;
+ size_t i;
+
+ char curl_command[512];
+ char cleanup_command[256];
+ char output_filename[] = "commits.json";
+
+ /* it ain't pretty, but it's not a libcurl tutorial */
+ sprintf(curl_command,
+ "curl -s \"https://api.github.com/repos/%s/%s/commits\" > %s",
+ username, repo, output_filename);
+ sprintf(cleanup_command, "rm -f %s", output_filename);
+ system(curl_command);
+
+ /* parsing json and validating output */
+ root_value = json_parse_file(output_filename);
+ if (json_value_get_type(root_value) != JSONArray) {
+ system(cleanup_command);
+ return;
+ }
+
+ /* getting array from root value and printing commit info */
+ commits = json_value_get_array(root_value);
+ printf("%-10.10s %-10.10s %s\n", "Date", "SHA", "Author");
+ for (i = 0; i < json_array_get_count(commits); i++) {
+ commit = json_array_get_object(commits, i);
+ printf("%.10s %.10s %s\n",
+ json_object_dotget_string(commit, "commit.author.date"),
+ json_object_get_string(commit, "sha"),
+ json_object_dotget_string(commit, "commit.author.name"));
+ }
+
+ /* cleanup code */
+ json_value_free(root_value);
+ system(cleanup_command);
+}
+
+void persistence_example(void) {
+ JSON_Value *schema = json_parse_string("{\"name\":\"\"}");
+ JSON_Value *user_data = json_parse_file("user_data.json");
+ char buf[256];
+ const char *name = NULL;
+ if (user_data == NULL || json_validate(schema, user_data) != JSONSuccess) {
+ puts("Enter your name:");
+ scanf("%s", buf);
+ user_data = json_value_init_object();
+ json_object_set_string(json_object(user_data), "name", buf);
+ json_serialize_to_file(user_data, "user_data.json");
+ }
+ name = json_object_get_string(json_object(user_data), "name");
+ printf("Hello, %s.", name);
+ json_value_free(schema);
+ json_value_free(user_data);
+ return;
+}
+
+void serialization_example(void) {
+ JSON_Value *root_value = json_value_init_object();
+ JSON_Object *root_object = json_value_get_object(root_value);
+ char *serialized_string = NULL;
+ json_object_set_string(root_object, "name", "John Smith");
+ json_object_set_number(root_object, "age", 25);
+ json_object_dotset_string(root_object, "address.city", "Cupertino");
+ json_object_dotset_value(root_object, "contact.emails",
+ json_parse_string("[\"email@example.com\", \"email2@example.com\"]"));
+ serialized_string = json_serialize_to_string_pretty(root_value);
+ puts(serialized_string);
+ json_free_serialized_string(serialized_string);
+ json_value_free(root_value);
+}
+
+static char * read_file(const char * filename) {
+ FILE *fp = fopen(filename, "r");
+ size_t size_to_read = 0;
+ size_t size_read = 0;
+ long pos;
+ char *file_contents;
+ if (!fp) {
+ return NULL;
+ }
+ fseek(fp, 0L, SEEK_END);
+ pos = ftell(fp);
+ if (pos < 0) {
+ fclose(fp);
+ return NULL;
+ }
+ size_to_read = pos;
+ rewind(fp);
+ file_contents = (char*)malloc(sizeof(char) * (size_to_read + 1));
+ if (!file_contents) {
+ fclose(fp);
+ return NULL;
+ }
+ size_read = fread(file_contents, 1, size_to_read, fp);
+ if (size_read == 0 || ferror(fp)) {
+ fclose(fp);
+ free(file_contents);
+ return NULL;
+ }
+ fclose(fp);
+ file_contents[size_read] = '\0';
+ return file_contents;
+}
+
+static void *counted_malloc(size_t size) {
+ void *res = malloc(size);
+ if (res != NULL) {
+ malloc_count++;
+ }
+ return res;
+}
+
+static void counted_free(void *ptr) {
+ if (ptr != NULL) {
+ malloc_count--;
+ }
+ free(ptr);
+}
diff --git a/vendor/parson/tests/test_1_1.txt b/vendor/parson/tests/test_1_1.txt
new file mode 100644
index 0000000..da78ef4
--- /dev/null
+++ b/vendor/parson/tests/test_1_1.txt
@@ -0,0 +1,59 @@
+
+ [
+ "JSON Test Pattern pass1",
+ {"object with 1 member":["array with 1 element"]},
+ {},
+ [],
+ -42,
+ true,
+ false,
+ null,
+ {
+ "integer": 1234567890,
+ "real": -9876.543210,
+ "e": 0.123456789e-12,
+ "E": 1.234567890E+34,
+ "": 23456789012E66,
+ "zero": 0,
+ "one": 1,
+ "space": " ",
+ "quote": "\"",
+ "backslash": "\\",
+ "controls": "\b\f\n\r\t",
+ "slash": "/ & \/",
+ "alpha": "abcdefghijklmnopqrstuvwyz",
+ "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
+ "digit": "0123456789",
+ "0123456789": "digit",
+ "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
+ "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
+ "true": true,
+ "false": false,
+ "null": null,
+ "array":[ ],
+ "object":{ },
+ "address": "50 St. James Street",
+ "url": "http://www.JSON.org/",
+ "comment": "// /* <!-- --",
+ "# -- --> */": " ",
+ " s p a c e d " :[1,2 , 3
+
+,
+
+4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
+ "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
+ "quotes": "&#34; \u0022 %22 0x22 034 &#x22;",
+ "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
+: "A key can be any string"
+ },
+ 0.5 ,98.6
+,
+99.44
+,
+
+1066,
+1e1,
+0.1e1,
+1e-1,
+1e00,2e+00,2e-00
+,"rosebud"] \ No newline at end of file
diff --git a/vendor/parson/tests/test_1_2.txt b/vendor/parson/tests/test_1_2.txt
new file mode 100644
index 0000000..c778517
--- /dev/null
+++ b/vendor/parson/tests/test_1_2.txt
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] \ No newline at end of file
diff --git a/vendor/parson/tests/test_1_3.txt b/vendor/parson/tests/test_1_3.txt
new file mode 100644
index 0000000..4528d51
--- /dev/null
+++ b/vendor/parson/tests/test_1_3.txt
@@ -0,0 +1,6 @@
+{
+ "JSON Test Pattern pass3": {
+ "The outermost value": "must be an object or array.",
+ "In this test": "It is an object."
+ }
+}
diff --git a/vendor/parson/tests/test_2.txt b/vendor/parson/tests/test_2.txt
new file mode 100644
index 0000000..f473599
--- /dev/null
+++ b/vendor/parson/tests/test_2.txt
@@ -0,0 +1,33 @@
+{
+ "string" : "lorem ipsum",
+ "utf string" : "\u006corem\u0020ipsum",
+ "utf-8 string": "あいうえお",
+ "surrogate string": "lorem\uD834\uDD1Eipsum\uD834\uDF67lorem",
+ "positive one" : 1,
+ "negative one" : -1,
+ "pi" : 3.14,
+ "hard to parse number" : -3.14e-4,
+ "big int": 2147483647,
+ "big uint": 4294967295,
+ "boolean true" : true,
+ "boolean false" : false,
+ "null" : null,
+ "string array" : ["lorem", "ipsum"],
+ "x^2 array" : [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100],
+ "/*" : null,
+ "object" : { "nested string" : "str",
+ "nested true" : true,
+ "nested false" : false,
+ "nested null" : null,
+ "nested number" : 123,
+ "nested array" : ["lorem", "ipsum"],
+ "nested object" : {"lorem": "ipsum"}
+ },
+ "*/" : null,
+ "/**/" : "comment",
+ "//" : "comment",
+ "url" : "https:\/\/www.example.com\/search?q=12345",
+ "escaped chars" : "\" \\ \/",
+ "empty object" : {},
+ "empty array" : []
+}
diff --git a/vendor/parson/tests/test_2_comments.txt b/vendor/parson/tests/test_2_comments.txt
new file mode 100644
index 0000000..504be86
--- /dev/null
+++ b/vendor/parson/tests/test_2_comments.txt
@@ -0,0 +1,43 @@
+/*
+ *Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ *ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ *dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+*/
+// Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+{ /* lorem ipsum */
+ "string" : "lorem ipsum", // lorem ipsum
+ "utf string" : "\u006corem\u0020ipsum", // lorem ipsum //
+ "utf-8 string": "あいうえお", // /* lorem ipsum */
+ "surrogate string": "lorem\uD834\uDD1Eipsum\uD834\uDF67lorem",
+ "positive one" : 1,
+ "negative one" : -1,
+ "pi" : 3.14,
+ "hard to parse number" : -3.14e-4,
+ "big int": 2147483647,
+ "big uint": 4294967295,
+ "boolean true" : true,
+ "boolean false" : false,
+ "null" : null,
+ "string array" : ["lorem",/*in array*/"ipsum"],
+ "x^2 array" : [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100],
+/* "x^2 array" : [],
+*/
+ "/*" : null,
+ "object" : { "nested string" : "str",
+ "nested true" : /* lorem ipsum */ true,
+ "nested false" : false,
+ "nested null" : null, // lorem ipsum
+ "nested number" : 123,
+ "nested array" : ["lorem", "ipsum"],
+ "nested object" : {"lorem": "ipsum"}
+ },
+ "*/" : null,
+ "/**/" : "comment",
+ "//" : "comment",
+ "url" : "https:\/\/www.example.com\/search?q=12345",
+ "escaped chars" : "\" \\ \/",
+ "empty object" : {},
+ "empty array" : []
+}
+/**/
+// \ No newline at end of file
diff --git a/vendor/parson/tests/test_2_pretty.txt b/vendor/parson/tests/test_2_pretty.txt
new file mode 100644
index 0000000..96aaaef
--- /dev/null
+++ b/vendor/parson/tests/test_2_pretty.txt
@@ -0,0 +1,51 @@
+{
+ "string": "lorem ipsum",
+ "utf string": "lorem ipsum",
+ "utf-8 string": "あいうえお",
+ "surrogate string": "lorem𝄞ipsum𝍧lorem",
+ "positive one": 1,
+ "negative one": -1,
+ "pi": 3.1400000000000001,
+ "hard to parse number": -0.00031399999999999999,
+ "big int": 2147483647,
+ "big uint": 4294967295,
+ "boolean true": true,
+ "boolean false": false,
+ "null": null,
+ "string array": [
+ "lorem",
+ "ipsum"
+ ],
+ "x^2 array": [
+ 0,
+ 1,
+ 4,
+ 9,
+ 16,
+ 25,
+ 36,
+ 49,
+ 64,
+ 81,
+ 100
+ ],
+ "\/*": null,
+ "object": {
+ "nested string": "str",
+ "nested true": true,
+ "nested false": false,
+ "nested null": null,
+ "nested number": 123,
+ "nested array": [
+ "lorem",
+ "ipsum"
+ ]
+ },
+ "*\/": null,
+ "\/**\/": "comment",
+ "\/\/": "comment",
+ "url": "https:\/\/www.example.com\/search?q=12345",
+ "escaped chars": "\" \\ \/",
+ "empty object": {},
+ "empty array": []
+} \ No newline at end of file
diff --git a/vendor/parson/tests/test_5.txt b/vendor/parson/tests/test_5.txt
new file mode 100644
index 0000000..fc71450
--- /dev/null
+++ b/vendor/parson/tests/test_5.txt
@@ -0,0 +1,15 @@
+{
+ "first": "John",
+ "last": "Doe",
+ "age": 25,
+ "registered": true,
+ "interests": [ "Reading", "Mountain Biking" ],
+ "favorites": {
+ "color": "blue",
+ "sport": "running"
+ },
+ "utf string" : "\u006corem\u0020ipsum",
+ "utf-8 string": "あいうえお",
+ "surrogate string": "lorem\uD834\uDD1Eipsum\uD834\uDF67lorem",
+ "windows path": "C:\\Windows\\Path"
+} \ No newline at end of file
diff --git a/vendor/src/Unity-stamp/Unity-mkdir b/vendor/src/Unity-stamp/Unity-mkdir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vendor/src/Unity-stamp/Unity-mkdir
diff --git a/vendor/src/Unity-stamp/Unity-urlinfo.txt b/vendor/src/Unity-stamp/Unity-urlinfo.txt
new file mode 100644
index 0000000..97dd2a6
--- /dev/null
+++ b/vendor/src/Unity-stamp/Unity-urlinfo.txt
@@ -0,0 +1,3 @@
+repository='external project URL'
+module='https://github.com/ThrowTheSwitch/Unity/archive/v2.4.3.tar.gz'
+tag=''
diff --git a/vendor/src/Unity-stamp/download-Unity.cmake b/vendor/src/Unity-stamp/download-Unity.cmake
new file mode 100644
index 0000000..13a8ee0
--- /dev/null
+++ b/vendor/src/Unity-stamp/download-Unity.cmake
@@ -0,0 +1,162 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+cmake_minimum_required(VERSION 3.5)
+
+function(check_file_hash has_hash hash_is_good)
+ if("${has_hash}" STREQUAL "")
+ message(FATAL_ERROR "has_hash Can't be empty")
+ endif()
+
+ if("${hash_is_good}" STREQUAL "")
+ message(FATAL_ERROR "hash_is_good Can't be empty")
+ endif()
+
+ if("" STREQUAL "")
+ # No check
+ set("${has_hash}" FALSE PARENT_SCOPE)
+ set("${hash_is_good}" FALSE PARENT_SCOPE)
+ return()
+ endif()
+
+ set("${has_hash}" TRUE PARENT_SCOPE)
+
+ message(STATUS "verifying file...
+ file='/code/build/v2.4.3.tar.gz'")
+
+ file("" "/code/build/v2.4.3.tar.gz" actual_value)
+
+ if(NOT "${actual_value}" STREQUAL "")
+ set("${hash_is_good}" FALSE PARENT_SCOPE)
+ message(STATUS " hash of
+ /code/build/v2.4.3.tar.gz
+ does not match expected value
+ expected: ''
+ actual: '${actual_value}'")
+ else()
+ set("${hash_is_good}" TRUE PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(sleep_before_download attempt)
+ if(attempt EQUAL 0)
+ return()
+ endif()
+
+ if(attempt EQUAL 1)
+ message(STATUS "Retrying...")
+ return()
+ endif()
+
+ set(sleep_seconds 0)
+
+ if(attempt EQUAL 2)
+ set(sleep_seconds 5)
+ elseif(attempt EQUAL 3)
+ set(sleep_seconds 5)
+ elseif(attempt EQUAL 4)
+ set(sleep_seconds 15)
+ elseif(attempt EQUAL 5)
+ set(sleep_seconds 60)
+ elseif(attempt EQUAL 6)
+ set(sleep_seconds 90)
+ elseif(attempt EQUAL 7)
+ set(sleep_seconds 300)
+ else()
+ set(sleep_seconds 1200)
+ endif()
+
+ message(STATUS "Retry after ${sleep_seconds} seconds (attempt #${attempt}) ...")
+
+ execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep "${sleep_seconds}")
+endfunction()
+
+if("/code/build/v2.4.3.tar.gz" STREQUAL "")
+ message(FATAL_ERROR "LOCAL can't be empty")
+endif()
+
+if("https://github.com/ThrowTheSwitch/Unity/archive/v2.4.3.tar.gz" STREQUAL "")
+ message(FATAL_ERROR "REMOTE can't be empty")
+endif()
+
+if(EXISTS "/code/build/v2.4.3.tar.gz")
+ check_file_hash(has_hash hash_is_good)
+ if(has_hash)
+ if(hash_is_good)
+ message(STATUS "File already exists and hash match (skip download):
+ file='/code/build/v2.4.3.tar.gz'
+ =''"
+ )
+ return()
+ else()
+ message(STATUS "File already exists but hash mismatch. Removing...")
+ file(REMOVE "/code/build/v2.4.3.tar.gz")
+ endif()
+ else()
+ message(STATUS "File already exists but no hash specified (use URL_HASH):
+ file='/code/build/v2.4.3.tar.gz'
+Old file will be removed and new file downloaded from URL."
+ )
+ file(REMOVE "/code/build/v2.4.3.tar.gz")
+ endif()
+endif()
+
+set(retry_number 5)
+
+message(STATUS "Downloading...
+ dst='/code/build/v2.4.3.tar.gz'
+ timeout='none'"
+)
+
+foreach(i RANGE ${retry_number})
+ sleep_before_download(${i})
+
+ foreach(url https://github.com/ThrowTheSwitch/Unity/archive/v2.4.3.tar.gz)
+ message(STATUS "Using src='${url}'")
+
+ set(CMAKE_TLS_VERIFY false)
+
+
+
+
+ file(
+ DOWNLOAD
+ "${url}" "/code/build/v2.4.3.tar.gz"
+ SHOW_PROGRESS
+ # no TIMEOUT
+ STATUS status
+ LOG log
+
+
+ )
+
+ list(GET status 0 status_code)
+ list(GET status 1 status_string)
+
+ if(status_code EQUAL 0)
+ check_file_hash(has_hash hash_is_good)
+ if(has_hash AND NOT hash_is_good)
+ message(STATUS "Hash mismatch, removing...")
+ file(REMOVE "/code/build/v2.4.3.tar.gz")
+ else()
+ message(STATUS "Downloading... done")
+ return()
+ endif()
+ else()
+ string(APPEND logFailedURLs "error: downloading '${url}' failed
+ status_code: ${status_code}
+ status_string: ${status_string}
+ log:
+ --- LOG BEGIN ---
+ ${log}
+ --- LOG END ---
+ "
+ )
+ endif()
+ endforeach()
+endforeach()
+
+message(FATAL_ERROR "Each download failed!
+ ${logFailedURLs}
+ "
+)
diff --git a/vendor/src/Unity-stamp/extract-Unity.cmake b/vendor/src/Unity-stamp/extract-Unity.cmake
new file mode 100644
index 0000000..f3a29cb
--- /dev/null
+++ b/vendor/src/Unity-stamp/extract-Unity.cmake
@@ -0,0 +1,58 @@
+# Make file names absolute:
+#
+get_filename_component(filename "/code/build/v2.4.3.tar.gz" ABSOLUTE)
+get_filename_component(directory "/code/vendor/unity" ABSOLUTE)
+
+message(STATUS "extracting...
+ src='${filename}'
+ dst='${directory}'")
+
+if(NOT EXISTS "${filename}")
+ message(FATAL_ERROR "error: file to extract does not exist: '${filename}'")
+endif()
+
+# Prepare a space for extracting:
+#
+set(i 1234)
+while(EXISTS "${directory}/../ex-Unity${i}")
+ math(EXPR i "${i} + 1")
+endwhile()
+set(ut_dir "${directory}/../ex-Unity${i}")
+file(MAKE_DIRECTORY "${ut_dir}")
+
+# Extract it:
+#
+message(STATUS "extracting... [tar xfz]")
+execute_process(COMMAND ${CMAKE_COMMAND} -E tar xfz ${filename}
+ WORKING_DIRECTORY ${ut_dir}
+ RESULT_VARIABLE rv)
+
+if(NOT rv EQUAL 0)
+ message(STATUS "extracting... [error clean up]")
+ file(REMOVE_RECURSE "${ut_dir}")
+ message(FATAL_ERROR "error: extract of '${filename}' failed")
+endif()
+
+# Analyze what came out of the tar file:
+#
+message(STATUS "extracting... [analysis]")
+file(GLOB contents "${ut_dir}/*")
+list(REMOVE_ITEM contents "${ut_dir}/.DS_Store")
+list(LENGTH contents n)
+if(NOT n EQUAL 1 OR NOT IS_DIRECTORY "${contents}")
+ set(contents "${ut_dir}")
+endif()
+
+# Move "the one" directory to the final directory:
+#
+message(STATUS "extracting... [rename]")
+file(REMOVE_RECURSE ${directory})
+get_filename_component(contents ${contents} ABSOLUTE)
+file(RENAME ${contents} ${directory})
+
+# Clean up:
+#
+message(STATUS "extracting... [clean up]")
+file(REMOVE_RECURSE "${ut_dir}")
+
+message(STATUS "extracting... done")
diff --git a/vendor/src/Unity-stamp/verify-Unity.cmake b/vendor/src/Unity-stamp/verify-Unity.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vendor/src/Unity-stamp/verify-Unity.cmake