NAME
CodeGen::Cpppp::Enum - Helper for enumerations and generating related utility functions
SYNOPSIS
## my $enum= CodeGen::Cpppp::Enum->new(
## prefix => 'MYENUM_', type => 'int', values => q(
## VAL_1 1
## VAL_2
## ALT_VAL
## SOME_VAL
## OTHER_VAL 1<<10
## NONE -1
## ));
## section PUBLIC;
${{ $enum->generate_declaration }}
extern const char * myenum_name(int value);
extern bool myenum_parse(const char *str, size_t len, int *value_out);
## section PRIVATE;
${{ $enum->generate_static_tables }}
const char * myenum_name(int value) {
${{ $enum->generate_lookup_by_value }}
}
bool myenum_parse(const char *str, size_t len, int *value_out) {
${{ $enum->generate_lookup_by_name }}
}
DESCRIPTION
This utility module helps you generate C code for enumerations.
First, you create an instance of this object and load it with a list of enum values. These can come from a supplied list, or you can parse a header to find them. This module supports multiple names with the same value, but not multiple values with the same name.
Next, you can generate the definition of the enum as either #define
macros or a C++ enum { ... }
syntax.
This also can generate code that looks up the name by the value, or parses a name to get the value. The header would generally look like:
#define EXAMPLE_1 1
#define EXAMPLE_2 2
// Returns true if found a match
extern bool example_parse(const char *ch, int len, int *value_out);
extern const char *example_name(int enum_val);
There are several implementations to choose from, and a sensible one will be chosen by default based on the patterns in your enum values.
CONSTRUCTOR
new
Standard constructor. Pass values for any of the non-readonly attributes below.
ATTRIBUTES
prefix
String to be prefixed onto each name of the enum. You may then optionally allow name lookups that match strings without the prefix as well as ones that include it.
type
Defaults to 'int'.
values
Returns a list of [ $name, $value ]
. You can initialize it with a list or arrayref containing $name
or [ $name, $value ]
. Any element without a value will get the next sequential value from the previous entry, starting from 0.
value_table_var
C Variable name of the constant which holds the official list of enum values.
indent
Set to a literal string to use for each level of indent in generated code.
num_format
Controls formatting of integers, as decimal or hex. Can be any single placeholder known to sprintf, like '%d', '%x', or '%X'.
max_waste_ratio
Permissible ratio of empty lookup table elements vs. populated elements. If there would be more empty cells than that, a different algorithm will be chosen. The default is 2, meaning that the table must be at least 1/3 populated.
algorithm
One of 'bsearch', 'hashtable', 'switch'.
For each, the enum is stored in an array of string/value pairs (unless the values match the array index, then they get omitted). If this happens to be the sorted order of the names or sorted order of the values, those optimizations are taken into account. Otherwise, the algorithm operates as follows:
- bsearch
-
Secondary arrays of integers are built that refer back to the enum array. These arrays are searched during name or value lookups using the C library
bsearch
function. This results in the least space usage. - hashtable
-
Hash tables will be built that refer back to the enum array. Hash function constants will be chosen to provide the fewest number of collisions possible. This results in good performance without much added code.
- switch
-
The lookup functions will be built using a combination of C 'switch' statements and binary character-comparison 'if' statements. This results in the absolute fastest performance, but may generate a fair amount of parsing code.
is_symbolic
True if one if your values is an expression instead of a constant integer. In this case, only the switch algorithm can be used for lookups.
is_sequential
Read-only, calculated by whether all the values have adjacent numeric values.
is_sequentialish
Read-only, calculated by whether all the values can be stored in an array at the offset of their numeric value without wasting more than max_waste_factor
elements.
generate_declaration
@code_lines= $enum->generate_declaration(%options);
Return either a list of #define NAME ...
or the lines of a C++ enum Foo { ... }
.
generate_static_tables
@code_lines= $enum->generate_static_tables(%options);
Return lines of code that declare the tables needed for the lookups. This always includes a table in the same order as the declaration of the enum values, but may also include additional hash tables or lookup tables to represent the values in alphabetical order.
generate_lookup_by_value
@code_lines= $enum->generate_lookup_by_value(%options);
Return lines of code that return a const char *
of the name associated with a value. The variable holding the value is named 'value' by default, and the implementation returns NULL if this value does not have a name.
generate_lookup_by_name
@code_lines= $enum->generate_lookup_by_name(%options);
Return lines of code that take a name in a variable str
, len
bytes long, and store the enum value for that name into a variable value_out
and then return true (if found) or false if not found.
AUTHOR
Michael Conrad <mike@nrdvana.net>
VERSION
version 0.005
COPYRIGHT AND LICENSE
This software is copyright (c) 2024 by Michael Conrad.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.