diff --git a/core/core.gypi b/core/core.gypi index 669d5f5..db55004 100644 --- a/core/core.gypi +++ b/core/core.gypi @@ -15,6 +15,7 @@ { 'variables': { 'core_cpp_files': [ + 'enum_validator.h' 'idl_base.h', 'idl_types.h', 'js_type_traits.h', diff --git a/core/enum_validator.h b/core/enum_validator.h new file mode 100644 index 0000000..3af4b19 --- /dev/null +++ b/core/enum_validator.h @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2017 The Bacardi Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CORE_ENUM_VALIDATOR_H_ +#define CORE_ENUM_VALIDATOR_H_ + +#include +#include + +class EnumValidator { + public: + static bool isValildEnum(const std::string value, + const std::set enum_values) { + if (enum_values.count(value) > 0) { + return true; + } + return false; + } +}; + +#endif // CORE_ENUM_VALIDATOR_H_ diff --git a/core/idl_types.h b/core/idl_types.h index f435a63..b2b23da 100644 --- a/core/idl_types.h +++ b/core/idl_types.h @@ -25,8 +25,5 @@ struct IDLLongLong final : public IDLBaseHelper {}; struct IDLLong final : public IDLBaseHelper {}; struct IDLShort final : public IDLBaseHelper {}; struct IDLString final : public IDLBaseHelper {}; -// FIXME(Hwansung): should be generated automatically in another file. -struct IDLOperationType final : public IDLBaseHelper {}; -struct IDLTestEnum final : public IDLBaseHelper {}; #endif // CORE_IDL_TYPES_H_ diff --git a/core/native_type_traits.h b/core/native_type_traits.h index 1a77ff7..6635959 100644 --- a/core/native_type_traits.h +++ b/core/native_type_traits.h @@ -160,81 +160,4 @@ struct NativeTypeTraits : public NativeTypeTraitsBase { } }; -// FIXME(Hwansung): should be generated automatically in another file. -template <> -struct NativeTypeTraits - : public NativeTypeTraitsBase { - static std::string NativeValue(const Napi::Env& env, - const Napi::Value& js_value) { - if (!js_value.IsString()) { - Napi::TypeError::New(env, "It's an invalid string.") - .ThrowAsJavaScriptException(); - return std::string(); - } - - std::string value = js_value.ToString().Utf8Value(); - if (!IsValidValue(value)) { - Napi::TypeError::New(env, "it not matched with values of enum in idl.") - .ThrowAsJavaScriptException(); - return std::string(); - } - - return js_value.ToString().Utf8Value(); - } - - static bool IsTypeEquals(const Napi::Value& js_value) { - if (js_value.IsString()) { - std::string value = js_value.ToString().Utf8Value(); - return IsValidValue(value); - } - return false; - } - - static bool IsValidValue(std::string value) { - if (value.compare("add") == 0 || value.compare("sub") == 0 || - value.compare("mul") == 0 || value.compare("div") == 0) { - return true; - } - return false; - } -}; - -template <> -struct NativeTypeTraits - : public NativeTypeTraitsBase { - static std::string NativeValue(const Napi::Env& env, - const Napi::Value& js_value) { - if (!js_value.IsString()) { - Napi::TypeError::New(env, "It's an invalid string.") - .ThrowAsJavaScriptException(); - return std::string(); - } - - std::string value = js_value.ToString().Utf8Value(); - if (!IsValidValue(value)) { - Napi::TypeError::New(env, "it not matched with values of enum in idl.") - .ThrowAsJavaScriptException(); - return std::string(); - } - - return js_value.ToString().Utf8Value(); - } - - static bool IsTypeEquals(const Napi::Value& js_value) { - if (js_value.IsString()) { - std::string value = js_value.ToString().Utf8Value(); - return IsValidValue(value); - } - return false; - } - - static bool IsValidValue(std::string value) { - if (value.compare("value1") == 0 || value.compare("value2") == 0 || - value.compare("value3") == 0) { - return true; - } - return false; - } -}; - #endif // CORE_NATIVE_TYPE_TRAITS_H_ diff --git a/generator/main.ts b/generator/main.ts index 7fe934c..f895be2 100644 --- a/generator/main.ts +++ b/generator/main.ts @@ -23,7 +23,10 @@ import * as reader from './reader/simple_reader'; import snakeCase = require('snake-case'); +import EnumTypes from './parser/enum_types'; import IDLDefinition from './parser/idl_definition'; +import IDLEnum from './parser/idl_enum'; +import IDLInterface from './parser/idl_interface'; import Parser from './parser/parser'; const TEMPLATE_DIR = path.resolve(__dirname, '../../../template'); @@ -72,6 +75,24 @@ async function generateInterface( }); } +// TODO(hwansueng): This function should be improved. +async function postProcessing(definitions: IDLDefinition[]) { + let enum_types: EnumTypes = new EnumTypes(definitions); + + for (const definition of definitions) { + if (definition.isIDLInterface()) { + const idl_interface: IDLInterface = definition as IDLInterface; + for (const member of idl_interface.members) { + if (member.arguments != null) { + for (let args of member.arguments) { + args.enum = enum_types.isEnumType(args.type); + } + } + } + } + } +} + async function main([root_dir, out_dir, ...idl_files]) { // We expect that current working directory will be $BACARDI_PATH. But it // might not be in Windows platform. So, we should resolve the path here. @@ -94,6 +115,7 @@ async function main([root_dir, out_dir, ...idl_files]) { let definitions: IDLDefinition[] = await Parser.parse(await reader.readAll(relative_idl_files)); + await postProcessing(definitions); await generateInterface(env, out_dir, definitions); await generateBacardi(env, out_dir, definitions); diff --git a/generator/parser/enum_types.ts b/generator/parser/enum_types.ts new file mode 100644 index 0000000..04ad9ce --- /dev/null +++ b/generator/parser/enum_types.ts @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2017 The Bacardi Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import IDLDefinition from './idl_definition'; +import IDLEnum from './idl_enum'; + + +export default class EnumTypes { + enums: IDLEnum[]; + + constructor(definitions: IDLDefinition[]) { + this.enums = []; + definitions.forEach((definition) => { + if (definition.isIDLEnum()) { + this.enums.push(definition as IDLEnum); + } + }); + } + + public isEnumType(source: string): IDLEnum { + for (const item of this.enums) { + if (item.name == source) { + return item; + } + } + return null; + } +} diff --git a/generator/parser/idl_interface.ts b/generator/parser/idl_interface.ts index 6906b80..6566d6a 100644 --- a/generator/parser/idl_interface.ts +++ b/generator/parser/idl_interface.ts @@ -15,6 +15,7 @@ */ import IDLDefinition from './idl_definition'; +import IDLEnum from './idl_enum'; import IDLIdentifier from './idl_identifier'; // FIXME(zino): We should consider attribute and operation concept. @@ -22,10 +23,12 @@ import IDLIdentifier from './idl_identifier'; class Argument implements IDLIdentifier { readonly type: string; readonly name: string; + enum?: IDLEnum; constructor(raw_argument_info: {}) { this.type = raw_argument_info['idlType']['idlType']; this.name = raw_argument_info['name']; + this.enum = null; } } diff --git a/template/interface_cpp.njk b/template/interface_cpp.njk index b450e23..a5f3c6f 100644 --- a/template/interface_cpp.njk +++ b/template/interface_cpp.njk @@ -18,6 +18,7 @@ #include "core/js_type_traits.h" #include "core/native_type_traits.h" +#include "core/enum_validator.h" void {{name}}Bridge::Init(Napi::Env env, Napi::Object exports) { Napi::Function js_constructor = @@ -106,11 +107,26 @@ Napi::Value {{name}}Bridge::{{member.name | camelcase}}(const Napi::CallbackInfo } {% for argument in member.arguments %} + {% if argument.enum %} + const std::set enum_value_set = { + {% for value in argument.enum.values %} + "{{value}}", + {% endfor %} + }; + auto {{argument.name}} = NativeTypeTraits::NativeValue(info.Env(), info[{{loop.index0}}]); + if (!EnumValidator::isValildEnum({{argument.name}}, enum_value_set)) { + Napi::TypeError::New(info.Env(), "it not matched with values of enum in idl.") + .ThrowAsJavaScriptException(); + return Napi::Value(); + } + {% else %} auto {{argument.name}} = NativeTypeTraits::NativeValue(info.Env(), info[{{loop.index0}}]); if (info.Env().IsExceptionPending()) { return Napi::Value(); } + {% endif %} {% endfor %} {% if member.type != "void" %}