text:
#include "stdafx.h"

// core/api.cpp*
#include "api.h"
#include "parallel.h"
#include "paramset.h"
#include "spectrum.h"
#include "scene.h"
#include "film.h"
#include "medium.h"
#include "stats.h"

// API Additional Headers
#include "accelerators/bvh.h"
#include "accelerators/kdtreeaccel.h"
#include "cameras/environment.h"
#include "cameras/orthographic.h"
#include "cameras/perspective.h"
#include "cameras/realistic.h"
#include "filters/box.h"
#include "filters/gaussian.h"
#include "filters/mitchell.h"
#include "filters/sinc.h"
#include "filters/triangle.h"
#include "integrators/bdpt.h"
#include "integrators/directlighting.h"
#include "integrators/mlt.h"
#include "integrators/path.h"
#include "integrators/sppm.h"
#include "integrators/volpath.h"
#include "integrators/whitted.h"
#include "lights/diffuse.h"
#include "lights/distant.h"
#include "lights/goniometric.h"
#include "lights/infinite.h"
#include "lights/point.h"
#include "lights/projection.h"
#include "lights/spot.h"
#include "materials/fourier.h"
#include "materials/glass.h"
#include "materials/hair.h"
#include "materials/kdsubsurface.h"
#include "materials/matte.h"
#include "materials/metal.h"
#include "materials/mirror.h"
#include "materials/mixmat.h"
#include "materials/plastic.h"
#include "materials/substrate.h"
#include "materials/subsurface.h"
#include "materials/translucent.h"
#include "materials/uber.h"
#include "samplers/halton.h"
#include "samplers/maxmin.h"
#include "samplers/random.h"
#include "samplers/sobol.h"
#include "samplers/stratified.h"
#include "samplers/zerotwosequence.h"
#include "shapes/cone.h"
#include "shapes/curve.h"
#include "shapes/cylinder.h"
#include "shapes/disk.h"
#include "shapes/heightfield.h"
#include "shapes/hyperboloid.h"
#include "shapes/loopsubdiv.h"
#include "shapes/nurbs.h"
#include "shapes/paraboloid.h"
#include "shapes/sphere.h"
#include "shapes/triangle.h"
#include "shapes/plymesh.h"
#include "textures/bilerp.h"
#include "textures/checkerboard.h"
#include "textures/constant.h"
#include "textures/dots.h"
#include "textures/fbm.h"
#include "textures/imagemap.h"
#include "textures/marble.h"
#include "textures/mix.h"
#include "textures/scale.h"
#include "textures/uv.h"
#include "textures/windy.h"
#include "textures/wrinkled.h"
#include "media/grid.h"
#include "media/homogeneous.h"
#include <map>
#include <stdio.h>

// API Global Variables
Options PbrtOptions;

// API Local Classes
PBRT_CONSTEXPR int MaxTransforms = 2;
PBRT_CONSTEXPR int StartTransformBits = 1 << 0;
PBRT_CONSTEXPR int EndTransformBits = 1 << 1;
PBRT_CONSTEXPR int AllTransformsBits = (1 << MaxTransforms) - 1;
struct TransformSet {
    // TransformSet Public Methods
    Transform &operator[](int i) {
        Assert(i >= 0 && i < MaxTransforms);
        return t[i];
    }
    const Transform &operator[](int i) const {
        Assert(i >= 0 && i < MaxTransforms);
        return t[i];
    }
    friend TransformSet Inverse(const TransformSet &ts) {
        TransformSet tInv;
        for (int i = 0; i < MaxTransforms; ++i) tInv.t[i] = Inverse(ts.t[i]);
        return tInv;
    }
    bool IsAnimated() const {
        for (int i = 0; i < MaxTransforms - 1; ++i)
            if (t[i] != t[i + 1]) return true;
        return false;
    }

  private:
    Transform t[MaxTransforms];
};

struct RenderOptions {
    // RenderOptions Public Methods
    Integrator *MakeIntegrator() const;
    Scene *MakeScene();
    Camera *MakeCamera() const;

    // RenderOptions Public Data
    Float transformStartTime = 0, transformEndTime = 1;
    std::string FilterName = "box";
    ParamSet FilterParams;
    std::string FilmName = "image";
    ParamSet FilmParams;
    std::string SamplerName = "halton";
    ParamSet SamplerParams;
    std::string AcceleratorName = "bvh";
    ParamSet AcceleratorParams;
    std::string IntegratorName = "path";
    ParamSet IntegratorParams;
    std::string CameraName = "perspective";
    ParamSet CameraParams;
    TransformSet CameraToWorld;
    std::map<std::string, std::shared_ptr<Medium>> namedMedia;
    std::vector<std::shared_ptr<Light>> lights;
    std::vector<std::shared_ptr<Primitive>> primitives;
    std::map<std::string, std::vector<std::shared_ptr<Primitive>>> instances;
    std::vector<std::shared_ptr<Primitive>> *currentInstance = nullptr;
};

struct GraphicsState {
    // Graphics State Methods
    std::shared_ptr<Material> CreateMaterial(const ParamSet &params);
    MediumInterface CreateMediumInterface();

    // Graphics State
    std::string currentInsideMedium, currentOutsideMedium;
    std::map<std::string, std::shared_ptr<Texture<Float>>> floatTextures;
    std::map<std::string, std::shared_ptr<Texture<Spectrum>>> spectrumTextures;
    ParamSet materialParams;
    std::string material = "matte";
    std::map<std::string, std::shared_ptr<Material>> namedMaterials;
    std::string currentNamedMaterial;
    ParamSet areaLightParams;
    std::string areaLight;
    bool reverseOrientation = false;
};

class TransformCache {
  public:
    // TransformCache Public Methods
    void Lookup(const Transform &t, Transform **tCached,
                Transform **tCachedInverse) {
        auto iter = cache.find(t);
        if (iter == cache.end()) {
            Transform *tr = arena.Alloc<Transform>();
            *tr = t;
            Transform *tinv = arena.Alloc<Transform>();
            *tinv = Transform(Inverse(t));
            cache[t] = std::make_pair(tr, tinv);
            iter = cache.find(t);
        }
        if (tCached) *tCached = iter->second.first;
        if (tCachedInverse) *tCachedInverse = iter->second.second;
    }
    void Clear() {
        arena.Reset();
        cache.erase(cache.begin(), cache.end());
    }

  private:
    // TransformCache Private Data
    std::map<Transform, std::pair<Transform *, Transform *>> cache;
    MemoryArena arena;
};

// API Static Data
enum class APIState { Uninitialized, OptionsBlock, WorldBlock };
static APIState currentApiState = APIState::Uninitialized;
static TransformSet curTransform;
static uint32_t activeTransformBits = AllTransformsBits;
static std::map<std::string, TransformSet> namedCoordinateSystems;
static std::unique_ptr<RenderOptions> renderOptions;
static GraphicsState graphicsState;
static std::vector<GraphicsState> pushedGraphicsStates;
static std::vector<TransformSet> pushedTransforms;
static std::vector<uint32_t> pushedActiveTransformBits;
static TransformCache transformCache;
static int catIndentCount = 0;

// API Forward Declarations
std::vector<std::shared_ptr<Shape>> MakeShapes(const std::string &name,
                                               const Transform *ObjectToWorld,
                                               const Transform *WorldToObject,
                                               bool reverseOrientation,
                                               const ParamSet &paramSet);

// API Macros
#define VERIFY_INITIALIZED(func)                           \
    if (currentApiState == APIState::Uninitialized) {      \
        Error(                                             \
            "pbrtInit() must be before calling \"%s()\". " \
            "Ignoring.",                                   \
            func);                                         \
        return;                                            \
    } else /* swallow trailing semicolon */
#define VERIFY_OPTIONS(func)                             \
    VERIFY_INITIALIZED(func);                            \
    if (currentApiState == APIState::WorldBlock) {       \
        Error(                                           \
            "Options cannot be set inside world block; " \
            "\"%s\" not allowed.  Ignoring.",            \
            func);                                       \
        return;                                          \
    } else /* swallow trailing semicolon */
#define VERIFY_WORLD(func)                                   \
    VERIFY_INITIALIZED(func);                                \
    if (currentApiState == APIState::OptionsBlock) {         \
        Error(                                               \
            "Scene description must be inside world block; " \
            "\"%s\" not allowed. Ignoring.",                 \
            func);                                           \
        return;                                              \
    } else /* swallow trailing semicolon */
#define FOR_ACTIVE_TRANSFORMS(expr)           \
    for (int i = 0; i < MaxTransforms; ++i)   \
        if (activeTransformBits & (1 << i)) { \
            expr                              \
        }
#define WARN_IF_ANIMATED_TRANSFORM(func)                             \
    do {                                                             \
        if (curTransform.IsAnimated())                               \
            Warning(                                                 \
                "Animated transformations set; ignoring for \"%s\" " \
                "and using the start transform only",                \
                func);                                               \
    } while (false) /* swallow trailing semicolon */

// Object Creation Function Definitions
std::vector<std::shared_ptr<Shape>> MakeShapes(const std::string &name,
                                               const Transform *object2world,
                                               const Transform *world2object,
                                               bool reverseOrientation,
                                               const ParamSet &paramSet) {
    std::vector<std::shared_ptr<Shape>> shapes;
    std::shared_ptr<Shape> s;
    if (name == "sphere")
        s = CreateSphereShape(object2world, world2object, reverseOrientation,
                              paramSet);
    // Create remaining single _Shape_ types
    else if (name == "cylinder")
        s = CreateCylinderShape(object2world, world2object, reverseOrientation,
                                paramSet);
    else if (name == "disk")
        s = CreateDiskShape(object2world, world2object, reverseOrientation,
                            paramSet);
    else if (name == "cone")
        s = CreateConeShape(object2world, world2object, reverseOrientation,
                            paramSet);
    else if (name == "paraboloid")
        s = CreateParaboloidShape(object2world, world2object,
                                  reverseOrientation, paramSet);
    else if (name == "hyperboloid")
        s = CreateHyperboloidShape(object2world, world2object,
                                   reverseOrientation, paramSet);
    if (s != nullptr) shapes.push_back(s);

    // Create multiple-_Shape_ types
    else if (name == "curve")
        shapes = CreateCurveShape(object2world, world2object,
                                  reverseOrientation, paramSet);
    else if (name == "trianglemesh") {
        if (PbrtOptions.toPly) {
            static int count = 1;
            char fn[128];
            const char *plyPrefix =
                getenv("PLY_PREFIX") ? getenv("PLY_PREFIX") : "mesh";
            sprintf(fn, "%s_%05d.ply", plyPrefix, count++);

            int nvi, npi, nuvi, nsi, nni;
            const int *vi = paramSet.FindInt("indices", &nvi);
            const Point3f *P = paramSet.FindPoint3f("P", &npi);
            const Point2f *uvs = paramSet.FindPoint2f("uv", &nuvi);
            if (!uvs) uvs = paramSet.FindPoint2f("st", &nuvi);
            std::vector<Point2f> tempUVs;
            if (!uvs) {
                const Float *fuv = paramSet.FindFloat("uv", &nuvi);
                if (!fuv) fuv = paramSet.FindFloat("st", &nuvi);
                if (fuv) {
                    nuvi /= 2;
                    tempUVs.reserve(nuvi);
                    for (int i = 0; i < nuvi; ++i)
                        tempUVs.push_back(Point2f(fuv[2 * i], fuv[2 * i + 1]));
                    uvs = &tempUVs[0];
                }
            }
            const Normal3f *N = paramSet.FindNormal3f("N", &nni);
            const Vector3f *S = paramSet.FindVector3f("S", &nsi);

            if (!WritePlyFile(fn, nvi / 3, vi, npi, P, S, N, uvs))
                Error("Unable to write PLY file \"%s\"", fn);

            printf("%*sShape \"plymesh\" \"string filename\" \"%s\" ",
                   catIndentCount, "", fn);

            std::string alphaTex = paramSet.FindTexture("alpha");
            if (alphaTex != "")
                printf("\n%*s\"texture alpha\" \"%s\" ", catIndentCount + 8, "",
                       alphaTex.c_str());
            else {
                int count;
                const Float *alpha = paramSet.FindFloat("alpha", &count);
                if (alpha)
                    printf("\n%*s\"float alpha\" %f ", catIndentCount + 8, "",
                           *alpha);
            }

            std::string shadowAlphaTex = paramSet.FindTexture("shadowalpha");
            if (shadowAlphaTex != "")
                printf("\n%*s\"texture shadowalpha\" \"%s\" ",
                       catIndentCount + 8, "", shadowAlphaTex.c_str());
            else {
                int count;
                const Float *alpha = paramSet.FindFloat("shadowalpha", &count);
                if (alpha)
                    printf("\n%*s\"float shadowalpha\" %f ", catIndentCount + 8,
                           "", *alpha);
            }
            printf("\n");
        } else
            shapes = CreateTriangleMeshShape(object2world, world2object,
                                             reverseOrientation, paramSet,
                                             &graphicsState.floatTextures);
    } else if (name == "plymesh")
        shapes = CreatePLYMesh(object2world, world2object, reverseOrientation,
                               paramSet, &graphicsState.floatTextures);
    else if (name == "heightfield")
        shapes = CreateHeightfield(object2world, world2object,
                                   reverseOrientation, paramSet);
    else if (name == "loopsubdiv")
        shapes = CreateLoopSubdiv(object2world, world2object,
                                  reverseOrientation, paramSet);
    else if (name == "nurbs")
        shapes = CreateNURBS(object2world, world2object, reverseOrientation,
                             paramSet);
    else
        Warning("Shape \"%s\" unknown.", name.c_str());
    paramSet.ReportUnused();
    return shapes;
}

