/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPackBits.h"
#include "SkTo.h"

#include <cstring>

size_t SkPackBits::ComputeMaxSize8(size_t srcSize) {
    // worst case is the number of 8bit values + 1 byte per (up to) 128 entries.
    return ((srcSize + 127) >> 7) + srcSize;
}

static uint8_t* flush_same8(uint8_t dst[], uint8_t value, size_t count) {
    while (count > 0) {
        size_t n = count > 128 ? 128 : count;
        *dst++ = (uint8_t)(n - 1);
        *dst++ = (uint8_t)value;
        count -= n;
    }
    return dst;
}

static uint8_t* flush_diff8(uint8_t* SK_RESTRICT dst,
                            const uint8_t* SK_RESTRICT src, size_t count) {
    while (count > 0) {
        size_t n = count > 128 ? 128 : count;
        *dst++ = (uint8_t)(n + 127);
        memcpy(dst, src, n);
        src += n;
        dst += n;
        count -= n;
    }
    return dst;
}

size_t SkPackBits::Pack8(const uint8_t* SK_RESTRICT src, size_t srcSize,
                         uint8_t* SK_RESTRICT dst, size_t dstSize) {
    if (dstSize < ComputeMaxSize8(srcSize)) {
        return 0;
    }

    uint8_t* const origDst = dst;
    const uint8_t* stop = src + srcSize;

    for (intptr_t count = stop - src; count > 0; count = stop - src) {
        if (1 == count) {
            *dst++ = 0;
            *dst++ = *src;
            break;
        }

        unsigned value = *src;
        const uint8_t* s = src + 1;

        if (*s == value) { // accumulate same values...
            do {
                s++;
                if (s == stop) {
                    break;
                }
            } while (*s == value);
            dst = flush_same8(dst, value, SkToInt(s - src));
        } else {    // accumulate diff values...
            do {
                if (++s == stop) {
                    goto FLUSH_DIFF;
                }
                // only stop if we hit 3 in a row,
                // otherwise we get bigger than compuatemax
            } while (*s != s[-1] || s[-1] != s[-2]);
            s -= 2; // back up so we don't grab the "same" values that follow
        FLUSH_DIFF:
            dst = flush_diff8(dst, src, SkToInt(s - src));
        }
        src = s;
    }
    return dst - origDst;
}

int SkPackBits::Unpack8(const uint8_t* SK_RESTRICT src, size_t srcSize,
                        uint8_t* SK_RESTRICT dst, size_t dstSize) {
    uint8_t* const origDst = dst;
    uint8_t* const endDst = dst + dstSize;
    const uint8_t* stop = src + srcSize;

    while (src < stop) {
        unsigned n = *src++;
        if (n <= 127) {   // repeat count (n + 1)
            n += 1;
            if (dst > (endDst - n) || src >= stop) {
                return 0;
            }
            memset(dst, *src++, n);
        } else {    // same count (n - 127)
            n -= 127;
            if (dst > (endDst - n) || src > (stop - n)) {
                return 0;
            }
            memcpy(dst, src, n);
            src += n;
        }
        dst += n;
    }
    SkASSERT(src <= stop);
    SkASSERT(dst <= endDst);
    return SkToInt(dst - origDst);
}
