Revision 302dfbeb savevm.c

b/savevm.c
2392 2392
{
2393 2393
    vmstate_register_ram(mr, NULL);
2394 2394
}
2395

  
2396
/*
2397
  page = zrun nzrun
2398
       | zrun nzrun page
2399

  
2400
  zrun = length
2401

  
2402
  nzrun = length byte...
2403

  
2404
  length = uleb128 encoded integer
2405
 */
2406
int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
2407
                         uint8_t *dst, int dlen)
2408
{
2409
    uint32_t zrun_len = 0, nzrun_len = 0;
2410
    int d = 0, i = 0;
2411
    long res, xor;
2412
    uint8_t *nzrun_start = NULL;
2413

  
2414
    g_assert(!(((uintptr_t)old_buf | (uintptr_t)new_buf | slen) %
2415
               sizeof(long)));
2416

  
2417
    while (i < slen) {
2418
        /* overflow */
2419
        if (d + 2 > dlen) {
2420
            return -1;
2421
        }
2422

  
2423
        /* not aligned to sizeof(long) */
2424
        res = (slen - i) % sizeof(long);
2425
        while (res && old_buf[i] == new_buf[i]) {
2426
            zrun_len++;
2427
            i++;
2428
            res--;
2429
        }
2430

  
2431
        /* word at a time for speed */
2432
        if (!res) {
2433
            while (i < slen &&
2434
                   (*(long *)(old_buf + i)) == (*(long *)(new_buf + i))) {
2435
                i += sizeof(long);
2436
                zrun_len += sizeof(long);
2437
            }
2438

  
2439
            /* go over the rest */
2440
            while (i < slen && old_buf[i] == new_buf[i]) {
2441
                zrun_len++;
2442
                i++;
2443
            }
2444
        }
2445

  
2446
        /* buffer unchanged */
2447
        if (zrun_len == slen) {
2448
            return 0;
2449
        }
2450

  
2451
        /* skip last zero run */
2452
        if (i == slen) {
2453
            return d;
2454
        }
2455

  
2456
        d += uleb128_encode_small(dst + d, zrun_len);
2457

  
2458
        zrun_len = 0;
2459
        nzrun_start = new_buf + i;
2460

  
2461
        /* overflow */
2462
        if (d + 2 > dlen) {
2463
            return -1;
2464
        }
2465
        /* not aligned to sizeof(long) */
2466
        res = (slen - i) % sizeof(long);
2467
        while (res && old_buf[i] != new_buf[i]) {
2468
            i++;
2469
            nzrun_len++;
2470
            res--;
2471
        }
2472

  
2473
        /* word at a time for speed, use of 32-bit long okay */
2474
        if (!res) {
2475
            /* truncation to 32-bit long okay */
2476
            long mask = 0x0101010101010101ULL;
2477
            while (i < slen) {
2478
                xor = *(long *)(old_buf + i) ^ *(long *)(new_buf + i);
2479
                if ((xor - mask) & ~xor & (mask << 7)) {
2480
                    /* found the end of an nzrun within the current long */
2481
                    while (old_buf[i] != new_buf[i]) {
2482
                        nzrun_len++;
2483
                        i++;
2484
                    }
2485
                    break;
2486
                } else {
2487
                    i += sizeof(long);
2488
                    nzrun_len += sizeof(long);
2489
                }
2490
            }
2491
        }
2492

  
2493
        d += uleb128_encode_small(dst + d, nzrun_len);
2494
        /* overflow */
2495
        if (d + nzrun_len > dlen) {
2496
            return -1;
2497
        }
2498
        memcpy(dst + d, nzrun_start, nzrun_len);
2499
        d += nzrun_len;
2500
        nzrun_len = 0;
2501
    }
2502

  
2503
    return d;
2504
}
2505

  
2506
int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen)
2507
{
2508
    int i = 0, d = 0;
2509
    int ret;
2510
    uint32_t count = 0;
2511

  
2512
    while (i < slen) {
2513

  
2514
        /* zrun */
2515
        if ((slen - i) < 2) {
2516
            return -1;
2517
        }
2518

  
2519
        ret = uleb128_decode_small(src + i, &count);
2520
        if (ret < 0 || (i && !count)) {
2521
            return -1;
2522
        }
2523
        i += ret;
2524
        d += count;
2525

  
2526
        /* overflow */
2527
        if (d > dlen) {
2528
            return -1;
2529
        }
2530

  
2531
        /* nzrun */
2532
        if ((slen - i) < 2) {
2533
            return -1;
2534
        }
2535

  
2536
        ret = uleb128_decode_small(src + i, &count);
2537
        if (ret < 0 || !count) {
2538
            return -1;
2539
        }
2540
        i += ret;
2541

  
2542
        /* overflow */
2543
        if (d + count > dlen || i + count > slen) {
2544
            return -1;
2545
        }
2546

  
2547
        memcpy(dst + d, src + i, count);
2548
        d += count;
2549
        i += count;
2550
    }
2551

  
2552
    return d;
2553
}

Also available in: Unified diff