/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include "SkMetaData.h"

#include "SkMalloc.h"
#include "SkRefCnt.h"

struct PtrPair {
    void*               fPtr;
    SkMetaData::PtrProc fProc;
};

void* SkMetaData::RefCntProc(void* ptr, bool doRef) {
    SkASSERT(ptr);
    SkRefCnt* refcnt = reinterpret_cast<SkRefCnt*>(ptr);

    if (doRef) {
        refcnt->ref();
    } else {
        refcnt->unref();
    }
    return ptr;
}

SkMetaData::SkMetaData() : fRec(nullptr)
{
}

SkMetaData::SkMetaData(const SkMetaData& src) : fRec(nullptr)
{
    *this = src;
}

SkMetaData::~SkMetaData()
{
    this->reset();
}

void SkMetaData::reset()
{
    Rec* rec = fRec;
    while (rec) {
        if (kPtr_Type == rec->fType) {
            PtrPair* pair = (PtrPair*)rec->data();
            if (pair->fProc && pair->fPtr) {
                pair->fPtr = pair->fProc(pair->fPtr, false);
            }
        }
        Rec* next = rec->fNext;
        Rec::Free(rec);
        rec = next;
    }
    fRec = nullptr;
}

SkMetaData& SkMetaData::operator=(const SkMetaData& src)
{
    this->reset();

    const Rec* rec = src.fRec;
    while (rec)
    {
        this->set(rec->name(), rec->data(), rec->fDataLen, (Type)rec->fType, rec->fDataCount);
        rec = rec->fNext;
    }
    return *this;
}

void SkMetaData::setS32(const char name[], int32_t value)
{
    (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1);
}

void SkMetaData::setScalar(const char name[], SkScalar value)
{
    (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1);
}

SkScalar* SkMetaData::setScalars(const char name[], int count, const SkScalar values[])
{
    SkASSERT(count > 0);
    if (count > 0)
        return (SkScalar*)this->set(name, values, sizeof(SkScalar), kScalar_Type, count);
    return nullptr;
}

void SkMetaData::setString(const char name[], const char value[])
{
    (void)this->set(name, value, sizeof(char), kString_Type, SkToInt(strlen(value) + 1));
}

void SkMetaData::setPtr(const char name[], void* ptr, PtrProc proc) {
    PtrPair pair = { ptr, proc };
    (void)this->set(name, &pair, sizeof(PtrPair), kPtr_Type, 1);
}

void SkMetaData::setBool(const char name[], bool value)
{
    (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
}

void SkMetaData::setData(const char name[], const void* data, size_t byteCount) {
    (void)this->set(name, data, sizeof(char), kData_Type, SkToInt(byteCount));
}

void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count)
{
    SkASSERT(name);
    SkASSERT(dataSize);
    SkASSERT(count > 0);

    (void)this->remove(name, type);

    size_t  len = strlen(name);
    Rec*    rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1);

#ifndef SK_DEBUG
    rec->fType = SkToU8(type);
#else
    rec->fType = type;
#endif
    rec->fDataLen = SkToU8(dataSize);
    rec->fDataCount = SkToU16(count);
    if (data)
        memcpy(rec->data(), data, dataSize * count);
    memcpy(rec->name(), name, len + 1);

    if (kPtr_Type == type) {
        PtrPair* pair = (PtrPair*)rec->data();
        if (pair->fProc && pair->fPtr) {
            pair->fPtr = pair->fProc(pair->fPtr, true);
        }
    }

    rec->fNext = fRec;
    fRec = rec;
    return rec->data();
}

bool SkMetaData::findS32(const char name[], int32_t* value) const
{
    const Rec* rec = this->find(name, kS32_Type);
    if (rec)
    {
        SkASSERT(rec->fDataCount == 1);
        if (value)
            *value = *(const int32_t*)rec->data();
        return true;
    }
    return false;
}

bool SkMetaData::findScalar(const char name[], SkScalar* value) const
{
    const Rec* rec = this->find(name, kScalar_Type);
    if (rec)
    {
        SkASSERT(rec->fDataCount == 1);
        if (value)
            *value = *(const SkScalar*)rec->data();
        return true;
    }
    return false;
}