std::shared_ptr<Material> MakeMaterial(const std::string &name,
                                       const TextureParams &mp) {
    Material *material = nullptr;
    if (name == "" || name == "none")
        return nullptr;
    else if (name == "matte")
        material = CreateMatteMaterial(mp);
    else if (name == "plastic")
        material = CreatePlasticMaterial(mp);
    else if (name == "translucent")
        material = CreateTranslucentMaterial(mp);
    else if (name == "glass")
        material = CreateGlassMaterial(mp);
    else if (name == "hair")
        material = CreateHairMaterial(mp);
    else if (name == "mirror")
        material = CreateMirrorMaterial(mp);
    else if (name == "mix") {
        std::string m1 = mp.FindString("namedmaterial1", "");
        std::string m2 = mp.FindString("namedmaterial2", "");
        std::shared_ptr<Material> mat1 = graphicsState.namedMaterials[m1];
        std::shared_ptr<Material> mat2 = graphicsState.namedMaterials[m2];
        if (!mat1) {
            Error("Named material \"%s\" undefined.  Using \"matte\"",
                  m1.c_str());
            mat1 = MakeMaterial("matte", mp);
        }
        if (!mat2) {
            Error("Named material \"%s\" undefined.  Using \"matte\"",
                  m2.c_str());
            mat2 = MakeMaterial("matte", mp);
        }

        material = CreateMixMaterial(mp, mat1, mat2);
    } else if (name == "metal")
        material = CreateMetalMaterial(mp);
    else if (name == "substrate")
        material = CreateSubstrateMaterial(mp);
    else if (name == "uber")
        material = CreateUberMaterial(mp);
    else if (name == "subsurface")
        material = CreateSubsurfaceMaterial(mp);
    else if (name == "kdsubsurface")
        material = CreateKdSubsurfaceMaterial(mp);
    else if (name == "fourier")
        material = CreateFourierMaterial(mp);
    else
        Warning("Material \"%s\" unknown.", name.c_str());

    if ((name == "subsurface" || name == "kdsubsurface") &&
        (renderOptions->IntegratorName != "path" &&
         (renderOptions->IntegratorName != "volpath")))
        Warning(
            "Subsurface scattering material \"%s\" used, but \"%s\" "
            "integrator doesn't support subsurface scattering. "
            "Use \"path\" or \"volpath\".",
            name.c_str(), renderOptions->IntegratorName.c_str());

    mp.ReportUnused();
    if (!material) Error("Unable to create material \"%s\"", name.c_str());
    return std::shared_ptr<Material>(material);
}

std::shared_ptr<Texture<Float>> MakeFloatTexture(const std::string &name,
                                                 const Transform &tex2world,
                                                 const TextureParams &tp) {
    Texture<Float> *tex = nullptr;
    if (name == "constant")
        tex = CreateConstantFloatTexture(tex2world, tp);
    else if (name == "scale")
        tex = CreateScaleFloatTexture(tex2world, tp);
    else if (name == "mix")
        tex = CreateMixFloatTexture(tex2world, tp);
    else if (name == "bilerp")
        tex = CreateBilerpFloatTexture(tex2world, tp);
    else if (name == "imagemap")
        tex = CreateImageFloatTexture(tex2world, tp);
    else if (name == "uv")
        tex = CreateUVFloatTexture(tex2world, tp);
    else if (name == "checkerboard")
        tex = CreateCheckerboardFloatTexture(tex2world, tp);
    else if (name == "dots")
        tex = CreateDotsFloatTexture(tex2world, tp);
    else if (name == "fbm")
        tex = CreateFBmFloatTexture(tex2world, tp);
    else if (name == "wrinkled")
        tex = CreateWrinkledFloatTexture(tex2world, tp);
    else if (name == "marble")
        tex = CreateMarbleFloatTexture(tex2world, tp);
    else if (name == "windy")
        tex = CreateWindyFloatTexture(tex2world, tp);
    else
        Warning("Float texture \"%s\" unknown.", name.c_str());
    tp.ReportUnused();
    return std::shared_ptr<Texture<Float>>(tex);
}

std::shared_ptr<Texture<Spectrum>> MakeSpectrumTexture(
    const std::string &name, const Transform &tex2world,
    const TextureParams &tp) {
    Texture<Spectrum> *tex = nullptr;
    if (name == "constant")
        tex = CreateConstantSpectrumTexture(tex2world, tp);
    else if (name == "scale")
        tex = CreateScaleSpectrumTexture(tex2world, tp);
    else if (name == "mix")
        tex = CreateMixSpectrumTexture(tex2world, tp);
    else if (name == "bilerp")
        tex = CreateBilerpSpectrumTexture(tex2world, tp);
    else if (name == "imagemap")
        tex = CreateImageSpectrumTexture(tex2world, tp);
    else if (name == "uv")
        tex = CreateUVSpectrumTexture(tex2world, tp);
    else if (name == "checkerboard")
        tex = CreateCheckerboardSpectrumTexture(tex2world, tp);
    else if (name == "dots")
        tex = CreateDotsSpectrumTexture(tex2world, tp);
    else if (name == "fbm")
        tex = CreateFBmSpectrumTexture(tex2world, tp);
    else if (name == "wrinkled")
        tex = CreateWrinkledSpectrumTexture(tex2world, tp);
    else if (name == "marble")
        tex = CreateMarbleSpectrumTexture(tex2world, tp);
    else if (name == "windy")
        tex = CreateWindySpectrumTexture(tex2world, tp);
    else
        Warning("Spectrum texture \"%s\" unknown.", name.c_str());
    tp.ReportUnused();
    return std::shared_ptr<Texture<Spectrum>>(tex);
}

std::shared_ptr<Medium> MakeMedium(const std::string &name,
                                   const ParamSet &paramSet,
                                   const Transform &medium2world) {
    Float sig_a_rgb[3] = {.0011f, .0024f, .014f},
          sig_s_rgb[3] = {2.55f, 3.21f, 3.77f};
    Spectrum sig_a = Spectrum::FromRGB(sig_a_rgb),
             sig_s = Spectrum::FromRGB(sig_s_rgb);
    std::string preset = paramSet.FindOneString("preset", "");
    bool found = GetMediumScatteringProperties(preset, &sig_a, &sig_s);
    if (preset != "" && !found)
        Warning("Material preset \"%s\" not found.  Using defaults.",
                preset.c_str());
    Float scale = paramSet.FindOneFloat("scale", 1.f);
    Float g = paramSet.FindOneFloat("g", 0.0f);
    sig_a = paramSet.FindOneSpectrum("sigma_a", sig_a) * scale;
    sig_s = paramSet.FindOneSpectrum("sigma_s", sig_s) * scale;
    Medium *m = NULL;
    if (name == "homogeneous") {
        m = new HomogeneousMedium(sig_a, sig_s, g);
    } else if (name == "heterogeneous") {
        int nitems;
        const Float *data = paramSet.FindFloat("density", &nitems);
        if (!data) {
            Error("No \"density\" values provided for heterogeneous medium?");
            return NULL;
        }
        int nx = paramSet.FindOneInt("nx", 1);
        int ny = paramSet.FindOneInt("ny", 1);
        int nz = paramSet.FindOneInt("nz", 1);
        Point3f p0 = paramSet.FindOnePoint3f("p0", Point3f(0.f, 0.f, 0.f));
        Point3f p1 = paramSet.FindOnePoint3f("p1", Point3f(1.f, 1.f, 1.f));
        if (nitems != nx * ny * nz) {
            Error(
                "GridDensityMedium has %d density values; expected nx*ny*nz = "
                "%d",
                nitems, nx * ny * nz);
            return NULL;
        }
        Transform data2Medium = Translate(Vector3f(p0)) *
                                Scale(p1.x - p0.x, p1.y - p0.y, p1.z - p0.z);
        m = new GridDensityMedium(sig_a, sig_s, g, nx, ny, nz,
                                  medium2world * data2Medium, data);
    } else
        Warning("Medium \"%s\" unknown.", name.c_str());
    paramSet.ReportUnused();
    return std::shared_ptr<Medium>(m);
}

std::shared_ptr<Light> MakeLight(const std::string &name,
                                 const ParamSet &paramSet,
                                 const Transform &light2world,
                                 const MediumInterface &mediumInterface) {
    std::shared_ptr<Light> light;
    if (name == "point")
        light =
            CreatePointLight(light2world, mediumInterface.outside, paramSet);
    else if (name == "spot")
        light = CreateSpotLight(light2world, mediumInterface.outside, paramSet);
    else if (name == "goniometric")
        light = CreateGoniometricLight(light2world, mediumInterface.outside,
                                       paramSet);
    else if (name == "projection")
        light = CreateProjectionLight(light2world, mediumInterface.outside,
                                      paramSet);
    else if (name == "distant")
        light = CreateDistantLight(light2world, paramSet);
    else if (name == "infinite" || name == "exinfinite")
        light = CreateInfiniteLight(light2world, paramSet);
    else
        Warning("Light \"%s\" unknown.", name.c_str());
    paramSet.ReportUnused();
    return light;
}

std::shared_ptr<AreaLight> MakeAreaLight(const std::string &name,
                                         const Transform &light2world,
                                         const MediumInterface &mediumInterface,
                                         const ParamSet &paramSet,
                                         const std::shared_ptr<Shape> &shape) {
    std::shared_ptr<AreaLight> area;
    if (name == "area" || name == "diffuse")
        area = CreateDiffuseAreaLight(light2world, mediumInterface.outside,
                                      paramSet, shape);
    else
        Warning("Area light \"%s\" unknown.", name.c_str());
    paramSet.ReportUnused();
    return area;
}

Integrator *MakeIntegrator(const std::string &name, const ParamSet &paramSet) {
    Integrator *si = nullptr;

    paramSet.ReportUnused();
    return si;
}

std::shared_ptr<Primitive> MakeAccelerator(
    const std::string &name,
    const std::vector<std::shared_ptr<Primitive>> &prims,
    const ParamSet &paramSet) {
    std::shared_ptr<Primitive> accel;
    if (name == "bvh")
        accel = CreateBVHAccelerator(prims, paramSet);
    else if (name == "kdtree")
        accel = CreateKdTreeAccelerator(prims, paramSet);
    else
        Warning("Accelerator \"%s\" unknown.", name.c_str());
    paramSet.ReportUnused();
    return accel;
}

