Skip to content

Hashes as text

Storing and reading back hashes and digests as hex strings.

Constants
PH_DIGEST_HEX_BUFFER_SIZE
Functions
ph_digest_to_hex() Encodes a digest as text: its kind, a colon, then its bytes in lowercase hex.
ph_digest_from_hex() Decodes the text form produced by ph_digest_to_hex() back into a digest, kind included.
ph_hash_to_hex() Encodes a 64-bit hash as a fixed 16-character lowercase hex string (big-endian, i.e. the most significant byte comes first).
ph_hash_from_hex() Decodes the text ph_hash_to_hex() writes back into a 64-bit hash.

Constants

PH_DIGEST_HEX_BUFFER_SIZE

#define PH_DIGEST_HEX_BUFFER_SIZE (13 + PH_DIGEST_MAX_BYTES * 2 + 1)

Buffer size that holds the text form of any digest, terminator included: the longest kind name plus its colon ("coefficients:", 13 characters), two hex digits per byte of a full PH_DIGEST_MAX_BYTES digest, and the NUL.

Functions

ph_digest_to_hex()

ph_error_t ph_digest_to_hex(const ph_digest_t *d, char *out, size_t out_size);

nodiscard · returns ph_error_t

Encodes a digest as text: its kind, a colon, then its bytes in lowercase hex.

The kind is the lowercase suffix of its ph_digest_kind_t name – unspecified, bits, coefficients, vector, histogram, vector16 – so a radial digest reads coefficients:1f80.... The bytes follow in order, data[0] first. Carrying the kind is what keeps the comparison functions able to refuse the wrong metric for digests that were stored and read back (see ph_digest_kind_t).

Parameters

Parameter Description
d Digest to encode.
out Output buffer. PH_DIGEST_HEX_BUFFER_SIZE bytes always suffice.
out_size Size of 'out' in bytes; at least the kind name's length + 1 + d->size * 2 + 1.

Returns PH_SUCCESS, or PH_ERR_INVALID_ARGUMENT if arguments are invalid, the digest's kind is not a ph_digest_kind_t value, or out_size is too small.

ph_digest_from_hex()

ph_error_t ph_digest_from_hex(const char *text, ph_digest_t *out);

nodiscard · returns ph_error_t

Decodes the text form produced by ph_digest_to_hex() back into a digest, kind included.

The kind prefix is required and must be one of the names ph_digest_to_hex() writes, in lowercase; the hex digits after the colon may be either case. A bare hex string without a prefix is rejected rather than read as an untagged digest: prefix it with unspecified: to accept it knowingly, or better, with the kind of the algorithm that produced it.

Parameters

Parameter Description
text NUL-terminated string <kind>:<hex>; the hex part must have an even number of digits and decode to at most PH_DIGEST_MAX_BYTES bytes.
out Output digest. Untouched on error.

Returns PH_SUCCESS, or PH_ERR_INVALID_ARGUMENT if text is malformed, has no or an unknown kind prefix, or is too long.

ph_hash_to_hex()

ph_error_t ph_hash_to_hex(uint64_t hash, char *out, size_t out_size);

nodiscard · returns ph_error_t

Encodes a 64-bit hash as a fixed 16-character lowercase hex string (big-endian, i.e. the most significant byte comes first).

Parameters

Parameter Description
hash Hash value to encode.
out Output buffer.
out_size Size of 'out' in bytes; must be at least 17.

Returns PH_SUCCESS, or PH_ERR_INVALID_ARGUMENT if arguments are invalid or out_size is too small.

ph_hash_from_hex()

ph_error_t ph_hash_from_hex(const char *hex, uint64_t *out);

nodiscard · returns ph_error_t

Decodes the text ph_hash_to_hex() writes back into a 64-bit hash.

Exactly 16 hex digits, most significant byte first, either case; nothing before or after them (no "0x", no whitespace). Unlike the digest text form there is no kind prefix: a uint64_t hash is always a bit vector.

Parameters

Parameter Direction Description
hex in NUL-terminated string of 16 hex digits.
out out Receives the hash. Untouched on error.

Returns PH_SUCCESS, or PH_ERR_INVALID_ARGUMENT for a NULL argument or any other length or character.