<commit_before>/*
* Copyright 2019 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#ifndef SkReflected_DEFINED
#define SkReflected_DEFINED

#include "SkColor.h"
#include "SkRefCnt.h"
#include "SkString.h"
#include "SkTArray.h"

#include <string.h>

struct SkCurve;
class SkFieldVisitor;
class SkRandom;

/**
 * Classes and macros for a lightweight reflection system.
 *
 * Classes that derive from SkReflected have several features:
 *   - Access to an SkReflected::Type instance, via static GetType() or virtual getType()
 *     The Type instance can be used to create additional instances (fFactory), get the name
 *     of the type, and answer queries of the form "is X derived from Y".
 *   - Given a string containing a type name, SkReflected can create an instance of that type.
 *   - SkReflected::VisitTypes can be used to enumerate all Types.
 *
 * Together, this simplifies the implementation of serialization and other dynamic type factories.
 *
 * Finally, all SkReflected-derived types must implement visitFields, which provides field-level
 * reflection, in conjunction with SkFieldVisitor. See SkFieldVisitor, below.
 *
 * To create a new reflected class:
 *   - Derive the class (directly or indirectly) from SkReflected.
 *   - Ensure that the class can be default constructed.
 *   - In the public area of the class declaration, add REFLECTED(<ClassName>, <BaseClassName>).
 *     If the class is abstract, use REFLECTED_ABSTRACT(<ClassName>, <BaseClassName>) instead.
 *   - Add a one-time call to REGISTER_REFLECTED(<ClassName>) at initialization time.
 *   - Implement visitFields(), as described below.
 */
class SkReflected : public SkRefCnt {
public:
    typedef sk_sp<SkReflected>(*Factory)();
    struct Type {
        const char* fName;
        const Type* fBase;
        Factory     fFactory;

        bool isDerivedFrom(const Type* t) const {
            const Type* base = fBase;
            while (base) {
                if (base == t) {
                    return true;
                }
                base = base->fBase;
            }
            return false;
        }
    };

    virtual const Type* getType() const = 0;
    static const Type* GetType() {
        static Type gType{ "SkReflected", nullptr, nullptr };
        return &gType;
    }

    bool isOfType(const Type* t) const {
        const Type* thisType = this->getType();
        return thisType == t || thisType->isDerivedFrom(t);
    }

    static void Register(const Type* type) {
        gTypes.push_back(type);
    }

    static sk_sp<SkReflected> CreateInstance(const char* name) {
        for (const Type* type : gTypes) {
            if (0 == strcmp(name, type->fName)) {
                return type->fFactory();
            }
        }
        return nullptr;
    }

    virtual void visitFields(SkFieldVisitor*) = 0;

    static void VisitTypes(std::function<void(const Type*)> visitor);

private:
    static SkSTArray<16, const Type*, true> gTypes;
};

