Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for binary integer values #236

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

cozzyd
Copy link

@cozzyd cozzyd commented Apr 3, 2024

This adds support for binary integers to the libconfig grammar, specified by a 0b or 0B prefix. These are treated very similarly to how hex integers are treated (including defining an integer format for them so they may be output, and having an L suffix for 64-bit integers). One might accuse me of grepping for hex and then doing the same thing for binary...

A few salient points:

  • This isn't using the %b format specifier for output that is supported by newer glibc, instead writing a custom formatter. This is because I don't know how widespread or portable this is (I think it's party of a new C standard?).
  • I added a test, which tests both binary and hex together (since the implementation is quite parallel)
  • It could be possible to automatically detect binary (and hex, for that matter) that doesn't fit in 32 bits using the grammar, but I didn't implement that.
  • I haven't updated any documentation, but I can do that if this is accepted.

cozzyd added 3 commits April 2, 2024 23:30
Modifiy the libconfig grammar to include binary integers (and 64-bit integers),
prefixed with 0b (or 0B). This also adds a binary integer format so that
they can then be output as binary.

Binaries are output using a custom formatter, even though some C
libraries now support %b/%B format specifiers. This could be improved in
the future.

The code is based heavily on the hexadecimal handling (so, e.g. only the
L serves as an indicator that it should be 64-bits, not the number of
zeroes).
Copy link
Owner

@hyperrealm hyperrealm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks good. Thanks for doing this (and adding tests!).

If you could please update the libconfig.texi as well to document the new functionality; you can 'make pdf' to generate the PDF doc to review your changes.

lib/util.c Outdated
unsigned i = 0;
while ( (c < 64) && (i < buflen -1) )
{
buf[i] = (val & ( 1ll << (63-c))) ? '1' : '0';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: fix spacing

(1ll << (63 - c )))

lib/util.c Outdated
i++;
c++;
}
buf[i]=0;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buf[i] = 0;

@cozzyd
Copy link
Author

cozzyd commented Apr 16, 2024

Thanks for the positive reception!

Do you know yet what the next version will be (so that the version adding the feature can be documented)?

Also, I noticed that the documentation implies that values outside a 32-bit range will automatically be promoted to 64-bit, but as far as I can tell this is not the case for hex. Is this a bug or a conscious decision (maybe because of the MINGW32 workaround potentially causing some degradation in the 32-bit case?). I copied the same behavior as hex for binary, but automatic promotion to 64-bits would probably be better (and also more consistent with documentation), so I'll go ahead and implement that unless you have an objection?

@hyperrealm
Copy link
Owner

hyperrealm commented Apr 16, 2024 via email

cozzyd added 4 commits April 17, 2024 00:50
    This commit does a few different things:

    1) Includes error checking for all integer types (integer, hex, bin)
    2) This includes swalling anny errno set by stro[u]ll and restoring
       errno to original tate
    3) Automatically extends hex and bin to 64 bits even with no L
       present. In this case, we only check against INT_MAX since it's
       rare you'd want to consider negative numbers here, I think.

    We nowalways use the parse_integer/hex/bin functions in the scanner,
    which now all fill ok (and eat errno if necessary). They also all take
    an L_ok argument, which determines if it's ok have L's at the end of the
    digits (this is set to 1 for integer64/hex64/bin64, 0 otherwise).

    Note that the previous code was setting errno to 0 on failure rather
    than to err_save, which I think was probably a bug, unless I'm missing
    something
@cozzyd
Copy link
Author

cozzyd commented Apr 17, 2024

I've gone ahead and tried to make all the integer parsing consistent, including automatic promotion to 64 bits and error detection. This passes tests, but probably needs to be sanity checked a bit more to make sure I didn't introduce any silly bugs. I have also taken a stab at updating the docs.

more hexadecimal digits (@samp{0} - @samp{9}, @samp{A} - @samp{F},
@samp{a} - @samp{f}). Additionally, octal notation integers (that is,
those having a leading zero with non-zero value) are also allowed.
Integers can be represented in one of two ways: as a series of one or more
Copy link
Owner

@hyperrealm hyperrealm Apr 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/one of two/the following/

library, the trailing `L' is optional; if the integer value exceeds the range
of a 32-bit integer, it will automatically be interpreted as a 64-bit integer.
As of version 1.7.4 of the library this behavior is extended to hexadecimal
(and binary) integers as well.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for parens around 'and binary'

@@ -57,6 +57,7 @@ extern "C" {

#define CONFIG_FORMAT_DEFAULT 0
#define CONFIG_FORMAT_HEX 1
#define CONFIG_FORMAT_BIN 2
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the C++ wrapper needs to be updated as well to update the corresponding enum there

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also update the C++ section of the documentation; there's a 'format' enum there as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants