| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * mpq-header.c -- MPQ archive header wire-format encoding and decoding. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2026-2026 Maik Broemme <mbroemme@libmpq.org> | ||
| 5 | * | ||
| 6 | * This file is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU Lesser General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2.1 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This file is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU Lesser General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU Lesser General Public License | ||
| 17 | * along with this file; if not, see <https://www.gnu.org/licenses/>. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include "mpq-header.h" | ||
| 21 | #include "mpq-endian.h" | ||
| 22 | #include <libmpq/mpq.h> | ||
| 23 | |||
| 24 | /* Decode only wire fields; archive validation remains with the reader. */ | ||
| 25 | int32_t | ||
| 26 | 2149 | libmpq__header_decode(mpq_header_s *header, const uint8_t *wire, size_t size) | |
| 27 | { | ||
| 28 |
4/6✓ Branch 0 taken 2149 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2149 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2148 times.
|
2149 | if (header == NULL || wire == NULL || size < LIBMPQ_HEADER_WIRE_SIZE) |
| 29 | 1 | return LIBMPQ_ERROR_SIZE; | |
| 30 | |||
| 31 | 2148 | header->mpq_magic = libmpq__load_le32(wire); | |
| 32 | 2148 | header->header_size = libmpq__load_le32(wire + 4); | |
| 33 | 2148 | header->archive_size = libmpq__load_le32(wire + 8); | |
| 34 | 2148 | header->version = libmpq__load_le16(wire + 12); | |
| 35 | 2148 | header->block_size = libmpq__load_le16(wire + 14); | |
| 36 | 2148 | header->hash_table_offset = libmpq__load_le32(wire + 16); | |
| 37 | 2148 | header->block_table_offset = libmpq__load_le32(wire + 20); | |
| 38 | 2148 | header->hash_table_count = libmpq__load_le32(wire + 24); | |
| 39 | 2148 | header->block_table_count = libmpq__load_le32(wire + 28); | |
| 40 | 2148 | return 0; | |
| 41 | } | ||
| 42 | |||
| 43 | /* Decode the optional version 2 extension from its 12 wire bytes. */ | ||
| 44 | int32_t | ||
| 45 | 497 | libmpq__header_ex_decode(mpq_header_ex_s *header, const uint8_t *wire, size_t size) | |
| 46 | { | ||
| 47 |
4/6✓ Branch 0 taken 497 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 497 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 496 times.
|
497 | if (header == NULL || wire == NULL || size < LIBMPQ_HEADER_EX_WIRE_SIZE) |
| 48 | 1 | return LIBMPQ_ERROR_SIZE; | |
| 49 | |||
| 50 | 496 | header->extended_offset = libmpq__load_le64(wire); | |
| 51 | 496 | header->hash_table_offset_high = libmpq__load_le16(wire + 8); | |
| 52 | 496 | header->block_table_offset_high = libmpq__load_le16(wire + 10); | |
| 53 | 496 | return 0; | |
| 54 | } | ||
| 55 | |||
| 56 | /* Encode fixed native fields into the exact 32-byte little-endian base header. */ | ||
| 57 | int32_t | ||
| 58 | 741 | libmpq__header_encode(const mpq_header_s *header, uint8_t *wire, size_t size) | |
| 59 | { | ||
| 60 |
4/6✓ Branch 0 taken 741 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 741 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 740 times.
|
741 | if (header == NULL || wire == NULL || size < LIBMPQ_HEADER_WIRE_SIZE) |
| 61 | 1 | return LIBMPQ_ERROR_SIZE; | |
| 62 | |||
| 63 | 740 | libmpq__store_le32(wire, header->mpq_magic); | |
| 64 | 740 | libmpq__store_le32(wire + 4, header->header_size); | |
| 65 | 740 | libmpq__store_le32(wire + 8, header->archive_size); | |
| 66 | 740 | libmpq__store_le16(wire + 12, header->version); | |
| 67 | 740 | libmpq__store_le16(wire + 14, header->block_size); | |
| 68 | 740 | libmpq__store_le32(wire + 16, header->hash_table_offset); | |
| 69 | 740 | libmpq__store_le32(wire + 20, header->block_table_offset); | |
| 70 | 740 | libmpq__store_le32(wire + 24, header->hash_table_count); | |
| 71 | 740 | libmpq__store_le32(wire + 28, header->block_table_count); | |
| 72 | 740 | return 0; | |
| 73 | } | ||
| 74 | |||
| 75 | /* Encode the optional version 2 extension into exactly 12 wire bytes. */ | ||
| 76 | int32_t | ||
| 77 | 264 | libmpq__header_ex_encode(const mpq_header_ex_s *header, uint8_t *wire, size_t size) | |
| 78 | { | ||
| 79 |
4/6✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 264 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 263 times.
|
264 | if (header == NULL || wire == NULL || size < LIBMPQ_HEADER_EX_WIRE_SIZE) |
| 80 | 1 | return LIBMPQ_ERROR_SIZE; | |
| 81 | |||
| 82 | 263 | libmpq__store_le64(wire, header->extended_offset); | |
| 83 | 263 | libmpq__store_le16(wire + 8, header->hash_table_offset_high); | |
| 84 | 263 | libmpq__store_le16(wire + 10, header->block_table_offset_high); | |
| 85 | 263 | return 0; | |
| 86 | } | ||
| 87 |