简体   繁体   中英

Check if a read value is hex or decimal in python?

I'm working on a IPv6 header compressor called SCHC, and in my code I have to read a value that sometimes it's decimal, and others is hexadecimal. I'll show you an example:

#                  fID                 pos  dir   tv                    mo         cda

rule = {"ruleid"  : 0,
     "content" : [["IPv6.version",      1,  "bi", 6,                  "equal", "not-sent"],
                  ["IPv6.trafficClass", 1,  "bi", 0x00,               "equal", "not-sent"],
                  ["IPv6.flowLabel",    1,  "bi", 0x000000,           "ignore", "not-sent"],
                  ["IPv6.payloadLength",1,  "bi", None,               "ignore", "compute-length"],
                  ["IPv6.nextHeader",   1,  "bi", 17,                 "equal", "not-sent"],
                  ["IPv6.hopLimit",     1,  "bi", 30,                 "equal", "not-sent"],
                  ["IPv6.prefixES",     1,  "bi", 0x200104701f1209f2, "equal", "not-sent"],
                  ["IPv6.iidES",        1,  "bi", 0x000000000000000b, "equal", "not-sent"],
                  ["IPv6.prefixLA",     1,  "bi", [0xFE80000000000000,
                                                  0x2001123456789012,
                                                  0x200104701f1209f2,
                                                  0x200141d004013100],"match-mapping", "mapping-sent"],
                  ["IPv6.iidLA",        1,  "bi", 0x0000000000003682, "equal", "not-sent"],
                  ["UDP.PortES",        1,  "bi", 5684,               "equal", "not-sent"],
                  ["UDP.PortLA",        1,  "bi", 5684,               "equal", "not-sent"],
                  ["UDP.length",        1,  "bi", None,               "ignore", "compute-length"],
                  ["UDP.checksum",      1,  "bi", None,               "ignore", "compute-checksum"],
                  ["CoAP.version",      1,  "bi", 1,                  "equal", "not-sent"],
                  ["CoAP.type",         1,  "up", 0,                  "equal", "not-sent"],
                  ["CoAP.type",         1,  "dw", 2,                  "equal", "not-sent"],
                  ["CoAP.tokenLength",  1,  "bi", 1,                  "equal", "not-sent"],
                  ["CoAP.code",         1,  "up", 2,                  "equal", "not-sent"],
                  ["CoAP.code",         1,  "dw", [69, 132],          "match-mapping", "mapping-sent"],
                  ["CoAP.messageID",    1,  "bi", 0,                  "MSB(12)", "LSB"],
                  ["CoAP.token",        1,  "bi", 0x80,               "MSB(4)", "LSB"],
                  ["CoAP.Uri-Path",     1,  "up", "foo",              "equal", "not-sent"],
                  ["CoAP.Uri-Path",     2,  "up", "bar",              "equal", "not-sent"],
                  ["CoAP.Uri-Path",     3,  "up", None,               "ignore", "value-sent"],
                  ["CoAP.Content-Format",1, "dw", None,               "ignore", "value-sent"],
                  ["CoAP.Uri-Query",    1,  "up", "k=",               "MSB(16)", "LSB"],
                  ["CoAP.Option-End",   1,  "up", 0xFF,               "equal", "not-sent"]
               ]}

This is an example of a rule compression for SCHC. As you can see, the tv (target value) field can be sometimes an integer, a string, an array... and in the case of integers, they may have decimal or hexadecimal representation. What I want to do is rewrite in a string the value of that integer, but my problem is that when I access to that value I have no way to know if it was hex or dec.

I have already tryed many things such as regular expressions, using functions like str(tv) but it returns always in decimal unless I write str(hex(tv)), but still have the same problem that I don't know if the original value was hex or dec.

Thank you in advance, and I hope that my explanation was clear!

--- Update ---

So, if I do something like this right after the declaration of the variable "rule",

for line in rule['content']:
  fID,pos,di,tv,mo,cda = line
  print(line[3])

the output of the print will be "2306129363794528754" in the IPv6.prefixES line, instead of 0x200104701f1209f2.

The same output is done if I write "print(str(line[3])" instead.

Integers in Python prefixed by 0x are represented under the hood in just the same way as integers that aren't. This means that to Python, 0xFF is the same as 255, and there's no way to tell them apart; 0x is just a convenient way to describe ints when you're working in hex base. The same goes for 0b , the binary representation.

As such, there's no way to tell them apart as they are in your code. Try the following in a REPL:

>>> 0xFF == 255
True
>>> isinstance(255, int)
True
>>> isinstance(0xFF, int)
True
>>> 0xFF
255
>>> 0b11111111 == 0xFF == 255
True

Your regex doesn't work because the regex expects a string; when it sees your integer, it casts the int to a string but since the default representation is to cast an integer to base 10, it appears as just that: a base 10 integer.

The solution in your case would be to actually store the hex values as string and then convert them back to integers when you actually want to use them, that is:

["IPv6.prefixES", 1, "bi", "0x200104701f1209f2", "equal", "not-sent"],

(note that the quotes indicate it's a string)

Or to store it as an integer as you are doing, and then get their hexadecimal representation whenever you want to show it as a hex number.

Using int() works nicely for this, and Python does all the checking for you :)

int('00480065006C006C006F00200077006F0072006C00640021', 16)
6896377547970387516320582441726837832153446723333914657L

will work. In case of failure you will receive a ValueError exception.

Short example:

int('af', 16)
175

int('ah', 16)
 ...
ValueError: invalid literal for int() with base 16: 'ah'

Source : Check if a string is hexadecimal

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM