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.