<commit_before>// Copyright 2015-2020 <NAME>. All rights reserved.

#ifndef OUZEL_XCODEPROJECT_HPP
#define OUZEL_XCODEPROJECT_HPP

#include <fstream>
#include <map>
#include <random>
#include <stack>
#include <type_traits>
#include "OuzelProject.hpp"
#include "storage/FileSystem.hpp"
#include "utils/Plist.hpp"

namespace ouzel
{
    namespace
    {
        std::string generateId()
        {
            std::random_device randomDevice;
            std::mt19937 randomEngine(randomDevice());
            std::uniform_int_distribution<uint32_t> distribution(0, 255);

            std::string result;
            result.resize(2 * 12);

            for (size_t i = 0; i < 12; ++i)
            {
                constexpr char digits[] = "0123456789ABCDEF";
                auto n = distribution(randomEngine);
                result[i * 2 + 0] = digits[(n >> 4) & 0x0F];
                result[i * 2 + 1] = digits[(n >> 0) & 0x0F];
            }

            return result;
        }

        class Object
        {
        public:
            Object(const std::string& i,
                   const std::string& n): isa{i}, name{n} {}
            virtual ~Object() = default;

            const std::string& getId() const noexcept { return id; }
            const std::string& getIsa() const noexcept { return isa; }
            const std::string& getName() const noexcept { return name; }

        private:
            std::string id = generateId();
            std::string isa;
            std::string name;
        };

        class PbxFileElement: public Object
        {
        public:
            PbxFileElement(const std::string& i,
                           const std::string& n):
                Object{i, n} {}
        };

        enum class PbxSourceTree
        {
            Absolute,
            Group,
            SourceRoot,
            BuildProductsDir,
            SdkRoot,
            DeveloperDir
        };

        std::string sourceTreeToString(PbxSourceTree sourceTree)
        {
            switch (sourceTree)
            {
                case PbxSourceTree::Absolute: return "<absolute>";
                case PbxSourceTree::Group: return "<group>";
                case PbxSourceTree::SourceRoot: return "SOURCE_ROOT";
                case PbxSourceTree::BuildProductsDir: return "BUILT_PRODUCTS_DIR";
                case PbxSourceTree::SdkRoot: return "SDKROOT";
                case PbxSourceTree::DeveloperDir: return "DEVELOPER_DIR";
            }
        }

        class PbxFileReference final: public PbxFileElement
        {
        public:
            PbxFileReference(const storage::Path& p, PbxSourceTree tree):
                PbxFileElement{"PBXFileReference", std::string{p}}, path{p}, sourceTree{tree} {}
            const storage::Path& getPath() const noexcept { return path; }

            plist::Value getValue() const
            {
                const auto extension = path.getExtension();
                const std::string fileType = (sourceTree == PbxSourceTree::BuildProductsDir) ?
                    "wrapper.application" :
                    extension == "plist" ? "text.plist.xml" : "sourcecode.cpp." + extension;

                return plist::Value::Dictionary{
                    {"isa", getIsa()},
                    {"explicitFileType", fileType},
                    {"includeInIndex", 0},
                    {"path", std::string(path)},
                    {"sourceTree", sourceTreeToString(sourceTree)}
                };
            }

        private:
            storage::Path path;
            PbxSourceTree sourceTree;
        };

        class PbxBuildFile final: public Object
        {
        public:
            PbxBuildFile(const PbxFileReference& ref):
                Object{"PBXBuildFile", ref.getName()}, fileRef{ref} {}

            plist::Value getValue() const
            {
                return plist::Value::Dictionary{
                    {"isa", getIsa()},
                    {"fileRef", fileRef.getId()}
                };
            }

        private:
            const PbxFileReference& fileRef;
        };

        class PbxGroup final: public PbxFileElement
        {
        public:
            PbxGroup(const std::string& n,
                     const storage::Path& p,
                     const std::vector<const PbxFileElement*>& c,
                     PbxSourceTree tree):
                PbxFileElement{"PBXGroup", n},
                path{p},
                children{c},
                sourceTree{tree} {}

            plist::Value getValue() const
            {
                auto result = plist::Value::Dictionary{
                    {"isa", getIsa()},
                    {"children", plist::Value::Array{}},
                    {"sourceTree", sourceTreeToString(sourceTree)}
                };

                if (!std::string(path).empty())
                    result["path"] = std::string(path);
                else if (!getName().empty())
                    result["name"] = getName();

                for (auto child : children)
                    result["children"].pushBack(child->getId());

                return result;
            }

        private:
            storage::Path path;
            std::vector<const PbxFileElement*> children;
            PbxSourceTree sourceTree;
        };

        class XcBuildConfiguration final: public Object
        {
        public:
            XcBuildConfiguration(const std::string& n,
                                 const std::string& p = ""):
                Object{"XCBuildConfiguration", n},
                productName{p} {}

            plist::Value getValue() const
            {
                auto result = plist::Value::Dictionary{
                    {"isa", getIsa()},
                    {"buildSettings", plist::Value::Dictionary{}},
                    {"name", getName()}
                };

                if (!productName.empty())
                    result["PRODUCT_NAME"] = productName;

                return result;
            }

        private:
            std::string productName;
        };