#define REFLECTED(TYPE, BASE)                                    \
    static sk_sp<SkReflected> CreateProc() {                     \
        return sk_sp<SkReflected>(new TYPE());                   \
    }                                                            \
    static const Type* GetType() {                               \
        static Type gType{ #TYPE, BASE::GetType(), CreateProc }; \
        return &gType;                                           \
    }                                                            \
    const Type* getType() const override { return GetType(); }

#define REFLECTED_ABSTRACT(TYPE, BASE)                          \
    static const Type* GetType() {                              \
        static Type gType{ #TYPE, BASE::GetType(), nullptr };   \
        return &gType;                                          \
    }                                                           \
    const Type* getType() const override { return GetType(); }

#define REGISTER_REFLECTED(TYPE) SkReflected::Register(TYPE::GetType())

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

struct SkPoint;

/**
 * SkFieldVisitor is an interface that can be implemented by any class to visit all fields of
 * SkReflected types, and of types that implement the visitFields() function.
 *<commit_msg>SkReflected - avoid double registration, auto register base types, etc.<commit_after>/*
* Copyright 2019 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#ifndef SkReflected_DEFINED
#define SkReflected_DEFINED

#include "SkColor.h"
#include "SkRefCnt.h"
#include "SkString.h"
#include "SkTArray.h"

#include <string.h>

struct SkCurve;
class SkFieldVisitor;
class SkRandom;

/**
 * Classes and macros for a lightweight reflection system.
 *
 * Classes that derive from SkReflected have several features:
 *   - Access to an SkReflected::Type instance, via static GetType() or virtual getType()
 *     The Type instance can be used to create additional instances (fFactory), get the name
 *     of the type, and answer queries of the form "is X derived from Y".
 *   - Given a string containing a type name, SkReflected can create an instance of that type.
 *   - SkReflected::VisitTypes can be used to enumerate all Types.
 *
 * Together, this simplifies the implementation of serialization and other dynamic type factories.
 *
 * Finally, all SkReflected-derived types must implement visitFields, which provides field-level
 * reflection, in conjunction with SkFieldVisitor. See SkFieldVisitor, below.
 *
 * To create a new reflected class:
 *   - Derive the class (directly or indirectly) from SkReflected.
 *   - Ensure that the class can be default constructed.
 *   - In the public area of the class declaration, add REFLECTED(<ClassName>, <BaseClassName>).
 *     If the class is abstract, use REFLECTED_ABSTRACT(<ClassName>, <BaseClassName>) instead.
 *   - Add a one-time call to REGISTER_REFLECTED(<ClassName>) at initialization time.
 *   - Implement visitFields(), as described below.
 */
class SkReflected : public SkRefCnt {
public:
    typedef sk_sp<SkReflected>(*Factory)();
    struct Type {
        const char* fName;
        const Type* fBase;
        Factory     fFactory;
        bool        fRegistered = false;

        bool isDerivedFrom(const Type* t) const {
            const Type* base = fBase;
            while (base) {
                if (base == t) {
                    return true;
                }
                base = base->fBase;
            }
            return false;
        }
    };

    virtual const Type* getType() const = 0;
    static const Type* GetType() {
        static Type gType{ "SkReflected", nullptr, nullptr };
        RegisterOnce(&gType);
        return &gType;
    }

    bool isOfType(const Type* t) const {
        const Type* thisType = this->getType();
        return thisType == t || thisType->isDerivedFrom(t);
    }

    static sk_sp<SkReflected> CreateInstance(const char* name) {
        for (const Type* type : gTypes) {
            if (0 == strcmp(name, type->fName)) {
                return type->fFactory();
            }
        }
        return nullptr;
    }

    virtual void visitFields(SkFieldVisitor*) = 0;

    static void VisitTypes(std::function<void(const Type*)> visitor);

protected:
    static void RegisterOnce(Type* type) {
        if (!type->fRegistered) {
            gTypes.push_back(type);
            type->fRegistered = true;
        }
    }

private:
    static SkSTArray<16, const Type*, true> gTypes;
};

#define REFLECTED(TYPE, BASE)                                    \
    static sk_sp<SkReflected> CreateProc() {                     \
        return sk_sp<SkReflected>(new TYPE());                   \
    }                                                            \
    static const Type* GetType() {                               \
        static Type gType{ #TYPE, BASE::GetType(), CreateProc }; \
        RegisterOnce(&gType);                                    \
        return &gType;                                           \
    }                                                            \
    const Type* getType() const override { return GetType(); }

#define REFLECTED_ABSTRACT(TYPE, BASE)                          \
    static const Type* GetType() {                              \
        static Type gType{ #TYPE, BASE::GetType(), nullptr };   \
        RegisterOnce(&gType);                                   \
        return &gType;                                          \
    }                                                           \
    const Type* getType() const override { return GetType(); }

#define REGISTER_REFLECTED(TYPE) TYPE::GetType()

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

struct SkPoint;

/**
 * SkFieldVisitor is an interface that can be implemented by any class to visit all fields of
 * SkReflected types, and of types that implement the visitFields() function.
 *
{'fraction_non_alphanumeric': 0.10545932909449682, 'fraction_numerical': 0.0019732514799386098, 'mean_word_length': 1.845601996257018, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '917908', 'n_tokens_mistral': 2375, 'n_tokens_neox': 2301, 'n_words': 812}