// Copyright 2018 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "tools/cddl/codegen.h" #include <algorithm> #include <cinttypes> #include <iostream> #include <limits> #include <memory> #include <optional> #include <set> #include <sstream> #include <string> #include <utility> #include <vector> // Convert '-' to '_' to use a CDDL identifier as a C identifier. std::string ToUnderscoreId(const std::string& x) { … } // Return default value for each type. The default value is used to // avoid undefined behavior when struct is initialized on the stack. std::string GetTypeDefaultValue(const std::string& type) { … } // Convert a CDDL identifier to camel case for use as a C typename. E.g. // presentation-connection-message to PresentationConnectionMessage. std::string ToCamelCase(const std::string& x) { … } // Returns a string which represents the C++ type of |cpp_type|. Returns an // empty string if there is no valid representation for |cpp_type| (e.g. a // vector with an invalid element type). std::string CppTypeToString(const CppType& cpp_type) { … } bool WriteEnumEqualityOperatorSwitchCases(int fd, const CppType& parent, std::string child_name, std::string parent_name) { … } // Write the equality operators for comparing an enum and its parent types. bool WriteEnumEqualityOperator(int fd, const CppType& type, const CppType& parent) { … } bool WriteEnumStreamOperatorSwitchCases(int fd, const CppType& type, std::string name) { … } bool WriteEnumOperators(int fd, const CppType& type) { … } // Writes the equality operator for a specific Discriminated Union. bool WriteDiscriminatedUnionEqualityOperator( int fd, const CppType& type, const std::string& name_prefix = "") { … } // Writes the equality operator for a specific C++ struct. bool WriteStructEqualityOperator(int fd, const CppType& type, const std::string& name_prefix = "") { … } // Write the C++ struct member definitions of every type in |members| to the // file descriptor |fd|. bool WriteStructMembers( int fd, const std::string& name, const std::vector<CppType::Struct::CppMember>& members) { … } void WriteEnumMembers(int fd, const CppType& type) { … } // Writes a C++ type definition for |type| to the file descriptor |fd|. This // only generates a definition for enums and structs. bool WriteTypeDefinition(int fd, const CppType& type) { … } // Ensures that any dependencies within |cpp_type| are written to the file // descriptor |fd| before writing |cpp_type| to the file descriptor |fd|. This // is done by walking the tree of types defined by |cpp_type| (e.g. all the // members for a struct). |defs| contains the names of types that have already // been written. If a type hasn't been written and needs to be, its name will // also be added to |defs|. bool EnsureDependentTypeDefinitionsWritten(int fd, const CppType& cpp_type, std::set<std::string>* defs) { … } // Writes the type definition for every C++ type in |table|. This function // makes sure to write them in such an order that all type dependencies are // written before they are need so the resulting text in the file descriptor // |fd| will compile without modification. For example, the following would be // bad output: // // struct Foo { // Bar bar; // int x; // }; // // struct Bar { // int alpha; // }; // // This function ensures that Bar would be written sometime before Foo. bool WriteTypeDefinitions(int fd, CppSymbolTable* table) { … } // Writes a parser that takes in a uint64_t and outputs the corresponding Type // if one matches up, or Type::kUnknown if none does. // NOTE: In future, this could be changes to use a Trie, which would allow for // manufacturers to more easily add their own type ids to ours. bool WriteTypeParserDefinition(int fd, CppSymbolTable* table) { … } // Writes the function prototypes for the encode and decode functions for each // type in |table| to the file descriptor |fd|. bool WriteFunctionDeclarations(int fd, CppSymbolTable* table) { … } bool WriteMapEncoder(int fd, const std::string& name, const std::vector<CppType::Struct::CppMember>& members, const std::string& nested_type_scope, int encoder_depth = 1); bool WriteArrayEncoder(int fd, const std::string& name, const std::vector<CppType::Struct::CppMember>& members, const std::string& nested_type_scope, int encoder_depth = 1); // Writes the encoding function for the C++ type |cpp_type| to the file // descriptor |fd|. |name| is the C++ variable name that needs to be encoded. // |nested_type_scope| is the closest C++ scope name (i.e. struct name), which // may be used to access local enum constants. |encoder_depth| is used to // independently name independent cbor encoders that need to be created. bool WriteEncoder(int fd, const std::string& name, const CppType& cpp_type, const std::string& nested_type_scope, int encoder_depth) { … } struct MemberCountResult { … }; MemberCountResult CountMemberTypes( int fd, const std::string& name_id, const std::vector<CppType::Struct::CppMember>& members) { … } // Writes the encoding function for a CBOR map with the C++ type members in // |members| to the file descriptor |fd|. |name| is the C++ variable name that // needs to be encoded. |nested_type_scope| is the closest C++ scope name (i.e. // struct name), which may be used to access local enum constants. // |encoder_depth| is used to independently name independent cbor encoders that // need to be created. bool WriteMapEncoder(int fd, const std::string& name, const std::vector<CppType::Struct::CppMember>& members, const std::string& nested_type_scope, int encoder_depth) { … } // Writes the encoding function for a CBOR array with the C++ type members in // |members| to the file descriptor |fd|. |name| is the C++ variable name that // needs to be encoded. |nested_type_scope| is the closest C++ scope name (i.e. // struct name), which may be used to access local enum constants. // |encoder_depth| is used to independently name independent cbor encoders that // need to be created. bool WriteArrayEncoder(int fd, const std::string& name, const std::vector<CppType::Struct::CppMember>& members, const std::string& nested_type_scope, int encoder_depth) { … } uint8_t GetByte(uint64_t value, size_t byte) { … } std::string GetEncodedTypeKey(const CppType& type) { … } // Writes encoding functions for each type in |table| to the file descriptor // |fd|. bool WriteEncoders(int fd, CppSymbolTable* table) { … } bool WriteMapDecoder(int fd, const std::string& name, const std::vector<CppType::Struct::CppMember>& members, int decoder_depth, int* temporary_count); bool WriteArrayDecoder(int fd, const std::string& name, const std::vector<CppType::Struct::CppMember>& members, int decoder_depth, int* temporary_count); // Writes the decoding function for the C++ type |cpp_type| to the file // descriptor |fd|. |name| is the C++ variable name that needs to be decoded. // |decoder_depth| is used to independently name independent cbor // decoders that need to be created. |temporary_count| is used to ensure // temporaries get unique names by appending an automatically incremented // integer. bool WriteDecoder(int fd, const std::string& name, const CppType& cpp_type, int decoder_depth, int* temporary_count) { … } // Writes the decoding function for the CBOR map with members in |members| to // the file descriptor |fd|. |name| is the C++ variable name that needs to be // decoded. |decoder_depth| is used to independently name independent // cbor decoders that need to be created. |temporary_count| is used to ensure // temporaries get unique names by appending an automatically incremented // integer. bool WriteMapDecoder(int fd, const std::string& name, const std::vector<CppType::Struct::CppMember>& members, int decoder_depth, int* temporary_count) { … } // Writes the decoding function for the CBOR array with members in |members| to // the file descriptor |fd|. |name| is the C++ variable name that needs to be // decoded. |decoder_depth| is used to independently name independent // cbor decoders that need to be created. |temporary_count| is used to ensure // temporaries get unique names by appending an automatically incremented // integer. bool WriteArrayDecoder(int fd, const std::string& name, const std::vector<CppType::Struct::CppMember>& members, int decoder_depth, int* temporary_count) { … } // Writes the equality operators for all structs. bool WriteEqualityOperators(int fd, CppSymbolTable* table) { … } // Writes a decoder function definition for every type in |table| to the file // descriptor |fd|. bool WriteDecoders(int fd, CppSymbolTable* table) { … } // Converts the filename |header_filename| to a preprocessor token that can be // used as a header guard macro name. std::string ToHeaderGuard(const std::string& header_filename) { … } bool WriteHeaderPrologue(int fd, const std::string& header_filename) { … } bool WriteHeaderEpilogue(int fd, const std::string& header_filename) { … } bool WriteSourcePrologue(int fd, const std::string& header_filename) { … } bool WriteSourceEpilogue(int fd) { … }