Camera *MakeCamera(const std::string &name, const ParamSet &paramSet,
                   const TransformSet &cam2worldSet, Float transformStart,
                   Float transformEnd, Film *film) {
    Camera *camera = nullptr;
    MediumInterface mediumInterface = graphicsState.CreateMediumInterface();
    Assert(MaxTransforms == 2);
    Transform *cam2world[2];
    transformCache.Lookup(cam2worldSet[0], &cam2world[0], nullptr);
    transformCache.Lookup(cam2worldSet[1], &cam2world[1], nullptr);
    AnimatedTransform animatedCam2World(cam2world[0], transformStart,
                                        cam2world[1], transformEnd);
    if (name == "perspective")
        camera = CreatePerspectiveCamera(paramSet, animatedCam2World, film,
                                         mediumInterface.outside);
    else if (name == "orthographic")
        camera = CreateOrthographicCamera(paramSet, animatedCam2World, film,
                                          mediumInterface.outside);
    else if (name == "realistic")
        camera = CreateRealisticCamera(paramSet, animatedCam2World, film,
                                       mediumInterface.outside);
    else if (name == "environment")
        camera = CreateEnvironmentCamera(paramSet, animatedCam2World, film,
                                         mediumInterface.outside);
    else
        Warning("Camera \"%s\" unknown.", name.c_str());
    paramSet.ReportUnused();
    return camera;
}

std::shared_ptr<Sampler> MakeSampler(const std::string &name,
                                     const ParamSet &paramSet,
                                     const Film *film) {
    Sampler *sampler = nullptr;
    if (name == "lowdiscrepancy" || name == "02sequence")
        sampler = CreateZeroTwoSequenceSampler(paramSet);
    else if (name == "maxmindist")
        sampler = CreateMaxMinDistSampler(paramSet);
    else if (name == "halton")
        sampler = CreateHaltonSampler(paramSet, film->GetSampleBounds());
    else if (name == "sobol")
        sampler = CreateSobolSampler(paramSet, film->GetSampleBounds());
    else if (name == "random")
        sampler = CreateRandomSampler(paramSet);
    else if (name == "stratified")
        sampler = CreateStratifiedSampler(paramSet);
    else
        Warning("Sampler \"%s\" unknown.", name.c_str());
    paramSet.ReportUnused();
    return std::shared_ptr<Sampler>(sampler);
}

std::unique_ptr<Filter> MakeFilter(const std::string &name,
                                   const ParamSet &paramSet) {
    Filter *filter = nullptr;
    if (name == "box")
        filter = CreateBoxFilter(paramSet);
    else if (name == "gaussian")
        filter = CreateGaussianFilter(paramSet);
    else if (name == "mitchell")
        filter = CreateMitchellFilter(paramSet);
    else if (name == "sinc")
        filter = CreateSincFilter(paramSet);
    else if (name == "triangle")
        filter = CreateTriangleFilter(paramSet);
    else {
        Error("Filter \"%s\" unknown.", name.c_str());
        exit(1);
    }
    paramSet.ReportUnused();
    return std::unique_ptr<Filter>(filter);
}

Film *MakeFilm(const std::string &name, const ParamSet &paramSet,
               std::unique_ptr<Filter> filter) {
    Film *film = nullptr;
    if (name == "image")
        film = CreateFilm(paramSet, std::move(filter));
    else
        Warning("Film \"%s\" unknown.", name.c_str());
    paramSet.ReportUnused();
    return film;
}

// API Function Definitions
void pbrtInit(const Options &opt) {
    PbrtOptions = opt;
    // API Initialization
    if (currentApiState != APIState::Uninitialized)
        Error("pbrtInit() has already been called.");
    currentApiState = APIState::OptionsBlock;
    renderOptions.reset(new RenderOptions);
    graphicsState = GraphicsState();
    catIndentCount = 0;

    // General \pbrt Initialization
    SampledSpectrum::Init();
    InitProfiler();
}

void pbrtCleanup() {
    // API Cleanup
    if (currentApiState == APIState::Uninitialized)
        Error("pbrtCleanup() called without pbrtInit().");
    else if (currentApiState == APIState::WorldBlock)
        Error("pbrtCleanup() called while inside world block.");
    currentApiState = APIState::Uninitialized;
    TerminateWorkerThreads();
    renderOptions.reset(nullptr);
}

void pbrtIdentity() {
    VERIFY_INITIALIZED("Identity");
    FOR_ACTIVE_TRANSFORMS(curTransform[i] = Transform();)
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sIdentity\n", catIndentCount, "");
}

void pbrtTranslate(Float dx, Float dy, Float dz) {
    VERIFY_INITIALIZED("Translate");
    FOR_ACTIVE_TRANSFORMS(curTransform[i] = curTransform[i] *
                                            Translate(Vector3f(dx, dy, dz));)
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sTranslate %.10f %.10f %.10f\n", catIndentCount, "", dx, dy,
               dz);
}

void pbrtTransform(Float tr[16]) {
    VERIFY_INITIALIZED("Transform");
    FOR_ACTIVE_TRANSFORMS(
        curTransform[i] = Transform(Matrix4x4(
            tr[0], tr[4], tr[8], tr[12], tr[1], tr[5], tr[9], tr[13], tr[2],
            tr[6], tr[10], tr[14], tr[3], tr[7], tr[11], tr[15]));)
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sTransform [ ", catIndentCount, "");
        for (int i = 0; i < 16; ++i) printf("%.10f ", tr[i]);
        printf(" ]\n");
    }
}

void pbrtConcatTransform(Float tr[16]) {
    VERIFY_INITIALIZED("ConcatTransform");
    FOR_ACTIVE_TRANSFORMS(
        curTransform[i] =
            curTransform[i] *
            Transform(Matrix4x4(tr[0], tr[4], tr[8], tr[12], tr[1], tr[5],
                                tr[9], tr[13], tr[2], tr[6], tr[10], tr[14],
                                tr[3], tr[7], tr[11], tr[15]));)
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sConcatTransform [ ", catIndentCount, "");
        for (int i = 0; i < 16; ++i) printf("%.10f ", tr[i]);
        printf(" ]\n");
    }
}

void pbrtRotate(Float angle, Float dx, Float dy, Float dz) {
    VERIFY_INITIALIZED("Rotate");
    FOR_ACTIVE_TRANSFORMS(curTransform[i] =
                              curTransform[i] *
                              Rotate(angle, Vector3f(dx, dy, dz));)
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sRotate %.10f %.10f %.10f %.10f\n", catIndentCount, "", angle,
               dx, dy, dz);
}

void pbrtScale(Float sx, Float sy, Float sz) {
    VERIFY_INITIALIZED("Scale");
    FOR_ACTIVE_TRANSFORMS(curTransform[i] =
                              curTransform[i] * Scale(sx, sy, sz);)
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sScale %.10f %.10f %.10f\n", catIndentCount, "", sx, sy, sz);
}

void pbrtLookAt(Float ex, Float ey, Float ez, Float lx, Float ly, Float lz,
                Float ux, Float uy, Float uz) {
    VERIFY_INITIALIZED("LookAt");
    Transform lookAt =
        LookAt(Point3f(ex, ey, ez), Point3f(lx, ly, lz), Vector3f(ux, uy, uz));
    FOR_ACTIVE_TRANSFORMS(curTransform[i] = curTransform[i] * lookAt;);
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf(
            "%*sLookAt %.10f %.10f %.10f\n%*s%.10f %.10f %.10f\n"
            "%*s%.10f %.10f %.10f\n",
            catIndentCount, "", ex, ey, ez, catIndentCount + 8, "", lx, ly, lz,
            catIndentCount + 8, "", ux, uy, uz);
}

void pbrtCoordinateSystem(const std::string &name) {
    VERIFY_INITIALIZED("CoordinateSystem");
    namedCoordinateSystems[name] = curTransform;
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sCoordinateSystem \"%s\"\n", catIndentCount, "",
               name.c_str());
}

void pbrtCoordSysTransform(const std::string &name) {
    VERIFY_INITIALIZED("CoordSysTransform");
    if (namedCoordinateSystems.find(name) != namedCoordinateSystems.end())
        curTransform = namedCoordinateSystems[name];
    else
        Warning("Couldn't find named coordinate system \"%s\"", name.c_str());
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sCoordSysTransform \"%s\"\n", catIndentCount, "",
               name.c_str());
}

void pbrtActiveTransformAll() {
    activeTransformBits = AllTransformsBits;
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sActiveTransform All\n", catIndentCount, "");
}

void pbrtActiveTransformEndTime() {
    activeTransformBits = EndTransformBits;
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sActiveTransform EndTime\n", catIndentCount, "");
}

void pbrtActiveTransformStartTime() {
    activeTransformBits = StartTransformBits;
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sActiveTransform StartTime\n", catIndentCount, "");
}

void pbrtTransformTimes(Float start, Float end) {
    VERIFY_OPTIONS("TransformTimes");
    renderOptions->transformStartTime = start;
    renderOptions->transformEndTime = end;
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sTransformTimes %.10f %.10f\n", catIndentCount, "", start,
               end);
}

