summaryrefslogtreecommitdiff
path: root/xdelta3/xdelta3.c
diff options
context:
space:
mode:
Diffstat (limited to 'xdelta3/xdelta3.c')
-rw-r--r--xdelta3/xdelta3.c480
1 files changed, 6 insertions, 474 deletions
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c
index 78a331e..8513aac 100644
--- a/xdelta3/xdelta3.c
+++ b/xdelta3/xdelta3.c
@@ -294,16 +294,6 @@
294#endif 294#endif
295#endif 295#endif
296 296
297#ifndef GENERIC_ENCODE_TABLES /* These three are the RFC-spec app-specific */
298#define GENERIC_ENCODE_TABLES 0 /* code features. This is tested but not */
299#endif /* recommended unless there's a real use. */
300#ifndef GENERIC_ENCODE_TABLES_COMPUTE
301#define GENERIC_ENCODE_TABLES_COMPUTE 0
302#endif
303#ifndef GENERIC_ENCODE_TABLES_COMPUTE_PRINT
304#define GENERIC_ENCODE_TABLES_COMPUTE_PRINT 0
305#endif
306
307#if XD3_ENCODER 297#if XD3_ENCODER
308#define IF_ENCODER(x) x 298#define IF_ENCODER(x) x
309#else 299#else
@@ -559,8 +549,6 @@ static void xd3_verify_small_state (xd3_stream *stream,
559static int xd3_decode_allocate (xd3_stream *stream, usize_t size, 549static int xd3_decode_allocate (xd3_stream *stream, usize_t size,
560 uint8_t **copied1, usize_t *alloc1); 550 uint8_t **copied1, usize_t *alloc1);
561 551
562static void xd3_compute_code_table_string (const xd3_dinst *code_table,
563 uint8_t *str);
564static void* xd3_alloc (xd3_stream *stream, usize_t elts, usize_t size); 552static void* xd3_alloc (xd3_stream *stream, usize_t elts, usize_t size);
565static void xd3_free (xd3_stream *stream, void *ptr); 553static void xd3_free (xd3_stream *stream, void *ptr);
566 554
@@ -881,14 +869,10 @@ const uint16_t __single_hash[256] =
881 869
882/* The XD3_CHOOSE_INSTRUCTION calls xd3_choose_instruction with the 870/* The XD3_CHOOSE_INSTRUCTION calls xd3_choose_instruction with the
883 * table description when GENERIC_ENCODE_TABLES are in use. The 871 * table description when GENERIC_ENCODE_TABLES are in use. The
884 * IF_GENCODETBL macro enables generic-code-table specific code. */ 872 * IF_GENCODETBL macro enables generic-code-table specific code
885#if GENERIC_ENCODE_TABLES 873 * (removed 10/2014). */
886#define XD3_CHOOSE_INSTRUCTION(stream,prev,inst) xd3_choose_instruction (stream->code_table_desc, prev, inst) 874#define XD3_CHOOSE_INSTRUCTION(stream,prev,inst) \
887#define IF_GENCODETBL(x) x 875 xd3_choose_instruction (prev, inst)
888#else
889#define XD3_CHOOSE_INSTRUCTION(stream,prev,inst) xd3_choose_instruction (prev, inst)
890#define IF_GENCODETBL(x)
891#endif
892 876
893/* This structure maintains information needed by 877/* This structure maintains information needed by
894 * xd3_choose_instruction to compute the code for a double instruction 878 * xd3_choose_instruction to compute the code for a double instruction
@@ -950,50 +934,6 @@ static const xd3_code_table_desc __rfc3284_code_table_desc = {
950 { {4,247,1},{4,248,1},{4,249,1},{4,250,1},{4,251,1},{4,252,1},{4,253,1},{4,254,1},{4,255,1} }, 934 { {4,247,1},{4,248,1},{4,249,1},{4,250,1},{4,251,1},{4,252,1},{4,253,1},{4,254,1},{4,255,1} },
951}; 935};
952 936
953#if GENERIC_ENCODE_TABLES
954/* An alternate code table for testing (5 near, 0 same):
955 *
956 * TYPE SIZE MODE TYPE SIZE MODE INDEX
957 * ---------------------------------------------------------------
958 * 1. Run 0 0 Noop 0 0 0
959 * 2. Add 0, [1,23] 0 Noop 0 0 [1,24]
960 * 3. Copy 0, [4,20] 0 Noop 0 0 [25,42]
961 * 4. Copy 0, [4,20] 1 Noop 0 0 [43,60]
962 * 5. Copy 0, [4,20] 2 Noop 0 0 [61,78]
963 * 6. Copy 0, [4,20] 3 Noop 0 0 [79,96]
964 * 7. Copy 0, [4,20] 4 Noop 0 0 [97,114]
965 * 8. Copy 0, [4,20] 5 Noop 0 0 [115,132]
966 * 9. Copy 0, [4,20] 6 Noop 0 0 [133,150]
967 * 10. Add [1,4] 0 Copy [4,6] 0 [151,162]
968 * 11. Add [1,4] 0 Copy [4,6] 1 [163,174]
969 * 12. Add [1,4] 0 Copy [4,6] 2 [175,186]
970 * 13. Add [1,4] 0 Copy [4,6] 3 [187,198]
971 * 14. Add [1,4] 0 Copy [4,6] 4 [199,210]
972 * 15. Add [1,4] 0 Copy [4,6] 5 [211,222]
973 * 16. Add [1,4] 0 Copy [4,6] 6 [223,234]
974 * 17. Copy 4 [0,6] Add [1,3] 0 [235,255]
975 * --------------------------------------------------------------- */
976static const xd3_code_table_desc __alternate_code_table_desc = {
977 23, /* add sizes */
978 5, /* near modes */
979 0, /* same modes */
980 17, /* copy sizes */
981
982 4, /* add-copy max add */
983 6, /* add-copy max cpy, near */
984 0, /* add-copy max cpy, same */
985
986 3, /* copy-add max add */
987 4, /* copy-add max cpy, near */
988 0, /* copy-add max cpy, same */
989
990 /* addcopy */
991 { {6,151,3},{6,163,3},{6,175,3},{6,187,3},{6,199,3},{6,211,3},{6,223,3},{0,0,0},{0,0,0} },
992 /* copyadd */
993 { {4,235,1},{4,238,1},{4,241,1},{4,244,1},{4,247,1},{4,250,1},{4,253,1},{0,0,0},{0,0,0} },
994};
995#endif
996
997/* Computes code table entries of TBL using the specified description. */ 937/* Computes code table entries of TBL using the specified description. */
998static void 938static void
999xd3_build_code_table (const xd3_code_table_desc *desc, xd3_dinst *tbl) 939xd3_build_code_table (const xd3_code_table_desc *desc, xd3_dinst *tbl)
@@ -1076,117 +1016,6 @@ xd3_rfc3284_code_table (void)
1076} 1016}
1077 1017
1078#if XD3_ENCODER 1018#if XD3_ENCODER
1079#if GENERIC_ENCODE_TABLES
1080/* This function generates the alternate code table. */
1081static const xd3_dinst*
1082xd3_alternate_code_table (void)
1083{
1084 static xd3_dinst __alternate_code_table[256];
1085
1086 if (__alternate_code_table[0].type1 != XD3_RUN)
1087 {
1088 xd3_build_code_table (& __alternate_code_table_desc, __alternate_code_table);
1089 }
1090
1091 return __alternate_code_table;
1092}
1093
1094/* This function computes the ideal second instruction INST based on
1095 * preceding instruction PREV. If it is possible to issue a double
1096 * instruction based on this pair it sets PREV->code2, otherwise it
1097 * sets INST->code1. */
1098static void
1099xd3_choose_instruction (const xd3_code_table_desc *desc, xd3_rinst *prev, xd3_rinst *inst)
1100{
1101 switch (inst->type)
1102 {
1103 case XD3_RUN:
1104 /* The 0th instruction is RUN */
1105 inst->code1 = 0;
1106 break;
1107
1108 case XD3_ADD:
1109
1110 if (inst->size > desc->add_sizes)
1111 {
1112 /* The first instruction is non-immediate ADD */
1113 inst->code1 = 1;
1114 }
1115 else
1116 {
1117 /* The following ADD_SIZES instructions are immediate ADDs */
1118 inst->code1 = 1 + inst->size;
1119
1120 /* Now check for a possible COPY-ADD double instruction */
1121 if (prev != NULL)
1122 {
1123 int prev_mode = prev->type - XD3_CPY;
1124
1125 /* If previous is a copy. Note: as long as the previous
1126 * is not a RUN instruction, it should be a copy because
1127 * it cannot be an add. This check is more clear. */
1128 if (prev_mode >= 0 && inst->size <= desc->copyadd_add_max)
1129 {
1130 const xd3_code_table_sizes *sizes =
1131 & desc->copyadd_max_sizes[prev_mode];
1132
1133 /* This check and the inst->size-<= above are == in
1134 the default table. */
1135 if (prev->size <= sizes->cpy_max)
1136 {
1137 /* The second and third exprs are 0 in the
1138 default table. */
1139 prev->code2 = sizes->offset +
1140 (sizes->mult * (prev->size - MIN_MATCH)) +
1141 (inst->size - MIN_ADD);
1142 }
1143 }
1144 }
1145 }
1146 break;
1147
1148 default:
1149 {
1150 int mode = inst->type - XD3_CPY;
1151
1152 /* The large copy instruction is offset by the run, large add,
1153 * and immediate adds, then multipled by the number of
1154 * immediate copies plus one (the large copy) (i.e., if there
1155 * are 15 immediate copy instructions then there are 16 copy
1156 * instructions per mode). */
1157 inst->code1 = 2 + desc->add_sizes + (1 + desc->cpy_sizes) * mode;
1158
1159 /* Now if the copy is short enough for an immediate instruction. */
1160 if (inst->size < MIN_MATCH + desc->cpy_sizes &&
1161 /* TODO: there needs to be a more comprehensive test for this
1162 * boundary condition, merge is now exercising code in which
1163 * size < MIN_MATCH is possible and it's unclear if the above
1164 * size < (MIN_MATCH + cpy_sizes) should be a <= from inspection
1165 * of the default table version below. */
1166 inst->size >= MIN_MATCH)
1167 {
1168 inst->code1 += inst->size + 1 - MIN_MATCH;
1169
1170 /* Now check for a possible ADD-COPY double instruction. */
1171 if ( (prev != NULL) &&
1172 (prev->type == XD3_ADD) &&
1173 (prev->size <= desc->addcopy_add_max) )
1174 {
1175 const xd3_code_table_sizes *sizes = & desc->addcopy_max_sizes[mode];
1176
1177 if (inst->size <= sizes->cpy_max)
1178 {
1179 prev->code2 = sizes->offset +
1180 (sizes->mult * (prev->size - MIN_ADD)) +
1181 (inst->size - MIN_MATCH);
1182 }
1183 }
1184 }
1185 }
1186 }
1187}
1188#else /* GENERIC_ENCODE_TABLES */
1189
1190/* This version of xd3_choose_instruction is hard-coded for the default 1019/* This version of xd3_choose_instruction is hard-coded for the default
1191 table. */ 1020 table. */
1192static void 1021static void
@@ -1254,262 +1083,8 @@ xd3_choose_instruction (xd3_rinst *prev, xd3_rinst *inst)
1254 break; 1083 break;
1255 } 1084 }
1256} 1085}
1257#endif /* GENERIC_ENCODE_TABLES */
1258
1259/***********************************************************************
1260 Instruction table encoder/decoder
1261 ***********************************************************************/
1262
1263#if GENERIC_ENCODE_TABLES
1264#if GENERIC_ENCODE_TABLES_COMPUTE == 0
1265
1266/* In this case, we hard-code the result of
1267 * compute_code_table_encoding for each alternate code table,
1268 * presuming that saves time/space. This has been 131 bytes, but
1269 * secondary compression was turned off. */
1270static const uint8_t __alternate_code_table_compressed[178] =
1271{0xd6,0xc3,0xc4,0x00,0x00,0x01,0x8a,0x6f,0x40,0x81,0x27,0x8c,0x00,0x00,0x4a,0x4a,0x0d,0x02,0x01,0x03,
12720x01,0x03,0x00,0x01,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
12730x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x00,0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04,
12740x04,0x04,0x04,0x00,0x04,0x05,0x06,0x01,0x02,0x03,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x05,0x05,0x05,
12750x06,0x06,0x06,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x00,0x02,0x00,0x18,0x13,0x63,0x00,0x1b,0x00,0x54,
12760x00,0x15,0x23,0x6f,0x00,0x28,0x13,0x54,0x00,0x15,0x01,0x1a,0x31,0x23,0x6c,0x0d,0x23,0x48,0x00,0x15,
12770x93,0x6f,0x00,0x28,0x04,0x23,0x51,0x04,0x32,0x00,0x2b,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,
12780x12,0x00,0x12,0x53,0x57,0x9c,0x07,0x43,0x6f,0x00,0x34,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,
12790x0c,0x00,0x0c,0x00,0x15,0x00,0x82,0x6f,0x00,0x15,0x12,0x0c,0x00,0x03,0x03,0x00,0x06,0x00,};
1280
1281static int
1282xd3_compute_alternate_table_encoding (xd3_stream *stream, const uint8_t **data, usize_t *size)
1283{
1284 (*data) = __alternate_code_table_compressed;
1285 (*size) = sizeof (__alternate_code_table_compressed);
1286 return 0;
1287}
1288
1289#else
1290
1291/* The alternate code table will be computed and stored here. */
1292static uint8_t __alternate_code_table_compressed[CODE_TABLE_VCDIFF_SIZE];
1293static usize_t __alternate_code_table_compressed_size;
1294
1295/* This function generates a delta describing the code table for
1296 * encoding within a VCDIFF file. This function is NOT thread safe
1297 * because it is only intended that this function is used to generate
1298 * statically-compiled strings. "comp_string" must be sized
1299 * CODE_TABLE_VCDIFF_SIZE. */
1300int xd3_compute_code_table_encoding (xd3_stream *in_stream,
1301 const xd3_dinst *code_table,
1302 uint8_t *comp_string,
1303 usize_t *comp_string_size)
1304{
1305 /* Use DJW secondary compression if it is on by default. This saves
1306 * about 20 bytes. */
1307 uint8_t dflt_string[CODE_TABLE_STRING_SIZE];
1308 uint8_t code_string[CODE_TABLE_STRING_SIZE];
1309
1310 xd3_compute_code_table_string (xd3_rfc3284_code_table (), dflt_string);
1311 xd3_compute_code_table_string (code_table, code_string);
1312
1313 return xd3_encode_memory (code_string, CODE_TABLE_STRING_SIZE,
1314 dflt_string, CODE_TABLE_STRING_SIZE,
1315 comp_string, comp_string_size,
1316 CODE_TABLE_VCDIFF_SIZE,
1317 /* flags */ 0);
1318}
1319
1320/* Compute a delta between alternate and rfc3284 tables. As soon as
1321 * another alternate table is added, this code should become generic.
1322 * For now there is only one alternate table for testing. */
1323static int
1324xd3_compute_alternate_table_encoding (xd3_stream *stream, const uint8_t **data, usize_t *size)
1325{
1326 int ret;
1327
1328 if (__alternate_code_table_compressed[0] == 0)
1329 {
1330 if ((ret = xd3_compute_code_table_encoding (stream, xd3_alternate_code_table (),
1331 __alternate_code_table_compressed,
1332 & __alternate_code_table_compressed_size)))
1333 {
1334 return ret;
1335 }
1336
1337 /* During development of a new code table, enable this variable to print
1338 * the new static contents and determine its size. At run time the
1339 * table will be filled in appropriately, but at least it should have
1340 * the proper size beforehand. */
1341#if GENERIC_ENCODE_TABLES_COMPUTE_PRINT
1342 {
1343 int i;
1344
1345 DP(RINT, "\nstatic const usize_t __alternate_code_table_compressed_size = %u;\n",
1346 __alternate_code_table_compressed_size);
1347
1348 DP(RINT, "static const uint8_t __alternate_code_table_compressed[%u] =\n{",
1349 __alternate_code_table_compressed_size);
1350
1351 for (i = 0; i < __alternate_code_table_compressed_size; i += 1)
1352 {
1353 DP(RINT, "0x%02x,", __alternate_code_table_compressed[i]);
1354 if ((i % 20) == 19) { DP(RINT, "\n"); }
1355 }
1356
1357 DP(RINT, "};\n");
1358 }
1359#endif
1360 }
1361
1362 (*data) = __alternate_code_table_compressed;
1363 (*size) = __alternate_code_table_compressed_size;
1364
1365 return 0;
1366}
1367#endif /* GENERIC_ENCODE_TABLES_COMPUTE != 0 */
1368#endif /* GENERIC_ENCODE_TABLES */
1369
1370#endif /* XD3_ENCODER */ 1086#endif /* XD3_ENCODER */
1371 1087
1372/* This function generates the 1536-byte string specified in sections 5.4 and
1373 * 7 of rfc3284, which is used to represent a code table within a VCDIFF
1374 * file. */
1375void xd3_compute_code_table_string (const xd3_dinst *code_table, uint8_t *str)
1376{
1377 int i, s;
1378
1379 XD3_ASSERT (CODE_TABLE_STRING_SIZE == 6 * 256);
1380
1381 for (s = 0; s < 6; s += 1)
1382 {
1383 for (i = 0; i < 256; i += 1)
1384 {
1385 switch (s)
1386 {
1387 case 0: *str++ = (code_table[i].type1 >= XD3_CPY ? XD3_CPY : code_table[i].type1); break;
1388 case 1: *str++ = (code_table[i].type2 >= XD3_CPY ? XD3_CPY : code_table[i].type2); break;
1389 case 2: *str++ = (code_table[i].size1); break;
1390 case 3: *str++ = (code_table[i].size2); break;
1391 case 4: *str++ = (code_table[i].type1 >= XD3_CPY ? code_table[i].type1 - XD3_CPY : 0); break;
1392 case 5: *str++ = (code_table[i].type2 >= XD3_CPY ? code_table[i].type2 - XD3_CPY : 0); break;
1393 }
1394 }
1395 }
1396}
1397
1398/* This function translates the code table string into the internal representation. The
1399 * stream's near and same-modes should already be set. */
1400static int
1401xd3_apply_table_string (xd3_stream *stream, const uint8_t *code_string)
1402{
1403 int i, s;
1404 int modes = TOTAL_MODES (stream);
1405 xd3_dinst *code_table;
1406
1407 if ((code_table = stream->code_table_alloc =
1408 (xd3_dinst*) xd3_alloc (stream,
1409 (usize_t) sizeof (xd3_dinst),
1410 256)) == NULL)
1411 {
1412 return ENOMEM;
1413 }
1414
1415 for (s = 0; s < 6; s += 1)
1416 {
1417 for (i = 0; i < 256; i += 1)
1418 {
1419 switch (s)
1420 {
1421 case 0:
1422 if (*code_string > XD3_CPY)
1423 {
1424 stream->msg = "invalid code-table opcode";
1425 return XD3_INTERNAL;
1426 }
1427 code_table[i].type1 = *code_string++;
1428 break;
1429 case 1:
1430 if (*code_string > XD3_CPY)
1431 {
1432 stream->msg = "invalid code-table opcode";
1433 return XD3_INTERNAL;
1434 }
1435 code_table[i].type2 = *code_string++;
1436 break;
1437 case 2:
1438 if (*code_string != 0 && code_table[i].type1 == XD3_NOOP)
1439 {
1440 stream->msg = "invalid code-table size";
1441 return XD3_INTERNAL;
1442 }
1443 code_table[i].size1 = *code_string++;
1444 break;
1445 case 3:
1446 if (*code_string != 0 && code_table[i].type2 == XD3_NOOP)
1447 {
1448 stream->msg = "invalid code-table size";
1449 return XD3_INTERNAL;
1450 }
1451 code_table[i].size2 = *code_string++;
1452 break;
1453 case 4:
1454 if (*code_string >= modes)
1455 {
1456 stream->msg = "invalid code-table mode";
1457 return XD3_INTERNAL;
1458 }
1459 if (*code_string != 0 && code_table[i].type1 != XD3_CPY)
1460 {
1461 stream->msg = "invalid code-table mode";
1462 return XD3_INTERNAL;
1463 }
1464 code_table[i].type1 += *code_string++;
1465 break;
1466 case 5:
1467 if (*code_string >= modes)
1468 {
1469 stream->msg = "invalid code-table mode";
1470 return XD3_INTERNAL;
1471 }
1472 if (*code_string != 0 && code_table[i].type2 != XD3_CPY)
1473 {
1474 stream->msg = "invalid code-table mode";
1475 return XD3_INTERNAL;
1476 }
1477 code_table[i].type2 += *code_string++;
1478 break;
1479 }
1480 }
1481 }
1482
1483 stream->code_table = code_table;
1484 return 0;
1485}
1486
1487/* This function applies a code table delta and returns an actual code table. */
1488static int
1489xd3_apply_table_encoding (xd3_stream *in_stream, const uint8_t *data, usize_t size)
1490{
1491 uint8_t dflt_string[CODE_TABLE_STRING_SIZE];
1492 uint8_t code_string[CODE_TABLE_STRING_SIZE];
1493 usize_t code_size;
1494 int ret;
1495
1496 xd3_compute_code_table_string (xd3_rfc3284_code_table (), dflt_string);
1497
1498 if ((ret = xd3_decode_memory (data, size,
1499 dflt_string, CODE_TABLE_STRING_SIZE,
1500 code_string, &code_size,
1501 CODE_TABLE_STRING_SIZE,
1502 0))) { return ret; }
1503
1504 if (code_size != sizeof (code_string))
1505 {
1506 in_stream->msg = "corrupt code-table encoding";
1507 return XD3_INTERNAL;
1508 }
1509
1510 return xd3_apply_table_string (in_stream, code_string);
1511}
1512
1513/***********************************************************************/ 1088/***********************************************************************/
1514 1089
1515static inline void 1090static inline void
@@ -2438,23 +2013,8 @@ xd3_config_stream(xd3_stream *stream,
2438 return XD3_INTERNAL; 2013 return XD3_INTERNAL;
2439 } 2014 }
2440 2015
2441 /* Check/set encoder code table. */ 2016 stream->code_table_desc = & __rfc3284_code_table_desc;
2442 switch (stream->flags & XD3_ALT_CODE_TABLE) { 2017 stream->code_table_func = xd3_rfc3284_code_table;
2443 case 0:
2444 stream->code_table_desc = & __rfc3284_code_table_desc;
2445 stream->code_table_func = xd3_rfc3284_code_table;
2446 break;
2447#if GENERIC_ENCODE_TABLES
2448 case XD3_ALT_CODE_TABLE:
2449 stream->code_table_desc = & __alternate_code_table_desc;
2450 stream->code_table_func = xd3_alternate_code_table;
2451 stream->comp_table_func = xd3_compute_alternate_table_encoding;
2452 break;
2453#endif
2454 default:
2455 stream->msg = "alternate code table support was not compiled";
2456 return XD3_INTERNAL;
2457 }
2458 2018
2459 /* Check sprevsz */ 2019 /* Check sprevsz */
2460 if (smatcher->small_chain == 1 && 2020 if (smatcher->small_chain == 1 &&
@@ -3420,11 +2980,8 @@ xd3_emit_hdr (xd3_stream *stream)
3420 { 2980 {
3421 usize_t hdr_ind = 0; 2981 usize_t hdr_ind = 0;
3422 int use_appheader = stream->enc_appheader != NULL; 2982 int use_appheader = stream->enc_appheader != NULL;
3423 int use_gencodetbl = GENERIC_ENCODE_TABLES &&
3424 (stream->code_table_desc != & __rfc3284_code_table_desc);
3425 2983
3426 if (use_secondary) { hdr_ind |= VCD_SECONDARY; } 2984 if (use_secondary) { hdr_ind |= VCD_SECONDARY; }
3427 if (use_gencodetbl) { hdr_ind |= VCD_CODETABLE; }
3428 if (use_appheader) { hdr_ind |= VCD_APPHEADER; } 2985 if (use_appheader) { hdr_ind |= VCD_APPHEADER; }
3429 2986
3430 if ((ret = xd3_emit_byte (stream, & HDR_TAIL (stream), 2987 if ((ret = xd3_emit_byte (stream, & HDR_TAIL (stream),
@@ -3450,31 +3007,6 @@ xd3_emit_hdr (xd3_stream *stream)
3450 } 3007 }
3451#endif 3008#endif
3452 3009
3453 /* Compressed code table */
3454 if (use_gencodetbl)
3455 {
3456 usize_t code_table_size;
3457 const uint8_t *code_table_data;
3458
3459 if ((ret = stream->comp_table_func (stream, & code_table_data,
3460 & code_table_size)))
3461 {
3462 return ret;
3463 }
3464
3465 if ((ret = xd3_emit_size (stream, & HDR_TAIL (stream),
3466 code_table_size + 2)) ||
3467 (ret = xd3_emit_byte (stream, & HDR_TAIL (stream),
3468 stream->code_table_desc->near_modes)) ||
3469 (ret = xd3_emit_byte (stream, & HDR_TAIL (stream),
3470 stream->code_table_desc->same_modes)) ||
3471 (ret = xd3_emit_bytes (stream, & HDR_TAIL (stream),
3472 code_table_data, code_table_size)))
3473 {
3474 return ret;
3475 }
3476 }
3477
3478 /* Application header */ 3010 /* Application header */
3479 if (use_appheader) 3011 if (use_appheader)
3480 { 3012 {