static void build_prepend_package_length(GArray *package, unsigned length, bool incl_self) { uint8_t byte; unsigned length_bytes; if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) { length_bytes = 1; } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) { length_bytes = 2; } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) { length_bytes = 3; } else { length_bytes = 4; } /* * NamedField uses PkgLength encoding but it doesn't include length * of PkgLength itself. */ if (incl_self) { /* * PkgLength is the length of the inclusive length of the data * and PkgLength's length itself when used for terms with * explitit length. */ length += length_bytes; } switch (length_bytes) { case 1: byte = length; build_prepend_byte(package, byte); return; case 4: byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT; build_prepend_byte(package, byte); length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1; /* fall through */ case 3: byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT; build_prepend_byte(package, byte); length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1; /* fall through */ case 2: byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT; build_prepend_byte(package, byte); length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1; /* fall through */ } /* * Most significant two bits of byte zero indicate how many following bytes * are in PkgLength encoding. */ byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length; build_prepend_byte(package, byte); }
static void build_prepend_package_length(GArray *package, unsigned min_bytes) { uint8_t byte; unsigned length = package->len; unsigned length_bytes; if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) { length_bytes = 1; } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) { length_bytes = 2; } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) { length_bytes = 3; } else { length_bytes = 4; } /* Force length to at least min_bytes. * This wastes memory but that's how bios did it. */ length_bytes = MAX(length_bytes, min_bytes); /* PkgLength is the length of the inclusive length of the data. */ length += length_bytes; switch (length_bytes) { case 1: byte = length; build_prepend_byte(package, byte); return; case 4: byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT; build_prepend_byte(package, byte); length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1; /* fall through */ case 3: byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT; build_prepend_byte(package, byte); length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1; /* fall through */ case 2: byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT; build_prepend_byte(package, byte); length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1; /* fall through */ } /* * Most significant two bits of byte zero indicate how many following bytes * are in PkgLength encoding. */ byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length; build_prepend_byte(package, byte); }
static void build_extop_package(GArray *package, uint8_t op) { build_package(package, op); build_prepend_byte(package, 0x5B); /* ExtOpPrefix */ }
static void build_package(GArray *package, uint8_t op) { build_prepend_package_length(package, package->len, true); build_prepend_byte(package, op); }
static void build_package(GArray *package, uint8_t op, unsigned min_bytes) { build_prepend_package_length(package, min_bytes); build_prepend_byte(package, op); }