void pbrtPixelFilter(const std::string &name, const ParamSet &params) {
    VERIFY_OPTIONS("PixelFilter");
    renderOptions->FilterName = name;
    renderOptions->FilterParams = params;
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sPixelFilter \"%s\" ", catIndentCount, "", name.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtFilm(const std::string &type, const ParamSet &params) {
    VERIFY_OPTIONS("Film");
    renderOptions->FilmParams = params;
    renderOptions->FilmName = type;
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sFilm \"%s\" ", catIndentCount, "", type.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtSampler(const std::string &name, const ParamSet &params) {
    VERIFY_OPTIONS("Sampler");
    renderOptions->SamplerName = name;
    renderOptions->SamplerParams = params;
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sSampler \"%s\" ", catIndentCount, "", name.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtAccelerator(const std::string &name, const ParamSet &params) {
    VERIFY_OPTIONS("Accelerator");
    renderOptions->AcceleratorName = name;
    renderOptions->AcceleratorParams = params;
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sAccelerator \"%s\" ", catIndentCount, "", name.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtIntegrator(const std::string &name, const ParamSet &params) {
    VERIFY_OPTIONS("Integrator");
    renderOptions->IntegratorName = name;
    renderOptions->IntegratorParams = params;
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sIntegrator \"%s\" ", catIndentCount, "", name.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtCamera(const std::string &name, const ParamSet &params) {
    VERIFY_OPTIONS("Camera");
    renderOptions->CameraName = name;
    renderOptions->CameraParams = params;
    renderOptions->CameraToWorld = Inverse(curTransform);
    namedCoordinateSystems["camera"] = renderOptions->CameraToWorld;
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sCamera \"%s\" ", catIndentCount, "", name.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtMakeNamedMedium(const std::string &name, const ParamSet &params) {
    VERIFY_INITIALIZED("MakeNamedMedium");
    WARN_IF_ANIMATED_TRANSFORM("MakeNamedMedium");
    std::string type = params.FindOneString("type", "");
    if (type == "")
        Error("No parameter string \"type\" found in MakeNamedMedium");
    else {
        std::shared_ptr<Medium> medium =
            MakeMedium(type, params, curTransform[0]);
        if (medium) renderOptions->namedMedia[name] = medium;
    }
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sMakeNamedMedium \"%s\" ", catIndentCount, "", name.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtMediumInterface(const std::string &insideName,
                         const std::string &outsideName) {
    VERIFY_INITIALIZED("MediumInterface");
    graphicsState.currentInsideMedium = insideName;
    graphicsState.currentOutsideMedium = outsideName;
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sMediumInterface \"%s\" \"%s\"\n", catIndentCount, "",
               insideName.c_str(), outsideName.c_str());
}

void pbrtWorldBegin() {
    VERIFY_OPTIONS("WorldBegin");
    currentApiState = APIState::WorldBlock;
    for (int i = 0; i < MaxTransforms; ++i) curTransform[i] = Transform();
    activeTransformBits = AllTransformsBits;
    namedCoordinateSystems["world"] = curTransform;
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf(
            "\n#############################################\nWorldBegin\n\n");
}

void pbrtAttributeBegin() {
    VERIFY_WORLD("AttributeBegin");
    pushedGraphicsStates.push_back(graphicsState);
    pushedTransforms.push_back(curTransform);
    pushedActiveTransformBits.push_back(activeTransformBits);
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("\n%*sAttributeBegin\n", catIndentCount, "");
        catIndentCount += 4;
    }
}

void pbrtAttributeEnd() {
    VERIFY_WORLD("AttributeEnd");
    if (!pushedGraphicsStates.size()) {
        Error(
            "Unmatched pbrtAttributeEnd() encountered. "
            "Ignoring it.");
        return;
    }
    graphicsState = pushedGraphicsStates.back();
    pushedGraphicsStates.pop_back();
    curTransform = pushedTransforms.back();
    pushedTransforms.pop_back();
    activeTransformBits = pushedActiveTransformBits.back();
    pushedActiveTransformBits.pop_back();
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        catIndentCount -= 4;
        printf("%*sAttributeEnd\n", catIndentCount, "");
    }
}

void pbrtTransformBegin() {
    VERIFY_WORLD("TransformBegin");
    pushedTransforms.push_back(curTransform);
    pushedActiveTransformBits.push_back(activeTransformBits);
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sTransformBegin\n", catIndentCount, "");
        catIndentCount += 4;
    }
}

void pbrtTransformEnd() {
    VERIFY_WORLD("TransformEnd");
    if (!pushedTransforms.size()) {
        Error(
            "Unmatched pbrtTransformEnd() encountered. "
            "Ignoring it.");
        return;
    }
    curTransform = pushedTransforms.back();
    pushedTransforms.pop_back();
    activeTransformBits = pushedActiveTransformBits.back();
    pushedActiveTransformBits.pop_back();
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        catIndentCount -= 4;
        printf("%*sTransformEnd\n", catIndentCount, "");
    }
}

void pbrtTexture(const std::string &name, const std::string &type,
                 const std::string &texname, const ParamSet &params) {
    VERIFY_WORLD("Texture");
    TextureParams tp(params, params, graphicsState.floatTextures,
                     graphicsState.spectrumTextures);
    if (type == "float") {
        // Create _Float_ texture and store in _floatTextures_
        if (graphicsState.floatTextures.find(name) !=
            graphicsState.floatTextures.end())
            Info("Texture \"%s\" being redefined", name.c_str());
        WARN_IF_ANIMATED_TRANSFORM("Texture");
        std::shared_ptr<Texture<Float>> ft =
            MakeFloatTexture(texname, curTransform[0], tp);
        if (ft) graphicsState.floatTextures[name] = ft;
    } else if (type == "color" || type == "spectrum") {
        // Create _color_ texture and store in _spectrumTextures_
        if (graphicsState.spectrumTextures.find(name) !=
            graphicsState.spectrumTextures.end())
            Info("Texture \"%s\" being redefined", name.c_str());
        WARN_IF_ANIMATED_TRANSFORM("Texture");
        std::shared_ptr<Texture<Spectrum>> st =
            MakeSpectrumTexture(texname, curTransform[0], tp);
        if (st) graphicsState.spectrumTextures[name] = st;
    } else
        Error("Texture type \"%s\" unknown.", type.c_str());
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sTexture \"%s\" \"%s\" \"%s\" ", catIndentCount, "",
               name.c_str(), type.c_str(), texname.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtMaterial(const std::string &name, const ParamSet &params) {
    VERIFY_WORLD("Material");
    graphicsState.material = name;
    graphicsState.materialParams = params;
    graphicsState.currentNamedMaterial = "";
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sMaterial \"%s\" ", catIndentCount, "", name.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtMakeNamedMaterial(const std::string &name, const ParamSet &params) {
    VERIFY_WORLD("MakeNamedMaterial");
    // error checking, warning if replace, what to use for transform?
    ParamSet emptyParams;
    TextureParams mp(params, emptyParams, graphicsState.floatTextures,
                     graphicsState.spectrumTextures);
    std::string matName = mp.FindString("type");
    WARN_IF_ANIMATED_TRANSFORM("MakeNamedMaterial");
    if (matName == "")
        Error("No parameter string \"type\" found in MakeNamedMaterial");
    else {
        std::shared_ptr<Material> mtl = MakeMaterial(matName, mp);
        if (mtl) graphicsState.namedMaterials[name] = mtl;
    }
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sMakeNamedMaterial \"%s\" ", catIndentCount, "",
               name.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtNamedMaterial(const std::string &name) {
    VERIFY_WORLD("NamedMaterial");
    graphicsState.currentNamedMaterial = name;
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sNamedMaterial \"%s\"\n", catIndentCount, "", name.c_str());
}

void pbrtLightSource(const std::string &name, const ParamSet &params) {
    VERIFY_WORLD("LightSource");
    WARN_IF_ANIMATED_TRANSFORM("LightSource");
    MediumInterface mi = graphicsState.CreateMediumInterface();
    std::shared_ptr<Light> lt = MakeLight(name, params, curTransform[0], mi);
    if (!lt)
        Error("LightSource: light type \"%s\" unknown.", name.c_str());
    else
        renderOptions->lights.push_back(lt);
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sLightSource \"%s\" ", catIndentCount, "", name.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtAreaLightSource(const std::string &name, const ParamSet &params) {
    VERIFY_WORLD("AreaLightSource");
    graphicsState.areaLight = name;
    graphicsState.areaLightParams = params;
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sAreaLightSource \"%s\" ", catIndentCount, "", name.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }
}

void pbrtShape(const std::string &name, const ParamSet &params) {
    VERIFY_WORLD("Shape");
    std::vector<std::shared_ptr<Primitive>> prims;
    std::vector<std::shared_ptr<AreaLight>> areaLights;
    if (PbrtOptions.cat || (PbrtOptions.toPly && name != "trianglemesh")) {
        printf("%*sShape \"%s\" ", catIndentCount, "", name.c_str());
        params.Print(catIndentCount);
        printf("\n");
    }

    if (!curTransform.IsAnimated()) {
        // Initialize _prims_ and _areaLights_ for static shape

        // Create shapes for shape _name_
        Transform *ObjToWorld, *WorldToObj;
        transformCache.Lookup(curTransform[0], &ObjToWorld, &WorldToObj);
        std::vector<std::shared_ptr<Shape>> shapes =
            MakeShapes(name, ObjToWorld, WorldToObj,
                       graphicsState.reverseOrientation, params);
        if (shapes.size() == 0) return;
        std::shared_ptr<Material> mtl = graphicsState.CreateMaterial(params);
        params.ReportUnused();
        MediumInterface mi = graphicsState.CreateMediumInterface();
        for (auto s : shapes) {
            // Possibly create area light for shape
            std::shared_ptr<AreaLight> area;
            if (graphicsState.areaLight != "") {
                area = MakeAreaLight(graphicsState.areaLight, curTransform[0],
                                     mi, graphicsState.areaLightParams, s);
                areaLights.push_back(area);
            }
            prims.push_back(
                std::make_shared<GeometricPrimitive>(s, mtl, area, mi));
        }
    } else {
        // Initialize _prims_ and _areaLights_ for animated shape

        // Create initial shape or shapes for animated shape
        if (graphicsState.areaLight != "")
            Warning(
                "Ignoring currently set area light when creating "
                "animated shape");
        Transform *identity;
        transformCache.Lookup(Transform(), &identity, nullptr);
        std::vector<std::shared_ptr<Shape>> shapes = MakeShapes(
            name, identity, identity, graphicsState.reverseOrientation, params);
        if (shapes.size() == 0) return;

        // Create _GeometricPrimitive_(s) for animated shape
        std::shared_ptr<Material> mtl = graphicsState.CreateMaterial(params);
        params.ReportUnused();
        MediumInterface mi = graphicsState.CreateMediumInterface();
        for (auto s : shapes)
            prims.push_back(
                std::make_shared<GeometricPrimitive>(s, mtl, nullptr, mi));

        // Create single _TransformedPrimitive_ for _prims_

        // Get _animatedObjectToWorld_ transform for shape
        Assert(MaxTransforms == 2);
        Transform *ObjToWorld[2];
        transformCache.Lookup(curTransform[0], &ObjToWorld[0], nullptr);
        transformCache.Lookup(curTransform[1], &ObjToWorld[1], nullptr);
        AnimatedTransform animatedObjectToWorld(
            ObjToWorld[0], renderOptions->transformStartTime, ObjToWorld[1],
            renderOptions->transformEndTime);
        if (prims.size() > 1) {
            std::shared_ptr<Primitive> bvh = std::make_shared<BVHAccel>(prims);
            prims.clear();
            prims.push_back(bvh);
        }
        prims[0] = std::make_shared<TransformedPrimitive>(
            prims[0], animatedObjectToWorld);
    }
    // Add _prims_ and _areaLights_ to scene or current instance
    if (renderOptions->currentInstance) {
        if (areaLights.size())
            Warning("Area lights not supported with object instancing");
        renderOptions->currentInstance->insert(
            renderOptions->currentInstance->end(), prims.begin(), prims.end());
    } else {
        renderOptions->primitives.insert(renderOptions->primitives.end(),
                                         prims.begin(), prims.end());
        if (areaLights.size())
            renderOptions->lights.insert(renderOptions->lights.end(),
                                         areaLights.begin(), areaLights.end());
    }
}

std::shared_ptr<Material> GraphicsState::CreateMaterial(
    const ParamSet &params) {
    TextureParams mp(params, materialParams, floatTextures, spectrumTextures);
    std::shared_ptr<Material> mtl;
    if (currentNamedMaterial != "" &&
        namedMaterials.find(currentNamedMaterial) != namedMaterials.end())
        mtl = namedMaterials[graphicsState.currentNamedMaterial];
    if (!mtl) mtl = MakeMaterial(material, mp);
    if (!mtl && material != "" && material != "none")
        mtl = MakeMaterial("matte", mp);
    return mtl;
}

MediumInterface GraphicsState::CreateMediumInterface() {
    MediumInterface m;
    if (currentInsideMedium != "") {
        if (renderOptions->namedMedia.find(currentInsideMedium) !=
            renderOptions->namedMedia.end())
            m.inside = renderOptions->namedMedia[currentInsideMedium].get();
        else
            Error("Named medium \"%s\" undefined.",
                  currentInsideMedium.c_str());
    }
    if (currentOutsideMedium != "") {
        if (renderOptions->namedMedia.find(currentOutsideMedium) !=
            renderOptions->namedMedia.end())
            m.outside = renderOptions->namedMedia[currentOutsideMedium].get();
        else
            Error("Named medium \"%s\" undefined.",
                  currentOutsideMedium.c_str());
    }
    return m;
}

void pbrtReverseOrientation() {
    VERIFY_WORLD("ReverseOrientation");
    graphicsState.reverseOrientation = !graphicsState.reverseOrientation;
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sReverseOrientation\n", catIndentCount, "");
}

void pbrtObjectBegin(const std::string &name) {
    VERIFY_WORLD("ObjectBegin");
    pbrtAttributeBegin();
    if (renderOptions->currentInstance)
        Error("ObjectBegin called inside of instance definition");
    renderOptions->instances[name] = std::vector<std::shared_ptr<Primitive>>();
    renderOptions->currentInstance = &renderOptions->instances[name];
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sObjectBegin \"%s\"\n", catIndentCount, "", name.c_str());
}

STAT_COUNTER("Scene/Object instances created", nObjectInstancesCreated);

void pbrtObjectEnd() {
    VERIFY_WORLD("ObjectEnd");
    if (!renderOptions->currentInstance)
        Error("ObjectEnd called outside of instance definition");
    renderOptions->currentInstance = nullptr;
    pbrtAttributeEnd();
    ++nObjectInstancesCreated;
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sObjectEnd\n", catIndentCount, "");
}

STAT_COUNTER("Scene/Object instances used", nObjectInstancesUsed);

void pbrtObjectInstance(const std::string &name) {
    VERIFY_WORLD("ObjectInstance");
    // Perform object instance error checking
    if (PbrtOptions.cat || PbrtOptions.toPly)
        printf("%*sObjectInstance \"%s\"\n", catIndentCount, "", name.c_str());
    if (renderOptions->currentInstance) {
        Error("ObjectInstance can't be called inside instance definition");
        return;
    }
    if (renderOptions->instances.find(name) == renderOptions->instances.end()) {
        Error("Unable to find instance named \"%s\"", name.c_str());
        return;
    }
    std::vector<std::shared_ptr<Primitive>> &in =
        renderOptions->instances[name];
    if (in.size() == 0) return;
    ++nObjectInstancesUsed;
    if (in.size() > 1) {
        // Create aggregate for instance _Primitive_s
        std::shared_ptr<Primitive> accel(
            MakeAccelerator(renderOptions->AcceleratorName, in,
                            renderOptions->AcceleratorParams));
        if (!accel) accel = std::make_shared<BVHAccel>(in);
        in.erase(in.begin(), in.end());
        in.push_back(accel);
    }
    Assert(MaxTransforms == 2);
    // Create _animatedInstanceToWorld_ transform for instance
    Transform *InstanceToWorld[2];
    transformCache.Lookup(curTransform[0], &InstanceToWorld[0], nullptr);
    transformCache.Lookup(curTransform[1], &InstanceToWorld[1], nullptr);
    AnimatedTransform animatedInstanceToWorld(
        InstanceToWorld[0], renderOptions->transformStartTime, InstanceToWorld[1],
        renderOptions->transformEndTime);
    std::shared_ptr<Primitive> prim(
        std::make_shared<TransformedPrimitive>(in[0], animatedInstanceToWorld));
    renderOptions->primitives.push_back(prim);
}

void pbrtWorldEnd() {
    VERIFY_WORLD("WorldEnd");
    // Ensure there are no pushed graphics states
    while (pushedGraphicsStates.size()) {
        Warning("Missing end to pbrtAttributeBegin()");
        pushedGraphicsStates.pop_back();
        pushedTransforms.pop_back();
    }
    while (pushedTransforms.size()) {
        Warning("Missing end to pbrtTransformBegin()");
        pushedTransforms.pop_back();
    }

    // Create scene and render
    if (PbrtOptions.cat || PbrtOptions.toPly) {
        printf("%*sWorldEnd\n", catIndentCount, "");
    } else {
        std::unique_ptr<Integrator> integrator(renderOptions->MakeIntegrator());
        std::unique_ptr<Scene> scene(renderOptions->MakeScene());
        if (scene && integrator) integrator->Render(*scene);
        TerminateWorkerThreads();
    }

    // Clean up after rendering
    graphicsState = GraphicsState();
    transformCache.Clear();
    currentApiState = APIState::OptionsBlock;
    ReportThreadStats();
    if (!PbrtOptions.quiet && !PbrtOptions.cat && !PbrtOptions.toPly) {
        PrintStats(stdout);
        ReportProfilerResults(stdout);
    }
    for (int i = 0; i < MaxTransforms; ++i) curTransform[i] = Transform();
    activeTransformBits = AllTransformsBits;
    namedCoordinateSystems.erase(namedCoordinateSystems.begin(),
                                 namedCoordinateSystems.end());
    ImageTexture<Float, Float>::ClearCache();
    ImageTexture<RGBSpectrum, Spectrum>::ClearCache();
}

Scene *RenderOptions::MakeScene() {
    std::shared_ptr<Primitive> accelerator =
        MakeAccelerator(AcceleratorName, primitives, AcceleratorParams);
    if (!accelerator) accelerator = std::make_shared<BVHAccel>(primitives);
    Scene *scene = new Scene(accelerator, lights);
    // Erase primitives and lights from _RenderOptions_
    primitives.erase(primitives.begin(), primitives.end());
    lights.erase(lights.begin(), lights.end());
    return scene;
}

Integrator *RenderOptions::MakeIntegrator() const {
    std::shared_ptr<const Camera> camera(MakeCamera());
    if (!camera) {
        Error("Unable to create camera");
        return nullptr;
    }

    std::shared_ptr<Sampler> sampler =
        MakeSampler(SamplerName, SamplerParams, camera->film);
    if (!sampler) {
        Error("Unable to create sampler.");
        return nullptr;
    }

    Integrator *integrator = nullptr;
    if (IntegratorName == "whitted")
        integrator = CreateWhittedIntegrator(IntegratorParams, sampler, camera);
    else if (IntegratorName == "directlighting")
        integrator =
            CreateDirectLightingIntegrator(IntegratorParams, sampler, camera);
    else if (IntegratorName == "path")
        integrator = CreatePathIntegrator(IntegratorParams, sampler, camera);
    else if (IntegratorName == "volpath")
        integrator = CreateVolPathIntegrator(IntegratorParams, sampler, camera);
    else if (IntegratorName == "bdpt") {
        integrator = CreateBDPTIntegrator(IntegratorParams, sampler, camera);
    } else if (IntegratorName == "mlt") {
        integrator = CreateMLTIntegrator(IntegratorParams, camera);
    } else if (IntegratorName == "sppm") {
        integrator = CreateSPPMIntegrator(IntegratorParams, camera);
    } else {
        Error("Integrator \"%s\" unknown.", IntegratorName.c_str());
        return nullptr;
    }

    IntegratorParams.ReportUnused();
    // Warn if no light sources are defined
    if (lights.size() == 0)
        Warning(
            "No light sources defined in scene; "
            "rendering a black image.");
    return integrator;
}

Camera *RenderOptions::MakeCamera() const {
    std::unique_ptr<Filter> filter = MakeFilter(FilterName, FilterParams);
    Film *film = MakeFilm(FilmName, FilmParams, std::move(filter));
    if (!film) {
        Error("Unable to create film.");
        return nullptr;
    }
    Camera *camera = ::MakeCamera(CameraName, CameraParams, CameraToWorld,
                                  renderOptions->transformStartTime,
                                  renderOptions->transformEndTime, film);
    return camera;
}


text:
#include "condor_common.h"
#include "condor_classad.h"
#include "condor_version.h"
#include "condor_debug.h"
#include "condor_config.h"
#include "condor_secman.h"
#include "command_strings.h"
#include "daemon.h"
#include "safe_sock.h"
#include "condor_distribution.h"
#include "daemon_list.h"
#include "dc_collector.h"
#include "my_hostname.h"

using namespace std;

void
usage( char *cmd )
{
	fprintf(stderr,"Usage: %s [options] TOKEN [TOKEN [TOKEN [...]]]\n",cmd);
	fprintf(stderr,"\nwhere TOKEN is ( ALL | <authorization-level> | <command-name> | <command-int> )\n\n");
	fprintf(stderr,"general options:\n");
	fprintf(stderr,"    -config <filename>              Add configuration from specified file\n");
	fprintf(stderr,"    -debug                          Show extra debugging info\n");
	fprintf(stderr,"    -version                        Display Condor version\n");
	fprintf(stderr,"    -help                           Display options\n");
	fprintf(stderr,"\nspecifying target options:\n");
	fprintf(stderr,"    -address <sinful>               Use this sinful string\n");
	fprintf(stderr,"    -pool    <host>                 Query this collector\n");
	fprintf(stderr,"    -name    <name>                 Find a daemon with this name\n");
	fprintf(stderr,"    -type    <subsystem>            Type of daemon to contact (default: SCHEDD)\n");
	fprintf(stderr,"\noutput options (specify only one):\n");
	fprintf(stderr,"    -quiet                          No output, only sets status\n");
	fprintf(stderr,"    -table                          Print one result per line\n");
	fprintf(stderr,"    -verbose                        Print all available information\n");
	fprintf(stderr,"\nExample:\n    %s -addr \"<127.0.0.1:9618>\" -table READ WRITE DAEMON\n\n",cmd);
}

void
version()
{
	printf( "%s\n%s\n", CondorVersion(), CondorPlatform() );
}

void process_err_stack(CondorError *errstack) {

	printf("%s\n", errstack->getFullText(true).c_str());

}

void print_useful_info_1(bool rv, MyString name, Sock*, ClassAd *ad, ClassAd *authz_ad, CondorError *) {
	MyString  val;

	if(!rv) {
		printf("%s failed!  Use -verbose for more information.\n", name.Value());
		return;
	}

	printf("%s using (", name.Value());

	ad->LookupString("encryption", val);
	if (strcasecmp(val.Value(), "no") == 0) {
		printf("no encryption");
	} else {
		ad->LookupString("cryptomethods", val);
		printf("%s", val.Value());
	}

	printf(", ");

	ad->LookupString("integrity", val);
	if (strcasecmp(val.Value(), "no") == 0) {
		printf("no integrity");
	} else {
		printf("MD5");
	}

	printf(", and ");

	ad->LookupString("authentication", val);
	if (strcasecmp(val.Value(), "no") == 0) {
		printf("no authentication");
	} else {
		ad->LookupString("authmethods", val);
		printf("%s", val.Value());
	}

	printf(") ");

	bool bval;
	authz_ad->LookupBool(ATTR_SEC_AUTHORIZATION_SUCCEEDED, bval);
	printf(bval ? "succeeded" : "failed");

	printf(" as ");

	ad->LookupString("myremoteusername", val);
	printf("%s", val.Value());

	printf ("\n");
}

void print_useful_info_2(bool rv, int cmd, MyString name, Sock*, ClassAd *ad, ClassAd *authz_ad, CondorError *errstack) {
	MyString  val;

	if(!rv) {
		printf("%s failed!\n", name.Value());
		process_err_stack(errstack);
		printf("\n");
		return;
	}

	ad->LookupString("remoteversion", val);
	printf("Remote Version:              %s\n", val.Value());
	val = CondorVersion();
	printf("Local  Version:              %s\n", val.Value());

	ad->LookupString("sid", val);
	printf("Session ID:                  %s\n", val.Value());
	printf("Instruction:                 %s\n", name.Value());
	printf("Command:                     %i\n", cmd);

	ad->LookupString("encryption", val);
	if (strcasecmp(val.Value(), "no") == 0) {
		printf("Encryption:                  none\n");
	} else {
		ad->LookupString("cryptomethods", val);
		printf("Encryption:                  %s\n", val.Value());
	}

	ad->LookupString("integrity", val);
	if (strcasecmp(val.Value(), "no") == 0) {
		printf("Integrity:                   none\n");
	} else {
		printf("Integrity:                   MD5\n");
	}

	ad->LookupString("authentication", val);
	if (strcasecmp(val.Value(), "no") == 0) {
		printf("Authentication:              none\n");
	} else {
		ad->LookupString("authmethods", val);
		printf("Authenticated using:         %s\n", val.Value());
		ad->LookupString("authmethodslist", val);
		printf("All authentication methods:  %s\n", val.Value());
	}

	ad->LookupString("myremoteusername", val);
	printf("Remote Mapping:              %s\n", val.Value());

	bool bval;
	authz_ad->LookupBool(ATTR_SEC_AUTHORIZATION_SUCCEEDED, bval);
	printf("Authorized:                  %s\n", (bval ? "TRUE" : "FALSE"));

	printf ("\n");

	if (errstack->getFullText() != "") {
		printf ("Information about authentication methods that were attempted but failed:\n");
		process_err_stack(errstack);
		printf ("\n");
	}

}

void print_useful_info_10(bool rv, MyString name, Sock*, ClassAd *ad, ClassAd *authz_ad, CondorError *) {
	MyString  val;

	printf("%20s", name.Value());

	if(!rv) {
		printf ("           FAIL       FAIL      FAIL     FAIL FAIL  (use -verbose for more info)\n");
		return;
	}

	ad->LookupString("authentication", val);
	if (strcasecmp(val.Value(), "no") == 0) {
		val = "none";
	} else {
		ad->LookupString("authmethods", val);
	}
	printf("%15s", val.Value());

	ad->LookupString("encryption", val);
	if (strcasecmp(val.Value(), "no") == 0) {
		val = "none";
	} else {
		ad->LookupString("cryptomethods", val);
	}
	printf("%11s", val.Value());

	ad->LookupString("integrity", val);
	if (strcasecmp(val.Value(), "no") == 0) {
		val = "none";
	} else {
		val = "MD5";
	}
	printf("%10s", val.Value());

	bool bval;
	authz_ad->LookupBool(ATTR_SEC_AUTHORIZATION_SUCCEEDED, bval);
	printf(bval ? "    ALLOW " : "     DENY ");

	ad->LookupString("myremoteusername", val);
	printf("%s", val.Value());

	printf("\n");
}

void print_info(bool rv, const char * addr, Sock* s, MyString name, int cmd, ClassAd *authz_ad, CondorError *errstack, int output_mode) {
	MyString cmd_map_ent;
	cmd_map_ent.formatstr ("{%s,<%i>}", addr, cmd);

	MyString session_id;
	KeyCacheEntry *k = NULL;
	ClassAd *policy = NULL;
	int ret = 0;

	if(rv) {
		// IMPORTANT: this hashtable returns 0 on success!
		ret = (SecMan::command_map).lookup(cmd_map_ent, session_id);
		if (ret) {
			printf("no cmd map!\n");
			return;
		}

		// IMPORTANT: this hashtable returns 1 on success!
		ret = (SecMan::session_cache).lookup(session_id.Value(), k);
		if (!ret) {
			printf("no session!\n");
			return;
		}

		policy = k->policy();
	}

	if (output_mode == 0) {
		// print nothing!!
	} else if (output_mode == 1) {
		print_useful_info_1(rv, name, s, policy, authz_ad, errstack);
	} else if (output_mode == 2) {
		print_useful_info_2(rv, cmd, name, s, policy, authz_ad, errstack);
	} else if (output_mode == 10) {
		print_useful_info_10(rv, name, s, policy, authz_ad, errstack);
	}
}

int getSomeCommandFromString ( const char * cmdstring ) {

	int res = -1;

	res = getPermissionFromString( cmdstring );
	if (res != -1) {
		res = getSampleCommand( res );
		dprintf( D_ALWAYS, "recognized %s as authorization level, using command %i.\n", cmdstring, res );
		return res;
	}

	res = getCommandNum( cmdstring );
	if (res != -1) {
		dprintf( D_ALWAYS, "recognized %s as command name, using command %i.\n", cmdstring, res );
		return res;
	}

	res = atoi ( cmdstring );
	if (res > 0 || (strcmp("0", cmdstring) == 0)) {
		char compare_conversion[20];
		sprintf(compare_conversion, "%i", res);
		if (strcmp(cmdstring, compare_conversion) == 0) {
			dprintf( D_ALWAYS, "recognized %i as command number.\n", res );
			return res;
		}
	}

	return -1;

}

bool do_item(Daemon* d, MyString name, int num, int output_mode) {

	CondorError errstack;
	ClassAd authz_ad;
	bool sc_success;
	ReliSock *sock = NULL;
	bool fn_success = false;

	sock = (ReliSock*) d->makeConnectedSocket( Stream::reli_sock, 0, 0, &errstack );
	if (sock) {

		sc_success = d->startSubCommand(DC_SEC_QUERY, num, sock, 0, &errstack);
		if (sc_success) {

			sock->decode();
			if (getClassAd(sock, authz_ad) &&
				sock->end_of_message()) {
				fn_success = true;
			}
		}
		print_info(fn_success, sock->get_connect_addr(), sock, name, num, &authz_ad, &errstack, output_mode);
	} else {
		// we know that d->addr() is not null because we checked before
		// calling do_item.  but i'll be paranoid and check again.
		fprintf(stderr, "ERROR: failed to make connection to %s\n", d->addr()?d->addr():"(null)");
	}

	return fn_success;

}

int main( int argc, char *argv[] )
{
	char *pool=0;
	char *name=0;
	char *address=0;
	char *optional_config=0;
	int  output_mode = -1;
	daemon_t dtype = DT_NONE;
	int i;

	ExtArray<MyString> worklist_name;
	ExtArray<int> worklist_number;
	int worklist_count = 0;
	Daemon * daemon = NULL;

	myDistro->Init( argc, argv );
	config();

	for( i=1; i<argc; i++ ) {
		if(!strncmp(argv[i],"-help",strlen(argv[i]))) {
			usage(argv[0]);
			exit(0);
		} else if(!strncmp(argv[i],"-quiet",strlen(argv[i]))) {
			if(output_mode == -1) {
				output_mode = 0;
			} else {
				fprintf(stderr,"ERROR: only one output mode may be specified.\n\n");
				usage(argv[0]);
				exit(1);
			}
		} else if(!strncmp(argv[i],"-table",strlen(argv[i]))) {
			if(output_mode == -1) {
				output_mode = 10;
			} else {
				fprintf(stderr,"ERROR: only one output mode may be specified.\n\n");
				usage(argv[0]);
				exit(1);
			}
		} else if(!strncmp(argv[i],"-verbose",strlen(argv[i]))) {
			if(output_mode == -1) {
				output_mode = 2;
			} else {
				fprintf(stderr,"ERROR: only one output mode may be specified.\n\n");
				usage(argv[0]);
				exit(1);
			}
		} else if(!strncmp(argv[i],"-config",strlen(argv[i]))) {
			i++;
			if(!argv[i]) {
				fprintf(stderr,"ERROR: -config requires an argument.\n\n");
				usage(argv[0]);
				exit(1);
			}
			optional_config = argv[i];
		} else if(!strncmp(argv[i],"-pool",strlen(argv[i]))) {
			i++;
			if(!argv[i]) {
				fprintf(stderr,"ERROR: -pool requires an argument.\n\n");
				usage(argv[0]);
				exit(1);
			}
			if(address) {
				fprintf(stderr,"ERROR: -address cannot be used with -pool or -name.\n\n");
				usage(argv[0]);
				exit(1);
			}
			pool = argv[i];
		} else if(!strncmp(argv[i],"-name",strlen(argv[i]))) {
			i++;
			if(!argv[i]) {
				fprintf(stderr,"ERROR: -name requires an argument.\n\n");
				usage(argv[0]);
				exit(1);
			}
			if(address) {
				fprintf(stderr,"ERROR: -address cannot be used with -pool or -name.\n\n");
				usage(argv[0]);
				exit(1);
			}
			name = argv[i];
		} else if(!strncmp(argv[i],"-type",strlen(argv[i]))) {
			i++;
			if(!argv[i]) {
				fprintf(stderr,"ERROR: -type requires an argument.\n\n");
				usage(argv[0]);
				exit(1);
			}
			dtype = stringToDaemonType(argv[i]);
			if( dtype == DT_NONE) {
				fprintf(stderr,"ERROR: unrecognized daemon type: %s\n\n", argv[i]);
				usage(argv[0]);
				exit(1);
			}
		} else if(!strncmp(argv[i],"-address",strlen(argv[i]))) {
			i++;
			if(!argv[i]) {
				fprintf(stderr,"ERROR: -address requires an argument.\n\n");
				usage(argv[0]);
				exit(1);
			}
			if(pool || name) {
				fprintf(stderr,"ERROR: -address cannot be used with -pool or -name.\n\n");
				usage(argv[0]);
				exit(1);
			}
			address = argv[i];
		} else if(!strcmp(argv[i],"-version")) {
			version();
			exit(0);
		} else if(!strcmp(argv[i],"-debug")) {
				// dprintf to console
			dprintf_set_tool_debug("TOOL", 0);
		} else if(argv[i][0]!='-' || !strcmp(argv[i],"-")) {
			// a special case
			if(strcasecmp("ALL", argv[i]) == 0) {
				worklist_name[worklist_count++] = "ALLOW";
				worklist_name[worklist_count++] = "READ";
				worklist_name[worklist_count++] = "WRITE";
				worklist_name[worklist_count++] = "NEGOTIATOR";
				worklist_name[worklist_count++] = "ADMINISTRATOR";
				worklist_name[worklist_count++] = "OWNER";
				worklist_name[worklist_count++] = "CONFIG";
				worklist_name[worklist_count++] = "DAEMON";
				worklist_name[worklist_count++] = "ADVERTISE_STARTD";
				worklist_name[worklist_count++] = "ADVERTISE_SCHEDD";
				worklist_name[worklist_count++] = "ADVERTISE_MASTER";
			} else {
				// an individual item to act on
				worklist_name[worklist_count++] = argv[i];
			}
		} else {
			fprintf(stderr,"ERROR: Unknown argument: %s\n\n",argv[i]);
			usage(argv[0]);
			exit(1);
		}
	}

	// 1 (normal) is the default
	if(output_mode == -1) {
		output_mode = 1;
	}

	// use some default
	if(worklist_count == 0) {
		if(output_mode) {
			fprintf( stderr, "WARNING: Missing <authz-level | command-name | command-int> argument, defaulting to DC_NOP\n");
		}
		worklist_name[0] = "DC_NOP";
		worklist_count++;
	}

	// convert each item
	bool all_okay = true;
	for (i=0; i<worklist_count; i++) {
		int c = getSomeCommandFromString(worklist_name[i].Value());
		if (c == -1) {
			if(output_mode) {
				fprintf(stderr, "ERROR: Could not understand TOKEN \"%s\".\n", worklist_name[i].Value());
			}
			all_okay = false;
		} else {
			worklist_number[i] = c;
		}
	}
	if (!all_okay) {
		exit(1);
	}

	//
	// LETS GET TO WORK!
	//

	if(dtype == DT_NONE) {
		dtype = DT_SCHEDD;
	}

	if(address) {
		daemon = new Daemon( DT_ANY, address, 0 );
	} else {
		if (pool) {
			DCCollector col( pool );
			if( ! col.addr() ) {
				fprintf( stderr, "ERROR: %s\n", col.error() );
				exit(1);
			}
			daemon = new Daemon( dtype, name, col.addr() );
		} else {
			daemon = new Daemon( dtype, name );
		}
	}

	if (!(daemon->locate())) {
		if(output_mode) {
			fprintf(stderr, "ERROR: couldn't locate %s!\n", address?address:name);
		}
		delete daemon;
		exit(1);
	}

	// add a check for address being null even though locate() succeeded.
	// this happens if the address doesn't parse.
	if(!daemon->addr()) {
		fprintf(stderr, "ERROR: unable to parse sinful string: %s\n", address);
		delete daemon;
		exit(1);
	}

	// do we need to print headers?
	if(output_mode == 10) {
		printf ("         Instruction Authentication Encryption Integrity Decision Identity\n");
	}

	// load the supplied config if specified
	if (optional_config) {
		process_config_source( optional_config, 0, "special config", NULL, true);
		//process_config_source( optional_config, 0, "special config", get_local_hostname().Value(), true);

		// ZKM TODO FIXME check the success of loading the config
	}

	all_okay = true;
	for(i=0; i<worklist_count; i++) {
		// any item failing induces failure of whole program
		if (!do_item(daemon, worklist_name[i], worklist_number[i], output_mode)) {
			all_okay = false;
		}
	}

	delete daemon;

	return (all_okay ? 0 : 1);

}

redpajama_set_name: RedPajamaGithub


text:
package org.apache.dubbo.common.logger;

import org.apache.dubbo.common.logger.jcl.JclLogger;
import org.apache.dubbo.common.logger.jcl.JclLoggerAdapter;
import org.apache.dubbo.common.logger.jdk.JdkLogger;
import org.apache.dubbo.common.logger.jdk.JdkLoggerAdapter;
import org.apache.dubbo.common.logger.log4j.Log4jLogger;
import org.apache.dubbo.common.logger.log4j.Log4jLoggerAdapter;
import org.apache.dubbo.common.logger.log4j2.Log4j2Logger;
import org.apache.dubbo.common.logger.log4j2.Log4j2LoggerAdapter;
import org.apache.dubbo.common.logger.slf4j.Slf4jLogger;
import org.apache.dubbo.common.logger.slf4j.Slf4jLoggerAdapter;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

public class LoggerAdapterTest {
    static Stream<Arguments> data() {
        return Stream.of(
                Arguments.of(JclLoggerAdapter.class, JclLogger.class),
                Arguments.of(JdkLoggerAdapter.class, JdkLogger.class),
                Arguments.of(Log4jLoggerAdapter.class, Log4jLogger.class),
                Arguments.of(Slf4jLoggerAdapter.class, Slf4jLogger.class),
                Arguments.of(Log4j2LoggerAdapter.class, Log4j2Logger.class)
        );
    }

    @ParameterizedTest
    @MethodSource("data")
    public void testGetLogger(Class<? extends LoggerAdapter> loggerAdapterClass, Class<? extends Logger> loggerClass) throws IllegalAccessException, InstantiationException {
        LoggerAdapter loggerAdapter = loggerAdapterClass.newInstance();
        Logger logger = loggerAdapter.getLogger(this.getClass());
        assertThat(logger.getClass().isAssignableFrom(loggerClass), is(true));

        logger = loggerAdapter.getLogger(this.getClass().getSimpleName());
        assertThat(logger.getClass().isAssignableFrom(loggerClass), is(true));

    }

    @ParameterizedTest
    @MethodSource("data")
    public void testLevel(Class<? extends LoggerAdapter> loggerAdapterClass) throws IllegalAccessException, InstantiationException {
        LoggerAdapter loggerAdapter = loggerAdapterClass.newInstance();
        for (Level targetLevel : Level.values()) {
            loggerAdapter.setLevel(targetLevel);
            assertThat(loggerAdapter.getLevel(), is(targetLevel));
        }
    }
}


text:
"""
SentientHome event handler.

Author:     Oliver Ratzesberger <https://github.com/fxstein>
Copyright:  Copyright (C) 2017 Oliver Ratzesberger
License:    Apache License, Version 2.0
"""

from collections import deque
import copy
import json
import os
import pickle
import requests
import time

class shEventHandler(object):
    """SentientHome event handler."""

    def __init__(self, app, interval_key='poll_interval', dedupe=False):
        """Initialize event handler."""
        self._app = app

        self._app.log.info('Starting feed for %s' % self._app._meta.label)

        self._interval_key = interval_key
        self._poll_interval = (float)(self._app.config.get(
            self._app._meta.label,
            self._interval_key,
            fallback=10.0))
        # See if we need to enable deduping logic
        self._dedupe = dedupe

        # In case we need to batch up events
        self._batch = []

        self.checkPoint()

        # If we are require to dedupe re-read the checkpoint file
        if self._dedupe is True:
            # Create empty event cache - Needed to dedup incoming events

            self._events_maxlen = (int)(self._app.config.get(
                self._app._meta.label,
                'events_max_len',
                fallback=-1))

            if self._events_maxlen == -1:
                self._events_maxlen = (int)(self._app.config.get(
                    'SentientHome',
                    'events_max_len',
                    fallback=10000))

                events_per_day = (int)(86400 / self._poll_interval)
                if events_per_day < self._events_maxlen:
                    self._events_maxlen = events_per_day

            self._app.log.debug('Maximum Dedupe Buffer Length: %s' %
                                self._events_maxlen)

            self._events = deque(maxlen=self._events_maxlen)
            self._events_modified = False
            # Assemble a filename for the physical checkpoint
            self._checkpoint_filename = os.path.join(
                os.path.expanduser(self._app.config.get('SentientHome',
                                                        'data_path')),
                self._app.origin_filename + '.p')
            # See if we can restore the event cache from a previsous checkpoint
            try:
                with open(self._checkpoint_filename, 'rb') as f:
                    # The protocol version used is detected automatically
                    self._events = pickle.load(f)
            except (OSError, EOFError) as e:
                self._app.log.warn(e)
                self._app.log.warn('Unable to read checkpoint file: %s' %
                                   self._checkpoint_filename)
                pass
            # Fianlly check if the current class version uses the same datatype
            if isinstance(deque(maxlen=self._events_maxlen),
                          type(self._events)) is False:
                # This is only a checkpoint: truncate, dont bother converting
                self._app.log.debug("Checkpoint file data type was: %s" %
                                    type(self._events))
                self._events = deque(maxlen=self._events_maxlen)
                self._app.log.debug("Checkpoint file data type now: %s" %
                                    type(self._events))

    def _postStore(self, event):
        if self._app.event_store_active == 1:
            try:
                r = self._app._event_store_client.write_points(event, 's')
                self._app.log.info('Event store response: %s' % r)
            except Exception as e:
                self._app.log.fatal(e)
                self._app.log.fatal('Exception posting data to event store: %s'
                                    % self._app._event_store_info)
                self._app.close(1)

    def _postEngine(self, event, timestamp):
        # Now post the same event into our event engine if active
        if self._app.event_engine_active == 1:
            event_for_engine = copy.deepcopy(event)
            # Apply the timestamp to all events heading to the event engine
            for e in event_for_engine:
                e['shtime1'] = timestamp

            try:
                r = self.post(self._app.event_engine_path,
                              data=json.dumps(event_for_engine))
                self._app.log.info('Event engine response: %s' % r)
            except Exception as e:
                self._app.log.fatal(e)
                self._app.log.fatal('Exception posting data to ' +
                                    'event engine: %s'
                                    % self._app.event_engine_path_safe)
                self._app.close(1)

    def _postListener(self, event, timestamp):
        # Now post the same event into the listener if active
        if self._app._listener_active == 1:
            event_for_listener = copy.deepcopy(event)
            # Apply the timestamp to all events heading to the event engine
            for e in event_for_listener:
                e['shtime1'] = timestamp

            try:
                r = self.post(self._app._listener_path + '/messages',
                              data=json.dumps(event_for_listener),
                              headers=self._app._listener_auth)
                self._app.log.info('Listener response: %s' % r)
            except Exception as e:
                self._app.log.fatal(e)
                self._app.log.fatal('Exception posting data to listener: %s'
                                    % self._app._listener_path)
                self._app.close(1)

    def postEvent(self, event, dedupe=False, batch=False):
        """Post event data to store, engine and optional listener."""
        # Timestamp the event - only applied to events heading to event engine
        timestamp = time.time()

        # Engage deduping logic if required
        if dedupe is True and self._dedupe is True:
            if event in self._events:
                self._app.log.debug('Duplicate event: %.25s...' %
                                    event)

                # Nothing left to do here. The same event was already sent
                return
            else:
                self._events_modified = True
                self._events.appendleft(event)
        elif dedupe is True:
            self._app.log.warn('Eventhandler dedupe logic not \
                                   inititalized. Ignoring dedupe.')

        if batch is True:
            for e in event:
                self._batch.append(e)
        else:
            # First deposit the event data into our event store
            self._postStore(event)

            # Next send event data to our in-memory event engine
            self._postEngine(event, timestamp)

            # Next send event data to a generic Listener if configured
            self._postListener(event, timestamp)

    def checkPoint(self, write=False):
        """Take a check point."""
        if self._app.checkpointing is True:
            if (self._dedupe and write and self._events_modified) is True:
                # Write checkpoint deque type manages maxlength automatically
                try:
                    with open(self._checkpoint_filename, 'wb') as f:
                        # Pickle the event cache
                        pickle.dump(self._events, f, pickle.HIGHEST_PROTOCOL)
                except OSError:
                    self._app.log.warn('Unable to write checkpoint file: %s' %
                                       self._checkpoint_filename)
                    pass

                # Now that we have written the checkpoint file reset modified
                self._events_modified = False

        self._checkpoint = time.clock()

    def sleep(self, sleeptime=None):
        """Go to sleep for configured time."""
        # Before anything else flush batch if one has been accumulated
        if len(self._batch) > 0:
            self._app.log.info('Batch Event Count: %s' % len(self._batch))
            self.postEvent(self._batch)
            # Reset batch
            self._batch = []

        # Update poll_interval if supplied
        self._poll_interval = (float)(self._app.config.get(
            self._app._meta.label,
            self._interval_key,
            fallback=10.0))
        if sleeptime is None:
            stime = self._poll_interval
        else:
            stime = sleeptime

        if self._dedupe is True:
            self._app.log.debug('Event Cache Count: %s' % len(self._events))
            self._app.log.debug('Event Cache Max Size: %s' %
                                self._events.maxlen)

        prior_checkpoint = self._checkpoint
        self.checkPoint(write=True)

        # Put processing to sleep until next polling interval
        if stime >= 0:
            # Logic to true up the poll interval time for time lost processing
            time_to_sleep = stime - (time.clock() - prior_checkpoint)
            # Enforce minimum of .1 sec and avoid negative
            if time_to_sleep < .1:
                time_to_sleep = .1

            self._app.log.debug('Time to sleep: %fs' % time_to_sleep)
            time.sleep(time_to_sleep)
        else:
            self._app.log.warn('No poll interval or sleep time defined. \
                                Nothing to sleep.')

        self.checkPoint()

    def get(self, url, auth=None):
        """Restful get helper to handle retries."""
        retries = 0

        while True:
            try:
                r = requests.get(url, auth=auth)
                if r.status_code not in [200, 201]:
                    self._app.log.error('Invalid status code: %s' %
                                        r.status_code)
                return r
            except Exception as e:
                retries += 1

                self._app.log.warn(e)
                self._app.log.warn('Cannot GET from %s. Attempt %s of %s' %
                                   (url, retries, self._app.retries))

                if retries >= self._app.retries:
                    self._app.log.error('Cannot GET from to %s. Exiting...' %
                                        url)
                    raise e

                # Wait until we retry
                self.sleep(self._app._retry_interval)
                continue

    def post(self, url, auth=None, data=None, headers=None):
        """Restful post helper to handle retries."""
        retries = 0

        while True:
            try:
                r = requests.post(url, auth=auth, data=data, headers=headers)
                if r.status_code not in [200, 201]:
                    self._app.log.error('Invalid status code: %s' %
                                        r.status_code)
                return r
            except Exception as e:
                retries += 1

                self._app.log.warn(e)
                self._app.log.warn('Cannot POST to %s. Attempt %s of %s' %
                                   (url, retries, self._app.retries))

                if retries >= self._app.retries:
                    self._app.log.error('Cannot POST to %s. Exiting...' %
                                        url)
                    raise e

                # Wait until we retry
                self.sleep(self._app._retry_interval)
                continue

#
# Do nothing
#
if __name__ == "__main__":
    import __main__
    print(__main__.__file__)
    print("syntax ok")

    exit(0)


text:
namespace Persistence.POCO
{
    public class RequestDetail
    {
        public virtual int Id { get; set; }

        public virtual Request Request { get; set; }
        public virtual Course Course { get; set; }
    }
}


text:
package at.ac.univie.mminf.luceneSKOS.test;

import java.io.IOException;

import org.apache.lucene.analysis.core.SimpleAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
import org.apache.lucene.queryparser.flexible.standard.StandardQueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;

import org.junit.Before;
import org.junit.Test;
import at.ac.univie.mminf.luceneSKOS.analysis.SKOSAnalyzer;

import static org.junit.Assert.assertEquals;

/**
 * Testing the SKOS Label Filter
 */
public class SKOSLabelFilterTest extends AbstractFilterTest {

    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();
        skosAnalyzer = new SKOSAnalyzer(skosEngine, SKOSAnalyzer.ExpansionType.LABEL);
        writer = new IndexWriter(directory, new IndexWriterConfig(skosAnalyzer));
    }

    @Test
    public void termQuerySearch() throws IOException {
        Document doc = new Document();
        doc.add(new Field("content", "The quick brown fox jumps over the lazy dog", TextField.TYPE_STORED));
        writer.addDocument(doc);
        searcher = new IndexSearcher(DirectoryReader.open(writer, false));
        TermQuery tq = new TermQuery(new Term("content", "hops"));
        assertEquals(1, searcher.search(tq, 1).totalHits);
    }

    @Test
    public void phraseQuerySearch() throws IOException {
        Document doc = new Document();
        doc.add(new Field("content", "The quick brown fox jumps over the lazy dog", TextField.TYPE_STORED));
        writer.addDocument(doc);
        searcher = new IndexSearcher(DirectoryReader.open(writer, false));
        PhraseQuery.Builder builder = new PhraseQuery.Builder();
        builder.add(new Term("content", "fox")).add(new Term("content", "hops"));
        assertEquals(1, searcher.search(builder.build(), 1).totalHits);
    }

    @Test
    public void queryParserSearch() throws IOException, QueryNodeException {
        Document doc = new Document();
        doc.add(new Field("content", "The quick brown fox jumps over the lazy dog", TextField.TYPE_STORED));
        writer.addDocument(doc);
        searcher = new IndexSearcher(DirectoryReader.open(writer, false));
        Query query = new StandardQueryParser(skosAnalyzer).parse("\"fox jumps\"", "content");
        assertEquals(1, searcher.search(query, 1).totalHits);
        assertEquals("content:\"fox (jumps hops leaps)\"", query.toString());
        assertEquals("org.apache.lucene.search.MultiPhraseQuery", query
                .getClass().getName());
        query = new StandardQueryParser(new StandardAnalyzer()).parse("\"fox jumps\"", "content");
        assertEquals(1, searcher.search(query, 1).totalHits);
        assertEquals("content:\"fox jumps\"", query.toString());
        assertEquals("org.apache.lucene.search.PhraseQuery", query.getClass().getName());
    }

    @Test
    public void testTermQuery() throws IOException, QueryNodeException {
        Document doc = new Document();
        doc.add(new Field("content", "I work for the united nations", TextField.TYPE_STORED));
        writer.addDocument(doc);
        searcher = new IndexSearcher(DirectoryReader.open(writer, false));
        StandardQueryParser parser = new StandardQueryParser(new SimpleAnalyzer());
        Query query = parser.parse("united nations", "content");
        assertEquals(1, searcher.search(query, 1).totalHits);
    }
}


text:
<?php

namespace Oro\Bundle\FilterBundle\Tests\Functional\Fixtures;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Oro\Bundle\OrganizationBundle\Entity\Organization;
use Oro\Bundle\SecurityBundle\Authentication\Token\UsernamePasswordOrganizationToken;
use Oro\Bundle\TagBundle\Entity\Tag;
use Oro\Bundle\UserBundle\Entity\User;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;

class LoadUserTags extends AbstractFixture implements DependentFixtureInterface, ContainerAwareInterface
{
    use ContainerAwareTrait;

    /** @var array */
    private static $tags = [
        'u1@example.com' => ['Friends'],
        'u2@example.com' => ['Developer', 'Wholesale'],
        'u3@example.com' => [],
    ];

    /**
     * {@inheritdoc}
     */
    public function getDependencies()
    {
        return [LoadUserWithBUAndOrganization::class];
    }

    /**
     * {@inheritDoc}
     */
    public function load(ObjectManager $manager)
    {
        $this->initToken($manager);

        $tagEntities = $this->buildTagEntities($manager);
        $tagManager = $this->container->get('oro_tag.tag.manager');

        foreach (self::$tags as $reference => $tags) {
            /** @var User $user */
            $user = $this->getReference($reference);

            $tagManager->setTags(
                $user,
                new ArrayCollection(
                    array_map(
                        function ($tag) use ($tagEntities) {
                            return $tagEntities[$tag];
                        },
                        $tags
                    )
                )
            );
            $tagManager->saveTagging($user, false);
        }

        $manager->flush();
    }

    /**
     * @param ObjectManager $manager
     */
    private function initToken(ObjectManager $manager): void
    {
        /** @var Organization $organization */
        $organization = $manager->getRepository(Organization::class)->getFirst();

        /** @var User $user */
        $user = $manager->getRepository(User::class)->findOneBy([], ['id' => 'ASC']);

        $tokenStorage = $this->container->get('security.token_storage');
        $tokenStorage->setToken(
            new UsernamePasswordOrganizationToken($user, $user->getUsername(), 'main', $organization)
        );
    }

    /**
     * @param ObjectManager $manager
     * @return array
     */
    private function buildTagEntities(ObjectManager $manager): array
    {
        /** @var Organization $organization */
        $organization = $manager->getRepository(Organization::class)->getFirst();

        $tags = array_unique(array_merge(...array_values(self::$tags)));

        $tagEntities = [];
        foreach ($tags as $tag) {
            $tagEntity = new Tag($tag);
            $tagEntity->setOrganization($organization);
            $tagEntities[$tag] = $tagEntity;

            $manager->persist($tagEntity);

            $this->setReference('tag.' . $tag, $tagEntity);
        }

        return $tagEntities;
    }
}


text:
<!DOCTYPE html>

    {% block head %}

        {% block meta %}
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <meta name="robots" content="NONE,NOARCHIVE" />
        {% endblock %}

        <title>{% block title %}Flask API{% endblock %}</title>

        {% block style %}
        {% block bootstrap_theme %}
            <link rel="stylesheet" type="text/css" href="{{url_for('flask-api.static', filename='css/bootstrap.min.css')}}"/>
            <link rel="stylesheet" type="text/css" href="{{url_for('flask-api.static', filename='css/bootstrap-tweaks.css')}}"/>
        {% endblock %}
        <link rel="stylesheet" type="text/css" href="{{url_for('flask-api.static', filename='css/prettify.css')}}"/>
        <link rel="stylesheet" type="text/css" href="{{url_for('flask-api.static', filename='css/default.css')}}"/>
        {% endblock %}

    {% endblock %}

    {% block navbar %}

                    {% block branding %}Flask API {{ version }}{% endblock %}

                    {% block userlinks %}

                    {% endblock %}

    {% endblock %}

        {% if 'GET' in allowed_methods %}
            <form id="get-form" class="pull-right">
                <fieldset>

                        GET

                        <button class="btn btn-primary dropdown-toggle js-tooltip" data-toggle="dropdown" title="Specify a format for the GET request">

                        </button>

                            {% for format in available_formats %}

                                    <a class="js-tooltip format-option" href='' rel="nofollow" title="Make a GET request on the {{ name }} resource with the format set to `{{ format }}`">{{ format }}

                            {% endfor %}

                </fieldset>
            </form>
        {% endif %}

        {% if 'DELETE' in allowed_methods %}
            <form class="button-form" action="{{ request.full_path }}" method="POST" class="pull-right">

                <input type="hidden" name="_method" value="DELETE" />
                <button class="btn btn-danger js-tooltip" title="Make a DELETE request on the resource">DELETE</button>
            </form>
        {% endif %}

{{ view_name }}

            {% if view_description %}
{{ view_description|safe }}
{% endif %}

{{ request.method }} {{ request.full_path }}

HTTP {{ status }}{% autoescape off %}
{% for key, val in headers.items() %}{{ key }}: {{ val|e }}
{% endfor %}

{% if content %}{{ content|urlize_quoted_links }}{% endif %}
{% endautoescape %}

                {% if 'POST' in allowed_methods or 'PUT' in allowed_methods or 'PATCH' in allowed_methods %}

                            <form action="{{ request.full_path }}" method="POST" class="form-horizontal">
                                <fieldset>

        Media type:

            <select id="id__content_type" name="_content_type">
<option value="application/json" selected="selected">application/json</option>
<option value="application/x-www-form-urlencoded">application/x-www-form-urlencoded</option>
<option value="multipart/form-data">multipart/form-data</option>
</select>

                                    Content:

                                        <textarea name="_content" cols="40" rows="10"></textarea>

                                    {% if 'POST' in allowed_methods %}
                                    <button class="btn btn-primary" title="Make a POST request on the resource">POST</button>
                                    {% endif %}
                                    {% if 'PUT' in allowed_methods %}
                                    <button class="btn btn-primary js-tooltip" name="_method" value="PUT" title="Make a PUT request on the resource">PUT</button>
                                    {% endif %}
                                    {% if 'PATCH' in allowed_methods %}
                                    <button class="btn btn-primary js-tooltip" name="_method" value="PATCH" title="Make a PATCH request on the resource">PATCH</button>
                                    {% endif %}

                                </fieldset>
                            </form>

                {% endif %}

    {% block footer %}
    {% endblock %}

    {% block script %}

    {% endblock %}


text:
%%% RenderToolbox3 Copyright (c) 2012-2013 The RenderToolbox3 Team.
%%% About Us://github.com/DavidBrainard/RenderToolbox3/wiki/About-Us
%%% RenderToolbox3 is released under the MIT License.  See LICENSE.txt.
%
% Add a parameter to a PBRT-XML document.
%   @param idMap
%   @param id
%   @param name
%   @param type
%   @param value
%
% @details
% Adds a parmater to the PBRT-XML document represented by @a idMap,
% using a standard format for node @a id and paramter @a name and @a type.
% Converts numeric @a value automatically to string representations.
%
% @details
% Used internally by ColladaToPBRT().
%
% @details
% Usage:
%   AddParameter(idMap, id, name, type, value)
%
% @ingroup ColladaToPBRT
function AddParameter(idMap, id, name, type, value)

% create new XML DOM nodes as needed
isCreate = true;

% declare the parameter
paramPath = {id, [':parameter|name=' name]};
value = VectorToString(value);
SetSceneValue(idMap, paramPath, value, isCreate);

% set the parameter type
paramPath = {id, [':parameter|name=' name], '.type'};
SetSceneValue(idMap, paramPath, type, isCreate);


text:
Local Conflicts

        Local Data
        Remote Data

            Deleted

              id
              change
              title

              {{conflict.sourceChange.modelId}}
              {{conflict.sourceChange.type()}}

                {{conflict.source.title}}

          <button ng-click="resolveUsingSource(conflict)">Use Local Version</button>

            Deleted

              id
              change
              title

              {{conflict.targetChange.modelId}}
              {{conflict.targetChange.type()}}

                {{conflict.target.title}}

          <button ng-click="resolveUsingTarget(conflict)">Use Server Version</button>

Merge Manually

      <input class="toggle" type="checkbox" ng-model="conflict.manual.completed">
      <input class="edit" ng-trim="false" ng-model="conflict.manual.title">
      <button ng-click="resolveManually(conflict)">Use This Version</button>

todos

    <form id="todo-form" ng-submit="addTodo()">
      <input id="new-todo" placeholder="What needs to be done?" ng-model="newTodo" autofocus>
    </form>

    <input id="toggle-all" type="checkbox" ng-model="allChecked" ng-click="markAll(allChecked)">
    Mark all as complete

          <input class="toggle" type="checkbox" ng-model="todo.completed" ng-change="todoCompleted(todo)">
          {{todo.title}}
          <button class="destroy" ng-click="removeTodo(todo)"></button>

        <form ng-submit="doneEditing(todo)">
          <input class="edit" ng-trim="false" ng-model="todo.title" ng-blur="doneEditing(todo)" todo-escape="revertEditing(todo)" todo-focus="todo == editedTodo">
        </form>

    {{remainingCount}}
      <ng-pluralize count="remainingCount" when="{ one: 'item left', other: 'items left' }"></ng-pluralize>

        All

        Active

        Completed

    <button id="clear-completed" ng-click="clearCompletedTodos()" ng-show="stats.remaining < todos.length">Clear completed ({{stats.completed}})</button>

Double-click to edit a todo

  <button ng-click="sync()" ng-class="{deltas: needSync}">Sync</button>
  <button ng-click="connect()">Connect</button>
  <button ng-click="disconnect()">Disconnect</button>
  Debug
   connected: {{ connected() }}