        class XcConfigurationList final: public Object
        {
        public:
            XcConfigurationList(const std::string& n,<commit_msg>Fix the product name setting<commit_after>// Copyright 2015-2020 <NAME>. All rights reserved.

#ifndef OUZEL_XCODEPROJECT_HPP
#define OUZEL_XCODEPROJECT_HPP

#include <fstream>
#include <map>
#include <random>
#include <stack>
#include <type_traits>
#include "OuzelProject.hpp"
#include "storage/FileSystem.hpp"
#include "utils/Plist.hpp"

namespace ouzel
{
    namespace
    {
        std::string generateId()
        {
            std::random_device randomDevice;
            std::mt19937 randomEngine(randomDevice());
            std::uniform_int_distribution<uint32_t> distribution(0, 255);

            std::string result;
            result.resize(2 * 12);

            for (size_t i = 0; i < 12; ++i)
            {
                constexpr char digits[] = "0123456789ABCDEF";
                auto n = distribution(randomEngine);
                result[i * 2 + 0] = digits[(n >> 4) & 0x0F];
                result[i * 2 + 1] = digits[(n >> 0) & 0x0F];
            }

            return result;
        }

        class Object
        {
        public:
            Object(const std::string& i,
                   const std::string& n): isa{i}, name{n} {}
            virtual ~Object() = default;

            const std::string& getId() const noexcept { return id; }
            const std::string& getIsa() const noexcept { return isa; }
            const std::string& getName() const noexcept { return name; }

        private:
            std::string id = generateId();
            std::string isa;
            std::string name;
        };

        class PbxFileElement: public Object
        {
        public:
            PbxFileElement(const std::string& i,
                           const std::string& n):
                Object{i, n} {}
        };

        enum class PbxSourceTree
        {
            Absolute,
            Group,
            SourceRoot,
            BuildProductsDir,
            SdkRoot,
            DeveloperDir
        };

        std::string sourceTreeToString(PbxSourceTree sourceTree)
        {
            switch (sourceTree)
            {
                case PbxSourceTree::Absolute: return "<absolute>";
                case PbxSourceTree::Group: return "<group>";
                case PbxSourceTree::SourceRoot: return "SOURCE_ROOT";
                case PbxSourceTree::BuildProductsDir: return "BUILT_PRODUCTS_DIR";
                case PbxSourceTree::SdkRoot: return "SDKROOT";
                case PbxSourceTree::DeveloperDir: return "DEVELOPER_DIR";
            }
        }

        class PbxFileReference final: public PbxFileElement
        {
        public:
            PbxFileReference(const storage::Path& p, PbxSourceTree tree):
                PbxFileElement{"PBXFileReference", std::string{p}}, path{p}, sourceTree{tree} {}
            const storage::Path& getPath() const noexcept { return path; }

            plist::Value getValue() const
            {
                const auto extension = path.getExtension();
                const std::string fileType = (sourceTree == PbxSourceTree::BuildProductsDir) ?
                    "wrapper.application" :
                    extension == "plist" ? "text.plist.xml" : "sourcecode.cpp." + extension;

                return plist::Value::Dictionary{
                    {"isa", getIsa()},
                    {"explicitFileType", fileType},
                    {"includeInIndex", 0},
                    {"path", std::string(path)},
                    {"sourceTree", sourceTreeToString(sourceTree)}
                };
            }

        private:
            storage::Path path;
            PbxSourceTree sourceTree;
        };

        class PbxBuildFile final: public Object
        {
        public:
            PbxBuildFile(const PbxFileReference& ref):
                Object{"PBXBuildFile", ref.getName()}, fileRef{ref} {}

            plist::Value getValue() const
            {
                return plist::Value::Dictionary{
                    {"isa", getIsa()},
                    {"fileRef", fileRef.getId()}
                };
            }

        private:
            const PbxFileReference& fileRef;
        };

        class PbxGroup final: public PbxFileElement
        {
        public:
            PbxGroup(const std::string& n,
                     const storage::Path& p,
                     const std::vector<const PbxFileElement*>& c,
                     PbxSourceTree tree):
                PbxFileElement{"PBXGroup", n},
                path{p},
                children{c},
                sourceTree{tree} {}

            plist::Value getValue() const
            {
                auto result = plist::Value::Dictionary{
                    {"isa", getIsa()},
                    {"children", plist::Value::Array{}},
                    {"sourceTree", sourceTreeToString(sourceTree)}
                };

                if (!std::string(path).empty())
                    result["path"] = std::string(path);
                else if (!getName().empty())
                    result["name"] = getName();

                for (auto child : children)
                    result["children"].pushBack(child->getId());

                return result;
            }

        private:
            storage::Path path;
            std::vector<const PbxFileElement*> children;
            PbxSourceTree sourceTree;
        };

        class XcBuildConfiguration final: public Object
        {
        public:
            XcBuildConfiguration(const std::string& n,
                                 const std::string& p = ""):
                Object{"XCBuildConfiguration", n},
                productName{p} {}

            plist::Value getValue() const
            {
                auto result = plist::Value::Dictionary{
                    {"isa", getIsa()},
                    {"buildSettings", plist::Value::Dictionary{}},
                    {"name", getName()}
                };

                if (!productName.empty())
                    result["buildSettings"]["PRODUCT_NAME"] = productName;

                return result;
            }

        private:
            std::string productName;
        };

        class XcConfigurationList final: public Object
        {
        public:
            XcConfigurationList(const std::string& n,
{'fraction_non_alphanumeric': 0.10903575989782886, 'fraction_numerical': 0.007343550446998723, 'mean_word_length': 1.4716906687709608, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5975077', 'n_tokens_mistral': 3412, 'n_tokens_neox': 3065, 'n_words': 705}