예제 #1
0
        protected override void GenerateFlush(messageType message)
        {
            IncludeWriter.WriteLine(@"        void flush();");
            CppWriter.WriteLine(
                @"
        void Abstract{0}::flush()
        {{", message.name.Capitalize());

            var allFields = message.field.OrderBy(_ => _.id);

            var messageFields = from fld in allFields
                                where fld.messageType != null &&
                                fld.type == typeType.nestedMessage
                                select fld;

            var has = false;

            foreach (var field in messageFields)
            {
                has = true;
                CppWriter.WriteLine(
                    field.modifier == modifierType.repeated
                        ? @"            m_{0}List.clear();"
                        : @"            m_{0}.reset();", field.name);
            }

            if (!has)
            {
                CppWriter.WriteLine(@"            // NOP");
            }

            CppWriter.WriteLine(@"        }");
            CppWriter.WriteLine();
        }
예제 #2
0
        void WriteFromWaveStream(string inputPath, string outputPath, WaveStream reader)
        {
            var waveFormat = reader.WaveFormat;
            int sampleRate = Math.Min(16000, waveFormat.SampleRate);

            using (WaveStream pcmStream = WaveFormatConversionStream.CreatePcmStream(reader))
            {
                WaveFormat newFormat = new WaveFormat(sampleRate, 8, 1);
                using (WaveStream eightBitPcmStream = new WaveFormatConversionStream(newFormat, pcmStream))
                {
                    CppWriter cppWriter = new CppWriter(Path.GetFileName(Path.GetFileNameWithoutExtension(inputPath)), outputPath);
                    cppWriter.Write(sampleRate);

                    List <byte> totalBytes = new List <byte>();
                    int         b          = eightBitPcmStream.ReadByte();
                    while (b != -1)
                    {
                        totalBytes.Add((byte)(b + 128));    // Make it signed 8-bit PCM, as this comes through as unsigned
                        b = eightBitPcmStream.ReadByte();
                    }

                    cppWriter.Write(totalBytes.Count);

                    foreach (byte data in totalBytes)
                    {
                        cppWriter.Write(data);
                    }

                    cppWriter.Finalise();
                    Console.WriteLine("Audio file \"" + Path.GetFullPath(outputPath) + "\" successfully converted");
                }
            }
        }
예제 #3
0
        protected override void CompileInternal(string outputFile, ObjectDumper dumper)
        {
            _cppWriter = new CppWriter(this, outputFile);

            var nodes = _dependencyGraph.MarkedNodeList;

            _cppWriter.OutputCode(nodes, NodeFactory);
        }
예제 #4
0
        protected override void CompileInternal(string outputFile)
        {
            _cppWriter = new CppWriter(this, outputFile);

            var nodes = _dependencyGraph.MarkedNodeList;

            _cppWriter.OutputCode(nodes, NodeFactory.CompilationModuleGroup.StartupCodeMain, NodeFactory);
        }
예제 #5
0
        void WriteHeader(CppWriter writer, UVs[] sliceCoordinates, Color[] palette, int dataLength, Compression.CompressionType compressionType, uint bpp)
        {
            UInt32 compressionTypeSize = Compression.ToGBACompressionHeader(compressionType, bpp);

            writer.Write((UInt32)sliceCoordinates.Length);
            writer.Write((byte)palette.Length);
            writer.Write((UInt32)dataLength);
            writer.Write((UInt32)compressionTypeSize);
        }
예제 #6
0
        void WritePalette(CppWriter writer, Color[] palette)
        {
            for (int i = 0; i < palette.Length; ++i)
            {
                Color  colour   = palette[i];
                UInt16 rbgColor = PaletteHelper.ToRgb16(colour);

                writer.Write(rbgColor);
            }
        }
예제 #7
0
 private void WriteSourceFile(LangStreamWrapper stream)
 {
     foreach (FunctionObj functionObj in _functions)
     {
         stream.NewLine();
         CppWriter.WriteFunctionString(stream, functionObj);
         stream.WriteLine("{");
         stream.WriteLine("}");
     }
 }
예제 #8
0
        internal override void GenerateFinalClientClasses(protozbuffType node)
        {
            // close file .lazy.h
            IncludeWriter.WriteLine(GetNamespaceEnd(GeneratedNamespace));
            IncludeWriter.Dispose();
            IncludeWriter = null;

            // close file .lazy.cpp
            CppWriter.WriteLine(GetNamespaceEnd(GeneratedNamespace));
            CppWriter.Dispose();
            CppWriter = null;

            base.GenerateFinalClientClasses(node);
        }
예제 #9
0
        private void WriterHeaderFile(LangStreamWrapper stream)
        {
            stream.NewLine();
            foreach (VariableObj variableObj in _variables)
            {
                CppWriter.WriteVariableString(stream, variableObj);
                stream.WriteLine(";");
            }

            stream.NewLine();
            foreach (FunctionObj functionObj in _functions)
            {
                CppWriter.WriteFunctionString(stream, functionObj);
                stream.WriteLine(";");
            }
        }
예제 #10
0
        protected override void GenerateSerialization(messageType message)
        {
            if (message.IsRoot)
            {
                IncludeWriter.WriteLine(
                    @"        static std::unique_ptr<{0}> ParseFrom(std::shared_ptr<std::iostream> s);
"
                    , message.name);

                CppWriter.WriteLine(
                    @"        std::unique_ptr<{0}> Abstract{0}::ParseFrom(std::shared_ptr<std::iostream> s)
        {{
            {0}Header header;
            auto success = Util::readDelimited(*s, header, true); // the root is always at the end of the stream
            assert((""Can't decode header!"", success));
            
            auto parsed = std::make_unique<{0}>(header, (long)s->tellg());
            parsed->setContentStream(s);
            return parsed;
        }}
"
                    , message.name);
                return;
            }

            IncludeWriter.WriteLine(
                @"        static std::unique_ptr<{0}> ParseFrom(std::iostream& s, int pos);
"
                , message.name);

            CppWriter.WriteLine(
                @"        std::unique_ptr<{0}> Abstract{0}::ParseFrom(std::iostream& s, int pos)
        {{
            s.seekg(pos, std::ios::beg);

            {0}Header header;
            auto success = Util::readDelimited(s, header);
            assert((""Can't decode header!"", success));

            auto parsed = std::make_unique<{0}>(header, pos);
            return parsed;
        }}
"
                , message.name);
        }
예제 #11
0
        protected override bool GenerateLazyImplementation(protozbuffType p)
        {
            var baseName = DocumentName + ".lazy";

            IncludeWriter = GetStream(IncludesFolder, baseName + ".h", GeneratedNamespace);
            CppWriter     = GetStream(CppFolder, baseName + ".cpp", GeneratedNamespace);

            WriteAutoGenerationWarning(IncludeWriter);
            WriteAutoGenerationWarning(CppWriter);

            IncludeWriter.WriteLine(@"
#pragma once
#include <memory>
#include <sstream>
#include <string>
#include ""{1}.pb.h""
#include ""{0}/ArrayList.h""
", GetNamespacePathSlash(ResourceNamespace), DocumentName);

            // forward declaration for final client classes
            IncludeWriter.WriteLine(GetNamespaceBegin(Namespace));
            foreach (var message in p.Items.OfType <messageType>())
            {
                IncludeWriter.WriteLine(@"class {0};", message.name.Capitalize());
            }
            IncludeWriter.WriteLine(GetNamespaceEnd(Namespace));
            IncludeWriter.WriteLine();
            IncludeWriter.WriteLine(GetNamespaceBegin(GeneratedNamespace));

            CppWriter.WriteLine(@"#include ""stdafx.h""");
            CppWriter.WriteLine("#include <sstream>");
            CppWriter.WriteLine("#include <{0}/{1}.h>", GetNamespacePathSlash(GeneratedNamespace), baseName);
            CppWriter.WriteLine("#include <{0}/Util.inc>", GetNamespacePathSlash(ResourceNamespace));
            foreach (var message in p.Items.OfType <messageType>())
            {
                CppWriter.WriteLine(@"#include <{0}/{1}.h>", GetNamespacePathSlash(Namespace), message.name.Capitalize());
            }

            CppWriter.WriteLine(@"using namespace {0};", ResourceNamespace);
            CppWriter.WriteLine(GetNamespaceBegin(GeneratedNamespace));

            return(base.GenerateLazyImplementation(p));
        }
예제 #12
0
        public void Convert(string inputPath, string outputPath, IList <Event> events)
        {
            CppWriter cppWriter = new CppWriter(Path.GetFileName(Path.GetFileNameWithoutExtension(inputPath)), outputPath);

            cppWriter.Write((uint)events.Count);

            foreach (var e in events)
            {
                cppWriter.Write(e.m_deltaTick);
                cppWriter.Write((ushort)((uint)e.m_properties.id | ((uint)e.m_properties.dataIndex << 2)));

                foreach (var eventData in e.m_properties.data)
                {
                    cppWriter.Write(eventData.data);
                }
            }

            Console.WriteLine("Dmg Midi \"" + System.IO.Path.GetFullPath(outputPath) + "\" successfully converted");

            cppWriter.Finalise();
        }
예제 #13
0
        internal override void GenerateProtoOrBuilderInterface()
        {
            IncludeWriter.WriteLine(
                @"    typedef ::google::protobuf::RepeatedField< ::google::protobuf::int32 > CoordinateList;
    class BaseFormat; 
    class ProtoOrBuilder
    {
    public:
        virtual ProtoOrBuilder* getRoot() = 0;
        virtual void addCoordinates(CoordinateList& coordinates) = 0;
        virtual LocalMessageDescriptor getLocalMessageDescriptor() = 0;
        virtual ProtoOrBuilder* decode(const CoordinateList& coordinates, int index) = 0;
        virtual ProtoOrBuilder* decode(const LocalMessageDescriptor& field) = 0;
        virtual std::iostream& contentStream() = 0;
        virtual std::string toString();
        virtual std::string toString(BaseFormat& format) = 0;
        virtual ~ProtoOrBuilder();
    };

    std::ostream& operator<<(std::ostream& out, ProtoOrBuilder& proto);
");

            CppWriter.WriteLine(
                @"        std::string ProtoOrBuilder::toString()
        {
            auto format = BaseFormat();
            return toString(format);
        }
        
        ProtoOrBuilder::~ProtoOrBuilder()
        {
        }

        std::ostream& operator<<(std::ostream& out, ProtoOrBuilder& proto)
        {
            out << proto.toString();
            return out;
        }
");
        }
예제 #14
0
        public override void WriteFile()
        {
            var cppWriter = new CppWriter();

            cppWriter.BeginWriter(_filename);
            {
                //write the beginning of the files
                cppWriter.HeaderStream.WriteLine("#pragma once");
                cppWriter.SourceStream.WriteLine($"#include \"{new FilenameInfo(_filename).Basename}.h\"");

                WriterHeaderFile(cppWriter.HeaderStream);
                WriteSourceFile(cppWriter.SourceStream);

                //write any classes
                foreach (CppClassBuilder classBuilder in _classes)
                {
                    cppWriter.HeaderStream.NewLine();
                    classBuilder.WriteClass(cppWriter);
                }
            }
            cppWriter.EndWriter();
        }
예제 #15
0
        protected override void GenerateClassConstructor(messageType message)
        {
            IncludeWriter.WriteLine(
                @"    protected: 
        Abstract{0}();
        Abstract{0}(const {0}Header& header, int posInContent);

        Abstract{0}(const Abstract{0}&) = delete;
        Abstract{0}& operator=(const Abstract{0}&) = delete;
", message.name);

            CppWriter.WriteLine(
                @"        
        Abstract{0}::Abstract{0}() : {1} m_positionInContent(-1)
        {{
        }}        

        Abstract{0}::Abstract{0}(const {0}Header& header, int pos) : {1} m_header(header), m_positionInContent(pos)
        {{
        }}

        ", message.name, message.IsRoot ? "" : "m_parent(nullptr), m_root(nullptr),");
        }
예제 #16
0
        protected override void GenerateClassSimpleField(messageType message, fieldType field)
        {
            var fieldTypeForList = FieldType(field);
            var fieldType        = fieldTypeForList;

            if (field.type == typeType.@string)
            {
                fieldType = "const " + fieldType + "&";
            }
            // In C++, a repeated enum is stored as a RepeatedField<int>
            var underlyingType = field.type == typeType.@enum ?
                                 "int" :
                                 fieldTypeForList;

            if (field.modifier == modifierType.repeated)
            {
                IncludeWriter.WriteLine(
                    @"        void add{1}({2} item);
        void remove{1}({2} item);
        std::vector<{3}> {0}List();
        {2} get{1}(int index);
        int {0}Count() const;
"
                    , field.name, field.name.Capitalize(), fieldType, fieldTypeForList);

                CppWriter.WriteLine(
                    @"        void Abstract{4}::add{1}({3} item)
        {{
            assert((""Can't modify an already built object!"", !isBuilt()));
            m_header.add_{2}(item);
        }}

        void Abstract{4}::remove{1}({3} item)
        {{
            assert((""Can't modify an already built object!"", !isBuilt()));
            auto vals = m_header.mutable_{2}();
            auto newEnd = std::remove_if(vals->begin(), vals->end(), [&item]({6} check) {{ return check != item; }});
            vals->Truncate(newEnd - vals->begin());
        }}

        std::vector<{5}> Abstract{4}::{0}List()
        {{
            auto count = {0}Count();
            auto list = std::vector<{3}>();
            list.reserve(count);
            for (auto i = 0; i < count; ++i)
            {{
                list.push_back(get{1}(i));
            }}
            return list;
        }}

        {3} Abstract{4}::get{1}(int index)
        {{
            return m_header.{2}(index);
        }}

        int Abstract{4}::{0}Count() const
        {{
            return m_header.{2}_size();
        }}
"
                    , field.name, field.name.Capitalize(), field.name.ToLowerInvariant(), fieldType, message.name, fieldTypeForList, underlyingType);
                return;
            }

            if (field.modifier == modifierType.optional)
            {
                IncludeWriter.WriteLine(
                    @"        bool has{0}() const {{ return m_header.has_{1}(); }}        
        void clear{0}() {{ m_header.clear_{1}(); }}
"
                    , field.name.Capitalize(), field.name.ToLowerInvariant());
            }

            IncludeWriter.WriteLine(
                @"        {3} {0}() const {{ return m_header.{2}(); }}
        void set{1}({3} value) {{ m_header.set_{2}(value); }}
"
                , field.name, field.name.Capitalize(), field.name.ToLowerInvariant(), fieldType);
        }
예제 #17
0
        public void Convert(string inputPath, string outputPath, Bitmap bitmap, UVs[] sliceCoordinates)
        {
            CppWriter cppWriter = new CppWriter(Path.GetFileName(Path.GetFileNameWithoutExtension(inputPath)), outputPath);

            Size size = bitmap.Size;

            if (size.Width % TileConfig.TileWidth != 0 || size.Height % TileConfig.TileHeight != 0)
            {
                throw new Exception("Size not compatible with GBA tiles. Width and height of pixels must be multiples of 8.");
            }

            Console.WriteLine("Processing colour palette");

            int xStart = 0;
            int yStart = 0;
            int width  = bitmap.Width;
            int height = bitmap.Height;

            Color[] preProcessedPalette = PaletteHelper.GeneratePaletteFromImage(bitmap, xStart, yStart, width, height);

            // Validate pallet length
            {
                if (preProcessedPalette.Length > 256)
                {
                    throw new Exception("Palette length out of range for the GBA");
                }

                // Todo, currently not supported
                if (preProcessedPalette.Length > 16)
                {
                    throw new Exception("Palette length out of range for 4bbp format");
                }
            }

            Console.WriteLine(String.Format("Palette length: {0}", preProcessedPalette.Length));

            Compression.CompressionType compressionType = Compression.CompressionType.BitPacked;
            uint maxColours = MathX.IsPowerOf2((uint)preProcessedPalette.Length) ? (uint)preProcessedPalette.Length : MathX.NextPowerOf2((uint)preProcessedPalette.Length);
            uint destBpp    = (uint)MathX.IndexOfHighestSetBit(maxColours);

            if (!MathX.IsPowerOf2(destBpp))
            {
                destBpp = MathX.NextPowerOf2(destBpp);
            }

            Console.WriteLine(string.Format("Compression type = {0}", compressionType.ToString()));
            Console.WriteLine(string.Format("Destination Bit Depth = {0}", destBpp));

            List <int>            dataOffsets = new List <int>();
            List <List <UInt32> > spriteData  = new List <List <UInt32> >();

            dataOffsets.Add(0);
            int totalData = 0;

            // Collect data and add offsets
            {
                Console.WriteLine("Processing sprite data");

                for (int i = 0; i < sliceCoordinates.Length; ++i)
                {
                    StringBuilder dataSb = new StringBuilder();
                    UVs           slice = sliceCoordinates[i];
                    int           spriteWidth = slice.width, spriteHeight = slice.height;
                    List <UInt32> data = WriteSpriteData(bitmap, preProcessedPalette, spriteWidth, spriteHeight, slice.x, slice.y, compressionType, destBpp);

                    spriteData.Add(data);

                    // Add offsets
                    if (i < sliceCoordinates.Length - 1)
                    {
                        dataOffsets.Add(dataOffsets[i] + data.Count);
                    }

                    totalData += data.Count;
                }
            }

            WriteHeader(cppWriter, sliceCoordinates, preProcessedPalette, totalData, compressionType, destBpp);
            WritePalette(cppWriter, preProcessedPalette);

            // Write width
            {
                for (int i = 0; i < sliceCoordinates.Length; ++i)
                {
                    int spriteWidth = sliceCoordinates[i].width;
                    cppWriter.Write((byte)spriteWidth);
                }
            }

            // Write height
            {
                for (int i = 0; i < sliceCoordinates.Length; ++i)
                {
                    int spriteHeight = sliceCoordinates[i].height;
                    cppWriter.Write((byte)spriteHeight);
                }
            }

            // Write offsets
            {
                for (int i = 0; i < dataOffsets.Count; i++)
                {
                    cppWriter.Write((UInt32)dataOffsets[i]);
                }
            }

            // Write data
            {
                foreach (var dataList in spriteData)
                {
                    foreach (UInt32 data in dataList)
                    {
                        cppWriter.Write((UInt32)data);
                    }
                }
            }

            Console.WriteLine("Sprite \"" + outputPath + "\" successfully converted");

            cppWriter.Finalise();
        }
        /// <param name="inputPath">Input file path, namespace name is derived from this</param>
        /// <param name="outputPath">Output cpp file</param>
        /// <param name="bitmaps">List of image files to map tilemaps from</param>
        /// <param name="paletteBankIndexOffset">Allows us to force things like UI palettes into the back of the palette bank</param>
        public void Convert(string inputPath, string outputPath, IList <Bitmap> bitmaps, byte paletteBankIndexOffset = 0)
        {
            CppWriter cppWriter = new CppWriter(Path.GetFileName(Path.GetFileNameWithoutExtension(inputPath)), outputPath);

            Console.WriteLine("Processing master palette");

            Color[]   masterPalette;
            Tile[]    masterTileSet;
            TileMap[] tileMapList;

            GenerateTileMaps(bitmaps, paletteBankIndexOffset, out masterPalette, out masterTileSet, out tileMapList);
            GBAMapData gbaMapData = GenerateMapData(tileMapList, paletteBankIndexOffset);

            const int maxMaps = sizeof(byte) * 8;

            if (gbaMapData.mapIsDynamic.Count >= maxMaps)
            {
                // Can't store this in the current bitmask size
                throw new Exception(string.Format("Too many tilemaps found. Maps = {0}, max is {1}. Consider increasing the bitmask of \"mapIsDynamicBitMask\".", gbaMapData.mapIsDynamic.Count, maxMaps));
            }

            Console.WriteLine("Total unique tiles = " + masterTileSet.Length);
            Console.WriteLine("Processing tilemaps");

            Compression.CompressionType compressionType = Compression.CompressionType.BitPacked;
            uint destBpp = CalculateDestBitsPerPixel(masterTileSet);

            List <UInt32> tileSetData = GenerateTileSetData(masterTileSet, compressionType, destBpp);

            // Write palette
            {
                cppWriter.Write(paletteBankIndexOffset);
                cppWriter.Write((byte)masterPalette.Length);

                for (int i = 0; i < masterPalette.Length; ++i)
                {
                    Color  colour   = masterPalette[i];
                    UInt16 rbgColor = PaletteHelper.ToRgb16(colour);
                    cppWriter.Write(rbgColor);
                }
            }

            // Write tileset
            {
                // Compression flags
                UInt32 compressionTypeSize = Compression.ToGBACompressionHeader(compressionType, destBpp);
                cppWriter.Write(compressionTypeSize);

                // Actual data
                cppWriter.Write((UInt32)tileSetData.Count);
                for (int i = 0; i < tileSetData.Count; ++i)
                {
                    cppWriter.Write(tileSetData[i]);
                }
            }

            // Write tile maps
            {
                cppWriter.Write((byte)tileMapList.Length);
                cppWriter.Write((UInt32)gbaMapData.screenEntries.Length);

                byte mapIsDynamicBitMask = BoolListToBitmaskU8(gbaMapData.mapIsDynamic);
                cppWriter.Write(mapIsDynamicBitMask);

                // Width and height arrays
                foreach (int width in gbaMapData.widthLists)
                {
                    cppWriter.Write((byte)width);
                }

                foreach (int height in gbaMapData.heightLists)
                {
                    cppWriter.Write((byte)height);
                }

                foreach (var mapEntry in gbaMapData.screenEntries)
                {
                    cppWriter.Write(mapEntry.m_data);
                }
            }

            Console.WriteLine("Tilemap \"" + outputPath + "\" successfully converted");

            cppWriter.Finalise();
        }
예제 #19
0
        protected override void GenerateBuild(messageType message)
        {
            IncludeWriter.WriteLine(
                @"        virtual void preBuild() {} // use this method to customize the build process
        std::iostream& contentStream() override;
        void build();
        void build(std::ostream& output, bool saveToOutput);
");

            if (!message.IsRoot)
            {
                CppWriter.WriteLine(
                    @"        
        std::iostream& Abstract{0}::contentStream() 
        {{
            return getRoot()->contentStream();
        }}", message.name);
            }
            else
            {
                IncludeWriter.WriteLine(@"        void setContentStream(std::shared_ptr<std::iostream> contentStream);");
                CppWriter.WriteLine(
                    @"
        std::iostream& Abstract{0}::contentStream() 
        {{
            if (m_contentStream == nullptr)
                m_contentStream.reset(new std::stringstream());
            return *m_contentStream;
        }}

        void Abstract{0}::setContentStream(std::shared_ptr<std::iostream> contentStream)
        {{
            assert(m_contentStream == nullptr);
            m_contentStream = contentStream;
        }}
", message.name);
            }

            CppWriter.WriteLine(
                @"
        void Abstract{0}::build()
        {{
            build(contentStream(), false);
        }}

        void Abstract{0}::build(std::ostream& content, bool saveToOutput)
        {{
            auto alreadyBuilt = isBuilt();
            if (alreadyBuilt && !saveToOutput)
                return;

            // prebuild hook
            preBuild();

            std::unique_ptr<{0}Header> headerCopy;
            auto* builder = &m_header;
            if (alreadyBuilt)
            {{
                headerCopy = std::make_unique<{0}Header>(m_header);
                builder = headerCopy.get();
            }}
            ", message.name);

            foreach (var field in message.field.Where(_ => _.type == typeType.nestedMessage))
            {
                CppWriter.WriteLine(@"            builder->clear_{0}();", field.name.ToLowerInvariant());
            }

            foreach (var index in message.index)
            {
                CppWriter.WriteLine(@"            builder->clear_{0}();", index.name.ToLowerInvariant());
            }

            CppWriter.WriteLine(
                @"
            // build all nested messages to have their position in the content stream");

            // do nothing for reference messages and pod types: the builder is already the owner of those fields

            foreach (var field in message.field.Where(_ => _.type == typeType.nestedMessage))
            {
                if (field.modifier == modifierType.repeated)
                {
                    CppWriter.WriteLine(
                        @"            auto tmp_{0}List = {0}List();
            for (auto* {0} : tmp_{0}List)
            {{
                auto oldPos = {0}->positionInContent();
                {0}->build(content, saveToOutput);
                builder->add_{1}({0}->positionInContent());
                if (alreadyBuilt || saveToOutput)
                    {0}->setPositionInContent(oldPos);
            }}"
                        , field.name, field.name.ToLowerInvariant());
                }
                else if (field.modifier == modifierType.optional)
                {
                    CppWriter.WriteLine(
                        @"
            auto* tmp_{0} = {0}();
            if (tmp_{0} != nullptr) 
            {{ 
                auto oldPos = tmp_{0}->positionInContent();
                tmp_{0}->build(content, saveToOutput); 
                builder->set_{1}(tmp_{0}->positionInContent());
                if (alreadyBuilt)
                    tmp_{0}->setPositionInContent(oldPos);
            }}"
                        , field.name, field.name.ToLowerInvariant());
                }
                else
                {
                    CppWriter.WriteLine(
                        @"
            auto* tmp_{0} = &{0}();
            if (tmp_{0} != nullptr) 
            {{ 
                auto oldPos = tmp_{0}->positionInContent();
                tmp_{0}->build(content, saveToOutput); 
                builder->set_{1}(tmp_{0}->positionInContent());
                if (alreadyBuilt)
                    tmp_{0}->setPositionInContent(oldPos);
            }}"
                        , field.name, field.name.ToLowerInvariant());
                }
            }

            // create indexes
            foreach (var index in message.index)
            {
                CppWriter.WriteLine(
                    @"
            std::sort(tmp_{0}List.begin(), tmp_{0}List.end(), []({1}* left, {1}* right) {{ return left->{2}() < right->{2}(); }});
            for (auto* {0} : tmp_{0}List)
            {{
                builder->add_{3}()->CopyFrom({0}->getLocalMessageDescriptor());
            }}
", index.ReferenceField.name, index.ReferenceField.messageType, index.SortingField.name, index.name.ToLowerInvariant());
            }

            CppWriter.WriteLine(
                @"
            // write the header
            content.seekp(0, std::ios::end);

            // if we write to output, the position in the content stream
            // will be restored when writing the parent header
            // => this is not possible (and not needed) for root message
            auto isRoot = {1};
            auto dontSavePos = saveToOutput && isRoot;
            if (!dontSavePos)
                setPositionInContent((long)content.tellp());

            {0}::Util::writeDelimited(*builder, content, isRoot);

            if ((!alreadyBuilt && !saveToOutput) || (alreadyBuilt && saveToOutput))
            {{
                flush();
            }}
        }}
", ResourceNamespace, message.IsRoot ? "true" : "false");

            if (!message.IsRoot)
            {
                return;
            }

            IncludeWriter.WriteLine(@"        void writeDelimitedTo(std::ostream& output);");

            CppWriter.WriteLine(
                @"        void Abstract{0}::writeDelimitedTo(std::ostream& output)
        {{
            build(output, true);
        }}
"
                , message.name);
        }
예제 #20
0
        protected override void GeneratePrivateOrBuilderImpl(messageType message)
        {
            IncludeWriter.WriteLine(@"    public:
");

            IncludeWriter.Write("        ProtoOrBuilder* getRoot() override { return ");
            IncludeWriter.Write(message.IsRoot ? @"this" : "m_root");
            IncludeWriter.WriteLine("; }");

            IncludeWriter.WriteLine(@"        ProtoOrBuilder* decode(const LocalMessageDescriptor& field) override;
        ProtoOrBuilder* decode(const CoordinateList& coordinates, int index) override;");
            CppWriter.WriteLine(
                @"
        ProtoOrBuilder* Abstract{0}::decode(const LocalMessageDescriptor& field)
        {{
            return decode(field.coordinate(), 0);
        }}

        ProtoOrBuilder* Abstract{0}::decode(const CoordinateList& coordinates, int index)
        {{
            if (coordinates.size() == 0)
                return nullptr;
            
            auto fieldIdIdx = index;
            auto fieldIndexIdx = index + 1;
            auto remainderIdx = index + 2;
            switch(coordinates.Get(fieldIdIdx))
            {{", message.name);
            var allFields = message.field.Where(_ => _.type == typeType.nestedMessage || _.type == typeType.referenceMessage).OrderBy(_ => _.id);

            foreach (var field in allFields)
            {
                CppWriter.WriteLine(
                    @"              case {0}:", field.id);

                if (field.modifier == modifierType.repeated)
                {
                    CppWriter.WriteLine(
                        field.type != typeType.nestedMessage
                            ?
                        @"                  return &this->get{0}(coordinates.Get(fieldIndexIdx));"
                            :
                        @"                  return coordinates.size() == remainderIdx ? &this->get{0}(coordinates.Get(fieldIndexIdx)) : this->get{0}(coordinates.Get(fieldIndexIdx)).decode(coordinates, remainderIdx);",
                        field.name.Capitalize());
                }
                else if (field.modifier == modifierType.optional)
                {
                    CppWriter.WriteLine(
                        field.type != typeType.nestedMessage
                            ?
                        @"                  return this->{0}();"
                            :
                        @"                  return coordinates.size() == remainderIdx ? &this->add{1}() : this->{0}()->decode(coordinates, remainderIdx);",
                        field.name, field.name.Capitalize());
                }
                else
                {
                    CppWriter.WriteLine(
                        field.type != typeType.nestedMessage
                            ?
                        @"                  return this->{0}();"
                            :
                        @"                  return coordinates.size() == remainderIdx ? &this->{0}() : this->{0}().decode(coordinates, remainderIdx);",
                        field.name);
                }
            }
            CppWriter.WriteLine(
                @"              default:
                  return nullptr;
            }
        }
");
            IncludeWriter.WriteLine(@"        void addCoordinates(CoordinateList& coordinates) override;");
            CppWriter.WriteLine(
                @"        void Abstract{0}::addCoordinates(CoordinateList& coordinates)
        {{", message.name);

            if (!message.IsRoot)
            {
                CppWriter.WriteLine(
                    @"            
            coordinates.Add(0);
            coordinates.Add(0);
            for (auto i = coordinates.size() - 1; i >= 2; --i)
            {
                coordinates.Set(i, coordinates.Get(i - 2));
            }

            coordinates.Set(0, fieldId());
            coordinates.Set(1, index());

            if (getParent() == nullptr)
                return;

            getParent()->addCoordinates(coordinates);");
            }

            CppWriter.WriteLine(@"        }
");

            IncludeWriter.WriteLine(@"        LocalMessageDescriptor getLocalMessageDescriptor() override;");

            CppWriter.WriteLine(
                @"        LocalMessageDescriptor Abstract{0}::getLocalMessageDescriptor()
        {{
            auto b = LocalMessageDescriptor();
            addCoordinates(*b.mutable_coordinate());
            return b;
        }}", message.name);

            IncludeWriter.WriteLine(@"        bool isBuilt() const { return m_positionInContent != -1; }");
        }
예제 #21
0
        protected override void GenerateClassIndex(messageType message, indexType index)
        {
            // indexes are build at build time
            var field      = index.ReferenceField;
            var fieldType  = FieldType(field);
            var sortByType = FieldType(index.SortingField);

            if (index.SortingField.type == typeType.@string)
            {
                sortByType = "const " + sortByType + "&";
            }

            IncludeWriter.WriteLine(
                @"        // Note: indexes are built during the build process, and aren't available before
        std::vector<{2}*> {0}List();
        {2}& get{1}(int index);
        int {0}Count() const;
        {2}* search{1}({3} item);
        {2}* search{1}({3} item, int min, int max);
"
                , index.name, index.name.Capitalize(), fieldType, sortByType);

            CppWriter.WriteLine(
                @"        std::vector<{3}*> Abstract{4}::{0}List()
        {{
            assert((""Index is not built yet!"", isBuilt()));

            auto count = {0}Count();
            auto list = std::vector<{3}*>();
            list.reserve(count);
            for (auto i = 0; i < count; ++i)
            {{
                list.push_back(&get{1}(i));
            }}
            return list;
        }}

        {3}& Abstract{4}::get{1}(int index)
        {{
            assert((""Index is not built yet!"", isBuilt()));
            return *dynamic_cast<{3}*>(getRoot()->decode(m_header.{2}(index)));
        }}

        int Abstract{4}::{0}Count() const
        {{
            assert((""Index is not built yet!"", isBuilt()));
            return m_header.{2}_size();
        }}

        {3}* Abstract{4}::search{1}({5} item)
        {{
            assert((""Index is not built yet!"", isBuilt()));

            // note: we don't use std::find so that 
            // we decode a minimum number of items
            return search{1}(item, 0, {0}Count() - 1);
        }}

        {3}* Abstract{4}::search{1}({5} item, int min, int max)
        {{
            assert((""Index is not built yet!"", isBuilt()));

            if (max < min)
                return nullptr;

            int avg = (min + max) >> 1;

            auto& candidate = get{1}(avg);
            {5} candidateKey = candidate.{6}();
            if (candidateKey == item)
                return &candidate;

            if (candidateKey < item)
                return search{1}(item, avg + 1, max);

            return search{1}(item, min, avg - 1);
        }}
"
                , index.name, index.name.Capitalize(), index.name.ToLowerInvariant(), fieldType, message.name, sortByType, index.sortBy);
        }
예제 #22
0
        protected override void GenerateClassNestedField(messageType message, fieldType field)
        {
            var fieldType = FieldType(field);

            if (field.modifier == modifierType.repeated)
            {
                IncludeWriter.WriteLine(
                    @"        {2}& add{1}();
        std::vector<{2}*> {0}List();
        {2}& get{1}(int index);
        int {0}Count() const;
"
                    , field.name, field.name.Capitalize(), fieldType);

                CppWriter.WriteLine(
                    @"        {3}& Abstract{4}::add{1}()
        {{
            assert((""Can't modify an already built object!"", !isBuilt()));
            auto index = m_{0}List.size();
            auto {0} = std::make_unique<{3}>();
            {0}->setFieldId({5});
            {0}->setIndex(index);
            {0}->setParent(this);
            m_{0}List.set(index, std::move({0}));
            return *m_{0}List.get(index);
        }}

        std::vector<{3}*> Abstract{4}::{0}List()
        {{
            auto count = {0}Count();
            auto list = std::vector<{3}*>();
            list.reserve(count);
            for (auto i = 0; i < count; ++i)
            {{
                list.push_back(&get{1}(i));
            }}
            return list;
        }}

        {3}& Abstract{4}::get{1}(int index)
        {{
            if (!m_{0}List.get(index))
            {{
                auto {0} = {3}::ParseFrom(contentStream(), m_header.{2}(index));
                {0}->setFieldId({5});
                {0}->setIndex(index);
                {0}->setParent(this);
                m_{0}List.set(index, std::move({0}));
            }}
            return *m_{0}List.get(index);
        }}

        int Abstract{4}::{0}Count() const
        {{
            return !isBuilt() ? m_{0}List.size() : m_header.{2}_size();
        }}"
                    , field.name, field.name.Capitalize(), field.name.ToLowerInvariant(), fieldType, message.name, field.id);
                return;
            }

            if (field.modifier == modifierType.optional)
            {
                IncludeWriter.WriteLine(
                    @"        {2}& add{1}(); // adds the optional {1}
        {2}* {0}();
        bool has{1}() const;
        void clear{1}();
        
"
                    , field.name, field.name.Capitalize(), fieldType);

                CppWriter.WriteLine(
                    @"        {3}& Abstract{4}::add{1}()
        {{
            if (m_{0} == nullptr)
            {{
                if (isBuilt() && has{1}())
                {{
                    {0}(); // decode from body
                }}
                else
                {{
                    assert((""Can't modify an already built object!"", !isBuilt()));
                    m_{0} = std::make_unique<{6}::{3}>();
                    m_{0}->setFieldId({5});
                    m_{0}->setParent(this);
                }}
            }}
            return *m_{0};
        }}

        {3}* Abstract{4}::{0}()
        {{
            if (isBuilt() && has{1}() && m_{0} == nullptr)
            {{
                m_{0} = {3}::ParseFrom(contentStream(), m_header.{2}());
                m_{0}->setFieldId({5});
                m_{0}->setParent(this);
            }}
            return m_{0}.get();
        }}

        bool Abstract{4}::has{1}() const
        {{
            return (isBuilt() && m_header.has_{2}()) || (!isBuilt() && m_{0} != nullptr);
        }}

        void Abstract{4}::clear{1}()
        {{
            assert((""Can't modify an already built object!"", !isBuilt()));
            m_{0}.reset();
        }}
"
                    , field.name, field.name.Capitalize(), field.name.ToLowerInvariant(), fieldType, message.name, field.id, Namespace);
                return;
            }

            IncludeWriter.WriteLine(@"        {1}& {0}();", field.name, fieldType);
            CppWriter.WriteLine(
                @"        {2}& Abstract{3}::{0}()
        {{
            if (m_{0} == nullptr)
            {{
                if (isBuilt())
                {{
                    m_{0} = {2}::ParseFrom(contentStream(), m_header.{1}());
                }}
                else
                {{
                    m_{0} = std::make_unique<{2}>();
                }}
                m_{0}->setFieldId({4});
                m_{0}->setParent(this);
            }}
            return *m_{0};
        }}
"
                , field.name, field.name.ToLowerInvariant(), fieldType, message.name, field.id);
        }
예제 #23
0
        protected override void GenerateClassReferenceField(messageType message, fieldType field)
        {
            var fieldType = FieldType(field);

            if (field.modifier == modifierType.repeated)
            {
                IncludeWriter.WriteLine(
                    @"        void add{1}({2}& item);
        void remove{1}({2}& item);
        std::vector<{2}*> {0}List();
        {2}& get{1}(int index);
        int {0}Count() const;
"
                    , field.name, field.name.Capitalize(), fieldType);

                CppWriter.WriteLine(
                    @"        void Abstract{4}::add{1}({3}& item)
        {{
            assert((""Can't modify an already built object!"", !isBuilt()));
            if (m_root != item.getRoot())
                throw std::runtime_error(""All objects should share the same root"");
            m_header.add_{2}()->CopyFrom(item.getLocalMessageDescriptor());
        }}

        void Abstract{4}::remove{1}({3}& item)
        {{
            assert((""Can't modify an already built object!"", !isBuilt()));
            auto vals = m_header.mutable_{2}();
            auto newEnd = std::remove_if(vals->begin(), vals->end(), [this, &item](const LocalMessageDescriptor& check) 
            {{ 
                return getRoot()->decode(check) == &item; 
            }});
            vals->DeleteSubrange(newEnd - vals->begin(), vals->end() - newEnd);
        }}

        std::vector<{3}*> Abstract{4}::{0}List()
        {{
            auto count = {0}Count();
            auto list = std::vector<{3}*>();
            list.reserve(count);
            for (auto i = 0; i < count; ++i)
            {{
                list.push_back(&get{1}(i));
            }}
            return list;
        }}

        {3}& Abstract{4}::get{1}(int index)
        {{
            return *dynamic_cast<{3}*>(getRoot()->decode(m_header.{2}(index)));
        }}

        int Abstract{4}::{0}Count() const
        {{
            return m_header.{2}_size();
        }}
"
                    , field.name, field.name.Capitalize(), field.name.ToLowerInvariant(), fieldType, message.name);
                return;
            }

            if (field.modifier == modifierType.optional)
            {
                IncludeWriter.WriteLine(
                    @"        bool has{0}() const {{ return m_header.has_{1}(); }}
        void clear{0}() {{ m_header.clear_{1}(); }}
"
                    , field.name.Capitalize(), field.name.ToLowerInvariant());
            }

            IncludeWriter.WriteLine(
                @"        void set{1}({2}& value);
        {2}* {0}();
"
                , field.name, field.name.Capitalize(), fieldType);

            CppWriter.WriteLine(
                @"        void Abstract{4}::set{1}({3}& value)
        {{
            if (m_root != value.getRoot())
                throw std::runtime_error(""All objects should share the same root"");
            m_header.clear_{2}();
            m_header.mutable_{2}()->CopyFrom(value.getLocalMessageDescriptor());
            // TODO see if that works // m_header.set_allocated_{2}(value.getLocalMessageDescriptor());
        }}

        {3}* Abstract{4}::{0}()
        {{
            return dynamic_cast<{3}*>(getRoot()->decode(m_header.{2}()));
        }}
"
                , field.name, field.name.Capitalize(), field.name.ToLowerInvariant(), fieldType, message.name);
        }
예제 #24
0
        protected override void GenerateToString(messageType message)
        {
            IncludeWriter.WriteLine(
                @"        using ProtoOrBuilder::toString;
        std::string toString(BaseFormat& format) override;
");
            CppWriter.WriteLine(
                @"        std::string Abstract{0}::toString(BaseFormat& format)
        {{
            auto bd = std::ostringstream();
", message.name);

            CppWriter.WriteLine(
                @"            format.formatHeader(bd,""{0}"");
", message.name);

            var fields = message.field.OrderBy(_ => _.id);

            foreach (var field in fields)
            {
                switch (field.modifier)
                {
                case modifierType.repeated:
                    if (field.type == typeType.referenceMessage)
                    {
                        CppWriter.WriteLine(
                            @"            format.formatField(bd, ""{1}List"", {0}Count()); 
    ", field.name, field.name.Capitalize());
                    }
                    else if (field.type == typeType.nestedMessage)
                    {
                        CppWriter.WriteLine(
                            @"            format.formatProtoField(bd, ""{1}List"", {0}List()); 
    ", field.name, field.name.Capitalize());
                    }
                    else
                    {
                        CppWriter.WriteLine(
                            @"            format.formatListField(bd, ""{1}List"", {0}List());
    ", field.name, field.name.Capitalize());
                    }
                    break;

                case modifierType.optional:
                    if (field.type == typeType.referenceMessage || field.type == typeType.nestedMessage)
                    {
                        CppWriter.WriteLine(
                            @"            format.formatProtoField(bd, ""{1}"", {0}(), has{1}());
", field.name, field.name.Capitalize());
                    }
                    else
                    {
                        CppWriter.WriteLine(
                            @"            format.formatField(bd, ""{1}"", {0}(), has{1}());
    ", field.name, field.name.Capitalize());
                    }
                    break;

                default:
                    if (field.type == typeType.referenceMessage || field.type == typeType.nestedMessage)
                    {
                        CppWriter.WriteLine(
                            @"            format.formatProtoField(bd, ""{0}"", {0}());", field.name);
                    }
                    else
                    {
                        CppWriter.WriteLine(
                            @"            format.formatField(bd, ""{0}"", {0}());", field.name);
                    }
                    break;
                }
            }

            CppWriter.WriteLine(
                @"            format.formatFooter(bd);
            return bd.str();
        }
");
        }
예제 #25
0
        protected override void GenerateClassFields(messageType message)
        {
            if (!message.IsRoot)
            {
                IncludeWriter.WriteLine(
                    @"    private: 
        ProtoOrBuilder* m_root;
        ProtoOrBuilder* m_parent;
        int m_fieldId = -1; // field's ID as defined in the protozbuf.xml file (=> the .proto file)
        int m_index = -1; // instance's index in the parent's list

    public: 
        ProtoOrBuilder* getParent() { return m_parent; }
        void setParent(ProtoOrBuilder* parent);

        int fieldId() const { return m_fieldId; }
        void setFieldId(int fieldId) { m_fieldId = fieldId; }
        int index() const { return m_index; }
        void setIndex(int index) { m_index = index; }
");

                CppWriter.WriteLine(
                    @"        void Abstract{0}::setParent(ProtoOrBuilder* parent)
        {{
            m_parent = parent;
            m_root = parent->getRoot();
        }}", message.name);
            }
            else
            {
                IncludeWriter.WriteLine(
                    @"    protected: 
        std::shared_ptr<std::iostream> m_contentStream;");
            }

            IncludeWriter.WriteLine(
                @"    protected: 
        {0}Header m_header;
        long m_positionInContent;

    public:
        int positionInContent() const {{ return m_positionInContent; }}
        void setPositionInContent(int positionInContent) {{ m_positionInContent = positionInContent; }}

    protected: "
                , message.name);

            var allFields = message.field.OrderBy(_ => _.id);

            var messageFields = from fld in allFields
                                where fld.messageType != null && fld.type != typeType.referenceMessage
                                select fld;

            foreach (var field in messageFields)
            {
                var fieldtype = FieldType(field);
                switch (field.modifier)
                {
                case modifierType.repeated:
                    IncludeWriter.WriteLine(
                        @"        {2}::ArrayList<{0}> m_{1}List;", fieldtype, field.name, ResourceNamespace);
                    break;

                default:
                    IncludeWriter.WriteLine(
                        @"        std::unique_ptr<{0}> m_{1};", fieldtype, field.name);
                    break;
                }
            }
        }