const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar values[]) const
{
    const Rec* rec = this->find(name, kScalar_Type);
    if (rec)
    {
        if (count)
            *count = rec->fDataCount;
        if (values)
            memcpy(values, rec->data(), rec->fDataCount * rec->fDataLen);
        return (const SkScalar*)rec->data();
    }
    return nullptr;
}

bool SkMetaData::findPtr(const char name[], void** ptr, PtrProc* proc) const {
    const Rec* rec = this->find(name, kPtr_Type);
    if (rec) {
        SkASSERT(rec->fDataCount == 1);
        const PtrPair* pair = (const PtrPair*)rec->data();
        if (ptr) {
            *ptr = pair->fPtr;
        }
        if (proc) {
            *proc = pair->fProc;
        }
        return true;
    }
    return false;
}

const char* SkMetaData::findString(const char name[]) const
{
    const Rec* rec = this->find(name, kString_Type);
    SkASSERT(rec == nullptr || rec->fDataLen == sizeof(char));
    return rec ? (const char*)rec->data() : nullptr;
}

bool SkMetaData::findBool(const char name[], bool* value) const
{
    const Rec* rec = this->find(name, kBool_Type);
    if (rec)
    {
        SkASSERT(rec->fDataCount == 1);
        if (value)
            *value = *(const bool*)rec->data();
        return true;
    }
    return false;
}

const void* SkMetaData::findData(const char name[], size_t* length) const {
    const Rec* rec = this->find(name, kData_Type);
    if (rec) {
        SkASSERT(rec->fDataLen == sizeof(char));
        if (length) {
            *length = rec->fDataCount;
        }
        return rec->data();
    }
    return nullptr;
}

const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const
{
    const Rec* rec = fRec;
    while (rec)
    {
        if (rec->fType == type && !strcmp(rec->name(), name))
            return rec;
        rec = rec->fNext;
    }
    return nullptr;
}

bool SkMetaData::remove(const char name[], Type type) {
    Rec* rec = fRec;
    Rec* prev = nullptr;
    while (rec) {
        Rec* next = rec->fNext;
        if (rec->fType == type && !strcmp(rec->name(), name)) {
            if (prev) {
                prev->fNext = next;
            } else {
                fRec = next;
            }

            if (kPtr_Type == type) {
                PtrPair* pair = (PtrPair*)rec->data();
                if (pair->fProc && pair->fPtr) {
                    (void)pair->fProc(pair->fPtr, false);
                }
            }
            Rec::Free(rec);
            return true;
        }
        prev = rec;
        rec = next;
    }
    return false;
}

bool SkMetaData::removeS32(const char name[])
{
    return this->remove(name, kS32_Type);
}

bool SkMetaData::removeScalar(const char name[])
{
    return this->remove(name, kScalar_Type);
}

bool SkMetaData::removeString(const char name[])
{
    return this->remove(name, kString_Type);
}

bool SkMetaData::removePtr(const char name[])
{
    return this->remove(name, kPtr_Type);
}

bool SkMetaData::removeBool(const char name[])
{
    return this->remove(name, kBool_Type);
}

bool SkMetaData::removeData(const char name[]) {
    return this->remove(name, kData_Type);
}

///////////////////////////////////////////////////////////////////////////////

SkMetaData::Iter::Iter(const SkMetaData& metadata) {
    fRec = metadata.fRec;
}

void SkMetaData::Iter::reset(const SkMetaData& metadata) {
    fRec = metadata.fRec;
}

const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) {
    const char* name = nullptr;

    if (fRec) {
        if (t) {
            *t = (SkMetaData::Type)fRec->fType;
        }
        if (count) {
            *count = fRec->fDataCount;
        }
        name = fRec->name();

        fRec = fRec->fNext;
    }
    return name;
}

///////////////////////////////////////////////////////////////////////////////

SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) {
    return (Rec*)sk_malloc_throw(size);
}

void SkMetaData::Rec::Free(Rec* rec) {
    sk_free(rec);
}
