Moving from govendor to dep, updated dependencies (#48)

* Moving from govendor to dep.

* Making the pull request template more friendly.

* Fixing akward space in PR template.

* goimports run on whole project using ` goimports -w $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./gen-go/*")`

source of command: https://gist.github.com/bgentry/fd1ffef7dbde01857f66
This commit is contained in:
Renan DelValle 2018-01-07 13:13:47 -08:00 committed by GitHub
parent 9631aa3aab
commit 8d445c1c77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2186 changed files with 400410 additions and 352 deletions

View file

@ -0,0 +1,206 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h)
find_package(FLEX REQUIRED)
find_package(BISON REQUIRED)
# Create flex and bison files and build the lib parse static library
BISON_TARGET(thrifty ${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/thrifty.yy ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.cc)
FLEX_TARGET(thriftl ${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/thriftl.ll ${CMAKE_CURRENT_BINARY_DIR}/thrift/thriftl.cc)
ADD_FLEX_BISON_DEPENDENCY(thriftl thrifty)
# HACK: Work around the fact that bison crates a .hh file but we need a .h file
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.h
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.hh ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.h
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.hh
)
set(libparse_SOURCES
${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.cc
${CMAKE_CURRENT_BINARY_DIR}/thrift/thriftl.cc
${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.h
)
add_library(libparse STATIC ${libparse_SOURCES})
# Create the thrift compiler
set(compiler_core
src/thrift/common.cc
src/thrift/generate/t_generator.cc
src/thrift/parse/t_typedef.cc
src/thrift/parse/parse.cc
${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h
)
set(thrift-compiler_SOURCES
src/thrift/main.cc
src/thrift/audit/t_audit.cpp
)
# This macro adds an option THRIFT_COMPILER_${NAME}
# that allows enabling or disabling certain languages
macro(THRIFT_ADD_COMPILER name description initial)
string(TOUPPER "THRIFT_COMPILER_${name}" enabler)
set(src "src/thrift/generate/t_${name}_generator.cc")
option(${enabler} ${description} ${initial})
if(${enabler})
list(APPEND thrift-compiler_SOURCES ${src})
endif()
endmacro()
# The following compiler can be enabled or disabled
THRIFT_ADD_COMPILER(c_glib "Enable compiler for C with Glib" ON)
THRIFT_ADD_COMPILER(cpp "Enable compiler for C++" ON)
THRIFT_ADD_COMPILER(java "Enable compiler for Java" ON)
THRIFT_ADD_COMPILER(as3 "Enable compiler for ActionScript 3" ON)
THRIFT_ADD_COMPILER(dart "Enable compiler for Dart" ON)
THRIFT_ADD_COMPILER(haxe "Enable compiler for Haxe" ON)
THRIFT_ADD_COMPILER(csharp "Enable compiler for C#" ON)
THRIFT_ADD_COMPILER(py "Enable compiler for Python 2.0" ON)
THRIFT_ADD_COMPILER(rb "Enable compiler for Ruby" ON)
THRIFT_ADD_COMPILER(perl "Enable compiler for Perl" ON)
THRIFT_ADD_COMPILER(php "Enable compiler for PHP" ON)
THRIFT_ADD_COMPILER(erl "Enable compiler for Erlang" ON)
THRIFT_ADD_COMPILER(cocoa "Enable compiler for Cocoa Objective-C" ON)
THRIFT_ADD_COMPILER(swift "Enable compiler for Cocoa Swift" ON)
THRIFT_ADD_COMPILER(st "Enable compiler for Smalltalk" ON)
THRIFT_ADD_COMPILER(ocaml "Enable compiler for OCaml" ON)
THRIFT_ADD_COMPILER(hs "Enable compiler for Haskell" ON)
THRIFT_ADD_COMPILER(xsd "Enable compiler for XSD" ON)
THRIFT_ADD_COMPILER(html "Enable compiler for HTML Documentation" ON)
THRIFT_ADD_COMPILER(js "Enable compiler for JavaScript" ON)
THRIFT_ADD_COMPILER(json "Enable compiler for JSON" ON)
THRIFT_ADD_COMPILER(javame "Enable compiler for Java ME" ON)
THRIFT_ADD_COMPILER(delphi "Enable compiler for Delphi" ON)
THRIFT_ADD_COMPILER(go "Enable compiler for Go" ON)
THRIFT_ADD_COMPILER(d "Enable compiler for D" ON)
THRIFT_ADD_COMPILER(lua "Enable compiler for Lua" ON)
THRIFT_ADD_COMPILER(gv "Enable compiler for GraphViz" ON)
THRIFT_ADD_COMPILER(xml "Enable compiler for XML" ON)
# Thrift is looking for include files in the src directory
# we also add the current binary directory for generated files
include_directories(${CMAKE_CURRENT_BINARY_DIR} src)
if(NOT ${WITH_PLUGIN})
list(APPEND thrift-compiler_SOURCES ${compiler_core})
endif()
add_executable(thrift-compiler ${thrift-compiler_SOURCES})
if(${WITH_PLUGIN})
add_executable(thrift-bootstrap ${compiler_core}
src/thrift/main.cc
src/thrift/audit/t_audit.cpp
src/thrift/generate/t_cpp_generator.cc
)
target_link_libraries(thrift-bootstrap libparse)
set(PLUGIN_GEN_SOURCES
${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_types.h
${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_types.cpp
${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_constants.h
${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_constants.cpp
)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin)
add_custom_command(OUTPUT ${PLUGIN_GEN_SOURCES}
DEPENDS thrift-bootstrap src/thrift/plugin/plugin.thrift
COMMAND thrift-bootstrap -gen cpp
-out ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin
${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/plugin/plugin.thrift
)
include_directories(../../lib/cpp/src)
include(ThriftMacros)
ADD_LIBRARY_THRIFT(thriftc
${compiler_core}
${PLUGIN_GEN_SOURCES}
src/thrift/logging.cc
src/thrift/plugin/plugin_output.cc
src/thrift/plugin/plugin.cc
)
TARGET_INCLUDE_DIRECTORIES_THRIFT(thriftc PUBLIC ${Boost_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES_THRIFT_AGAINST_THRIFT_LIBRARY(thriftc thrift PUBLIC)
target_compile_definitions(thrift-compiler PUBLIC THRIFT_ENABLE_PLUGIN)
LINK_AGAINST_THRIFT_LIBRARY(thrift-compiler thriftc)
endif()
set_target_properties(thrift-compiler PROPERTIES OUTPUT_NAME thrift)
target_link_libraries(thrift-compiler libparse)
install(TARGETS thrift-compiler DESTINATION "${BIN_INSTALL_DIR}")
if(${WITH_PLUGIN})
# Install the headers
install(FILES
"src/thrift/common.h"
"src/thrift/globals.h"
"src/thrift/logging.h"
"src/thrift/main.h"
"src/thrift/platform.h"
"${CMAKE_BINARY_DIR}/compiler/cpp/thrift/version.h"
DESTINATION "${INCLUDE_INSTALL_DIR}/thrift")
install(FILES
"src/thrift/audit/t_audit.h"
DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/audit")
install(FILES
"src/thrift/generate/t_generator.h"
"src/thrift/generate/t_generator_registry.h"
"src/thrift/generate/t_html_generator.h"
"src/thrift/generate/t_oop_generator.h"
DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/generate")
install(FILES
"src/thrift/parse/t_base_type.h"
"src/thrift/parse/t_const.h"
"src/thrift/parse/t_const_value.h"
"src/thrift/parse/t_container.h"
"src/thrift/parse/t_doc.h"
"src/thrift/parse/t_enum.h"
"src/thrift/parse/t_enum_value.h"
"src/thrift/parse/t_field.h"
"src/thrift/parse/t_function.h"
"src/thrift/parse/t_list.h"
"src/thrift/parse/t_map.h"
"src/thrift/parse/t_program.h"
"src/thrift/parse/t_scope.h"
"src/thrift/parse/t_service.h"
"src/thrift/parse/t_set.h"
"src/thrift/parse/t_struct.h"
"src/thrift/parse/t_typedef.h"
"src/thrift/parse/t_type.h"
DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/parse")
install(FILES
"src/thrift/plugin/plugin.h"
"src/thrift/plugin/plugin_output.h"
"src/thrift/plugin/type_util.h"
DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/plugin")
if(MSVC)
install(FILES
"src/thrift/windows/config.h"
DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/windows")
endif()
endif()
if(BUILD_TESTING)
add_subdirectory(test)
endif()

View file

@ -0,0 +1,203 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
#
# Contains some contributions under the Thrift Software License.
# Please see doc/old-thrift-license.txt in the Thrift distribution for
# details.
AUTOMAKE_OPTIONS = subdir-objects
# Note on why we have src/thrift and src/thrift/plugin directories:
# Since Automake supports only one set of BUILT_SOURCES per file and does not allow
# SUBDIRS built before BUILT_SOURCES, we end up separate Makefile.am for each source
# code generation, i.e. lex-yacc and Thrift, to achieve stable parallel make.
SUBDIRS = src src/thrift/plugin .
if WITH_TESTS
SUBDIRS += test
endif
bin_PROGRAMS = thrift
thrift_OBJDIR = obj
plugin_gen = src/thrift/plugin/plugin_types.h \
src/thrift/plugin/plugin_types.cpp \
src/thrift/plugin/plugin_constants.h \
src/thrift/plugin/plugin_constants.cpp
compiler_core = src/thrift/common.h \
src/thrift/common.cc \
src/thrift/generate/t_generator.cc \
src/thrift/generate/t_generator_registry.h \
src/thrift/globals.h \
src/thrift/platform.h \
src/thrift/logging.h \
src/thrift/parse/t_doc.h \
src/thrift/parse/t_type.h \
src/thrift/parse/t_base_type.h \
src/thrift/parse/t_enum.h \
src/thrift/parse/t_enum_value.h \
src/thrift/parse/t_typedef.h \
src/thrift/parse/t_typedef.cc \
src/thrift/parse/t_container.h \
src/thrift/parse/t_list.h \
src/thrift/parse/t_set.h \
src/thrift/parse/t_map.h \
src/thrift/parse/t_struct.h \
src/thrift/parse/t_field.h \
src/thrift/parse/t_service.h \
src/thrift/parse/t_function.h \
src/thrift/parse/t_program.h \
src/thrift/parse/t_scope.h \
src/thrift/parse/t_const.h \
src/thrift/parse/t_const_value.h \
src/thrift/parse/parse.cc \
src/thrift/generate/t_generator.h \
src/thrift/generate/t_oop_generator.h \
src/thrift/generate/t_html_generator.h
thrift_SOURCES = src/thrift/main.h \
src/thrift/main.cc \
src/thrift/audit/t_audit.cpp \
src/thrift/audit/t_audit.h
# Specific client generator source
thrift_SOURCES += src/thrift/generate/t_c_glib_generator.cc \
src/thrift/generate/t_cpp_generator.cc \
src/thrift/generate/t_java_generator.cc \
src/thrift/generate/t_json_generator.cc \
src/thrift/generate/t_as3_generator.cc \
src/thrift/generate/t_dart_generator.cc \
src/thrift/generate/t_haxe_generator.cc \
src/thrift/generate/t_csharp_generator.cc \
src/thrift/generate/t_py_generator.cc \
src/thrift/generate/t_rb_generator.cc \
src/thrift/generate/t_perl_generator.cc \
src/thrift/generate/t_php_generator.cc \
src/thrift/generate/t_erl_generator.cc \
src/thrift/generate/t_cocoa_generator.cc \
src/thrift/generate/t_swift_generator.cc \
src/thrift/generate/t_st_generator.cc \
src/thrift/generate/t_ocaml_generator.cc \
src/thrift/generate/t_hs_generator.cc \
src/thrift/generate/t_xsd_generator.cc \
src/thrift/generate/t_xml_generator.cc \
src/thrift/generate/t_html_generator.cc \
src/thrift/generate/t_js_generator.cc \
src/thrift/generate/t_javame_generator.cc \
src/thrift/generate/t_delphi_generator.cc \
src/thrift/generate/t_go_generator.cc \
src/thrift/generate/t_gv_generator.cc \
src/thrift/generate/t_d_generator.cc \
src/thrift/generate/t_lua_generator.cc
thrift_CPPFLAGS = -I$(srcdir)/src
thrift_CXXFLAGS = -Wall -Wextra -pedantic
thrift_LDADD = @LEXLIB@ src/thrift/libparse.a
if !WITH_PLUGIN
thrift_SOURCES += $(compiler_core)
else
lib_LTLIBRARIES = libthriftc.la
thrift_CPPFLAGS += -DTHRIFT_ENABLE_PLUGIN=1
thrift_LDADD += libthriftc.la
nodist_libthriftc_la_SOURCES = $(plugin_gen)
libthriftc_la_SOURCES = $(compiler_core) \
src/thrift/plugin/type_util.h \
src/thrift/plugin/plugin.h \
src/thrift/plugin/plugin.cc \
src/thrift/plugin/plugin_output.h \
src/thrift/plugin/plugin_output.cc \
src/thrift/plugin/plugin.thrift \
src/thrift/logging.cc
libthriftc_la_CPPFLAGS = -I$(srcdir)/src -Isrc -I$(top_builddir)/lib/cpp/src -DTHRIFT_ENABLE_PLUGIN=1
libthriftc_la_CXXFLAGS = -Wall -Wextra -pedantic
libthriftc_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la
include_thriftdir = $(includedir)/thrift
include_thrift_HEADERS = src/thrift/common.h \
src/thrift/globals.h \
src/thrift/logging.h \
src/thrift/main.h \
src/thrift/platform.h \
src/thrift/version.h
include_auditdir = $(include_thriftdir)/windows
include_audit_HEADERS = src/thrift/audit/t_audit.h
include_generatedir = $(include_thriftdir)/generate
include_generate_HEADERS = src/thrift/generate/t_generator.h \
src/thrift/generate/t_generator_registry.h \
src/thrift/generate/t_oop_generator.h \
src/thrift/generate/t_html_generator.h
include_parsedir = $(include_thriftdir)/parse
include_parse_HEADERS = src/thrift/parse/t_service.h \
src/thrift/parse/t_program.h \
src/thrift/parse/t_field.h \
src/thrift/parse/t_scope.h \
src/thrift/parse/t_typedef.h \
src/thrift/parse/t_set.h \
src/thrift/parse/t_const_value.h \
src/thrift/parse/t_enum_value.h \
src/thrift/parse/t_const.h \
src/thrift/parse/t_list.h \
src/thrift/parse/t_map.h \
src/thrift/parse/t_container.h \
src/thrift/parse/t_base_type.h \
src/thrift/parse/t_enum.h \
src/thrift/parse/t_function.h \
src/thrift/parse/t_type.h \
src/thrift/parse/t_doc.h \
src/thrift/parse/t_struct.h
include_plugindir = $(include_thriftdir)/plugin
include_plugin_HEADERS = src/thrift/plugin/plugin.h \
src/thrift/plugin/type_util.h \
src/thrift/plugin/plugin_output.h
include_windowsdir = $(include_thriftdir)/windows
include_windows_HEADERS = src/thrift/windows/config.h
endif
WINDOWS_DIST = \
compiler.sln \
compiler.vcxproj \
compiler.vcxproj.filters
EXTRA_DIST = \
coding_standards.md \
README.md \
CMakeLists.txt \
test \
$(WINDOWS_DIST)
clean-local:
$(RM) version.h $(plugin_gen)
src/thrift/main.cc: src/thrift/version.h
style-local:
$(CPPSTYLE_CMD)

View file

@ -0,0 +1,83 @@
# Build compiler using CMake
Use the following steps to build using cmake:
mkdir cmake-build
cd cmake-build
cmake ..
make
### Create an eclipse project
mkdir cmake-ec && cd cmake-ec
cmake -G "Eclipse CDT4 - Unix Makefiles" ..
make
Now open the folder cmake-ec using eclipse.
### Cross compile using mingw32 and generate a Windows Installer with CPack
mkdir cmake-mingw32 && cd cmake-mingw32
cmake -DCMAKE_TOOLCHAIN_FILE=../build/cmake/mingw32-toolchain.cmake -DBUILD_COMPILER=ON -DBUILD_LIBRARIES=OFF -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF ..
cpack
## Build on windows
### using Git Bash
Git Bash provides flex and bison, so you just need to do this:
mkdir cmake-vs && cd cmake-vs
cmake -DWITH_SHARED_LIB=off ..
### using Win flex-bison
In order to build on windows with winflexbison a few additional steps are necessary:
1. Download winflexbison from http://sourceforge.net/projects/winflexbison/
2. Extract the winflex bison files to for e.g. C:\winflexbison
3. Make the CMake variables point to the correct binaries.
* FLEX_EXECUTABLE = C:/winbuild/win_flex.exe
* BISON_EXECUTABLE = C:/winbuild/win_bison.exe
4. Generate a Visual Studio project:
```
mkdir cmake-vs && cd cmake-vs
cmake -G "Visual Studio 12" -DWITH_SHARED_LIB=off ..
```
5. Now open the folder build_vs using Visual Studio 2013.
# Building the Thrift IDL compiler in Windows
If you don't want to use CMake you can use the already available Visual Studio
2010 solution.
The Visual Studio project contains pre-build commands to generate the
thriftl.cc, thrifty.cc and thrifty.hh files which are necessary to build
the compiler. These depend on bison, flex and their dependencies to
work properly.
Download flex & bison as described above.
Place these binaries somewhere in the path and
rename win_flex.exe and win_bison.exe to flex.exe and bison.exe respectively.
If this doesn't work on a system, try these manual pre-build steps.
Open compiler.sln and remove the Pre-build commands under the project's
Properties -> Build Events -> Pre-Build Events.
From a command prompt:
> cd thrift/compiler/cpp
> flex -osrc\thrift\thriftl.cc src\thrift\thriftl.ll
In the generated thriftl.cc, comment out #include <unistd.h>
Place a copy of bison.simple in thrift/compiler/cpp
> bison -y -o "src/thrift/thrifty.cc" --defines src/thrift/thrifty.yy
> move src\thrift\thrifty.cc.hh src\thrift\thrifty.hh
Bison might generate the yacc header file "thrifty.cc.h" with just one h ".h" extension; in this case you'll have to rename to "thrifty.h".
> move src\thrift\version.h.in src\thrift\version.h
Download inttypes.h from the interwebs and place it in an include path
location (e.g. thrift/compiler/cpp/src).
Build the compiler in Visual Studio.

View file

@ -0,0 +1,4 @@
## Compiler Coding Standards
* When making small change / bugfix - follow style as seen in nearby code.
* When making major refactor and / or adding new feature - follow style for C++ library

View file

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "compiler", "compiler.vcxproj", "{89975A1A-F799-4556-98B8-64E30AB39A90}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{89975A1A-F799-4556-98B8-64E30AB39A90}.Debug|Win32.ActiveCfg = Debug|Win32
{89975A1A-F799-4556-98B8-64E30AB39A90}.Debug|Win32.Build.0 = Debug|Win32
{89975A1A-F799-4556-98B8-64E30AB39A90}.Release|Win32.ActiveCfg = Release|Win32
{89975A1A-F799-4556-98B8-64E30AB39A90}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,249 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\thrift\audit\t_audit.h" />
<ClInclude Include="src\thrift\common.h" />
<ClInclude Include="src\thrift\generate\t_generator.h" />
<ClInclude Include="src\thrift\generate\t_generator_registry.h" />
<ClInclude Include="src\thrift\generate\t_oop_generator.h" />
<ClInclude Include="src\thrift\generate\t_html_generator.h" />
<ClInclude Include="src\thrift\globals.h" />
<ClInclude Include="src\thrift\main.h" />
<ClInclude Include="src\thrift\parse\t_base_type.h" />
<ClInclude Include="src\thrift\parse\t_const.h" />
<ClInclude Include="src\thrift\parse\t_const_value.h" />
<ClInclude Include="src\thrift\parse\t_container.h" />
<ClInclude Include="src\thrift\parse\t_doc.h" />
<ClInclude Include="src\thrift\parse\t_enum.h" />
<ClInclude Include="src\thrift\parse\t_enum_value.h" />
<ClInclude Include="src\thrift\parse\t_field.h" />
<ClInclude Include="src\thrift\parse\t_function.h" />
<ClInclude Include="src\thrift\parse\t_list.h" />
<ClInclude Include="src\thrift\parse\t_map.h" />
<ClInclude Include="src\thrift\parse\t_program.h" />
<ClInclude Include="src\thrift\parse\t_scope.h" />
<ClInclude Include="src\thrift\parse\t_service.h" />
<ClInclude Include="src\thrift\parse\t_set.h" />
<ClInclude Include="src\thrift\parse\t_struct.h" />
<ClInclude Include="src\thrift\parse\t_type.h" />
<ClInclude Include="src\thrift\parse\t_typedef.h" />
<ClInclude Include="src\thrift\platform.h" />
<ClInclude Include="src\thrift\thrifty.hh" />
<ClInclude Include="src\thrift\windows\config.h" />
<ClInclude Include="src\thrift\version.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\thrift\audit\t_audit.cpp"/>
<ClCompile Include="src\thrift\common.cc" />
<ClCompile Include="src\thrift\generate\t_as3_generator.cc" />
<ClCompile Include="src\thrift\generate\t_cocoa_generator.cc" />
<ClCompile Include="src\thrift\generate\t_cpp_generator.cc" />
<ClCompile Include="src\thrift\generate\t_csharp_generator.cc" />
<ClCompile Include="src\thrift\generate\t_c_glib_generator.cc" />
<ClCompile Include="src\thrift\generate\t_d_generator.cc" />
<ClCompile Include="src\thrift\generate\t_dart_generator.cc" />
<ClCompile Include="src\thrift\generate\t_delphi_generator.cc" />
<ClCompile Include="src\thrift\generate\t_erl_generator.cc" />
<ClCompile Include="src\thrift\generate\t_generator.cc" />
<ClCompile Include="src\thrift\generate\t_go_generator.cc" />
<ClCompile Include="src\thrift\generate\t_gv_generator.cc" />
<ClCompile Include="src\thrift\generate\t_haxe_generator.cc" />
<ClCompile Include="src\thrift\generate\t_hs_generator.cc" />
<ClCompile Include="src\thrift\generate\t_html_generator.cc" />
<ClCompile Include="src\thrift\generate\t_javame_generator.cc" />
<ClCompile Include="src\thrift\generate\t_java_generator.cc" />
<ClCompile Include="src\thrift\generate\t_js_generator.cc" />
<ClCompile Include="src\thrift\generate\t_json_generator.cc" />
<ClCompile Include="src\thrift\generate\t_lua_generator.cc" />
<ClCompile Include="src\thrift\generate\t_ocaml_generator.cc" />
<ClCompile Include="src\thrift\generate\t_perl_generator.cc" />
<ClCompile Include="src\thrift\generate\t_php_generator.cc" />
<ClCompile Include="src\thrift\generate\t_py_generator.cc" />
<ClCompile Include="src\thrift\generate\t_rb_generator.cc" />
<ClCompile Include="src\thrift\generate\t_st_generator.cc" />
<ClCompile Include="src\thrift\generate\t_swift_generator.cc" />
<ClCompile Include="src\thrift\generate\t_xml_generator.cc" />
<ClCompile Include="src\thrift\generate\t_xsd_generator.cc" />
<ClCompile Include="src\thrift\main.cc" />
<ClCompile Include="src\thrift\parse\parse.cc" />
<ClCompile Include="src\thrift\parse\t_typedef.cc" />
<ClCompile Include="src\thrift\thriftl.cc" />
<ClCompile Include="src\thrift\thrifty.cc" />
</ItemGroup>
<ItemGroup>
<None Include="src\thrift\thriftl.ll" />
<None Include="src\thrift\thrifty.yy" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{89975A1A-F799-4556-98B8-64E30AB39A90}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>compiler</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(IncludePath)</IncludePath>
<TargetName>thrift</TargetName>
<ExecutablePath>$(ExecutablePath);C:\Program Files (x86)\Git\bin</ExecutablePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(IncludePath)</IncludePath>
<TargetName>thrift</TargetName>
<ExecutablePath>$(ExecutablePath);C:\Program Files (x86)\Git\bin</ExecutablePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(IncludePath)</IncludePath>
<TargetName>thrift</TargetName>
<ExecutablePath>$(ExecutablePath);C:\Program Files (x86)\Git\bin</ExecutablePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(IncludePath)</IncludePath>
<TargetName>thrift</TargetName>
<ExecutablePath>$(ExecutablePath);C:\Program Files (x86)\Git\bin</ExecutablePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;MINGW;YY_NO_UNISTD_H;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ForcedIncludeFiles>thrift\windows\config.h</ForcedIncludeFiles>
<CompileAs>CompileAsCpp</CompileAs>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PreBuildEvent>
<Command>flex -o "src\\thrift\\thriftl.cc" src/thrift/thriftl.ll &amp;&amp; bison -y -o "src\\thrift\\thrifty.cc" --defines="src\\thrift\\thrifty.hh" src/thrift/thrifty.yy</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;MINGW;YY_NO_UNISTD_H;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ForcedIncludeFiles>thrift\windows\config.h</ForcedIncludeFiles>
<CompileAs>CompileAsCpp</CompileAs>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PreBuildEvent>
<Command>flex -o "src\\thrift\\thriftl.cc" src/thrift/thriftl.ll &amp;&amp; bison -y -o "src\\thrift\\thrifty.cc" --defines="src\\thrift\\thrifty.hh" src/thrift/thrifty.yy</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;MINGW;YY_NO_UNISTD_H;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ForcedIncludeFiles>thrift\windows\config.h</ForcedIncludeFiles>
<CompileAs>CompileAsCpp</CompileAs>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PreBuildEvent>
<Command>flex -o "src\\thrift\\thriftl.cc" src/thrift/thriftl.ll &amp;&amp; bison -y -o "src\\thrift\\thrifty.cc" --defines="src\\thrift\\thrifty.hh" src/thrift/thrifty.yy</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;MINGW;YY_NO_UNISTD_H;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ForcedIncludeFiles>thrift\windows\config.h</ForcedIncludeFiles>
<CompileAs>CompileAsCpp</CompileAs>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PreBuildEvent>
<Command>flex -o "src\\thrift\\thriftl.cc" src/thrift/thriftl.ll &amp;&amp; bison -y -o "src\\thrift\\thrifty.cc" --defines="src\\thrift\\thrifty.hh" src/thrift/thrifty.yy</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,196 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClInclude Include="src\audit\t_audit.h" />
<ClInclude Include="src\generate\t_generator.h">
<Filter>generate</Filter>
</ClInclude>
<ClInclude Include="src\generate\t_generator_registry.h">
<Filter>generate</Filter>
</ClInclude>
<ClInclude Include="src\generate\t_oop_generator.h">
<Filter>generate</Filter>
</ClInclude>
<ClInclude Include="src\generate\t_html_generator.h">
<Filter>generate</Filter>
</ClInclude>
<ClInclude Include="src\globals.h" />
<ClInclude Include="src\main.h" />
<ClInclude Include="src\parse\t_base_type.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_const.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_const_value.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_container.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_doc.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_enum.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_enum_value.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_field.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_function.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_list.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_map.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_program.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_scope.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_service.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_set.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_struct.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_type.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\parse\t_typedef.h">
<Filter>parse</Filter>
</ClInclude>
<ClInclude Include="src\platform.h" />
<ClInclude Include="src\thrifty.hh" />
<ClInclude Include="src\windows\config.h">
<Filter>windows</Filter>
</ClInclude>
<ClInclude Include="src\windows\version.h">
<Filter>windows</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="windows">
<UniqueIdentifier>{ae9d0a15-57ae-4f01-87a4-81f790249b83}</UniqueIdentifier>
</Filter>
<Filter Include="parse">
<UniqueIdentifier>{5df016bb-591b-420a-a535-4330d9187fbf}</UniqueIdentifier>
</Filter>
<Filter Include="generate">
<UniqueIdentifier>{b5c626af-afa5-433c-8e10-ee734533cb68}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\audit\t_audit.cpp"/>
<ClCompile Include="src\generate\t_as3_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_cocoa_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_cpp_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_csharp_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_c_glib_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_d_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_dart_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_delphi_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_erl_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_go_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_gv_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_haxe_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_hs_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_html_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_javame_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_java_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_js_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_ocaml_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_perl_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_php_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_py_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_rb_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_st_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_swift_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_xsd_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_xml_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\main.cc" />
<ClCompile Include="src\parse\parse.cc">
<Filter>parse</Filter>
</ClCompile>
<ClCompile Include="src\thriftl.cc" />
<ClCompile Include="src\thrifty.cc" />
<ClCompile Include="src\parse\t_typedef.cc">
<Filter>parse</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_json_generator.cc">
<Filter>generate</Filter>
</ClCompile>
<ClCompile Include="src\generate\t_lua_generator.cc">
<Filter>generate</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="src\thriftl.ll" />
<None Include="src\thrifty.yy" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,87 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
#
# Contains some contributions under the Thrift Software License.
# Please see doc/old-thrift-license.txt in the Thrift distribution for
# details.
AUTOMAKE_OPTIONS = subdir-objects
AM_YFLAGS = -d
BUILT_SOURCES = thrift/thrifty.cc
noinst_LIBRARIES = thrift/libparse.a
thrift_libparse_a_CPPFLAGS = -I$(srcdir)
thrift_libparse_a_CXXFLAGS = -Wall -Wno-sign-compare -Wno-unused
thrift_libparse_a_SOURCES = thrift/thrifty.yy \
thrift/thriftl.ll
clean-local:
$(RM) thrift/thriftl.cc thrift/thrifty.cc thrift/thrifty.h thrift/thrifty.hh
if WITH_PLUGIN
noinst_PROGRAMS = thrift/thrift-bootstrap
thrift_thrift_bootstrap_SOURCES = \
thrift/common.h \
thrift/common.cc \
thrift/audit/t_audit.h \
thrift/audit/t_audit.cpp \
thrift/generate/t_generator.cc \
thrift/generate/t_generator_registry.h \
thrift/globals.h \
thrift/platform.h \
thrift/logging.h \
thrift/parse/t_doc.h \
thrift/parse/t_type.h \
thrift/parse/t_base_type.h \
thrift/parse/t_enum.h \
thrift/parse/t_enum_value.h \
thrift/parse/t_typedef.h \
thrift/parse/t_typedef.cc \
thrift/parse/t_container.h \
thrift/parse/t_list.h \
thrift/parse/t_set.h \
thrift/parse/t_map.h \
thrift/parse/t_struct.h \
thrift/parse/t_field.h \
thrift/parse/t_service.h \
thrift/parse/t_function.h \
thrift/parse/t_program.h \
thrift/parse/t_scope.h \
thrift/parse/t_const.h \
thrift/parse/t_const_value.h \
thrift/parse/parse.cc \
thrift/generate/t_generator.h \
thrift/generate/t_oop_generator.h \
thrift/generate/t_html_generator.h \
thrift/windows/config.h \
thrift/version.h \
thrift/generate/t_cpp_generator.cc \
thrift/main.h \
thrift/main.cc
main.cc: version.h
thrift_thrift_bootstrap_CXXFLAGS = -Wall -Wextra -pedantic
thrift_thrift_bootstrap_LDADD = @LEXLIB@ thrift/libparse.a
endif

View file

@ -0,0 +1,464 @@
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <string>
#include <algorithm>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>
// Careful: must include globals first for extern definitions
#include "thrift/globals.h"
#include "thrift/parse/t_program.h"
#include "thrift/parse/t_scope.h"
#include "thrift/parse/t_const.h"
#include "thrift/parse/t_field.h"
#include "thrift/version.h"
#include "thrift/audit/t_audit.h"
extern int g_warn;
extern std::string g_curpath;
extern bool g_return_failure;
void thrift_audit_warning(int level, const char* fmt, ...) {
if (g_warn < level) {
return;
}
va_list args;
printf("[Thrift Audit Warning:%s] ", g_curpath.c_str());
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
printf("\n");
}
void thrift_audit_failure(const char* fmt, ...) {
va_list args;
fprintf(stderr, "[Thrift Audit Failure:%s] ", g_curpath.c_str());
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "\n");
g_return_failure = true;
}
void compare_namespace(t_program* newProgram, t_program* oldProgram)
{
const std::map<std::string, std::string>& newNamespaceMap = newProgram->get_all_namespaces();
const std::map<std::string, std::string>& oldNamespaceMap = oldProgram->get_all_namespaces();
for(std::map<std::string, std::string>::const_iterator oldNamespaceMapIt = oldNamespaceMap.begin();
oldNamespaceMapIt != oldNamespaceMap.end();
oldNamespaceMapIt++)
{
std::map<std::string, std::string>::const_iterator newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt->first);
if(newNamespaceMapIt == newNamespaceMap.end())
{
thrift_audit_warning(1, "Language %s not found in new thrift file\n", (oldNamespaceMapIt->first).c_str());
}
else if((newNamespaceMapIt->second) != oldNamespaceMapIt->second)
{
thrift_audit_warning(1, "Namespace %s changed in new thrift file\n", (oldNamespaceMapIt->second).c_str());
}
}
}
void compare_enum_values(t_enum* newEnum,t_enum* oldEnum)
{
const std::vector<t_enum_value*>& oldEnumValues = oldEnum->get_constants();
for(std::vector<t_enum_value*>::const_iterator oldEnumValuesIt = oldEnumValues.begin();
oldEnumValuesIt != oldEnumValues.end();
oldEnumValuesIt++)
{
int enumValue = (*oldEnumValuesIt)->get_value();
t_enum_value* newEnumValue = newEnum->get_constant_by_value(enumValue);
if(newEnumValue != NULL)
{
std::string enumName = (*oldEnumValuesIt)->get_name();
if(enumName != newEnumValue->get_name())
{
thrift_audit_warning(1, "Name of the value %d changed in enum %s\n", enumValue, oldEnum->get_name().c_str());
}
}
else
{
thrift_audit_failure("Enum value %d missing in %s\n", enumValue, oldEnum->get_name().c_str());
}
}
}
void compare_enums(const std::vector<t_enum*>& newEnumList, const std::vector<t_enum*>& oldEnumList)
{
std::map<std::string,t_enum*> newEnumMap;
std::vector<t_enum*>::const_iterator newEnumIt;
for(newEnumIt = newEnumList.begin(); newEnumIt != newEnumList.end(); newEnumIt++)
{
newEnumMap[(*newEnumIt)->get_name()] = *newEnumIt;
}
std::vector<t_enum*>::const_iterator oldEnumIt;
for(oldEnumIt = oldEnumList.begin(); oldEnumIt != oldEnumList.end(); oldEnumIt++)
{
std::map<std::string,t_enum*>::iterator newEnumMapIt;
newEnumMapIt = newEnumMap.find((*oldEnumIt)->get_name());
if(newEnumMapIt == newEnumMap.end())
{
thrift_audit_warning(1, "Enum %s not found in new thrift file\n",(*oldEnumIt)->get_name().c_str());
}
else
{
compare_enum_values(newEnumMapIt->second, *oldEnumIt);
}
}
}
//This function returns 'true' if the two arguements are of same types.
//Returns false if they are of different type
bool compare_type(t_type* newType, t_type* oldType)
{
//Comparing names of two types will work when the newType and oldType are basic types or structs or enums.
//However, when they are containers, get_name() returns empty for which we have to compare the type of
//their elements as well.
if((newType->get_name()).empty() && (oldType->get_name()).empty())
{
if(newType->is_list() && oldType->is_list())
{
t_type* newElementType = ((t_list*)newType)->get_elem_type();
t_type* oldElementType = ((t_list*)oldType)->get_elem_type();
return compare_type(newElementType, oldElementType);
}
else if(newType->is_map() && oldType->is_map())
{
t_type* newKeyType = ((t_map*)newType)->get_key_type();
t_type* oldKeyType = ((t_map*)oldType)->get_key_type();
t_type* newValType = ((t_map*)newType)->get_val_type();
t_type* oldValType = ((t_map*)oldType)->get_val_type();
return (compare_type(newKeyType, oldKeyType) && compare_type(newValType, oldValType));
}
else if(newType->is_set() && oldType->is_set())
{
t_type* newElementType = ((t_set*)newType)->get_elem_type();
t_type* oldElementType = ((t_set*)oldType)->get_elem_type();
return compare_type(newElementType, oldElementType);
}
else
{
return false;
}
}
else if(newType->get_name() == oldType->get_name())
{
return true;
}
else
{
return false;
}
}
bool compare_pair(std::pair<t_const_value*, t_const_value*> newMapPair, std::pair<t_const_value*, t_const_value*> oldMapPair)
{
return compare_defaults(newMapPair.first, oldMapPair.first) && compare_defaults(newMapPair.second, oldMapPair.second);
}
// This function returns 'true' if the default values are same. Returns false if they are different.
bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault)
{
if(newStructDefault == NULL && oldStructDefault == NULL) return true;
else if(newStructDefault == NULL && oldStructDefault != NULL) return false;
else if (newStructDefault != NULL && oldStructDefault == NULL) return false;
if(newStructDefault->get_type() != oldStructDefault->get_type())
{
return false;
}
switch(newStructDefault->get_type())
{
case t_const_value::CV_INTEGER:
return (newStructDefault->get_integer() == oldStructDefault->get_integer());
case t_const_value::CV_DOUBLE:
return (newStructDefault->get_double() == oldStructDefault->get_double());
case t_const_value::CV_STRING:
return (newStructDefault->get_string() == oldStructDefault->get_string());
case t_const_value::CV_LIST:
{
const std::vector<t_const_value*>& oldDefaultList = oldStructDefault->get_list();
const std::vector<t_const_value*>& newDefaultList = newStructDefault->get_list();
bool defaultValuesCompare = (oldDefaultList.size() == newDefaultList.size());
return defaultValuesCompare && std::equal(newDefaultList.begin(), newDefaultList.end(), oldDefaultList.begin(), compare_defaults);
}
case t_const_value::CV_MAP:
{
const std::map<t_const_value*, t_const_value*> newMap = newStructDefault->get_map();
const std::map<t_const_value*, t_const_value*> oldMap = oldStructDefault->get_map();
bool defaultValuesCompare = (oldMap.size() == newMap.size());
return defaultValuesCompare && std::equal(newMap.begin(), newMap.end(), oldMap.begin(), compare_pair);
}
case t_const_value::CV_IDENTIFIER:
return (newStructDefault->get_identifier() == oldStructDefault->get_identifier());
default:
return false;
}
}
void compare_struct_field(t_field* newField, t_field* oldField, std::string oldStructName)
{
t_type* newFieldType = newField->get_type();
t_type* oldFieldType = oldField->get_type();
if(!compare_type(newFieldType, oldFieldType))
{
thrift_audit_failure("Struct Field Type Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
}
// A Struct member can be optional if it is mentioned explicitly, or if it is assigned with default values.
bool newStructFieldOptional = (newField->get_req() != t_field::T_REQUIRED);
bool oldStructFieldOptional = (oldField->get_req() != t_field::T_REQUIRED);
if(newStructFieldOptional != oldStructFieldOptional)
{
thrift_audit_failure("Struct Field Requiredness Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
}
if(newStructFieldOptional || oldStructFieldOptional)
{
if(!compare_defaults(newField->get_value(), oldField->get_value()))
{
thrift_audit_warning(1, "Default value changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
}
}
std::string fieldName = newField->get_name();
if(fieldName != oldField->get_name())
{
thrift_audit_warning(1, "Struct field name changed for Id = %d in %s\n", newField->get_key(), oldStructName.c_str());
}
}
void compare_single_struct(t_struct* newStruct, t_struct* oldStruct, const std::string& oldStructName = std::string())
{
std::string structName = oldStructName.empty() ? oldStruct->get_name() : oldStructName;
const std::vector<t_field*>& oldStructMembersInIdOrder = oldStruct->get_sorted_members();
const std::vector<t_field*>& newStructMembersInIdOrder = newStruct->get_sorted_members();
std::vector<t_field*>::const_iterator oldStructMemberIt = oldStructMembersInIdOrder.begin();
std::vector<t_field*>::const_iterator newStructMemberIt = newStructMembersInIdOrder.begin();
// Since we have the struct members in their ID order, comparing their IDs can be done by traversing the two member
// lists together.
while(!(oldStructMemberIt == oldStructMembersInIdOrder.end() && newStructMemberIt == newStructMembersInIdOrder.end()))
{
if(newStructMemberIt == newStructMembersInIdOrder.end() && oldStructMemberIt != oldStructMembersInIdOrder.end())
{
// A field ID has been removed from the end.
thrift_audit_failure("Struct Field removed for Id = %d in %s \n", (*oldStructMemberIt)->get_key(), structName.c_str());
oldStructMemberIt++;
}
else if(newStructMemberIt != newStructMembersInIdOrder.end() && oldStructMemberIt == oldStructMembersInIdOrder.end())
{
//New field ID has been added to the end.
if((*newStructMemberIt)->get_req() == t_field::T_REQUIRED)
{
thrift_audit_failure("Required Struct Field Added for Id = %d in %s \n", (*newStructMemberIt)->get_key(), structName.c_str());
}
newStructMemberIt++;
}
else if((*newStructMemberIt)->get_key() == (*oldStructMemberIt)->get_key())
{
//Field ID found in both structs. Compare field types, default values.
compare_struct_field(*newStructMemberIt, *oldStructMemberIt, structName);
newStructMemberIt++;
oldStructMemberIt++;
}
else if((*newStructMemberIt)->get_key() < (*oldStructMemberIt)->get_key())
{
//New Field Id is inserted in between
//Adding fields to struct is fine, but adding them in the middle is suspicious. Error!!
thrift_audit_failure("Struct field is added in the middle with Id = %d in %s\n", (*newStructMemberIt)->get_key(), structName.c_str());
newStructMemberIt++;
}
else if((*newStructMemberIt)->get_key() > (*oldStructMemberIt)->get_key())
{
//A field is deleted in newStruct.
thrift_audit_failure("Struct Field removed for Id = %d in %s \n", (*oldStructMemberIt)->get_key(), structName.c_str());
oldStructMemberIt++;
}
}
}
void compare_structs(const std::vector<t_struct*>& newStructList, const std::vector<t_struct*>& oldStructList)
{
std::map<std::string,t_struct*> newStructMap;
std::vector<t_struct*>::const_iterator newStructListIt;
for(newStructListIt = newStructList.begin(); newStructListIt != newStructList.end(); newStructListIt++)
{
newStructMap[(*newStructListIt)->get_name()] = *newStructListIt;
}
std::vector<t_struct*>::const_iterator oldStructListIt;
for(oldStructListIt = oldStructList.begin(); oldStructListIt != oldStructList.end(); oldStructListIt++)
{
std::map<std::string, t_struct*>::iterator newStructMapIt;
newStructMapIt = newStructMap.find((*oldStructListIt)->get_name());
if(newStructMapIt == newStructMap.end())
{
thrift_audit_failure("Struct %s not found in new thrift file\n", (*oldStructListIt)->get_name().c_str());
}
else
{
compare_single_struct(newStructMapIt->second, *oldStructListIt);
}
}
}
void compare_single_function(t_function* newFunction, t_function* oldFunction)
{
t_type* newFunctionReturnType = newFunction->get_returntype();
if(newFunction->is_oneway() != oldFunction->is_oneway())
{
thrift_audit_failure("Oneway attribute changed for function %s\n",oldFunction->get_name().c_str());
}
if(!compare_type(newFunctionReturnType, oldFunction->get_returntype()))
{
thrift_audit_failure("Return type changed for function %s\n",oldFunction->get_name().c_str());
}
//Compare function arguments.
compare_single_struct(newFunction->get_arglist(), oldFunction->get_arglist());
std::string exceptionName = oldFunction->get_name();
exceptionName += "_exception";
compare_single_struct(newFunction->get_xceptions(), oldFunction->get_xceptions(), exceptionName);
}
void compare_functions(const std::vector<t_function*>& newFunctionList, const std::vector<t_function*>& oldFunctionList)
{
std::map<std::string, t_function*> newFunctionMap;
std::map<std::string, t_function*>::iterator newFunctionMapIt;
for(std::vector<t_function*>::const_iterator newFunctionIt = newFunctionList.begin();
newFunctionIt != newFunctionList.end();
newFunctionIt++)
{
newFunctionMap[(*newFunctionIt)->get_name()] = *newFunctionIt;
}
for(std::vector<t_function*>::const_iterator oldFunctionIt = oldFunctionList.begin();
oldFunctionIt != oldFunctionList.end();
oldFunctionIt++)
{
newFunctionMapIt = newFunctionMap.find((*oldFunctionIt)->get_name());
if(newFunctionMapIt == newFunctionMap.end())
{
thrift_audit_failure("New Thrift File has missing function %s\n",(*oldFunctionIt)->get_name().c_str());
continue;
}
else
{
//Function is found in both thrift files. Compare return type and argument list
compare_single_function(newFunctionMapIt->second, *oldFunctionIt);
}
}
}
void compare_services(const std::vector<t_service*>& newServices, const std::vector<t_service*>& oldServices)
{
std::vector<t_service*>::const_iterator oldServiceIt;
std::map<std::string, t_service*> newServiceMap;
for(std::vector<t_service*>::const_iterator newServiceIt = newServices.begin();
newServiceIt != newServices.end();
newServiceIt++)
{
newServiceMap[(*newServiceIt)->get_name()] = *newServiceIt;
}
for(oldServiceIt = oldServices.begin(); oldServiceIt != oldServices.end(); oldServiceIt++)
{
const std::string oldServiceName = (*oldServiceIt)->get_name();
std::map<std::string, t_service*>::iterator newServiceMapIt = newServiceMap.find(oldServiceName);
if(newServiceMapIt == newServiceMap.end())
{
thrift_audit_failure("New Thrift file is missing a service %s\n", oldServiceName.c_str());
}
else
{
t_service* oldServiceExtends = (*oldServiceIt)->get_extends();
t_service* newServiceExtends = (newServiceMapIt->second)->get_extends();
if(oldServiceExtends == NULL)
{
// It is fine to add extends. So if service in older thrift did not have any extends, we are fine.
// DO Nothing
}
else if(oldServiceExtends != NULL && newServiceExtends == NULL)
{
thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str());
}
else
{
std::string oldExtendsName = oldServiceExtends->get_name();
std::string newExtendsName = newServiceExtends->get_name();
if( newExtendsName != oldExtendsName)
{
thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str());
}
}
compare_functions((newServiceMapIt->second)->get_functions(), (*oldServiceIt)->get_functions());
}
}
}
void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst)
{
std::vector<t_const*>::const_iterator newConstIt;
std::vector<t_const*>::const_iterator oldConstIt;
std::map<std::string, t_const*> newConstMap;
for(newConstIt = newConst.begin(); newConstIt != newConst.end(); newConstIt++)
{
newConstMap[(*newConstIt)->get_name()] = *newConstIt;
}
std::map<std::string, t_const*>::const_iterator newConstMapIt;
for(oldConstIt = oldConst.begin(); oldConstIt != oldConst.end(); oldConstIt++)
{
newConstMapIt = newConstMap.find((*oldConstIt)->get_name());
if(newConstMapIt == newConstMap.end())
{
thrift_audit_warning(1, "Constants Missing %s \n", ((*oldConstIt)->get_name()).c_str());
}
else if(!compare_type((newConstMapIt->second)->get_type(), (*oldConstIt)->get_type()))
{
thrift_audit_warning(1, "Constant %s is of different type \n", ((*oldConstIt)->get_name()).c_str());
}
else if(!compare_defaults((newConstMapIt->second)->get_value(), (*oldConstIt)->get_value()))
{
thrift_audit_warning(1, "Constant %s has different value\n", ((*oldConstIt)->get_name()).c_str());
}
}
}

View file

@ -0,0 +1,14 @@
#ifndef T_AUDIT_H
#define T_AUDIT_H
void compare_namespace(t_program* newProgram, t_program* oldProgram);
void compare_enums(const std::vector<t_enum*>& newEnumList,
const std::vector<t_enum*>& oldEnumList);
bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault);
void compare_structs(const std::vector<t_struct*>& newStructList,
const std::vector<t_struct*>& oldStructList);
void compare_services(const std::vector<t_service*>& newServices,
const std::vector<t_service*>& oldServices);
void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst);
#endif

View file

@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include "thrift/common.h"
#include "thrift/parse/t_base_type.h"
t_type* g_type_void;
t_type* g_type_string;
t_type* g_type_binary;
t_type* g_type_slist;
t_type* g_type_bool;
t_type* g_type_i8;
t_type* g_type_i16;
t_type* g_type_i32;
t_type* g_type_i64;
t_type* g_type_double;
void initGlobals() {
g_type_void = new t_base_type("void", t_base_type::TYPE_VOID);
g_type_string = new t_base_type("string", t_base_type::TYPE_STRING);
g_type_binary = new t_base_type("string", t_base_type::TYPE_STRING);
((t_base_type*)g_type_binary)->set_binary(true);
g_type_slist = new t_base_type("string", t_base_type::TYPE_STRING);
((t_base_type*)g_type_slist)->set_string_list(true);
g_type_bool = new t_base_type("bool", t_base_type::TYPE_BOOL);
g_type_i8 = new t_base_type("i8", t_base_type::TYPE_I8);
g_type_i16 = new t_base_type("i16", t_base_type::TYPE_I16);
g_type_i32 = new t_base_type("i32", t_base_type::TYPE_I32);
g_type_i64 = new t_base_type("i64", t_base_type::TYPE_I64);
g_type_double = new t_base_type("double", t_base_type::TYPE_DOUBLE);
}
void clearGlobals() {
delete g_type_void;
delete g_type_string;
delete g_type_bool;
delete g_type_i8;
delete g_type_i16;
delete g_type_i32;
delete g_type_i64;
delete g_type_double;
}
/**
* Those are not really needed for plugins but causes link errors without
*/
/**
* The location of the last parsed doctext comment.
*/
int g_doctext_lineno;
int g_program_doctext_lineno = 0;
PROGDOCTEXT_STATUS g_program_doctext_status = INVALID;

View file

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_COMMON_H
#define T_COMMON_H
#include "thrift/parse/t_type.h"
/**
* Global types for the parser to be able to reference
*/
extern t_type* g_type_void;
extern t_type* g_type_string;
extern t_type* g_type_binary;
extern t_type* g_type_slist;
extern t_type* g_type_bool;
extern t_type* g_type_i8;
extern t_type* g_type_i16;
extern t_type* g_type_i32;
extern t_type* g_type_i64;
extern t_type* g_type_double;
void initGlobals();
void clearGlobals();
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,728 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*
* Contains some contributions under the Thrift Software License.
* Please see doc/old-thrift-license.txt in the Thrift distribution for
* details.
*/
#include <cassert>
#include <fstream>
#include <iostream>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <sys/stat.h>
#include "thrift/platform.h"
#include "thrift/generate/t_oop_generator.h"
using std::map;
using std::ofstream;
using std::ostream;
using std::ostringstream;
using std::set;
using std::string;
using std::vector;
static const string endl = "\n"; // avoid ostream << std::endl flushes
/**
* D code generator.
*
* generate_*() functions are called by the base class to emit code for the
* given entity, print_*() functions write a piece of code to the passed
* stream, and render_*() return a string containing the D representation of
* the passed entity.
*/
class t_d_generator : public t_oop_generator {
public:
t_d_generator(t_program* program,
const std::map<string, string>& parsed_options,
const string& option_string)
: t_oop_generator(program) {
(void)option_string;
std::map<std::string, std::string>::const_iterator iter;
/* no options yet */
for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
throw "unknown option d:" + iter->first;
}
out_dir_base_ = "gen-d";
}
protected:
virtual void init_generator() {
// Make output directory
MKDIR(get_out_dir().c_str());
string dir = program_->get_namespace("d");
string subdir = get_out_dir();
string::size_type loc;
while ((loc = dir.find(".")) != string::npos) {
subdir = subdir + "/" + dir.substr(0, loc);
MKDIR(subdir.c_str());
dir = dir.substr(loc + 1);
}
if (!dir.empty()) {
subdir = subdir + "/" + dir;
MKDIR(subdir.c_str());
}
package_dir_ = subdir + "/";
// Make output file
string f_types_name = package_dir_ + program_name_ + "_types.d";
f_types_.open(f_types_name.c_str());
// Print header
f_types_ << autogen_comment() << "module " << render_package(*program_) << program_name_
<< "_types;" << endl << endl;
print_default_imports(f_types_);
// Include type modules from other imported programs.
const vector<t_program*>& includes = program_->get_includes();
for (size_t i = 0; i < includes.size(); ++i) {
f_types_ << "import " << render_package(*(includes[i])) << includes[i]->get_name()
<< "_types;" << endl;
}
if (!includes.empty())
f_types_ << endl;
}
virtual void close_generator() {
// Close output file
f_types_.close();
}
virtual void generate_consts(std::vector<t_const*> consts) {
if (!consts.empty()) {
string f_consts_name = package_dir_ + program_name_ + "_constants.d";
ofstream f_consts;
f_consts.open(f_consts_name.c_str());
f_consts << autogen_comment() << "module " << render_package(*program_) << program_name_
<< "_constants;" << endl << endl;
print_default_imports(f_consts);
f_consts << "import " << render_package(*get_program()) << program_name_ << "_types;" << endl
<< endl;
vector<t_const*>::iterator c_iter;
for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
string name = (*c_iter)->get_name();
t_type* type = (*c_iter)->get_type();
indent(f_consts) << "immutable(" << render_type_name(type) << ") " << name << ";" << endl;
}
f_consts << endl << "static this() {" << endl;
indent_up();
bool first = true;
for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
if (first) {
first = false;
} else {
f_consts << endl;
}
t_type* type = (*c_iter)->get_type();
indent(f_consts) << (*c_iter)->get_name() << " = ";
if (!is_immutable_type(type)) {
f_consts << "cast(immutable(" << render_type_name(type) << ")) ";
}
f_consts << render_const_value(type, (*c_iter)->get_value()) << ";" << endl;
}
indent_down();
indent(f_consts) << "}" << endl;
}
}
virtual void generate_typedef(t_typedef* ttypedef) {
f_types_ << indent() << "alias " << render_type_name(ttypedef->get_type()) << " "
<< ttypedef->get_symbolic() << ";" << endl << endl;
}
virtual void generate_enum(t_enum* tenum) {
vector<t_enum_value*> constants = tenum->get_constants();
string enum_name = tenum->get_name();
f_types_ << indent() << "enum " << enum_name << " {" << endl;
indent_up();
vector<t_enum_value*>::const_iterator c_iter;
bool first = true;
for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
if (first) {
first = false;
} else {
f_types_ << "," << endl;
}
indent(f_types_) << (*c_iter)->get_name();
f_types_ << " = " << (*c_iter)->get_value();
}
f_types_ << endl;
indent_down();
indent(f_types_) << "}" << endl;
f_types_ << endl;
}
virtual void generate_struct(t_struct* tstruct) {
print_struct_definition(f_types_, tstruct, false);
}
virtual void generate_xception(t_struct* txception) {
print_struct_definition(f_types_, txception, true);
}
virtual void generate_service(t_service* tservice) {
string svc_name = tservice->get_name();
// Service implementation file includes
string f_servicename = package_dir_ + svc_name + ".d";
std::ofstream f_service;
f_service.open(f_servicename.c_str());
f_service << autogen_comment() << "module " << render_package(*program_) << svc_name << ";"
<< endl << endl;
print_default_imports(f_service);
f_service << "import " << render_package(*get_program()) << program_name_ << "_types;" << endl;
t_service* extends_service = tservice->get_extends();
if (extends_service != NULL) {
f_service << "import " << render_package(*(extends_service->get_program()))
<< extends_service->get_name() << ";" << endl;
}
f_service << endl;
string extends = "";
if (tservice->get_extends() != NULL) {
extends = " : " + render_type_name(tservice->get_extends());
}
f_service << indent() << "interface " << svc_name << extends << " {" << endl;
indent_up();
// Collect all the exception types service methods can throw so we can
// emit the necessary aliases later.
set<t_type*> exception_types;
// Print the method signatures.
vector<t_function*> functions = tservice->get_functions();
vector<t_function*>::iterator fn_iter;
for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) {
f_service << indent();
print_function_signature(f_service, *fn_iter);
f_service << ";" << endl;
const vector<t_field*>& exceptions = (*fn_iter)->get_xceptions()->get_members();
vector<t_field*>::const_iterator ex_iter;
for (ex_iter = exceptions.begin(); ex_iter != exceptions.end(); ++ex_iter) {
exception_types.insert((*ex_iter)->get_type());
}
}
// Alias the exception types into the current scope.
if (!exception_types.empty())
f_service << endl;
set<t_type*>::const_iterator et_iter;
for (et_iter = exception_types.begin(); et_iter != exception_types.end(); ++et_iter) {
indent(f_service) << "alias " << render_package(*(*et_iter)->get_program())
<< (*et_iter)->get_program()->get_name() << "_types"
<< "." << (*et_iter)->get_name() << " " << (*et_iter)->get_name() << ";"
<< endl;
}
// Write the method metadata.
ostringstream meta;
indent_up();
bool first = true;
for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) {
if ((*fn_iter)->get_arglist()->get_members().empty()
&& (*fn_iter)->get_xceptions()->get_members().empty() && !(*fn_iter)->is_oneway()) {
continue;
}
if (first) {
first = false;
} else {
meta << ",";
}
meta << endl << indent() << "TMethodMeta(`" << (*fn_iter)->get_name() << "`, " << endl;
indent_up();
indent(meta) << "[";
bool first = true;
const vector<t_field*>& params = (*fn_iter)->get_arglist()->get_members();
vector<t_field*>::const_iterator p_iter;
for (p_iter = params.begin(); p_iter != params.end(); ++p_iter) {
if (first) {
first = false;
} else {
meta << ", ";
}
meta << "TParamMeta(`" << (*p_iter)->get_name() << "`, " << (*p_iter)->get_key();
t_const_value* cv = (*p_iter)->get_value();
if (cv != NULL) {
meta << ", q{" << render_const_value((*p_iter)->get_type(), cv) << "}";
}
meta << ")";
}
meta << "]";
if (!(*fn_iter)->get_xceptions()->get_members().empty() || (*fn_iter)->is_oneway()) {
meta << "," << endl << indent() << "[";
bool first = true;
const vector<t_field*>& exceptions = (*fn_iter)->get_xceptions()->get_members();
vector<t_field*>::const_iterator ex_iter;
for (ex_iter = exceptions.begin(); ex_iter != exceptions.end(); ++ex_iter) {
if (first) {
first = false;
} else {
meta << ", ";
}
meta << "TExceptionMeta(`" << (*ex_iter)->get_name() << "`, " << (*ex_iter)->get_key()
<< ", `" << (*ex_iter)->get_type()->get_name() << "`)";
}
meta << "]";
}
if ((*fn_iter)->is_oneway()) {
meta << "," << endl << indent() << "TMethodType.ONEWAY";
}
indent_down();
meta << endl << indent() << ")";
}
indent_down();
string meta_str(meta.str());
if (!meta_str.empty()) {
f_service << endl << indent() << "enum methodMeta = [" << meta_str << endl << indent() << "];"
<< endl;
}
indent_down();
indent(f_service) << "}" << endl;
// Server skeleton generation.
string f_skeletonname = package_dir_ + svc_name + "_server.skeleton.d";
std::ofstream f_skeleton;
f_skeleton.open(f_skeletonname.c_str());
print_server_skeleton(f_skeleton, tservice);
f_skeleton.close();
}
private:
/**
* Writes a server skeleton for the passed service to out.
*/
void print_server_skeleton(ostream& out, t_service* tservice) {
string svc_name = tservice->get_name();
out << "/*" << endl
<< " * This auto-generated skeleton file illustrates how to build a server. If you" << endl
<< " * intend to customize it, you should edit a copy with another file name to " << endl
<< " * avoid overwriting it when running the generator again." << endl << " */" << endl
<< "module " << render_package(*tservice->get_program()) << svc_name << "_server;" << endl
<< endl << "import std.stdio;" << endl << "import thrift.codegen.processor;" << endl
<< "import thrift.protocol.binary;" << endl << "import thrift.server.simple;" << endl
<< "import thrift.server.transport.socket;" << endl << "import thrift.transport.buffered;"
<< endl << "import thrift.util.hashset;" << endl << endl << "import "
<< render_package(*tservice->get_program()) << svc_name << ";" << endl << "import "
<< render_package(*get_program()) << program_name_ << "_types;" << endl << endl << endl
<< "class " << svc_name << "Handler : " << svc_name << " {" << endl;
indent_up();
out << indent() << "this() {" << endl << indent() << " // Your initialization goes here."
<< endl << indent() << "}" << endl << endl;
vector<t_function*> functions = tservice->get_functions();
vector<t_function*>::iterator f_iter;
for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
out << indent();
print_function_signature(out, *f_iter);
out << " {" << endl;
indent_up();
out << indent() << "// Your implementation goes here." << endl << indent() << "writeln(\""
<< (*f_iter)->get_name() << " called\");" << endl;
t_base_type* rt = (t_base_type*)(*f_iter)->get_returntype();
if (rt->get_base() != t_base_type::TYPE_VOID) {
indent(out) << "return typeof(return).init;" << endl;
}
indent_down();
out << indent() << "}" << endl << endl;
}
indent_down();
out << "}" << endl << endl;
out << indent() << "void main() {" << endl;
indent_up();
out << indent() << "auto protocolFactory = new TBinaryProtocolFactory!();" << endl << indent()
<< "auto processor = new TServiceProcessor!" << svc_name << "(new " << svc_name
<< "Handler);" << endl << indent() << "auto serverTransport = new TServerSocket(9090);"
<< endl << indent() << "auto transportFactory = new TBufferedTransportFactory;" << endl
<< indent() << "auto server = new TSimpleServer(" << endl << indent()
<< " processor, serverTransport, transportFactory, protocolFactory);" << endl << indent()
<< "server.serve();" << endl;
indent_down();
out << "}" << endl;
}
/**
* Writes the definition of a struct or an exception type to out.
*/
void print_struct_definition(ostream& out, t_struct* tstruct, bool is_exception) {
const vector<t_field*>& members = tstruct->get_members();
if (is_exception) {
indent(out) << "class " << tstruct->get_name() << " : TException {" << endl;
} else {
indent(out) << "struct " << tstruct->get_name() << " {" << endl;
}
indent_up();
// Declare all fields.
vector<t_field*>::const_iterator m_iter;
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
indent(out) << render_type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name() << ";"
<< endl;
}
if (!members.empty())
indent(out) << endl;
indent(out) << "mixin TStructHelpers!(";
if (!members.empty()) {
// If there are any fields, construct the TFieldMeta array to pass to
// TStructHelpers. We can't just pass an empty array if not because []
// doesn't pass the TFieldMeta[] constraint.
out << "[";
indent_up();
bool first = true;
vector<t_field*>::const_iterator m_iter;
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
if (first) {
first = false;
} else {
out << ",";
}
out << endl;
indent(out) << "TFieldMeta(`" << (*m_iter)->get_name() << "`, " << (*m_iter)->get_key();
t_const_value* cv = (*m_iter)->get_value();
t_field::e_req req = (*m_iter)->get_req();
out << ", " << render_req(req);
if (cv != NULL) {
out << ", q{" << render_const_value((*m_iter)->get_type(), cv) << "}";
}
out << ")";
}
indent_down();
out << endl << indent() << "]";
}
out << ");" << endl;
indent_down();
indent(out) << "}" << endl << endl;
}
/**
* Prints the D function signature (including return type) for the given
* method.
*/
void print_function_signature(ostream& out, t_function* fn) {
out << render_type_name(fn->get_returntype()) << " " << fn->get_name() << "(";
const vector<t_field*>& fields = fn->get_arglist()->get_members();
vector<t_field*>::const_iterator f_iter;
bool first = true;
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
if (first) {
first = false;
} else {
out << ", ";
}
out << render_type_name((*f_iter)->get_type(), true) << " " << (*f_iter)->get_name();
}
out << ")";
}
/**
* Returns the D representation of value. The result is guaranteed to be a
* single expression; for complex types, immediately called delegate
* literals are used to achieve this.
*/
string render_const_value(t_type* type, t_const_value* value) {
// Resolve any typedefs.
type = get_true_type(type);
ostringstream out;
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
switch (tbase) {
case t_base_type::TYPE_STRING:
out << '"' << get_escaped_string(value) << '"';
break;
case t_base_type::TYPE_BOOL:
out << ((value->get_integer() > 0) ? "true" : "false");
break;
case t_base_type::TYPE_I8:
case t_base_type::TYPE_I16:
out << "cast(" << render_type_name(type) << ")" << value->get_integer();
break;
case t_base_type::TYPE_I32:
out << value->get_integer();
break;
case t_base_type::TYPE_I64:
out << value->get_integer() << "L";
break;
case t_base_type::TYPE_DOUBLE:
if (value->get_type() == t_const_value::CV_INTEGER) {
out << value->get_integer();
} else {
out << value->get_double();
}
break;
default:
throw "Compiler error: No const of base type " + t_base_type::t_base_name(tbase);
}
} else if (type->is_enum()) {
out << "cast(" << render_type_name(type) << ")" << value->get_integer();
} else {
out << "{" << endl;
indent_up();
indent(out) << render_type_name(type) << " v;" << endl;
if (type->is_struct() || type->is_xception()) {
indent(out) << "v = " << (type->is_xception() ? "new " : "") << render_type_name(type)
<< "();" << endl;
const vector<t_field*>& fields = ((t_struct*)type)->get_members();
vector<t_field*>::const_iterator f_iter;
const map<t_const_value*, t_const_value*>& val = value->get_map();
map<t_const_value*, t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
t_type* field_type = NULL;
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
if ((*f_iter)->get_name() == v_iter->first->get_string()) {
field_type = (*f_iter)->get_type();
}
}
if (field_type == NULL) {
throw "Type error: " + type->get_name() + " has no field "
+ v_iter->first->get_string();
}
string val = render_const_value(field_type, v_iter->second);
indent(out) << "v.set!`" << v_iter->first->get_string() << "`(" << val << ");" << endl;
}
} else if (type->is_map()) {
t_type* ktype = ((t_map*)type)->get_key_type();
t_type* vtype = ((t_map*)type)->get_val_type();
const map<t_const_value*, t_const_value*>& val = value->get_map();
map<t_const_value*, t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
string key = render_const_value(ktype, v_iter->first);
string val = render_const_value(vtype, v_iter->second);
indent(out) << "v[";
if (!is_immutable_type(ktype)) {
out << "cast(immutable(" << render_type_name(ktype) << "))";
}
out << key << "] = " << val << ";" << endl;
}
} else if (type->is_list()) {
t_type* etype = ((t_list*)type)->get_elem_type();
const vector<t_const_value*>& val = value->get_list();
vector<t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
string val = render_const_value(etype, *v_iter);
indent(out) << "v ~= " << val << ";" << endl;
}
} else if (type->is_set()) {
t_type* etype = ((t_set*)type)->get_elem_type();
const vector<t_const_value*>& val = value->get_list();
vector<t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
string val = render_const_value(etype, *v_iter);
indent(out) << "v ~= " << val << ";" << endl;
}
} else {
throw "Compiler error: Invalid type in render_const_value: " + type->get_name();
}
indent(out) << "return v;" << endl;
indent_down();
indent(out) << "}()";
}
return out.str();
}
/**
* Returns the D package to which modules for program are written (with a
* trailing dot, if not empty).
*/
string render_package(const t_program& program) const {
string package = program.get_namespace("d");
if (package.size() == 0)
return "";
return package + ".";
}
/**
* Returns the name of the D repesentation of ttype.
*
* If isArg is true, a const reference to the type will be returned for
* structs.
*/
string render_type_name(const t_type* ttype, bool isArg = false) const {
if (ttype->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
switch (tbase) {
case t_base_type::TYPE_VOID:
return "void";
case t_base_type::TYPE_STRING:
return "string";
case t_base_type::TYPE_BOOL:
return "bool";
case t_base_type::TYPE_I8:
return "byte";
case t_base_type::TYPE_I16:
return "short";
case t_base_type::TYPE_I32:
return "int";
case t_base_type::TYPE_I64:
return "long";
case t_base_type::TYPE_DOUBLE:
return "double";
default:
throw "Compiler error: No D type name for base type " + t_base_type::t_base_name(tbase);
}
}
if (ttype->is_container()) {
t_container* tcontainer = (t_container*)ttype;
if (tcontainer->has_cpp_name()) {
return tcontainer->get_cpp_name();
} else if (ttype->is_map()) {
t_map* tmap = (t_map*)ttype;
t_type* ktype = tmap->get_key_type();
string name = render_type_name(tmap->get_val_type()) + "[";
if (!is_immutable_type(ktype)) {
name += "immutable(";
}
name += render_type_name(ktype);
if (!is_immutable_type(ktype)) {
name += ")";
}
name += "]";
return name;
} else if (ttype->is_set()) {
t_set* tset = (t_set*)ttype;
return "HashSet!(" + render_type_name(tset->get_elem_type()) + ")";
} else if (ttype->is_list()) {
t_list* tlist = (t_list*)ttype;
return render_type_name(tlist->get_elem_type()) + "[]";
}
}
if (ttype->is_struct() && isArg) {
return "ref const(" + ttype->get_name() + ")";
} else {
return ttype->get_name();
}
}
/**
* Returns the D TReq enum member corresponding to req.
*/
string render_req(t_field::e_req req) const {
switch (req) {
case t_field::T_OPT_IN_REQ_OUT:
return "TReq.OPT_IN_REQ_OUT";
case t_field::T_OPTIONAL:
return "TReq.OPTIONAL";
case t_field::T_REQUIRED:
return "TReq.REQUIRED";
default: {
std::stringstream ss;
ss << "Compiler error: Invalid requirement level " << req;
throw ss.str();
}
}
}
/**
* Writes the default list of imports (which are written to every generated
* module) to f.
*/
void print_default_imports(ostream& out) {
indent(out) << "import thrift.base;" << endl << "import thrift.codegen.base;" << endl
<< "import thrift.util.hashset;" << endl << endl;
}
/**
* Returns whether type is »intrinsically immutable«, in the sense that
* a value of that type is implicitly castable to immutable(type), and it is
* allowed for AA keys without an immutable() qualifier.
*/
bool is_immutable_type(t_type* type) const {
t_type* ttype = get_true_type(type);
return ttype->is_base_type() || ttype->is_enum();
}
/*
* File streams, stored here to avoid passing them as parameters to every
* function.
*/
ofstream f_types_;
ofstream f_header_;
string package_dir_;
};
THRIFT_REGISTER_GENERATOR(d, "D", "")

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,190 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include "thrift/generate/t_generator.h"
using namespace std;
/**
* Top level program generation function. Calls the generator subclass methods
* for preparing file streams etc. then iterates over all the parts of the
* program to perform the correct actions.
*
* @param program The thrift program to compile into C++ source
*/
void t_generator::generate_program() {
// Initialize the generator
init_generator();
// Generate enums
vector<t_enum*> enums = program_->get_enums();
vector<t_enum*>::iterator en_iter;
for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
generate_enum(*en_iter);
}
// Generate typedefs
vector<t_typedef*> typedefs = program_->get_typedefs();
vector<t_typedef*>::iterator td_iter;
for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
generate_typedef(*td_iter);
}
// Generate structs, exceptions, and unions in declared order
vector<t_struct*> objects = program_->get_objects();
vector<t_struct*>::iterator o_iter;
for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
generate_forward_declaration(*o_iter);
}
for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
if ((*o_iter)->is_xception()) {
generate_xception(*o_iter);
} else {
generate_struct(*o_iter);
}
}
// Generate constants
vector<t_const*> consts = program_->get_consts();
generate_consts(consts);
// Generate services
vector<t_service*> services = program_->get_services();
vector<t_service*>::iterator sv_iter;
for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
service_name_ = get_service_name(*sv_iter);
generate_service(*sv_iter);
}
// Close the generator
close_generator();
}
string t_generator::escape_string(const string& in) const {
string result = "";
for (string::const_iterator it = in.begin(); it < in.end(); it++) {
std::map<char, std::string>::const_iterator res = escape_.find(*it);
if (res != escape_.end()) {
result.append(res->second);
} else {
result.push_back(*it);
}
}
return result;
}
void t_generator::generate_consts(vector<t_const*> consts) {
vector<t_const*>::iterator c_iter;
for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
generate_const(*c_iter);
}
}
void t_generator::generate_docstring_comment(ostream& out,
const string& comment_start,
const string& line_prefix,
const string& contents,
const string& comment_end) {
if (comment_start != "")
indent(out) << comment_start;
stringstream docs(contents, ios_base::in);
while (!(docs.eof() || docs.fail())) {
char line[1024];
docs.getline(line, 1024);
// Just prnt a newline when the line & prefix are empty.
if (strlen(line) == 0 && line_prefix == "" && !docs.eof()) {
out << std::endl;
} else if (strlen(line) > 0 || !docs.eof()) { // skip the empty last line
indent(out) << line_prefix << line << std::endl;
}
}
if (comment_end != "")
indent(out) << comment_end;
}
void t_generator_registry::register_generator(t_generator_factory* factory) {
gen_map_t& the_map = get_generator_map();
if (the_map.find(factory->get_short_name()) != the_map.end()) {
failure("Duplicate generators for language \"%s\"!\n", factory->get_short_name().c_str());
}
the_map[factory->get_short_name()] = factory;
}
void t_generator::parse_options(const string& options,
string& language,
map<string, string>& parsed_options) {
string::size_type colon = options.find(':');
language = options.substr(0, colon);
if (colon != string::npos) {
string::size_type pos = colon + 1;
while (pos != string::npos && pos < options.size()) {
string::size_type next_pos = options.find(',', pos);
string option = options.substr(pos, next_pos - pos);
pos = ((next_pos == string::npos) ? next_pos : next_pos + 1);
string::size_type separator = option.find('=');
string key, value;
if (separator == string::npos) {
key = option;
value = "";
} else {
key = option.substr(0, separator);
value = option.substr(separator + 1);
}
parsed_options[key] = value;
}
}
}
t_generator* t_generator_registry::get_generator(t_program* program,
const string& language,
const map<string, string>& parsed_options,
const std::string& options) {
gen_map_t& the_map = get_generator_map();
gen_map_t::iterator iter = the_map.find(language);
if (iter == the_map.end()) {
return NULL;
}
return iter->second->get_generator(program, parsed_options, options);
}
t_generator* t_generator_registry::get_generator(t_program* program, const string& options) {
string language;
map<string, string> parsed_options;
t_generator::parse_options(options, language, parsed_options);
return get_generator(program, language, parsed_options, options);
}
t_generator_registry::gen_map_t& t_generator_registry::get_generator_map() {
// http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12
static gen_map_t* the_map = new gen_map_t();
return *the_map;
}
t_generator_factory::t_generator_factory(const std::string& short_name,
const std::string& long_name,
const std::string& documentation)
: short_name_(short_name), long_name_(long_name), documentation_(documentation) {
t_generator_registry::register_generator(this);
}

View file

@ -0,0 +1,310 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_GENERATOR_H
#define T_GENERATOR_H
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include "thrift/common.h"
#include "thrift/version.h"
#include "thrift/generate/t_generator_registry.h"
#include "thrift/parse/t_program.h"
/**
* Base class for a thrift code generator. This class defines the basic
* routines for code generation and contains the top level method that
* dispatches code generation across various components.
*
*/
class t_generator {
public:
t_generator(t_program* program) {
tmp_ = 0;
indent_ = 0;
program_ = program;
program_name_ = get_program_name(program);
escape_['\n'] = "\\n";
escape_['\r'] = "\\r";
escape_['\t'] = "\\t";
escape_['"'] = "\\\"";
escape_['\\'] = "\\\\";
}
virtual ~t_generator() {}
/**
* Framework generator method that iterates over all the parts of a program
* and performs general actions. This is implemented by the base class and
* should not normally be overwritten in the subclasses.
*/
virtual void generate_program();
const t_program* get_program() const { return program_; }
void generate_docstring_comment(std::ostream& out,
const std::string& comment_start,
const std::string& line_prefix,
const std::string& contents,
const std::string& comment_end);
static void parse_options(const std::string& options, std::string& language,
std::map<std::string, std::string>& parsed_options);
/**
* check whether sub-namespace declaraction is used by generator.
* e.g. allow
* namespace py.twisted bar
* to specify namespace to use when -gen py:twisted is specified.
* Will be called with subnamespace, i.e. is_valid_namespace("twisted")
* will be called for the above example.
*/
static bool is_valid_namespace(const std::string& sub_namespace) {
(void)sub_namespace;
return false;
}
/**
* Escape string to use one in generated sources.
*/
virtual std::string escape_string(const std::string& in) const;
std::string get_escaped_string(t_const_value* constval) {
return escape_string(constval->get_string());
}
protected:
/**
* Optional methods that may be imlemented by subclasses to take necessary
* steps at the beginning or end of code generation.
*/
virtual void init_generator() {}
virtual void close_generator() {}
virtual void generate_consts(std::vector<t_const*> consts);
/**
* Pure virtual methods implemented by the generator subclasses.
*/
virtual void generate_typedef(t_typedef* ttypedef) = 0;
virtual void generate_enum(t_enum* tenum) = 0;
virtual void generate_const(t_const* tconst) { (void)tconst; }
virtual void generate_struct(t_struct* tstruct) = 0;
virtual void generate_service(t_service* tservice) = 0;
virtual void generate_forward_declaration(t_struct*) {}
virtual void generate_xception(t_struct* txception) {
// By default exceptions are the same as structs
generate_struct(txception);
}
/**
* Method to get the program name, may be overridden
*/
virtual std::string get_program_name(t_program* tprogram) { return tprogram->get_name(); }
/**
* Method to get the service name, may be overridden
*/
virtual std::string get_service_name(t_service* tservice) { return tservice->get_name(); }
/**
* Get the current output directory
*/
virtual std::string get_out_dir() const {
if (program_->is_out_path_absolute()) {
return program_->get_out_path() + "/";
}
return program_->get_out_path() + out_dir_base_ + "/";
}
/**
* Creates a unique temporary variable name, which is just "name" with a
* number appended to it (i.e. name35)
*/
std::string tmp(std::string name) {
std::ostringstream out;
out << name << tmp_++;
return out.str();
}
/**
* Generates a comment about this code being autogenerated, using C++ style
* comments, which are also fair game in Java / PHP, yay!
*
* @return C-style comment mentioning that this file is autogenerated.
*/
virtual std::string autogen_comment() {
return std::string("/**\n") + " * " + autogen_summary() + "\n" + " *\n"
+ " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
+ " * @generated\n" + " */\n";
}
virtual std::string autogen_summary() {
return std::string("Autogenerated by Thrift Compiler (") + THRIFT_VERSION + ")";
}
/**
* Indentation level modifiers
*/
void indent_up() { ++indent_; }
void indent_down() { --indent_; }
/**
* Indentation print function
*/
std::string indent() {
std::string ind = "";
int i;
for (i = 0; i < indent_; ++i) {
ind += indent_str();
}
return ind;
}
/**
* Indentation utility wrapper
*/
std::ostream& indent(std::ostream& os) { return os << indent(); }
/**
* Capitalization helpers
*/
std::string capitalize(std::string in) {
in[0] = toupper(in[0]);
return in;
}
std::string decapitalize(std::string in) {
in[0] = tolower(in[0]);
return in;
}
static std::string lowercase(std::string in) {
for (size_t i = 0; i < in.size(); ++i) {
in[i] = tolower(in[i]);
}
return in;
}
static std::string uppercase(std::string in) {
for (size_t i = 0; i < in.size(); ++i) {
in[i] = toupper(in[i]);
}
return in;
}
/**
* Transforms a camel case string to an equivalent one separated by underscores
* e.g. aMultiWord -> a_multi_word
* someName -> some_name
* CamelCase -> camel_case
* name -> name
* Name -> name
*/
std::string underscore(std::string in) {
in[0] = tolower(in[0]);
for (size_t i = 1; i < in.size(); ++i) {
if (isupper(in[i])) {
in[i] = tolower(in[i]);
in.insert(i, "_");
}
}
return in;
}
/**
* Transforms a string with words separated by underscores to a camel case equivalent
* e.g. a_multi_word -> aMultiWord
* some_name -> someName
* name -> name
*/
std::string camelcase(std::string in) {
std::ostringstream out;
bool underscore = false;
for (size_t i = 0; i < in.size(); i++) {
if (in[i] == '_') {
underscore = true;
continue;
}
if (underscore) {
out << (char)toupper(in[i]);
underscore = false;
continue;
}
out << in[i];
}
return out.str();
}
public:
/**
* Get the true type behind a series of typedefs.
*/
static const t_type* get_true_type(const t_type* type) { return type->get_true_type(); }
static t_type* get_true_type(t_type* type) { return type->get_true_type(); }
protected:
/**
* The program being generated
*/
t_program* program_;
/**
* Quick accessor for formatted program name that is currently being
* generated.
*/
std::string program_name_;
/**
* Quick accessor for formatted service name that is currently being
* generated.
*/
std::string service_name_;
/**
* Output type-specifc directory name ("gen-*")
*/
std::string out_dir_base_;
/**
* Map of characters to escape in string literals.
*/
std::map<char, std::string> escape_;
virtual std::string indent_str() const {
return " ";
}
private:
/**
* Current code indentation level
*/
int indent_;
/**
* Temporary variable counter, for making unique variable names
*/
int tmp_;
};
#endif

View file

@ -0,0 +1,106 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_GENERATOR_REGISTRY_H
#define T_GENERATOR_REGISTRY_H
class t_generator;
/**
* A factory for producing generator classes of a particular language.
*
* This class is also responsible for:
* - Registering itself with the generator registry.
* - Providing documentation for the generators it produces.
*/
class t_generator_factory {
public:
t_generator_factory(const std::string& short_name,
const std::string& long_name,
const std::string& documentation);
virtual ~t_generator_factory() {}
virtual t_generator* get_generator(
// The program to generate.
t_program* program,
// Note: parsed_options will not exist beyond the call to get_generator.
const std::map<std::string, std::string>& parsed_options,
// Note: option_string might not exist beyond the call to get_generator.
const std::string& option_string) = 0;
virtual bool is_valid_namespace(const std::string& sub_namespace) = 0;
std::string get_short_name() { return short_name_; }
std::string get_long_name() { return long_name_; }
std::string get_documentation() { return documentation_; }
private:
std::string short_name_;
std::string long_name_;
std::string documentation_;
};
template <typename generator>
class t_generator_factory_impl : public t_generator_factory {
public:
t_generator_factory_impl(const std::string& short_name,
const std::string& long_name,
const std::string& documentation)
: t_generator_factory(short_name, long_name, documentation) {}
virtual t_generator* get_generator(t_program* program,
const std::map<std::string, std::string>& parsed_options,
const std::string& option_string) {
return new generator(program, parsed_options, option_string);
}
virtual bool is_valid_namespace(const std::string& sub_namespace) {
return generator::is_valid_namespace(sub_namespace);
}
};
class t_generator_registry {
public:
static void register_generator(t_generator_factory* factory);
static t_generator* get_generator(t_program* program, const std::string& options);
static t_generator* get_generator(t_program* program,
const std::string& laugnage,
const std::map<std::string, std::string>& parsed_options,
const std::string& options);
typedef std::map<std::string, t_generator_factory*> gen_map_t;
static gen_map_t& get_generator_map();
private:
t_generator_registry();
t_generator_registry(const t_generator_registry&);
};
#define THRIFT_REGISTER_GENERATOR(language, long_name, doc) \
class t_##language##_generator_factory_impl \
: public t_generator_factory_impl<t_##language##_generator> { \
public: \
t_##language##_generator_factory_impl() \
: t_generator_factory_impl<t_##language##_generator>(#language, long_name, doc) {} \
}; \
static t_##language##_generator_factory_impl _registerer;
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,345 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <stdlib.h>
#include <sys/stat.h>
#include <sstream>
#include "thrift/platform.h"
#include "thrift/generate/t_generator.h"
using std::map;
using std::ofstream;
using std::ostringstream;
using std::pair;
using std::string;
using std::stringstream;
using std::vector;
static const string endl = "\n"; // avoid ostream << std::endl flushes
/**
* Graphviz code generator
*/
class t_gv_generator : public t_generator {
public:
t_gv_generator(t_program* program,
const std::map<std::string, std::string>& parsed_options,
const std::string& option_string)
: t_generator(program) {
(void)option_string;
std::map<std::string, std::string>::const_iterator iter;
exception_arrows = false;
for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
if( iter->first.compare("exceptions") == 0) {
exception_arrows = true;
} else {
throw "unknown option gv:" + iter->first;
}
}
out_dir_base_ = "gen-gv";
}
/**
* Init and end of generator
*/
void init_generator();
void close_generator();
/**
* Program-level generation functions
*/
void generate_typedef(t_typedef* ttypedef);
void generate_enum(t_enum* tenum);
void generate_const(t_const* tconst);
void generate_struct(t_struct* tstruct);
void generate_service(t_service* tservice);
protected:
/**
* Helpers
*/
void print_type(t_type* ttype, string struct_field_ref);
void print_const_value(t_type* type, t_const_value* tvalue);
private:
std::ofstream f_out_;
std::list<string> edges;
bool exception_arrows;
};
/**
* Init generator:
* - Adds some escaping for the Graphviz domain.
* - Create output directory and open file for writting.
* - Write the file header.
*/
void t_gv_generator::init_generator() {
escape_['{'] = "\\{";
escape_['}'] = "\\}";
// Make output directory
MKDIR(get_out_dir().c_str());
string fname = get_out_dir() + program_->get_name() + ".gv";
f_out_.open(fname.c_str());
f_out_ << "digraph \"" << escape_string(program_name_) << "\" {" << endl;
f_out_ << "node [style=filled, shape=record];" << endl;
f_out_ << "edge [arrowsize=0.5];" << endl;
f_out_ << "rankdir=LR" << endl;
}
/**
* Closes generator:
* - Print accumulated nodes connections.
* - Print footnote.
* - Closes file.
*/
void t_gv_generator::close_generator() {
// Print edges
std::list<string>::iterator iter = edges.begin();
for (; iter != edges.end(); iter++) {
f_out_ << (*iter) << endl;
}
// Print graph end } and close file
f_out_ << "}" << endl;
f_out_.close();
}
void t_gv_generator::generate_typedef(t_typedef* ttypedef) {
string name = ttypedef->get_name();
f_out_ << "node [fillcolor=azure];" << endl;
f_out_ << name << " [label=\"";
f_out_ << escape_string(name);
f_out_ << " :: ";
print_type(ttypedef->get_type(), name);
f_out_ << "\"];" << endl;
}
void t_gv_generator::generate_enum(t_enum* tenum) {
string name = tenum->get_name();
f_out_ << "node [fillcolor=white];" << endl;
f_out_ << name << " [label=\"enum " << escape_string(name);
vector<t_enum_value*> values = tenum->get_constants();
vector<t_enum_value*>::iterator val_iter;
for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) {
f_out_ << '|' << (*val_iter)->get_name();
f_out_ << " = ";
f_out_ << (*val_iter)->get_value();
}
f_out_ << "\"];" << endl;
}
void t_gv_generator::generate_const(t_const* tconst) {
string name = tconst->get_name();
f_out_ << "node [fillcolor=aliceblue];" << endl;
f_out_ << "const_" << name << " [label=\"";
f_out_ << escape_string(name);
f_out_ << " = ";
print_const_value(tconst->get_type(), tconst->get_value());
f_out_ << " :: ";
print_type(tconst->get_type(), "const_" + name);
f_out_ << "\"];" << endl;
}
void t_gv_generator::generate_struct(t_struct* tstruct) {
string name = tstruct->get_name();
if (tstruct->is_xception()) {
f_out_ << "node [fillcolor=lightpink];" << endl;
f_out_ << name << " [label=\"";
f_out_ << "exception " << escape_string(name);
} else if (tstruct->is_union()) {
f_out_ << "node [fillcolor=lightcyan];" << endl;
f_out_ << name << " [label=\"";
f_out_ << "union " << escape_string(name);
} else {
f_out_ << "node [fillcolor=beige];" << endl;
f_out_ << name << " [label=\"";
f_out_ << "struct " << escape_string(name);
}
vector<t_field*> members = tstruct->get_members();
vector<t_field*>::iterator mem_iter = members.begin();
for (; mem_iter != members.end(); mem_iter++) {
string field_name = (*mem_iter)->get_name();
// print port (anchor reference)
f_out_ << "|<field_" << field_name << '>';
// field name :: field type
f_out_ << (*mem_iter)->get_name();
f_out_ << " :: ";
print_type((*mem_iter)->get_type(), name + ":field_" + field_name);
}
f_out_ << "\"];" << endl;
}
void t_gv_generator::print_type(t_type* ttype, string struct_field_ref) {
if (ttype->is_container()) {
if (ttype->is_list()) {
f_out_ << "list\\<";
print_type(((t_list*)ttype)->get_elem_type(), struct_field_ref);
f_out_ << "\\>";
} else if (ttype->is_set()) {
f_out_ << "set\\<";
print_type(((t_set*)ttype)->get_elem_type(), struct_field_ref);
f_out_ << "\\>";
} else if (ttype->is_map()) {
f_out_ << "map\\<";
print_type(((t_map*)ttype)->get_key_type(), struct_field_ref);
f_out_ << ", ";
print_type(((t_map*)ttype)->get_val_type(), struct_field_ref);
f_out_ << "\\>";
}
} else if (ttype->is_base_type()) {
f_out_ << (((t_base_type*)ttype)->is_binary() ? "binary" : ttype->get_name());
} else {
f_out_ << ttype->get_name();
edges.push_back(struct_field_ref + " -> " + ttype->get_name());
}
}
/**
* Prints out an string representation of the provided constant value
*/
void t_gv_generator::print_const_value(t_type* type, t_const_value* tvalue) {
bool first = true;
switch (tvalue->get_type()) {
case t_const_value::CV_INTEGER:
f_out_ << tvalue->get_integer();
break;
case t_const_value::CV_DOUBLE:
f_out_ << tvalue->get_double();
break;
case t_const_value::CV_STRING:
f_out_ << "\\\"" << get_escaped_string(tvalue) << "\\\"";
break;
case t_const_value::CV_MAP: {
f_out_ << "\\{ ";
map<t_const_value*, t_const_value*> map_elems = tvalue->get_map();
map<t_const_value*, t_const_value*>::iterator map_iter;
for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) {
if (!first) {
f_out_ << ", ";
}
first = false;
print_const_value(((t_map*)type)->get_key_type(), map_iter->first);
f_out_ << " = ";
print_const_value(((t_map*)type)->get_val_type(), map_iter->second);
}
f_out_ << " \\}";
} break;
case t_const_value::CV_LIST: {
f_out_ << "\\{ ";
vector<t_const_value*> list_elems = tvalue->get_list();
;
vector<t_const_value*>::iterator list_iter;
for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) {
if (!first) {
f_out_ << ", ";
}
first = false;
if (type->is_list()) {
print_const_value(((t_list*)type)->get_elem_type(), *list_iter);
} else {
print_const_value(((t_set*)type)->get_elem_type(), *list_iter);
}
}
f_out_ << " \\}";
} break;
case t_const_value::CV_IDENTIFIER:
f_out_ << escape_string(type->get_name()) << "."
<< escape_string(tvalue->get_identifier_name());
break;
default:
f_out_ << "UNKNOWN";
break;
}
}
void t_gv_generator::generate_service(t_service* tservice) {
string service_name = get_service_name(tservice);
f_out_ << "subgraph cluster_" << service_name << " {" << endl;
f_out_ << "node [fillcolor=bisque];" << endl;
f_out_ << "style=dashed;" << endl;
f_out_ << "label = \"" << escape_string(service_name) << " service\";" << endl;
// TODO: service extends
vector<t_function*> functions = tservice->get_functions();
vector<t_function*>::iterator fn_iter = functions.begin();
for (; fn_iter != functions.end(); fn_iter++) {
string fn_name = (*fn_iter)->get_name();
f_out_ << "function_" << service_name << fn_name;
f_out_ << "[label=\"<return_type>function " << escape_string(fn_name);
f_out_ << " :: ";
print_type((*fn_iter)->get_returntype(), "function_" + service_name + fn_name + ":return_type");
vector<t_field*> args = (*fn_iter)->get_arglist()->get_members();
vector<t_field*>::iterator arg_iter = args.begin();
for (; arg_iter != args.end(); arg_iter++) {
f_out_ << "|<param_" << (*arg_iter)->get_name() << ">";
f_out_ << (*arg_iter)->get_name();
if ((*arg_iter)->get_value() != NULL) {
f_out_ << " = ";
print_const_value((*arg_iter)->get_type(), (*arg_iter)->get_value());
}
f_out_ << " :: ";
print_type((*arg_iter)->get_type(),
"function_" + service_name + fn_name + ":param_" + (*arg_iter)->get_name());
}
// end of node
f_out_ << "\"];" << endl;
// Exception edges
if (exception_arrows) {
vector<t_field*> excepts = (*fn_iter)->get_xceptions()->get_members();
vector<t_field*>::iterator ex_iter = excepts.begin();
for (; ex_iter != excepts.end(); ex_iter++) {
edges.push_back("function_" + service_name + fn_name + " -> "
+ (*ex_iter)->get_type()->get_name() + " [color=red]");
}
}
}
f_out_ << " }" << endl;
}
THRIFT_REGISTER_GENERATOR(
gv,
"Graphviz",
" exceptions: Whether to draw arrows from functions to exception.\n")

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,240 @@
#define BOOTSTRAP_CSS() \
"/*!\n" \
" * Bootstrap v2.0.3\n" \
" *\n" \
" * Copyright 2012 Twitter, Inc\n" \
" * Licensed under the Apache License v2.0\n" \
" * http://www.apache.org/licenses/LICENSE-2.0\n" \
" *\n" \
" * Designed and built with all the love in the world @twitter by @mdo and @fat.\n" \
" */\n" \
".clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:\"\";}\n" \
".clearfix:after{clear:both;}\n" \
".hide-text{font:0/0 " \
"a;color:transparent;text-shadow:none;background-color:transparent;border:0;}\n" \
".input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-" \
"moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;}\n" \
"article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}\n" \
"audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}\n" \
"audio:not([controls]){display:none;}\n" \
"html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}\n" \
"a:focus{outline:thin dotted #333;outline:5px auto " \
"-webkit-focus-ring-color;outline-offset:-2px;}\n" \
"a:hover,a:active{outline:0;}\n" \
"sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}\n" \
"sup{top:-0.5em;}\n" \
"sub{bottom:-0.25em;}\n" \
"img{max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic;}\n" \
"button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;}\n" \
"button,input{*overflow:visible;line-height:normal;}\n" \
"button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}\n" \
"button,input[type=\"button\"],input[type=\"reset\"],input[type=\"submit\"]{cursor:pointer;-" \
"webkit-appearance:button;}\n" \
"input[type=\"search\"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:" \
"content-box;-webkit-appearance:textfield;}\n" \
"input[type=\"search\"]::-webkit-search-decoration,input[type=\"search\"]::-webkit-search-" \
"cancel-button{-webkit-appearance:none;}\n" \
"textarea{overflow:auto;vertical-align:top;}\n" \
"body{margin:0;font-family:\"Helvetica " \
"Neue\",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333333;background-" \
"color:#ffffff;}\n" \
"a{color:#0088cc;text-decoration:none;}\n" \
"a:hover{color:#005580;text-decoration:underline;}\n" \
".row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:\"\";}\n" \
".row:after{clear:both;}\n" \
"[class*=\"span\"]{float:left;margin-left:20px;}\n" \
".container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px;}\n" \
".span12{width:940px;}\n" \
".span11{width:860px;}\n" \
".span10{width:780px;}\n" \
".span9{width:700px;}\n" \
".span8{width:620px;}\n" \
".span7{width:540px;}\n" \
".span6{width:460px;}\n" \
".span5{width:380px;}\n" \
".span4{width:300px;}\n" \
".span3{width:220px;}\n" \
".span2{width:140px;}\n" \
".span1{width:60px;}\n" \
".offset12{margin-left:980px;}\n" \
".offset11{margin-left:900px;}\n" \
".offset10{margin-left:820px;}\n" \
".offset9{margin-left:740px;}\n" \
".offset8{margin-left:660px;}\n" \
".offset7{margin-left:580px;}\n" \
".offset6{margin-left:500px;}\n" \
".offset5{margin-left:420px;}\n" \
".offset4{margin-left:340px;}\n" \
".offset3{margin-left:260px;}\n" \
".offset2{margin-left:180px;}\n" \
".offset1{margin-left:100px;}\n" \
".row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:\"\";}" \
"\n" \
".row-fluid:after{clear:both;}\n" \
".row-fluid " \
"[class*=\"span\"]{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-" \
"box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:" \
"2.127659574%;*margin-left:2.0744680846382977%;}\n" \
".row-fluid [class*=\"span\"]:first-child{margin-left:0;}\n" \
".row-fluid .span12{width:99.99999998999999%;*width:99.94680850063828%;}\n" \
".row-fluid .span11{width:91.489361693%;*width:91.4361702036383%;}\n" \
".row-fluid .span10{width:82.97872339599999%;*width:82.92553190663828%;}\n" \
".row-fluid .span9{width:74.468085099%;*width:74.4148936096383%;}\n" \
".row-fluid .span8{width:65.95744680199999%;*width:65.90425531263828%;}\n" \
".row-fluid .span7{width:57.446808505%;*width:57.3936170156383%;}\n" \
".row-fluid .span6{width:48.93617020799999%;*width:48.88297871863829%;}\n" \
".row-fluid .span5{width:40.425531911%;*width:40.3723404216383%;}\n" \
".row-fluid .span4{width:31.914893614%;*width:31.8617021246383%;}\n" \
".row-fluid .span3{width:23.404255317%;*width:23.3510638276383%;}\n" \
".row-fluid .span2{width:14.89361702%;*width:14.8404255306383%;}\n" \
".row-fluid .span1{width:6.382978723%;*width:6.329787233638298%;}\n" \
".container{margin-right:auto;margin-left:auto;*zoom:1;}.container:before,.container:after{" \
"display:table;content:\"\";}\n" \
".container:after{clear:both;}\n" \
".container-fluid{padding-right:20px;padding-left:20px;*zoom:1;}.container-fluid:before,." \
"container-fluid:after{display:table;content:\"\";}\n" \
".container-fluid:after{clear:both;}\n" \
"p{margin:0 0 9px;font-family:\"Helvetica " \
"Neue\",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;}p " \
"small{font-size:11px;color:#999999;}\n" \
".lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px;}\n" \
"h1,h2,h3,h4,h5,h6{margin:0;font-family:inherit;font-weight:bold;color:inherit;text-rendering:" \
"optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 " \
"small{font-weight:normal;color:#999999;}\n" \
"h1{font-size:30px;line-height:36px;}h1 small{font-size:18px;}\n" \
"h2{font-size:24px;line-height:36px;}h2 small{font-size:18px;}\n" \
"h3{font-size:18px;line-height:27px;}h3 small{font-size:14px;}\n" \
"h4,h5,h6{line-height:18px;}\n" \
"h4{font-size:14px;}h4 small{font-size:12px;}\n" \
"h5{font-size:12px;}\n" \
"h6{font-size:11px;color:#999999;text-transform:uppercase;}\n" \
".page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eeeeee;}\n" \
".page-header h1{line-height:1;}\n" \
"ul,ol{padding:0;margin:0 0 9px 25px;}\n" \
"ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}\n" \
"ul{list-style:disc;}\n" \
"ol{list-style:decimal;}\n" \
"li{line-height:18px;}\n" \
"ul.unstyled,ol.unstyled{margin-left:0;list-style:none;}\n" \
"dl{margin-bottom:18px;}\n" \
"dt,dd{line-height:18px;}\n" \
"dt{font-weight:bold;line-height:17px;}\n" \
"dd{margin-left:9px;}\n" \
".dl-horizontal " \
"dt{float:left;width:120px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;" \
"white-space:nowrap;}\n" \
".dl-horizontal dd{margin-left:130px;}\n" \
"hr{margin:18px 0;border:0;border-top:1px solid #eeeeee;border-bottom:1px solid #ffffff;}\n" \
"strong{font-weight:bold;}\n" \
"em{font-style:italic;}\n" \
".muted{color:#999999;}\n" \
"abbr[title]{cursor:help;border-bottom:1px dotted #ddd;}\n" \
"abbr.initialism{font-size:90%;text-transform:uppercase;}\n" \
"blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eeeeee;}blockquote " \
"p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px;}\n" \
"blockquote small{display:block;line-height:18px;color:#999999;}blockquote " \
"small:before{content:'\\2014 \\00A0';}\n" \
"blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid " \
"#eeeeee;border-left:0;}blockquote.pull-right p,blockquote.pull-right " \
"small{text-align:right;}\n" \
"q:before,q:after,blockquote:before,blockquote:after{content:\"\";}\n" \
"address{display:block;margin-bottom:18px;font-style:normal;line-height:18px;}\n" \
"small{font-size:100%;}\n" \
"cite{font-style:normal;}\n" \
"code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,Consolas,\"Courier " \
"New\",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;" \
"border-radius:3px;}\n" \
"code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;}\n" \
"pre{display:block;padding:8.5px;margin:0 0 " \
"9px;font-size:12.025px;line-height:18px;word-break:break-all;word-wrap:break-word;white-space:" \
"pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid " \
"rgba(0, 0, 0, " \
"0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}pre.prettyprint{" \
"margin-bottom:18px;}\n" \
"pre code{padding:0;color:inherit;background-color:transparent;border:0;}\n" \
".pre-scrollable{max-height:340px;overflow-y:scroll;}\n" \
".label,.badge{font-size:10.998px;font-weight:bold;line-height:14px;color:#ffffff;vertical-" \
"align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0, 0, 0, " \
"0.25);background-color:#999999;}\n" \
".label{padding:1px 4px " \
"2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}\n" \
".badge{padding:1px 9px " \
"2px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px;}\n" \
"a.label:hover,a.badge:hover{color:#ffffff;text-decoration:none;cursor:pointer;}\n" \
".label-important,.badge-important{background-color:#b94a48;}\n" \
".label-important[href],.badge-important[href]{background-color:#953b39;}\n" \
".label-warning,.badge-warning{background-color:#f89406;}\n" \
".label-warning[href],.badge-warning[href]{background-color:#c67605;}\n" \
".label-success,.badge-success{background-color:#468847;}\n" \
".label-success[href],.badge-success[href]{background-color:#356635;}\n" \
".label-info,.badge-info{background-color:#3a87ad;}\n" \
".label-info[href],.badge-info[href]{background-color:#2d6987;}\n" \
".label-inverse,.badge-inverse{background-color:#333333;}\n" \
".label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a;}\n" \
"table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0;}" \
"\n" \
".table{width:100%;margin-bottom:18px;}.table th,.table " \
"td{padding:8px;line-height:18px;text-align:left;vertical-align:top;border-top:1px solid " \
"#dddddd;}\n" \
".table th{font-weight:bold;}\n" \
".table thead th{vertical-align:bottom;}\n" \
".table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table " \
"colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table " \
"thead:first-child tr:first-child th,.table thead:first-child tr:first-child " \
"td{border-top:0;}\n" \
".table tbody+tbody{border-top:2px solid #dddddd;}\n" \
".table-condensed th,.table-condensed td{padding:4px 5px;}\n" \
".table-bordered{border:1px solid " \
"#dddddd;border-collapse:separate;*border-collapse:collapsed;border-left:0;-webkit-border-" \
"radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th,.table-bordered " \
"td{border-left:1px solid #dddddd;}\n" \
".table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child " \
"th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead " \
"tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered " \
"colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child " \
"th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child " \
"tr:first-child td{border-top:0;}\n" \
".table-bordered thead:first-child tr:first-child th:first-child,.table-bordered " \
"tbody:first-child tr:first-child " \
"td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-" \
"radius-topleft:4px;}\n" \
".table-bordered thead:first-child tr:first-child th:last-child,.table-bordered " \
"tbody:first-child tr:first-child " \
"td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-" \
"radius-topright:4px;}\n" \
".table-bordered thead:last-child tr:last-child th:first-child,.table-bordered " \
"tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 " \
"4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 " \
"4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-" \
"bottomleft:4px;}\n" \
".table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child " \
"tr:last-child " \
"td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-" \
"border-radius-bottomright:4px;}\n" \
".table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) " \
"th{background-color:#f9f9f9;}\n" \
".table tbody tr:hover td,.table tbody tr:hover th{background-color:#f5f5f5;}\n" \
"table .span1{float:none;width:44px;margin-left:0;}\n" \
"table .span2{float:none;width:124px;margin-left:0;}\n" \
"table .span3{float:none;width:204px;margin-left:0;}\n" \
"table .span4{float:none;width:284px;margin-left:0;}\n" \
"table .span5{float:none;width:364px;margin-left:0;}\n" \
"table .span6{float:none;width:444px;margin-left:0;}\n" \
"table .span7{float:none;width:524px;margin-left:0;}\n" \
"table .span8{float:none;width:604px;margin-left:0;}\n" \
"table .span9{float:none;width:684px;margin-left:0;}\n" \
"table .span10{float:none;width:764px;margin-left:0;}\n" \
"table .span11{float:none;width:844px;margin-left:0;}\n" \
"table .span12{float:none;width:924px;margin-left:0;}\n" \
"table .span13{float:none;width:1004px;margin-left:0;}\n" \
"table .span14{float:none;width:1084px;margin-left:0;}\n" \
"table .span15{float:none;width:1164px;margin-left:0;}\n" \
"table .span16{float:none;width:1244px;margin-left:0;}\n" \
"table .span17{float:none;width:1324px;margin-left:0;}\n" \
"table .span18{float:none;width:1404px;margin-left:0;}\n" \
"table .span19{float:none;width:1484px;margin-left:0;}\n" \
"table .span20{float:none;width:1564px;margin-left:0;}\n" \
"table .span21{float:none;width:1644px;margin-left:0;}\n" \
"table .span22{float:none;width:1724px;margin-left:0;}\n" \
"table .span23{float:none;width:1804px;margin-left:0;}\n" \
"table .span24{float:none;width:1884px;margin-left:0;}"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,727 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*
* Contains some contributions under the Thrift Software License.
* Please see doc/old-thrift-license.txt in the Thrift distribution for
* details.
*/
#include <fstream>
#include <iostream>
#include <sstream>
#include <limits>
#include <stdlib.h>
#include <sys/stat.h>
#include <sstream>
#include "thrift/platform.h"
#include "thrift/generate/t_generator.h"
using std::map;
using std::ofstream;
using std::ostream;
using std::ostringstream;
using std::string;
using std::stringstream;
using std::vector;
using std::stack;
static const string endl = "\n";
static const string quot = "\"";
static const bool NO_INDENT = false;
static const bool FORCE_STRING = true;
class t_json_generator : public t_generator {
public:
t_json_generator(t_program* program,
const std::map<std::string, std::string>& parsed_options,
const std::string& option_string)
: t_generator(program) {
(void)option_string;
std::map<std::string, std::string>::const_iterator iter;
should_merge_includes_ = false;
for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
if( iter->first.compare("merge") == 0) {
should_merge_includes_ = true;
} else {
throw "unknown option json:" + iter->first;
}
}
out_dir_base_ = "gen-json";
}
virtual ~t_json_generator() {}
/**
* Init and close methods
*/
void init_generator();
void close_generator();
void generate_typedef(t_typedef* ttypedef);
void generate_enum(t_enum* tenum);
void generate_program();
void generate_function(t_function* tfunc);
void generate_field(t_field* field);
void generate_service(t_service* tservice);
void generate_struct(t_struct* tstruct);
private:
bool should_merge_includes_;
std::ofstream f_json_;
std::stack<bool> comma_needed_;
template <typename T>
string number_to_string(T t) {
std::ostringstream out;
out.imbue(std::locale::classic());
out.precision(std::numeric_limits<T>::digits10);
out << t;
return out.str();
}
template <typename T>
void write_number(T n) {
f_json_ << number_to_string(n);
}
string get_type_name(t_type* ttype);
string get_qualified_name(t_type* ttype);
void start_object(bool should_indent = true);
void start_array();
void end_object();
void end_array();
void write_comma_if_needed();
void indicate_comma_needed();
string escape_json_string(const string& input);
string json_str(const string& str);
void merge_includes(t_program*);
void generate_constant(t_const* con);
void write_type_spec_entry(const char* name, t_type* ttype);
void write_type_spec_object(const char* name, t_type* ttype);
void write_type_spec(t_type* ttype);
void write_string(const string& value);
void write_value(t_type* tvalue);
void write_const_value(t_const_value* value, bool force_string = false);
void write_key_and(string key);
void write_key_and_string(string key, string val);
void write_key_and_integer(string key, int val);
void write_key_and_bool(string key, bool val);
};
void t_json_generator::init_generator() {
MKDIR(get_out_dir().c_str());
string f_json_name = get_out_dir() + program_->get_name() + ".json";
f_json_.open(f_json_name.c_str());
// Merge all included programs into this one so we can output one big file.
if (should_merge_includes_) {
merge_includes(program_);
}
}
string t_json_generator::escape_json_string(const string& input) {
std::ostringstream ss;
for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) {
switch (*iter) {
case '\\':
ss << "\\\\";
break;
case '"':
ss << "\\\"";
break;
case '/':
ss << "\\/";
break;
case '\b':
ss << "\\b";
break;
case '\f':
ss << "\\f";
break;
case '\n':
ss << "\\n";
break;
case '\r':
ss << "\\r";
break;
case '\t':
ss << "\\t";
break;
default:
ss << *iter;
break;
}
}
return ss.str();
}
void t_json_generator::start_object(bool should_indent) {
f_json_ << (should_indent ? indent() : "") << "{" << endl;
indent_up();
comma_needed_.push(false);
}
void t_json_generator::start_array() {
f_json_ << "[" << endl;
indent_up();
comma_needed_.push(false);
}
void t_json_generator::write_comma_if_needed() {
if (comma_needed_.top()) {
f_json_ << "," << endl;
}
}
void t_json_generator::indicate_comma_needed() {
comma_needed_.pop();
comma_needed_.push(true);
}
void t_json_generator::write_key_and(string key) {
write_comma_if_needed();
indent(f_json_) << json_str(key) << ": ";
indicate_comma_needed();
}
void t_json_generator::write_key_and_integer(string key, int val) {
write_comma_if_needed();
indent(f_json_) << json_str(key) << ": " << number_to_string(val);
indicate_comma_needed();
}
void t_json_generator::write_key_and_string(string key, string val) {
write_comma_if_needed();
indent(f_json_) << json_str(key) << ": " << json_str(val);
indicate_comma_needed();
}
void t_json_generator::write_key_and_bool(string key, bool val) {
write_comma_if_needed();
indent(f_json_) << json_str(key) << ": " << (val ? "true" : "false");
indicate_comma_needed();
}
void t_json_generator::end_object() {
indent_down();
f_json_ << endl << indent() << "}";
comma_needed_.pop();
}
void t_json_generator::end_array() {
indent_down();
if (comma_needed_.top()) {
f_json_ << endl;
}
indent(f_json_) << "]";
comma_needed_.pop();
}
void t_json_generator::write_type_spec_object(const char* name, t_type* ttype) {
ttype = ttype->get_true_type();
if (ttype->is_struct() || ttype->is_xception() || ttype->is_container()) {
write_key_and(name);
start_object(NO_INDENT);
write_key_and("typeId");
write_type_spec(ttype);
end_object();
}
}
void t_json_generator::write_type_spec_entry(const char* name, t_type* ttype) {
write_key_and(name);
write_type_spec(ttype);
}
void t_json_generator::write_type_spec(t_type* ttype) {
ttype = ttype->get_true_type();
write_string(get_type_name(ttype));
if (ttype->is_struct() || ttype->is_xception()) {
write_key_and_string("class", get_qualified_name(ttype));
} else if (ttype->is_map()) {
t_type* ktype = ((t_map*)ttype)->get_key_type();
t_type* vtype = ((t_map*)ttype)->get_val_type();
write_key_and_string("keyTypeId", get_type_name(ktype));
write_key_and_string("valueTypeId", get_type_name(vtype));
write_type_spec_object("keyType", ktype);
write_type_spec_object("valueType", vtype);
} else if (ttype->is_list() || ttype->is_set()) {
t_type* etype = ((t_list*)ttype)->get_elem_type();
write_key_and_string("elemTypeId", get_type_name(etype));
write_type_spec_object("elemType", etype);
}
}
void t_json_generator::close_generator() {
f_json_ << endl;
f_json_.close();
}
void t_json_generator::merge_includes(t_program* program) {
vector<t_program*> includes = program->get_includes();
vector<t_program*>::iterator inc_iter;
for (inc_iter = includes.begin(); inc_iter != includes.end(); ++inc_iter) {
t_program* include = *inc_iter;
// recurse in case we get crazy
merge_includes(include);
// merge enums
vector<t_enum*> enums = include->get_enums();
vector<t_enum*>::iterator en_iter;
for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
program->add_enum(*en_iter);
}
// merge typedefs
vector<t_typedef*> typedefs = include->get_typedefs();
vector<t_typedef*>::iterator td_iter;
for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
program->add_typedef(*td_iter);
}
// merge structs
vector<t_struct*> objects = include->get_objects();
vector<t_struct*>::iterator o_iter;
for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
program->add_struct(*o_iter);
}
// merge constants
vector<t_const*> consts = include->get_consts();
vector<t_const*>::iterator c_iter;
for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
program->add_const(*c_iter);
}
// merge services
vector<t_service*> services = include->get_services();
vector<t_service*>::iterator sv_iter;
for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
program->add_service(*sv_iter);
}
}
}
void t_json_generator::generate_program() {
init_generator();
start_object();
write_key_and_string("name", program_->get_name());
if (program_->has_doc()) {
write_key_and_string("doc", program_->get_doc());
}
// When merging includes, the "namespaces" and "includes" sections
// become ambiguous, so just skip them.
if (!should_merge_includes_) {
// Generate namespaces
write_key_and("namespaces");
start_object(NO_INDENT);
const map<string, string>& namespaces = program_->get_namespaces();
map<string, string>::const_iterator ns_it;
for (ns_it = namespaces.begin(); ns_it != namespaces.end(); ++ns_it) {
write_key_and_string(ns_it->first, ns_it->second);
indicate_comma_needed();
}
end_object();
// Generate includes
write_key_and("includes");
start_array();
const vector<t_program*> includes = program_->get_includes();
vector<t_program*>::const_iterator inc_it;
for (inc_it = includes.begin(); inc_it != includes.end(); ++inc_it) {
write_comma_if_needed();
write_string((*inc_it)->get_name());
indicate_comma_needed();
}
end_array();
}
// Generate enums
write_key_and("enums");
start_array();
vector<t_enum*> enums = program_->get_enums();
vector<t_enum*>::iterator en_iter;
for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
write_comma_if_needed();
generate_enum(*en_iter);
indicate_comma_needed();
}
end_array();
// Generate typedefs
write_key_and("typedefs");
start_array();
vector<t_typedef*> typedefs = program_->get_typedefs();
vector<t_typedef*>::iterator td_iter;
for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
write_comma_if_needed();
generate_typedef(*td_iter);
indicate_comma_needed();
}
end_array();
// Generate structs, exceptions, and unions in declared order
write_key_and("structs");
start_array();
vector<t_struct*> objects = program_->get_objects();
vector<t_struct*>::iterator o_iter;
for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
write_comma_if_needed();
if ((*o_iter)->is_xception()) {
generate_xception(*o_iter);
} else {
generate_struct(*o_iter);
}
indicate_comma_needed();
}
end_array();
// Generate constants
write_key_and("constants");
start_array();
vector<t_const*> consts = program_->get_consts();
vector<t_const*>::iterator c_iter;
for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
write_comma_if_needed();
generate_constant(*c_iter);
indicate_comma_needed();
}
end_array();
// Generate services
write_key_and("services");
start_array();
vector<t_service*> services = program_->get_services();
vector<t_service*>::iterator sv_iter;
for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
write_comma_if_needed();
generate_service(*sv_iter);
indicate_comma_needed();
}
end_array();
end_object();
// Close the generator
close_generator();
}
void t_json_generator::generate_typedef(t_typedef* ttypedef) {
start_object();
write_key_and_string("name", get_qualified_name(ttypedef));
write_key_and_string("typeId", get_type_name(ttypedef->get_true_type()));
write_type_spec_object("type", ttypedef->get_true_type());
if (ttypedef->has_doc()) {
write_key_and_string("doc", ttypedef->get_doc());
}
end_object();
}
void t_json_generator::write_string(const string& value) {
f_json_ << quot << escape_json_string(value) << quot;
}
void t_json_generator::write_const_value(t_const_value* value, bool should_force_string) {
switch (value->get_type()) {
case t_const_value::CV_IDENTIFIER:
case t_const_value::CV_INTEGER:
if (should_force_string) {
write_string(number_to_string(value->get_integer()));
} else {
write_number(value->get_integer());
}
break;
case t_const_value::CV_DOUBLE:
if (should_force_string) {
write_string(number_to_string(value->get_double()));
} else {
write_number(value->get_double());
}
break;
case t_const_value::CV_STRING:
write_string(value->get_string());
break;
case t_const_value::CV_LIST: {
start_array();
std::vector<t_const_value*> list = value->get_list();
std::vector<t_const_value*>::iterator lit;
for (lit = list.begin(); lit != list.end(); ++lit) {
write_comma_if_needed();
f_json_ << indent();
write_const_value(*lit);
indicate_comma_needed();
}
end_array();
break;
}
case t_const_value::CV_MAP: {
start_object(NO_INDENT);
std::map<t_const_value*, t_const_value*> map = value->get_map();
std::map<t_const_value*, t_const_value*>::iterator mit;
for (mit = map.begin(); mit != map.end(); ++mit) {
write_comma_if_needed();
f_json_ << indent();
// JSON objects only allow string keys
write_const_value(mit->first, FORCE_STRING);
f_json_ << ": ";
write_const_value(mit->second);
indicate_comma_needed();
}
end_object();
break;
}
default:
f_json_ << "null";
break;
}
}
string t_json_generator::json_str(const string& str) {
return quot + escape_json_string(str) + quot;
}
void t_json_generator::generate_constant(t_const* con) {
start_object();
write_key_and_string("name", con->get_name());
write_key_and_string("typeId", get_type_name(con->get_type()));
write_type_spec_object("type", con->get_type());
if (con->has_doc()) {
write_key_and_string("doc", con->get_doc());
}
write_key_and("value");
write_const_value(con->get_value());
end_object();
}
void t_json_generator::generate_enum(t_enum* tenum) {
start_object();
write_key_and_string("name", tenum->get_name());
if (tenum->has_doc()) {
write_key_and_string("doc", tenum->get_doc());
}
write_key_and("members");
start_array();
vector<t_enum_value*> values = tenum->get_constants();
vector<t_enum_value*>::iterator val_iter;
for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) {
write_comma_if_needed();
t_enum_value* val = (*val_iter);
start_object();
write_key_and_string("name", val->get_name());
write_key_and_integer("value", val->get_value());
if (val->has_doc()) {
write_key_and_string("doc", val->get_doc());
}
end_object();
indicate_comma_needed();
}
end_array();
end_object();
}
void t_json_generator::generate_struct(t_struct* tstruct) {
start_object();
write_key_and_string("name", tstruct->get_name());
if (tstruct->has_doc()) {
write_key_and_string("doc", tstruct->get_doc());
}
write_key_and_bool("isException", tstruct->is_xception());
write_key_and_bool("isUnion", tstruct->is_union());
write_key_and("fields");
start_array();
vector<t_field*> members = tstruct->get_members();
vector<t_field*>::iterator mem_iter;
for (mem_iter = members.begin(); mem_iter != members.end(); mem_iter++) {
write_comma_if_needed();
generate_field(*mem_iter);
indicate_comma_needed();
}
end_array();
end_object();
}
void t_json_generator::generate_service(t_service* tservice) {
start_object();
write_key_and_string("name", get_qualified_name(tservice));
if (tservice->get_extends()) {
write_key_and_string("extends", get_qualified_name(tservice->get_extends()));
}
if (tservice->has_doc()) {
write_key_and_string("doc", tservice->get_doc());
}
write_key_and("functions");
start_array();
vector<t_function*> functions = tservice->get_functions();
vector<t_function*>::iterator fn_iter = functions.begin();
for (; fn_iter != functions.end(); fn_iter++) {
write_comma_if_needed();
generate_function(*fn_iter);
indicate_comma_needed();
}
end_array();
end_object();
}
void t_json_generator::generate_function(t_function* tfunc) {
start_object();
write_key_and_string("name", tfunc->get_name());
write_key_and_string("returnTypeId", get_type_name(tfunc->get_returntype()));
write_type_spec_object("returnType", tfunc->get_returntype());
write_key_and_bool("oneway", tfunc->is_oneway());
if (tfunc->has_doc()) {
write_key_and_string("doc", tfunc->get_doc());
}
write_key_and("arguments");
start_array();
vector<t_field*> members = tfunc->get_arglist()->get_members();
vector<t_field*>::iterator mem_iter = members.begin();
for (; mem_iter != members.end(); mem_iter++) {
write_comma_if_needed();
generate_field(*mem_iter);
indicate_comma_needed();
}
end_array();
write_key_and("exceptions");
start_array();
vector<t_field*> excepts = tfunc->get_xceptions()->get_members();
vector<t_field*>::iterator ex_iter = excepts.begin();
for (; ex_iter != excepts.end(); ex_iter++) {
write_comma_if_needed();
generate_field(*ex_iter);
indicate_comma_needed();
}
end_array();
end_object();
}
void t_json_generator::generate_field(t_field* field) {
start_object();
write_key_and_integer("key", field->get_key());
write_key_and_string("name", field->get_name());
write_key_and_string("typeId", get_type_name(field->get_type()));
write_type_spec_object("type", field->get_type());
if (field->has_doc()) {
write_key_and_string("doc", field->get_doc());
}
write_key_and("required");
switch (field->get_req()) {
case t_field::T_REQUIRED:
write_string("required");
break;
case t_field::T_OPT_IN_REQ_OUT:
write_string("req_out");
break;
default:
write_string("optional");
break;
}
if (field->get_value()) {
write_key_and("default");
write_const_value(field->get_value());
}
end_object();
}
string t_json_generator::get_type_name(t_type* ttype) {
ttype = ttype->get_true_type();
if (ttype->is_list()) {
return "list";
}
if (ttype->is_set()) {
return "set";
}
if (ttype->is_map()) {
return "map";
}
if (ttype->is_enum()) {
return "i32";
}
if (ttype->is_struct()) {
return ((t_struct*)ttype)->is_union() ? "union" : "struct";
}
if (ttype->is_xception()) {
return "exception";
}
if (ttype->is_base_type()) {
t_base_type* tbasetype = (t_base_type*)ttype;
return tbasetype->is_binary() ? "binary" : t_base_type::t_base_name(tbasetype->get_base());
}
return "(unknown)";
}
string t_json_generator::get_qualified_name(t_type* ttype) {
if (should_merge_includes_ || ttype->get_program() == program_) {
return ttype->get_name();
}
return ttype->get_program()->get_name() + "." + ttype->get_name();
}
THRIFT_REGISTER_GENERATOR(json,
"JSON",
" merge: Generate output with included files merged\n")

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,112 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_OOP_GENERATOR_H
#define T_OOP_GENERATOR_H
#include <string>
#include <iostream>
#include "thrift/common.h"
#include "thrift/generate/t_generator.h"
#include <algorithm>
/**
* Class with utility methods shared across common object oriented languages.
* Specifically, most of this stuff is for C++/Java.
*
*/
class t_oop_generator : public t_generator {
public:
t_oop_generator(t_program* program) : t_generator(program) {}
/**
* Scoping, using curly braces!
*/
void scope_up(std::ostream& out) {
indent(out) << "{" << std::endl;
indent_up();
}
void scope_down(std::ostream& out) {
indent_down();
indent(out) << "}" << std::endl;
}
std::string upcase_string(std::string original) {
std::transform(original.begin(), original.end(), original.begin(), (int (*)(int))toupper);
return original;
}
virtual std::string get_enum_class_name(t_type* type) {
std::string package = "";
t_program* program = type->get_program();
if (program != NULL && program != program_) {
package = program->get_namespace("java") + ".";
}
return package + type->get_name();
}
virtual void generate_java_docstring_comment(std::ofstream& out, std::string contents) {
generate_docstring_comment(out, "/**\n", " * ", contents, " */\n");
}
virtual void generate_java_doc(std::ofstream& out, t_field* field) {
if (field->get_type()->is_enum()) {
std::string combined_message = field->get_doc() + "\n@see "
+ get_enum_class_name(field->get_type());
generate_java_docstring_comment(out, combined_message);
} else {
generate_java_doc(out, (t_doc*)field);
}
}
/**
* Emits a JavaDoc comment if the provided object has a doc in Thrift
*/
virtual void generate_java_doc(std::ofstream& out, t_doc* tdoc) {
if (tdoc->has_doc()) {
generate_java_docstring_comment(out, tdoc->get_doc());
}
}
/**
* Emits a JavaDoc comment if the provided function object has a doc in Thrift
*/
virtual void generate_java_doc(std::ofstream& out, t_function* tfunction) {
if (tfunction->has_doc()) {
std::stringstream ss;
ss << tfunction->get_doc();
const std::vector<t_field*>& fields = tfunction->get_arglist()->get_members();
std::vector<t_field*>::const_iterator p_iter;
for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
t_field* p = *p_iter;
ss << "\n@param " << p->get_name();
if (p->has_doc()) {
ss << " " << p->get_doc();
}
}
generate_docstring_comment(out, "/**\n", " * ", ss.str(), " */\n");
}
}
};
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,687 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include <fstream>
#include <iostream>
#include <sstream>
#include <limits>
#include <stdlib.h>
#include <sys/stat.h>
#include <sstream>
#include "thrift/platform.h"
#include "thrift/generate/t_generator.h"
using std::map;
using std::ofstream;
using std::ostream;
using std::ostringstream;
using std::string;
using std::stringstream;
using std::vector;
using std::stack;
using std::set;
static const string endl = "\n";
static const string quot = "\"";
static const string default_ns_prefix = "http://thrift.apache.org/xml/ns/";
/**
* This generator creates an XML model of the parsed IDL tree, and is designed
* to make it easy to use this file as the input for other template engines,
* such as XSLT. To this end, the generated XML is slightly more verbose than
* you might expect... for example, references to "id" types (such as structs,
* unions, etc) always specify the name of the IDL document, even if the type
* is defined in the same document as the reference.
*/
class t_xml_generator : public t_generator {
public:
t_xml_generator( t_program* program,
const std::map<std::string, std::string>& parsed_options,
const std::string& option_string)
: t_generator(program) {
(void)option_string;
std::map<std::string, std::string>::const_iterator iter;
should_merge_includes_ = false;
should_use_default_ns_ = true;
should_use_namespaces_ = true;
for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
if( iter->first.compare("merge") == 0) {
should_merge_includes_ = true;
} else if( iter->first.compare("no_default_ns") == 0) {
should_use_default_ns_ = false;
} else if( iter->first.compare("no_namespaces") == 0) {
should_use_namespaces_ = false;
} else {
throw "unknown option xml:" + iter->first;
}
}
out_dir_base_ = "gen-xml";
}
virtual ~t_xml_generator() {}
void init_generator();
void close_generator();
void generate_program();
void iterate_program(t_program* program);
void generate_typedef(t_typedef* ttypedef);
void generate_enum(t_enum* tenum);
void generate_function(t_function* tfunc);
void generate_field(t_field* field);
void generate_service(t_service* tservice);
void generate_struct(t_struct* tstruct);
void generate_annotations(std::map<std::string, std::string> annotations);
private:
bool should_merge_includes_;
bool should_use_default_ns_;
bool should_use_namespaces_;
std::ofstream f_xml_;
std::set<string> programs_;
std::stack<string> elements_;
bool top_element_is_empty;
bool top_element_is_open;
string target_namespace(t_program* program);
void write_element_start(const string name);
void close_top_element();
void write_element_end();
void write_attribute(string key, string val);
void write_int_attribute(string key, int val);
string escape_xml_string(const string& input);
void write_xml_comment(string msg);
void write_type(t_type* ttype);
void write_doc(t_doc* tdoc);
template <typename T>
string number_to_string(T t) {
std::ostringstream out;
out.imbue(std::locale::classic());
out.precision(std::numeric_limits<T>::digits10);
out << t;
return out.str();
}
template <typename T>
void write_number(T n) {
f_xml_ << number_to_string(n);
}
template <typename T>
void write_element_number(string name, T n) {
write_element_string(name, number_to_string(n));
}
string get_type_name(t_type* ttype);
void generate_constant(t_const* con);
void write_element_string(string name, string value);
void write_value(t_type* tvalue);
void write_const_value(t_const_value* value);
virtual std::string xml_autogen_comment() {
return std::string("\n") + " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
+ " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n";
}
};
void t_xml_generator::init_generator() {
MKDIR(get_out_dir().c_str());
string f_xml_name = get_out_dir() + program_->get_name() + ".xml";
f_xml_.open(f_xml_name.c_str());
top_element_is_open = false;
}
string t_xml_generator::target_namespace(t_program* program) {
std::map<std::string, std::string> map;
std::map<std::string, std::string>::iterator iter;
map = program->get_namespace_annotations("xml");
if ((iter = map.find("targetNamespace")) != map.end()) {
return iter->second;
}
map = program->get_namespaces();
if ((iter = map.find("xml")) != map.end()) {
return default_ns_prefix + iter->second;
}
map = program->get_namespace_annotations("*");
if ((iter = map.find("xml.targetNamespace")) != map.end()) {
return iter->second;
}
map = program->get_namespaces();
if ((iter = map.find("*")) != map.end()) {
return default_ns_prefix + iter->second;
}
return default_ns_prefix + program->get_name();
}
void t_xml_generator::write_xml_comment(string msg) {
close_top_element();
// TODO: indent any EOLs that may occur with msg
// TODO: proper msg escaping needed?
f_xml_ << indent() << "<!-- " << msg << " -->" << endl;
top_element_is_empty = false;
}
void t_xml_generator::close_top_element() {
if( top_element_is_open) {
top_element_is_open = false;
if (elements_.size() > 0 && top_element_is_empty) {
f_xml_ << ">" << endl;
}
}
}
void t_xml_generator::write_element_start(string name) {
if (should_use_namespaces_ && !should_use_default_ns_) {
name = "idl:" + name;
}
close_top_element();
f_xml_ << indent() << "<" << name;
elements_.push(name);
top_element_is_empty = true;
top_element_is_open = true;
indent_up();
}
void t_xml_generator::write_element_end() {
indent_down();
if (top_element_is_empty && top_element_is_open) {
f_xml_ << " />" << endl;
} else {
f_xml_ << indent() << "</" << elements_.top() << ">" << endl;
}
top_element_is_empty = false;
elements_.pop();
}
void t_xml_generator::write_attribute(string key, string val) {
f_xml_ << " " << key << "=\"" << escape_xml_string(val) << "\"";
}
void t_xml_generator::write_int_attribute(string key, int val) {
write_attribute(key, number_to_string(val));
}
void t_xml_generator::write_element_string(string name, string val) {
if (should_use_namespaces_ && !should_use_default_ns_) {
name = "idl:" + name;
}
close_top_element();
top_element_is_empty = false;
f_xml_ << indent()
<< "<" << name << ">" << escape_xml_string(val) << "</" << name << ">"
<< endl;
}
string t_xml_generator::escape_xml_string(const string& input) {
std::ostringstream ss;
for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) {
switch (*iter) {
case '&':
ss << "&amp;";
break;
case '"':
ss << "&quot;";
break;
case '\'':
ss << "&apos;";
break;
case '<':
ss << "&lt;";
break;
case '>':
ss << "&gt;";
break;
default:
ss << *iter;
break;
}
}
return ss.str();
}
void t_xml_generator::close_generator() {
f_xml_.close();
}
void t_xml_generator::generate_program() {
init_generator();
write_element_start("idl");
if (should_use_namespaces_) {
if (should_use_default_ns_) {
write_attribute("xmlns", "http://thrift.apache.org/xml/idl");
}
write_attribute("xmlns:idl", "http://thrift.apache.org/xml/idl");
}
write_xml_comment( xml_autogen_comment());
iterate_program(program_);
write_element_end();
close_generator();
}
void t_xml_generator::iterate_program(t_program* program) {
write_element_start("document");
write_attribute("name", program->get_name());
if (should_use_namespaces_) {
const string targetNamespace = target_namespace(program);
write_attribute("targetNamespace", targetNamespace);
write_attribute("xmlns:" + program->get_name(), targetNamespace);
}
write_doc(program);
const vector<t_program*> includes = program->get_includes();
vector<t_program*>::const_iterator inc_it;
for (inc_it = includes.begin(); inc_it != includes.end(); ++inc_it) {
write_element_start("include");
write_attribute("name", (*inc_it)->get_name());
write_element_end();
}
const map<string, string>& namespaces = program->get_namespaces();
map<string, string>::const_iterator ns_it;
for (ns_it = namespaces.begin(); ns_it != namespaces.end(); ++ns_it) {
write_element_start("namespace");
write_attribute("name", ns_it->first);
write_attribute("value", ns_it->second);
generate_annotations(program->get_namespace_annotations(ns_it->first));
write_element_end();
}
// TODO: can constants have annotations?
vector<t_const*> consts = program->get_consts();
vector<t_const*>::iterator c_iter;
for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
generate_constant(*c_iter);
}
vector<t_typedef*> typedefs = program->get_typedefs();
vector<t_typedef*>::iterator td_iter;
for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
generate_typedef(*td_iter);
}
vector<t_enum*> enums = program->get_enums();
vector<t_enum*>::iterator en_iter;
for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
generate_enum(*en_iter);
}
vector<t_struct*> objects = program->get_objects();
vector<t_struct*>::iterator o_iter;
for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
if ((*o_iter)->is_xception()) {
generate_xception(*o_iter);
} else {
generate_struct(*o_iter);
}
}
vector<t_service*> services = program->get_services();
vector<t_service*>::iterator sv_iter;
for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
generate_service(*sv_iter);
}
write_element_end();
if (should_merge_includes_) {
programs_.insert(program->get_name());
const vector<t_program*> programs = program->get_includes();
vector<t_program*>::const_iterator prog_it;
for (prog_it = programs.begin(); prog_it != programs.end(); ++prog_it) {
if (!programs_.count((*prog_it)->get_name())) {
iterate_program(*prog_it);
}
}
}
}
void t_xml_generator::generate_typedef(t_typedef* ttypedef) {
write_element_start("typedef");
write_attribute("name", ttypedef->get_name());
write_doc(ttypedef);
write_type(ttypedef->get_true_type());
generate_annotations(ttypedef->annotations_);
write_element_end();
return;
}
void t_xml_generator::write_type(t_type* ttype) {
const string type = get_type_name(ttype);
write_attribute("type", type);
if (type == "id") {
write_attribute("type-module", ttype->get_program()->get_name());
write_attribute("type-id", ttype->get_name());
} else if (type == "list" || type == "set") {
t_type* etype = ((t_list*)ttype)->get_elem_type();
write_element_start("elemType");
write_type(etype);
write_element_end();
} else if (type == "map") {
t_type* ktype = ((t_map*)ttype)->get_key_type();
write_element_start("keyType");
write_type(ktype);
write_element_end();
t_type* vtype = ((t_map*)ttype)->get_val_type();
write_element_start("valueType");
write_type(vtype);
write_element_end();
}
}
void t_xml_generator::write_doc(t_doc* tdoc) {
if (tdoc->has_doc()) {
string doc = tdoc->get_doc();
// for some reason there always seems to be a trailing newline on doc
// comments; loop below naively tries to strip off trailing cr/lf
int n = 0;
for (string::reverse_iterator i = doc.rbegin(); i != doc.rend(); i++,n++) {
if (*i != '\n' || *i == '\r') {
if (n > 0) {
doc.erase(doc.length() - n);
}
break;
}
}
write_attribute("doc", doc);
}
}
void t_xml_generator::generate_annotations(
std::map<std::string, std::string> annotations) {
std::map<std::string, std::string>::iterator iter;
for (iter = annotations.begin(); iter != annotations.end(); ++iter) {
write_element_start("annotation");
write_attribute("key", iter->first);
write_attribute("value", iter->second);
write_element_end();
}
}
void t_xml_generator::generate_constant(t_const* con) {
write_element_start("const");
write_attribute("name", con->get_name());
write_doc(con);
write_type(con->get_type());
write_const_value(con->get_value());
write_element_end();
}
void t_xml_generator::write_const_value(t_const_value* value) {
switch (value->get_type()) {
case t_const_value::CV_IDENTIFIER:
case t_const_value::CV_INTEGER:
write_element_number("int", value->get_integer());
break;
case t_const_value::CV_DOUBLE:
write_element_number("double", value->get_double());
break;
case t_const_value::CV_STRING:
write_element_string("string", value->get_string());
break;
case t_const_value::CV_LIST: {
write_element_start("list");
std::vector<t_const_value*> list = value->get_list();
std::vector<t_const_value*>::iterator lit;
for (lit = list.begin(); lit != list.end(); ++lit) {
write_element_start("entry");
write_const_value(*lit);
write_element_end();
}
write_element_end();
break;
}
case t_const_value::CV_MAP: {
write_element_start("map");
std::map<t_const_value*, t_const_value*> map = value->get_map();
std::map<t_const_value*, t_const_value*>::iterator mit;
for (mit = map.begin(); mit != map.end(); ++mit) {
write_element_start("entry");
write_element_start("key");
write_const_value(mit->first);
write_element_end();
write_element_start("value");
write_const_value(mit->second);
write_element_end();
write_element_end();
}
write_element_end();
break;
}
default:
indent_up();
f_xml_ << indent() << "<null />" << endl;
indent_down();
break;
}
}
void t_xml_generator::generate_enum(t_enum* tenum) {
write_element_start("enum");
write_attribute("name", tenum->get_name());
write_doc(tenum);
vector<t_enum_value*> values = tenum->get_constants();
vector<t_enum_value*>::iterator val_iter;
for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) {
t_enum_value* val = (*val_iter);
write_element_start("member");
write_attribute("name", val->get_name());
write_int_attribute("value", val->get_value());
write_doc(val);
generate_annotations(val->annotations_);
write_element_end();
}
generate_annotations(tenum->annotations_);
write_element_end();
}
void t_xml_generator::generate_struct(t_struct* tstruct) {
string tagname = "struct";
if (tstruct->is_union()) {
tagname = "union";
} else if (tstruct->is_xception()) {
tagname = "exception";
}
write_element_start(tagname);
write_attribute("name", tstruct->get_name());
write_doc(tstruct);
vector<t_field*> members = tstruct->get_members();
vector<t_field*>::iterator mem_iter;
for (mem_iter = members.begin(); mem_iter != members.end(); mem_iter++) {
write_element_start("field");
generate_field(*mem_iter);
write_element_end();
}
generate_annotations(tstruct->annotations_);
write_element_end();
}
void t_xml_generator::generate_field(t_field* field) {
write_attribute("name", field->get_name());
write_int_attribute("field-id", field->get_key());
write_doc(field);
string requiredness;
switch (field->get_req()) {
case t_field::T_REQUIRED:
requiredness = "required";
break;
case t_field::T_OPTIONAL:
requiredness = "optional";
break;
default:
requiredness = "";
break;
}
if (requiredness != "") {
write_attribute("required", requiredness);
}
write_type(field->get_type());
if (field->get_value()) {
write_element_start("default");
write_const_value(field->get_value());
write_element_end();
}
generate_annotations(field->annotations_);
}
void t_xml_generator::generate_service(t_service* tservice) {
write_element_start("service");
write_attribute("name", tservice->get_name());
if (should_use_namespaces_) {
string prog_ns = target_namespace(tservice->get_program());
if (*prog_ns.rbegin() != '/') {
prog_ns.push_back('/');
}
const string tns = prog_ns + tservice->get_name();
write_attribute("targetNamespace", tns);
write_attribute("xmlns:tns", tns);
}
if (tservice->get_extends()) {
const t_service* extends = tservice->get_extends();
write_attribute("parent-module", extends->get_program()->get_name());
write_attribute("parent-id", extends->get_name());
}
write_doc(tservice);
vector<t_function*> functions = tservice->get_functions();
vector<t_function*>::iterator fn_iter = functions.begin();
for (; fn_iter != functions.end(); fn_iter++) {
generate_function(*fn_iter);
}
generate_annotations(tservice->annotations_);
write_element_end();
}
void t_xml_generator::generate_function(t_function* tfunc) {
write_element_start("method");
write_attribute("name", tfunc->get_name());
if (tfunc->is_oneway()) {
write_attribute("oneway", "true");
}
write_doc(tfunc);
write_element_start("returns");
write_type(tfunc->get_returntype());
write_element_end();
vector<t_field*> members = tfunc->get_arglist()->get_members();
vector<t_field*>::iterator mem_iter = members.begin();
for (; mem_iter != members.end(); mem_iter++) {
write_element_start("arg");
generate_field(*mem_iter);
write_element_end();
}
vector<t_field*> excepts = tfunc->get_xceptions()->get_members();
vector<t_field*>::iterator ex_iter = excepts.begin();
for (; ex_iter != excepts.end(); ex_iter++) {
write_element_start("throws");
generate_field(*ex_iter);
write_element_end();
}
generate_annotations(tfunc->annotations_);
write_element_end();
}
string t_xml_generator::get_type_name(t_type* ttype) {
if (ttype->is_list()) {
return "list";
}
if (ttype->is_set()) {
return "set";
}
if (ttype->is_map()) {
return "map";
}
if ((ttype->is_enum() )||
(ttype->is_struct() )||
(ttype->is_typedef() )||
(ttype->is_xception())){
return "id";
}
if (ttype->is_base_type()) {
t_base_type* tbasetype = (t_base_type*)ttype;
if (tbasetype->is_binary() ) {
return "binary";
}
return t_base_type::t_base_name(tbasetype->get_base());
}
return "(unknown)";
}
THRIFT_REGISTER_GENERATOR(
xml,
"XML",
" merge: Generate output with included files merged\n"
" no_default_ns: Omit default xmlns and add idl: prefix to all elements\n"
" no_namespaces: Do not add namespace definitions to the XML model\n")

View file

@ -0,0 +1,376 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <sys/stat.h>
#include <sstream>
#include "thrift/version.h"
#include "thrift/platform.h"
#include "thrift/generate/t_generator.h"
using std::map;
using std::ofstream;
using std::ostream;
using std::ostringstream;
using std::string;
using std::stringstream;
using std::vector;
static const string endl = "\n"; // avoid ostream << std::endl flushes
/**
* XSD generator, creates an XSD for the base types etc.
*
*/
class t_xsd_generator : public t_generator {
public:
t_xsd_generator(t_program* program,
const std::map<std::string, std::string>& parsed_options,
const std::string& option_string)
: t_generator(program) {
(void)option_string;
std::map<std::string, std::string>::const_iterator iter;
/* no options yet */
for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
throw "unknown option xsd:" + iter->first;
}
out_dir_base_ = "gen-xsd";
}
virtual ~t_xsd_generator() {}
/**
* Init and close methods
*/
void init_generator();
void close_generator();
/**
* Program-level generation functions
*/
void generate_typedef(t_typedef* ttypedef);
void generate_enum(t_enum* tenum) { (void)tenum; }
void generate_service(t_service* tservice);
void generate_struct(t_struct* tstruct);
private:
void generate_element(std::ostream& out,
std::string name,
t_type* ttype,
t_struct* attrs = NULL,
bool optional = false,
bool nillable = false,
bool list_element = false);
std::string ns(std::string in, std::string ns) { return ns + ":" + in; }
std::string xsd(std::string in) { return ns(in, "xsd"); }
std::string type_name(t_type* ttype);
std::string base_type_name(t_base_type::t_base tbase);
virtual std::string xml_autogen_comment() {
return std::string("<!--\n") + " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
+ " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
+ " -->\n";
}
/**
* Output xsd/php file
*/
std::ofstream f_xsd_;
std::ofstream f_php_;
/**
* Output string stream
*/
std::ostringstream s_xsd_types_;
};
void t_xsd_generator::init_generator() {
// Make output directory
MKDIR(get_out_dir().c_str());
// Make output file
string f_php_name = get_out_dir() + program_->get_name() + "_xsd.php";
f_php_.open(f_php_name.c_str());
f_php_ << "<?php" << endl
<< autogen_comment() << endl;
}
void t_xsd_generator::close_generator() {
f_php_ << "?>" << endl;
f_php_.close();
}
void t_xsd_generator::generate_typedef(t_typedef* ttypedef) {
indent(s_xsd_types_) << "<xsd:simpleType name=\"" << ttypedef->get_name() << "\">" << endl;
indent_up();
if (ttypedef->get_type()->is_string() && ((t_base_type*)ttypedef->get_type())->is_string_enum()) {
indent(s_xsd_types_) << "<xsd:restriction base=\"" << type_name(ttypedef->get_type()) << "\">"
<< endl;
indent_up();
const vector<string>& values = ((t_base_type*)ttypedef->get_type())->get_string_enum_vals();
vector<string>::const_iterator v_iter;
for (v_iter = values.begin(); v_iter != values.end(); ++v_iter) {
indent(s_xsd_types_) << "<xsd:enumeration value=\"" << (*v_iter) << "\" />" << endl;
}
indent_down();
indent(s_xsd_types_) << "</xsd:restriction>" << endl;
} else {
indent(s_xsd_types_) << "<xsd:restriction base=\"" << type_name(ttypedef->get_type()) << "\" />"
<< endl;
}
indent_down();
indent(s_xsd_types_) << "</xsd:simpleType>" << endl << endl;
}
void t_xsd_generator::generate_struct(t_struct* tstruct) {
vector<t_field*>::const_iterator m_iter;
const vector<t_field*>& members = tstruct->get_members();
bool xsd_all = tstruct->get_xsd_all();
indent(s_xsd_types_) << "<xsd:complexType name=\"" << tstruct->get_name() << "\">" << endl;
indent_up();
if (xsd_all) {
indent(s_xsd_types_) << "<xsd:all>" << endl;
} else {
indent(s_xsd_types_) << "<xsd:sequence>" << endl;
}
indent_up();
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
generate_element(s_xsd_types_,
(*m_iter)->get_name(),
(*m_iter)->get_type(),
(*m_iter)->get_xsd_attrs(),
(*m_iter)->get_xsd_optional() || xsd_all,
(*m_iter)->get_xsd_nillable());
}
indent_down();
if (xsd_all) {
indent(s_xsd_types_) << "</xsd:all>" << endl;
} else {
indent(s_xsd_types_) << "</xsd:sequence>" << endl;
}
indent_down();
indent(s_xsd_types_) << "</xsd:complexType>" << endl << endl;
}
void t_xsd_generator::generate_element(ostream& out,
string name,
t_type* ttype,
t_struct* attrs,
bool optional,
bool nillable,
bool list_element) {
string sminOccurs = (optional || list_element) ? " minOccurs=\"0\"" : "";
string smaxOccurs = list_element ? " maxOccurs=\"unbounded\"" : "";
string soptional = sminOccurs + smaxOccurs;
string snillable = nillable ? " nillable=\"true\"" : "";
if (ttype->is_void() || ttype->is_list()) {
indent(out) << "<xsd:element name=\"" << name << "\"" << soptional << snillable << ">" << endl;
indent_up();
if (attrs == NULL && ttype->is_void()) {
indent(out) << "<xsd:complexType />" << endl;
} else {
indent(out) << "<xsd:complexType>" << endl;
indent_up();
if (ttype->is_list()) {
indent(out) << "<xsd:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">" << endl;
indent_up();
string subname;
t_type* subtype = ((t_list*)ttype)->get_elem_type();
if (subtype->is_base_type() || subtype->is_container()) {
subname = name + "_elt";
} else {
subname = type_name(subtype);
}
f_php_ << "$GLOBALS['" << program_->get_name() << "_xsd_elt_" << name << "'] = '" << subname
<< "';" << endl;
generate_element(out, subname, subtype, NULL, false, false, true);
indent_down();
indent(out) << "</xsd:sequence>" << endl;
indent(out) << "<xsd:attribute name=\"list\" type=\"xsd:boolean\" />" << endl;
}
if (attrs != NULL) {
const vector<t_field*>& members = attrs->get_members();
vector<t_field*>::const_iterator a_iter;
for (a_iter = members.begin(); a_iter != members.end(); ++a_iter) {
indent(out) << "<xsd:attribute name=\"" << (*a_iter)->get_name() << "\" type=\""
<< type_name((*a_iter)->get_type()) << "\" />" << endl;
}
}
indent_down();
indent(out) << "</xsd:complexType>" << endl;
}
indent_down();
indent(out) << "</xsd:element>" << endl;
} else {
if (attrs == NULL) {
indent(out) << "<xsd:element name=\"" << name << "\""
<< " type=\"" << type_name(ttype) << "\"" << soptional << snillable << " />"
<< endl;
} else {
// Wow, all this work for a SIMPLE TYPE with attributes?!?!?!
indent(out) << "<xsd:element name=\"" << name << "\"" << soptional << snillable << ">"
<< endl;
indent_up();
indent(out) << "<xsd:complexType>" << endl;
indent_up();
indent(out) << "<xsd:complexContent>" << endl;
indent_up();
indent(out) << "<xsd:extension base=\"" << type_name(ttype) << "\">" << endl;
indent_up();
const vector<t_field*>& members = attrs->get_members();
vector<t_field*>::const_iterator a_iter;
for (a_iter = members.begin(); a_iter != members.end(); ++a_iter) {
indent(out) << "<xsd:attribute name=\"" << (*a_iter)->get_name() << "\" type=\""
<< type_name((*a_iter)->get_type()) << "\" />" << endl;
}
indent_down();
indent(out) << "</xsd:extension>" << endl;
indent_down();
indent(out) << "</xsd:complexContent>" << endl;
indent_down();
indent(out) << "</xsd:complexType>" << endl;
indent_down();
indent(out) << "</xsd:element>" << endl;
}
}
}
void t_xsd_generator::generate_service(t_service* tservice) {
// Make output file
string f_xsd_name = get_out_dir() + tservice->get_name() + ".xsd";
f_xsd_.open(f_xsd_name.c_str());
string ns = program_->get_namespace("xsd");
const std::map<std::string, std::string> annot = program_->get_namespace_annotations("xsd");
const std::map<std::string, std::string>::const_iterator uri = annot.find("uri");
if (uri != annot.end()) {
ns = uri->second;
}
if (ns.size() > 0) {
ns = " targetNamespace=\"" + ns + "\" xmlns=\"" + ns + "\" "
+ "elementFormDefault=\"qualified\"";
}
// Print the XSD header
f_xsd_ << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" << endl
<< "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" << ns << ">" << endl
<< xml_autogen_comment()
<< endl;
// Print out the type definitions
indent(f_xsd_) << s_xsd_types_.str();
// Keep a list of all the possible exceptions that might get thrown
map<string, t_struct*> all_xceptions;
// List the elements that you might actually get
vector<t_function*> functions = tservice->get_functions();
vector<t_function*>::iterator f_iter;
for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
string elemname = (*f_iter)->get_name() + "_response";
t_type* returntype = (*f_iter)->get_returntype();
generate_element(f_xsd_, elemname, returntype);
f_xsd_ << endl;
t_struct* xs = (*f_iter)->get_xceptions();
const std::vector<t_field*>& xceptions = xs->get_members();
vector<t_field*>::const_iterator x_iter;
for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
all_xceptions[(*x_iter)->get_name()] = (t_struct*)((*x_iter)->get_type());
}
}
map<string, t_struct*>::iterator ax_iter;
for (ax_iter = all_xceptions.begin(); ax_iter != all_xceptions.end(); ++ax_iter) {
generate_element(f_xsd_, ax_iter->first, ax_iter->second);
}
// Close the XSD document
f_xsd_ << endl << "</xsd:schema>" << endl;
f_xsd_.close();
}
string t_xsd_generator::type_name(t_type* ttype) {
if (ttype->is_typedef()) {
return ttype->get_name();
}
if (ttype->is_base_type()) {
return xsd(base_type_name(((t_base_type*)ttype)->get_base()));
}
if (ttype->is_enum()) {
return xsd("int");
}
if (ttype->is_struct() || ttype->is_xception()) {
return ttype->get_name();
}
return "container";
}
/**
* Returns the XSD type that corresponds to the thrift type.
*
* @param tbase The base type
* @return Explicit XSD type, i.e. xsd:string
*/
string t_xsd_generator::base_type_name(t_base_type::t_base tbase) {
switch (tbase) {
case t_base_type::TYPE_VOID:
return "void";
case t_base_type::TYPE_STRING:
return "string";
case t_base_type::TYPE_BOOL:
return "boolean";
case t_base_type::TYPE_I8:
return "byte";
case t_base_type::TYPE_I16:
return "short";
case t_base_type::TYPE_I32:
return "int";
case t_base_type::TYPE_I64:
return "long";
case t_base_type::TYPE_DOUBLE:
return "decimal";
default:
throw "compiler error: no XSD base type name for base type " + t_base_type::t_base_name(tbase);
}
}
THRIFT_REGISTER_GENERATOR(xsd, "XSD", "")

View file

@ -0,0 +1,141 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_GLOBALS_H
#define T_GLOBALS_H
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <string>
/**
* This module contains all the global variables (slap on the wrist) that are
* shared throughout the program. The reason for this is to facilitate simple
* interaction between the parser and the rest of the program. Before calling
* yyparse(), the main.cc program will make necessary adjustments to these
* global variables such that the parser does the right thing and puts entries
* into the right containers, etc.
*
*/
/**
* Hooray for forward declaration of types!
*/
class t_program;
class t_scope;
class t_type;
/**
* Parsing mode, two passes up in this gin rummy!
*/
enum PARSE_MODE { INCLUDES = 1, PROGRAM = 2 };
/**
* Strictness level
*/
extern int g_strict;
/**
* The master program parse tree. This is accessed from within the parser code
* to build up the program elements.
*/
extern t_program* g_program;
/**
* The scope that we are currently parsing into
*/
extern t_scope* g_scope;
/**
* The parent scope to also load symbols into
*/
extern t_scope* g_parent_scope;
/**
* The prefix for the parent scope entries
*/
extern std::string g_parent_prefix;
/**
* The parsing pass that we are on. We do different things on each pass.
*/
extern PARSE_MODE g_parse_mode;
/**
* Global time string, used in formatting error messages etc.
*/
extern char* g_time_str;
/**
* The last parsed doctext comment.
*/
extern char* g_doctext;
/**
* The location of the last parsed doctext comment.
*/
extern int g_doctext_lineno;
/**
* Status of program level doctext candidate
*/
enum PROGDOCTEXT_STATUS {
INVALID = 0,
STILL_CANDIDATE = 1, // the text may or may not be the program doctext
ALREADY_PROCESSED = 2, // doctext has been used and is no longer available
ABSOLUTELY_SURE = 3, // this is the program doctext
NO_PROGRAM_DOCTEXT = 4 // there is no program doctext
};
/**
* The program level doctext. Stored separately to make parsing easier.
*/
extern char* g_program_doctext_candidate;
extern int g_program_doctext_lineno;
extern PROGDOCTEXT_STATUS g_program_doctext_status;
/**
* Whether or not negative field keys are accepted.
*
* When a field does not have a user-specified key, thrift automatically
* assigns a negative value. However, this is fragile since changes to the
* file may unintentionally change the key numbering, resulting in a new
* protocol that is not backwards compatible.
*
* When g_allow_neg_field_keys is enabled, users can explicitly specify
* negative keys. This way they can write a .thrift file with explicitly
* specified keys that is still backwards compatible with older .thrift files
* that did not specify key values.
*/
extern int g_allow_neg_field_keys;
/**
* Whether or not 64-bit constants will generate a warning.
*
* Some languages don't support 64-bit constants, but many do, so we can
* suppress this warning for projects that don't use any non-64-bit-safe
* languages.
*/
extern int g_allow_64bit_consts;
#endif

View file

@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/**
* Logging functions copied from main.cc to avoid link errors for plugins
*/
#include "thrift/logging.h"
#include "thrift/globals.h"
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
// TODO: make plugins accept log options from main compiler
int g_debug = 0;
int g_warn = 1;
int g_verbose = 0;
void pdebug(const char* fmt, ...) {
if (g_debug == 0) {
return;
}
va_list args;
// printf("[PARSE:%d] ", yylineno);
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
printf("\n");
}
void pverbose(const char* fmt, ...) {
if (g_verbose == 0) {
return;
}
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
void pwarning(int level, const char* fmt, ...) {
if (g_warn < level) {
return;
}
va_list args;
// printf("[WARNING:%s:%d] ", g_curpath.c_str(), yylineno);
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
printf("\n");
}
void failure(const char* fmt, ...) {
va_list args;
// fprintf(stderr, "[FAILURE:%s:%d] ", g_curpath.c_str(), yylineno);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
printf("\n");
exit(1);
}

View file

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_LOGGING_H
#define T_LOGGING_H
extern int g_debug;
extern int g_warn;
extern int g_verbose;
/**
* Parse debugging output, used to print helpful info
*/
void pdebug(const char* fmt, ...);
/**
* Parser warning
*/
void pwarning(int level, const char* fmt, ...);
/**
* Print verbose output message
*/
void pverbose(const char* fmt, ...);
/**
* Failure!
*/
void failure(const char* fmt, ...);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,119 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_MAIN_H
#define T_MAIN_H
#include <string>
#include <cstdio>
#include "thrift/logging.h"
#include "thrift/parse/t_const.h"
#include "thrift/parse/t_field.h"
/**
* Defined in the flex library
*/
extern "C" { int yylex(void); }
int yyparse(void);
/**
* Expected to be defined by Flex/Bison
*/
void yyerror(const char* fmt, ...);
/**
* Check simple identifier names
*/
void validate_simple_identifier(const char* identifier);
/**
* Check constant types
*/
void validate_const_type(t_const* c);
/**
* Check constant types
*/
void validate_field_value(t_field* field, t_const_value* cv);
/**
* Check members of a throws block
*/
bool validate_throws(t_struct* throws);
/**
* Converts a string filename into a thrift program name
*/
std::string program_name(std::string filename);
/**
* Gets the directory path of a filename
*/
std::string directory_name(std::string filename);
/**
* Get the absolute path for an include file
*/
std::string include_file(std::string filename);
/**
* Clears any previously stored doctext string.
*/
void clear_doctext();
/**
* Cleans up text commonly found in doxygen-like comments
*/
char* clean_up_doctext(char* doctext);
/**
* We are sure the program doctext candidate is really the program doctext.
*/
void declare_valid_program_doctext();
/**
* Emits a warning on list<byte>, binary type is typically a much better choice.
*/
void check_for_list_of_bytes(t_type* list_elem_type);
/**
* Emits a one-time warning on byte type, promoting the new i8 type instead
*/
void emit_byte_type_warning();
/**
* Prints deprecation notice for old NS declarations that are no longer supported
* If new_form is NULL, old_form is assumed to be a language identifier, such as "cpp"
* If new_form is not NULL, both arguments are used exactly as given
*/
void error_unsupported_namespace_decl(const char* old_form, const char* new_form = NULL);
/**
* Flex utilities
*/
extern int yylineno;
extern char yytext[];
extern std::FILE* yyin;
#endif

View file

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include "thrift/parse/t_type.h"
#include "thrift/parse/t_typedef.h"
#include "thrift/main.h"
t_type* t_type::get_true_type() {
t_type* type = this;
while (type->is_typedef()) {
type = ((t_typedef*)type)->get_type();
}
return type;
}
const t_type* t_type::get_true_type() const {
const t_type* type = this;
while (type->is_typedef()) {
type = ((t_typedef*)type)->get_type();
}
return type;
}

View file

@ -0,0 +1,117 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_BASE_TYPE_H
#define T_BASE_TYPE_H
#include <cstdlib>
#include "thrift/parse/t_type.h"
/**
* A thrift base type, which must be one of the defined enumerated types inside
* this definition.
*
*/
class t_base_type : public t_type {
public:
/**
* Enumeration of thrift base types
*/
enum t_base {
TYPE_VOID,
TYPE_STRING,
TYPE_BOOL,
TYPE_I8,
TYPE_I16,
TYPE_I32,
TYPE_I64,
TYPE_DOUBLE
};
t_base_type(std::string name, t_base base)
: t_type(name), base_(base), string_list_(false), binary_(false), string_enum_(false) {}
t_base get_base() const { return base_; }
bool is_void() const { return base_ == TYPE_VOID; }
bool is_string() const { return base_ == TYPE_STRING; }
bool is_bool() const { return base_ == TYPE_BOOL; }
void set_string_list(bool val) { string_list_ = val; }
bool is_string_list() const { return (base_ == TYPE_STRING) && string_list_; }
void set_binary(bool val) { binary_ = val; }
bool is_binary() const { return (base_ == TYPE_STRING) && binary_; }
void set_string_enum(bool val) { string_enum_ = val; }
bool is_string_enum() const { return base_ == TYPE_STRING && string_enum_; }
void add_string_enum_val(std::string val) { string_enum_vals_.push_back(val); }
const std::vector<std::string>& get_string_enum_vals() const { return string_enum_vals_; }
bool is_base_type() const { return true; }
static std::string t_base_name(t_base tbase) {
switch (tbase) {
case TYPE_VOID:
return "void";
break;
case TYPE_STRING:
return "string";
break;
case TYPE_BOOL:
return "bool";
break;
case TYPE_I8:
return "i8";
break;
case TYPE_I16:
return "i16";
break;
case TYPE_I32:
return "i32";
break;
case TYPE_I64:
return "i64";
break;
case TYPE_DOUBLE:
return "double";
break;
default:
return "(unknown)";
break;
}
}
private:
t_base base_;
bool string_list_;
bool binary_;
bool string_enum_;
std::vector<std::string> string_enum_vals_;
};
#endif

View file

@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_CONST_H
#define T_CONST_H
#include "thrift/parse/t_type.h"
#include "thrift/parse/t_const_value.h"
/**
* A const is a constant value defined across languages that has a type and
* a value. The trick here is that the declared type might not match the type
* of the value object, since that is not determined until after parsing the
* whole thing out.
*
*/
class t_const : public t_doc {
public:
t_const(t_type* type, std::string name, t_const_value* value)
: type_(type), name_(name), value_(value) {}
t_type* get_type() const { return type_; }
std::string get_name() const { return name_; }
t_const_value* get_value() const { return value_; }
private:
t_type* type_;
std::string name_;
t_const_value* value_;
};
#endif

View file

@ -0,0 +1,155 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_CONST_VALUE_H
#define T_CONST_VALUE_H
#include "thrift/parse/t_enum.h"
#include <stdint.h>
#include <map>
#include <vector>
#include <string>
namespace plugin_output {
template <typename From, typename To>
void convert(From*, To&);
}
/**
* A const value is something parsed that could be a map, set, list, struct
* or whatever.
*
*/
class t_const_value {
public:
enum t_const_value_type { CV_INTEGER, CV_DOUBLE, CV_STRING, CV_MAP, CV_LIST, CV_IDENTIFIER };
t_const_value() {}
t_const_value(int64_t val) { set_integer(val); }
t_const_value(std::string val) { set_string(val); }
void set_string(std::string val) {
valType_ = CV_STRING;
stringVal_ = val;
}
std::string get_string() const { return stringVal_; }
void set_integer(int64_t val) {
valType_ = CV_INTEGER;
intVal_ = val;
}
int64_t get_integer() const {
if (valType_ == CV_IDENTIFIER) {
if (enum_ == NULL) {
throw "have identifier \"" + get_identifier() + "\", but unset enum on line!";
}
std::string identifier = get_identifier();
std::string::size_type dot = identifier.rfind('.');
if (dot != std::string::npos) {
identifier = identifier.substr(dot + 1);
}
t_enum_value* val = enum_->get_constant_by_name(identifier);
if (val == NULL) {
throw "Unable to find enum value \"" + identifier + "\" in enum \"" + enum_->get_name()
+ "\"";
}
return val->get_value();
} else {
return intVal_;
}
}
void set_double(double val) {
valType_ = CV_DOUBLE;
doubleVal_ = val;
}
double get_double() const { return doubleVal_; }
void set_map() { valType_ = CV_MAP; }
void add_map(t_const_value* key, t_const_value* val) { mapVal_[key] = val; }
const std::map<t_const_value*, t_const_value*>& get_map() const { return mapVal_; }
void set_list() { valType_ = CV_LIST; }
void add_list(t_const_value* val) { listVal_.push_back(val); }
const std::vector<t_const_value*>& get_list() const { return listVal_; }
void set_identifier(std::string val) {
valType_ = CV_IDENTIFIER;
identifierVal_ = val;
}
std::string get_identifier() const { return identifierVal_; }
std::string get_identifier_name() const {
std::string ret = get_identifier();
size_t s = ret.find('.');
if (s == std::string::npos) {
throw "error: identifier " + ret + " is unqualified!";
}
ret = ret.substr(s + 1);
s = ret.find('.');
if (s != std::string::npos) {
ret = ret.substr(s + 1);
}
return ret;
}
std::string get_identifier_with_parent() const {
std::string ret = get_identifier();
size_t s = ret.find('.');
if (s == std::string::npos) {
throw "error: identifier " + ret + " is unqualified!";
}
size_t s2 = ret.find('.', s + 1);
if (s2 != std::string::npos) {
ret = ret.substr(s + 1);
}
return ret;
}
void set_enum(t_enum* tenum) { enum_ = tenum; }
t_const_value_type get_type() const { return valType_; }
private:
std::map<t_const_value*, t_const_value*> mapVal_;
std::vector<t_const_value*> listVal_;
std::string stringVal_;
int64_t intVal_;
double doubleVal_;
std::string identifierVal_;
t_enum* enum_;
t_const_value_type valType_;
// to read enum_
template <typename From, typename To>
friend void plugin_output::convert(From*, To&);
};
#endif

View file

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_CONTAINER_H
#define T_CONTAINER_H
#include "thrift/parse/t_type.h"
class t_container : public t_type {
public:
t_container() : cpp_name_(), has_cpp_name_(false) {}
virtual ~t_container() {}
void set_cpp_name(std::string cpp_name) {
cpp_name_ = cpp_name;
has_cpp_name_ = true;
}
bool has_cpp_name() const { return has_cpp_name_; }
std::string get_cpp_name() const { return cpp_name_; }
bool is_container() const { return true; }
private:
std::string cpp_name_;
bool has_cpp_name_;
};
#endif

View file

@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_DOC_H
#define T_DOC_H
#include "thrift/globals.h"
#include "thrift/logging.h"
/**
* Documentation stubs
*
*/
class t_doc {
public:
t_doc() : has_doc_(false) {}
virtual ~t_doc() {}
void set_doc(const std::string& doc) {
doc_ = doc;
has_doc_ = true;
if ((g_program_doctext_lineno == g_doctext_lineno)
&& (g_program_doctext_status == STILL_CANDIDATE)) {
g_program_doctext_status = ALREADY_PROCESSED;
pdebug("%s", "program doctext set to ALREADY_PROCESSED");
}
}
const std::string& get_doc() const { return doc_; }
bool has_doc() { return has_doc_; }
private:
std::string doc_;
bool has_doc_;
};
#endif

View file

@ -0,0 +1,110 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_ENUM_H
#define T_ENUM_H
#include <vector>
#include "thrift/parse/t_enum_value.h"
#include "thrift/parse/t_type.h"
/**
* An enumerated type. A list of constant objects with a name for the type.
*
*/
class t_enum : public t_type {
public:
t_enum(t_program* program) : t_type(program) {}
void set_name(const std::string& name) { name_ = name; }
void append(t_enum_value* constant) { constants_.push_back(constant); }
const std::vector<t_enum_value*>& get_constants() const { return constants_; }
t_enum_value* get_constant_by_name(const std::string& name) {
const std::vector<t_enum_value*>& enum_values = get_constants();
std::vector<t_enum_value*>::const_iterator c_iter;
for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
if ((*c_iter)->get_name() == name) {
return *c_iter;
}
}
return NULL;
}
t_enum_value* get_constant_by_value(int64_t value) {
const std::vector<t_enum_value*>& enum_values = get_constants();
std::vector<t_enum_value*>::const_iterator c_iter;
for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
if ((*c_iter)->get_value() == value) {
return *c_iter;
}
}
return NULL;
}
t_enum_value* get_min_value() {
const std::vector<t_enum_value*>& enum_values = get_constants();
std::vector<t_enum_value*>::const_iterator c_iter;
t_enum_value* min_value;
if (enum_values.size() == 0) {
min_value = NULL;
} else {
int min_value_value;
min_value = enum_values.front();
min_value_value = min_value->get_value();
for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
if ((*c_iter)->get_value() < min_value_value) {
min_value = (*c_iter);
min_value_value = min_value->get_value();
}
}
}
return min_value;
}
t_enum_value* get_max_value() {
const std::vector<t_enum_value*>& enum_values = get_constants();
std::vector<t_enum_value*>::const_iterator c_iter;
t_enum_value* max_value;
if (enum_values.size() == 0) {
max_value = NULL;
} else {
int max_value_value;
max_value = enum_values.back();
max_value_value = max_value->get_value();
for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
if ((*c_iter)->get_value() > max_value_value) {
max_value = (*c_iter);
max_value_value = max_value->get_value();
}
}
}
return max_value;
}
bool is_enum() const { return true; }
private:
std::vector<t_enum_value*> constants_;
};
#endif

View file

@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_ENUM_VALUE_H
#define T_ENUM_VALUE_H
#include <map>
#include <string>
#include "thrift/parse/t_doc.h"
/**
* A constant. These are used inside of enum definitions. Constants are just
* symbol identifiers that may or may not have an explicit value associated
* with them.
*
*/
class t_enum_value : public t_doc {
public:
t_enum_value(std::string name, int value) : name_(name), value_(value) {}
~t_enum_value() {}
const std::string& get_name() const { return name_; }
int get_value() const { return value_; }
std::map<std::string, std::string> annotations_;
private:
std::string name_;
int value_;
};
#endif

View file

@ -0,0 +1,134 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_FIELD_H
#define T_FIELD_H
#include <map>
#include <string>
#include <sstream>
#include "thrift/parse/t_doc.h"
#include "thrift/parse/t_type.h"
// Forward declare for xsd_attrs
class t_struct;
/**
* Class to represent a field in a thrift structure. A field has a data type,
* a symbolic name, and a numeric identifier.
*
*/
class t_field : public t_doc {
public:
t_field(t_type* type, std::string name)
: type_(type),
name_(name),
key_(0),
value_(NULL),
xsd_optional_(false),
xsd_nillable_(false),
xsd_attrs_(NULL),
reference_(false) {}
t_field(t_type* type, std::string name, int32_t key)
: type_(type),
name_(name),
key_(key),
req_(T_OPT_IN_REQ_OUT),
value_(NULL),
xsd_optional_(false),
xsd_nillable_(false),
xsd_attrs_(NULL),
reference_(false) {}
~t_field() {}
t_type* get_type() { return type_; }
const t_type* get_type() const { return type_; }
const std::string& get_name() const { return name_; }
int32_t get_key() const { return key_; }
enum e_req { T_REQUIRED, T_OPTIONAL, T_OPT_IN_REQ_OUT };
void set_req(e_req req) { req_ = req; }
e_req get_req() const { return req_; }
void set_value(t_const_value* value) { value_ = value; }
t_const_value* get_value() { return value_; }
const t_const_value* get_value() const { return value_; }
void set_xsd_optional(bool xsd_optional) { xsd_optional_ = xsd_optional; }
bool get_xsd_optional() const { return xsd_optional_; }
void set_xsd_nillable(bool xsd_nillable) { xsd_nillable_ = xsd_nillable; }
bool get_xsd_nillable() const { return xsd_nillable_; }
void set_xsd_attrs(t_struct* xsd_attrs) { xsd_attrs_ = xsd_attrs; }
t_struct* get_xsd_attrs() { return xsd_attrs_; }
/**
* Comparator to sort fields in ascending order by key.
* Make this a functor instead of a function to help GCC inline it.
* The arguments are (const) references to const pointers to const t_fields.
*/
struct key_compare {
bool operator()(t_field const* const& a, t_field const* const& b) {
return a->get_key() < b->get_key();
}
};
std::map<std::string, std::string> annotations_;
bool get_reference() { return reference_; }
void set_reference(bool reference) { reference_ = reference; }
private:
t_type* type_;
std::string name_;
int32_t key_;
e_req req_;
t_const_value* value_;
bool xsd_optional_;
bool xsd_nillable_;
t_struct* xsd_attrs_;
bool reference_;
};
/**
* A simple struct for the parser to use to store a field ID, and whether or
* not it was specified by the user or automatically chosen.
*/
struct t_field_id {
int32_t value;
bool auto_assigned;
};
#endif

View file

@ -0,0 +1,84 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_FUNCTION_H
#define T_FUNCTION_H
#include <string>
#include "thrift/parse/t_type.h"
#include "thrift/parse/t_struct.h"
#include "thrift/parse/t_doc.h"
/**
* Representation of a function. Key parts are return type, function name,
* optional modifiers, and an argument list, which is implemented as a thrift
* struct.
*
*/
class t_function : public t_doc {
public:
t_function(t_type* returntype, std::string name, t_struct* arglist, bool oneway = false)
: returntype_(returntype), name_(name), arglist_(arglist), oneway_(oneway) {
xceptions_ = new t_struct(NULL);
if (oneway_ && (!returntype_->is_void())) {
pwarning(1, "Oneway methods should return void.\n");
}
}
t_function(t_type* returntype,
std::string name,
t_struct* arglist,
t_struct* xceptions,
bool oneway = false)
: returntype_(returntype),
name_(name),
arglist_(arglist),
xceptions_(xceptions),
oneway_(oneway) {
if (oneway_ && !xceptions_->get_members().empty()) {
throw std::string("Oneway methods can't throw exceptions.");
}
if (oneway_ && (!returntype_->is_void())) {
pwarning(1, "Oneway methods should return void.\n");
}
}
~t_function() {}
t_type* get_returntype() const { return returntype_; }
const std::string& get_name() const { return name_; }
t_struct* get_arglist() const { return arglist_; }
t_struct* get_xceptions() const { return xceptions_; }
bool is_oneway() const { return oneway_; }
std::map<std::string, std::string> annotations_;
private:
t_type* returntype_;
std::string name_;
t_struct* arglist_;
t_struct* xceptions_;
bool oneway_;
};
#endif

View file

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_LIST_H
#define T_LIST_H
#include "thrift/parse/t_container.h"
/**
* A list is a lightweight container type that just wraps another data type.
*
*/
class t_list : public t_container {
public:
t_list(t_type* elem_type) : elem_type_(elem_type) {}
t_type* get_elem_type() const { return elem_type_; }
bool is_list() const { return true; }
private:
t_type* elem_type_;
};
#endif

View file

@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_MAP_H
#define T_MAP_H
#include "thrift/parse/t_container.h"
/**
* A map is a lightweight container type that just wraps another two data
* types.
*
*/
class t_map : public t_container {
public:
t_map(t_type* key_type, t_type* val_type) : key_type_(key_type), val_type_(val_type) {}
t_type* get_key_type() const { return key_type_; }
t_type* get_val_type() const { return val_type_; }
bool is_map() const { return true; }
private:
t_type* key_type_;
t_type* val_type_;
};
#endif

View file

@ -0,0 +1,395 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_PROGRAM_H
#define T_PROGRAM_H
#include <map>
#include <string>
#include <vector>
// For program_name()
#include "thrift/main.h"
#include "thrift/parse/t_doc.h"
#include "thrift/parse/t_scope.h"
#include "thrift/parse/t_base_type.h"
#include "thrift/parse/t_typedef.h"
#include "thrift/parse/t_enum.h"
#include "thrift/parse/t_const.h"
#include "thrift/parse/t_struct.h"
#include "thrift/parse/t_service.h"
#include "thrift/parse/t_list.h"
#include "thrift/parse/t_map.h"
#include "thrift/parse/t_set.h"
#include "thrift/generate/t_generator_registry.h"
//#include "thrift/parse/t_doc.h"
/**
* Top level class representing an entire thrift program. A program consists
* fundamentally of the following:
*
* Typedefs
* Enumerations
* Constants
* Structs
* Exceptions
* Services
*
* The program module also contains the definitions of the base types.
*
*/
class t_program : public t_doc {
public:
t_program(std::string path, std::string name)
: path_(path), name_(name), out_path_("./"), out_path_is_absolute_(false), scope_(new t_scope) {}
t_program(std::string path) : path_(path), out_path_("./"), out_path_is_absolute_(false) {
name_ = program_name(path);
scope_ = new t_scope();
}
~t_program() {
if (scope_) {
delete scope_;
scope_ = NULL;
}
}
// Path accessor
const std::string& get_path() const { return path_; }
// Output path accessor
const std::string& get_out_path() const { return out_path_; }
// Create gen-* dir accessor
bool is_out_path_absolute() const { return out_path_is_absolute_; }
// Name accessor
const std::string& get_name() const { return name_; }
// Namespace
const std::string& get_namespace() const { return namespace_; }
// Include prefix accessor
const std::string& get_include_prefix() const { return include_prefix_; }
// Accessors for program elements
const std::vector<t_typedef*>& get_typedefs() const { return typedefs_; }
const std::vector<t_enum*>& get_enums() const { return enums_; }
const std::vector<t_const*>& get_consts() const { return consts_; }
const std::vector<t_struct*>& get_structs() const { return structs_; }
const std::vector<t_struct*>& get_xceptions() const { return xceptions_; }
const std::vector<t_struct*>& get_objects() const { return objects_; }
const std::vector<t_service*>& get_services() const { return services_; }
const std::map<std::string, std::string>& get_namespaces() const { return namespaces_; }
// Program elements
void add_typedef(t_typedef* td) { typedefs_.push_back(td); }
void add_enum(t_enum* te) { enums_.push_back(te); }
void add_const(t_const* tc) { consts_.push_back(tc); }
void add_struct(t_struct* ts) {
objects_.push_back(ts);
structs_.push_back(ts);
}
void add_xception(t_struct* tx) {
objects_.push_back(tx);
xceptions_.push_back(tx);
}
void add_service(t_service* ts) { services_.push_back(ts); }
// Programs to include
const std::vector<t_program*>& get_includes() const { return includes_; }
void set_out_path(std::string out_path, bool out_path_is_absolute) {
out_path_ = out_path;
out_path_is_absolute_ = out_path_is_absolute;
// Ensure that it ends with a trailing '/' (or '\' for windows machines)
char c = out_path_.at(out_path_.size() - 1);
if (!(c == '/' || c == '\\')) {
out_path_.push_back('/');
}
}
// Typename collision detection
/**
* Search for typename collisions
* @param t the type to test for collisions
* @return true if a certain collision was found, otherwise false
*/
bool is_unique_typename(t_type* t) {
int occurrences = program_typename_count(this, t);
for (std::vector<t_program*>::iterator it = includes_.begin(); it != includes_.end(); ++it) {
occurrences += program_typename_count(*it, t);
}
return 0 == occurrences;
}
/**
* Search all type collections for duplicate typenames
* @param prog the program to search
* @param t the type to test for collisions
* @return the number of certain typename collisions
*/
int program_typename_count(t_program* prog, t_type* t) {
int occurrences = 0;
occurrences += collection_typename_count(prog, prog->typedefs_, t);
occurrences += collection_typename_count(prog, prog->enums_, t);
occurrences += collection_typename_count(prog, prog->objects_, t);
occurrences += collection_typename_count(prog, prog->services_, t);
return occurrences;
}
/**
* Search a type collection for duplicate typenames
* @param prog the program to search
* @param type_collection the type collection to search
* @param t the type to test for collisions
* @return the number of certain typename collisions
*/
template <class T>
int collection_typename_count(t_program* prog, T type_collection, t_type* t) {
int occurrences = 0;
for (typename T::iterator it = type_collection.begin(); it != type_collection.end(); ++it)
if (t != *it && 0 == t->get_name().compare((*it)->get_name()) && is_common_namespace(prog, t))
++occurrences;
return occurrences;
}
/**
* Determine whether identical typenames will collide based on namespaces.
*
* Because we do not know which languages the user will generate code for,
* collisions within programs (IDL files) having namespace declarations can be
* difficult to determine. Only guaranteed collisions return true (cause an error).
* Possible collisions involving explicit namespace declarations produce a warning.
* Other possible collisions go unreported.
* @param prog the program containing the preexisting typename
* @param t the type containing the typename match
* @return true if a collision within namespaces is found, otherwise false
*/
bool is_common_namespace(t_program* prog, t_type* t) {
// Case 1: Typenames are in the same program [collision]
if (prog == t->get_program()) {
pwarning(1,
"Duplicate typename %s found in %s",
t->get_name().c_str(),
t->get_program()->get_name().c_str());
return true;
}
// Case 2: Both programs have identical namespace scope/name declarations [collision]
bool match = true;
for (std::map<std::string, std::string>::iterator it = prog->namespaces_.begin();
it != prog->namespaces_.end();
++it) {
if (0 == it->second.compare(t->get_program()->get_namespace(it->first))) {
pwarning(1,
"Duplicate typename %s found in %s,%s,%s and %s,%s,%s [file,scope,ns]",
t->get_name().c_str(),
t->get_program()->get_name().c_str(),
it->first.c_str(),
it->second.c_str(),
prog->get_name().c_str(),
it->first.c_str(),
it->second.c_str());
} else {
match = false;
}
}
for (std::map<std::string, std::string>::iterator it = t->get_program()->namespaces_.begin();
it != t->get_program()->namespaces_.end();
++it) {
if (0 == it->second.compare(prog->get_namespace(it->first))) {
pwarning(1,
"Duplicate typename %s found in %s,%s,%s and %s,%s,%s [file,scope,ns]",
t->get_name().c_str(),
t->get_program()->get_name().c_str(),
it->first.c_str(),
it->second.c_str(),
prog->get_name().c_str(),
it->first.c_str(),
it->second.c_str());
} else {
match = false;
}
}
if (0 == prog->namespaces_.size() && 0 == t->get_program()->namespaces_.size()) {
pwarning(1,
"Duplicate typename %s found in %s and %s",
t->get_name().c_str(),
t->get_program()->get_name().c_str(),
prog->get_name().c_str());
}
return match;
}
// Scoping and namespacing
void set_namespace(std::string name) { namespace_ = name; }
// Scope accessor
t_scope* scope() const { return scope_; }
// Includes
void add_include(t_program* program) {
includes_.push_back(program);
}
void add_include(std::string path, std::string include_site) {
t_program* program = new t_program(path);
// include prefix for this program is the site at which it was included
// (minus the filename)
std::string include_prefix;
std::string::size_type last_slash = std::string::npos;
if ((last_slash = include_site.rfind("/")) != std::string::npos) {
include_prefix = include_site.substr(0, last_slash);
}
program->set_include_prefix(include_prefix);
includes_.push_back(program);
}
std::vector<t_program*>& get_includes() { return includes_; }
void set_include_prefix(std::string include_prefix) {
include_prefix_ = include_prefix;
// this is intended to be a directory; add a trailing slash if necessary
std::string::size_type len = include_prefix_.size();
if (len > 0 && include_prefix_[len - 1] != '/') {
include_prefix_ += '/';
}
}
// Language neutral namespace / packaging
void set_namespace(std::string language, std::string name_space) {
if (language != "*") {
size_t sub_index = language.find('.');
std::string base_language = language.substr(0, sub_index);
std::string sub_namespace;
if (base_language == "smalltalk") {
pwarning(1, "Namespace 'smalltalk' is deprecated. Use 'st' instead");
base_language = "st";
}
t_generator_registry::gen_map_t my_copy = t_generator_registry::get_generator_map();
t_generator_registry::gen_map_t::iterator it;
it = my_copy.find(base_language);
if (it == my_copy.end()) {
std::string warning = "No generator named '" + base_language + "' could be found!";
pwarning(1, warning.c_str());
} else {
if (sub_index != std::string::npos) {
std::string sub_namespace = language.substr(sub_index + 1);
if (!it->second->is_valid_namespace(sub_namespace)) {
std::string warning = base_language + " generator does not accept '" + sub_namespace
+ "' as sub-namespace!";
pwarning(1, warning.c_str());
}
}
}
}
namespaces_[language] = name_space;
}
std::string get_namespace(std::string language) const {
std::map<std::string, std::string>::const_iterator iter;
if ((iter = namespaces_.find(language)) != namespaces_.end()
|| (iter = namespaces_.find("*")) != namespaces_.end()) {
return iter->second;
}
return std::string();
}
const std::map<std::string, std::string>& get_all_namespaces(){
return namespaces_;
}
void set_namespace_annotations(std::string language, std::map<std::string, std::string> annotations) {
namespace_annotations_[language] = annotations;
}
const std::map<std::string, std::string>& get_namespace_annotations(std::string language) {
return namespace_annotations_[language];
}
// Language specific namespace / packaging
void add_cpp_include(std::string path) { cpp_includes_.push_back(path); }
const std::vector<std::string>& get_cpp_includes() { return cpp_includes_; }
void add_c_include(std::string path) { c_includes_.push_back(path); }
const std::vector<std::string>& get_c_includes() { return c_includes_; }
private:
// File path
std::string path_;
// Name
std::string name_;
// Output directory
std::string out_path_;
// Output directory is absolute location for generated source (no gen-*)
bool out_path_is_absolute_;
// Namespace
std::string namespace_;
// Included programs
std::vector<t_program*> includes_;
// Include prefix for this program, if any
std::string include_prefix_;
// Identifier lookup scope
t_scope* scope_;
// Components to generate code for
std::vector<t_typedef*> typedefs_;
std::vector<t_enum*> enums_;
std::vector<t_const*> consts_;
std::vector<t_struct*> objects_;
std::vector<t_struct*> structs_;
std::vector<t_struct*> xceptions_;
std::vector<t_service*> services_;
// Dynamic namespaces
std::map<std::string, std::string> namespaces_;
// Annotations for dynamic namespaces
std::map<std::string, std::map<std::string, std::string> > namespace_annotations_;
// C++ extra includes
std::vector<std::string> cpp_includes_;
// C extra includes
std::vector<std::string> c_includes_;
};
#endif

View file

@ -0,0 +1,181 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_SCOPE_H
#define T_SCOPE_H
#include <map>
#include <string>
#include <sstream>
#include "thrift/parse/t_type.h"
#include "thrift/parse/t_service.h"
#include "thrift/parse/t_const.h"
#include "thrift/parse/t_const_value.h"
#include "thrift/parse/t_base_type.h"
#include "thrift/parse/t_map.h"
#include "thrift/parse/t_list.h"
namespace plugin_output {
template <typename From, typename To>
void convert(From*, To&);
}
/**
* This represents a variable scope used for looking up predefined types and
* services. Typically, a scope is associated with a t_program. Scopes are not
* used to determine code generation, but rather to resolve identifiers at
* parse time.
*
*/
class t_scope {
public:
t_scope() {}
void add_type(std::string name, t_type* type) { types_[name] = type; }
t_type* get_type(std::string name) { return types_[name]; }
void add_service(std::string name, t_service* service) { services_[name] = service; }
t_service* get_service(std::string name) { return services_[name]; }
void add_constant(std::string name, t_const* constant) {
if (constants_.find(name) != constants_.end()) {
throw "Enum " + name + " is already defined!";
} else {
constants_[name] = constant;
}
}
t_const* get_constant(std::string name) { return constants_[name]; }
void print() {
std::map<std::string, t_type*>::iterator iter;
for (iter = types_.begin(); iter != types_.end(); ++iter) {
printf("%s => %s\n", iter->first.c_str(), iter->second->get_name().c_str());
}
}
void resolve_const_value(t_const_value* const_val, t_type* ttype) {
if (ttype->is_map()) {
const std::map<t_const_value*, t_const_value*>& map = const_val->get_map();
std::map<t_const_value*, t_const_value*>::const_iterator v_iter;
for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) {
resolve_const_value(v_iter->first, ((t_map*)ttype)->get_key_type());
resolve_const_value(v_iter->second, ((t_map*)ttype)->get_val_type());
}
} else if (ttype->is_list() || ttype->is_set()) {
const std::vector<t_const_value*>& val = const_val->get_list();
std::vector<t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
resolve_const_value((*v_iter), ((t_list*)ttype)->get_elem_type());
}
} else if (ttype->is_struct()) {
t_struct* tstruct = (t_struct*)ttype;
const std::map<t_const_value*, t_const_value*>& map = const_val->get_map();
std::map<t_const_value*, t_const_value*>::const_iterator v_iter;
for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) {
t_field* field = tstruct->get_field_by_name(v_iter->first->get_string());
if (field == NULL) {
throw "No field named \"" + v_iter->first->get_string()
+ "\" was found in struct of type \"" + tstruct->get_name() + "\"";
}
resolve_const_value(v_iter->second, field->get_type());
}
} else if (const_val->get_type() == t_const_value::CV_IDENTIFIER) {
if (ttype->is_enum()) {
const_val->set_enum((t_enum*)ttype);
} else {
t_const* constant = get_constant(const_val->get_identifier());
if (constant == NULL) {
throw "No enum value or constant found named \"" + const_val->get_identifier() + "\"!";
}
// Resolve typedefs to the underlying type
t_type* const_type = constant->get_type()->get_true_type();
if (const_type->is_base_type()) {
switch (((t_base_type*)const_type)->get_base()) {
case t_base_type::TYPE_I16:
case t_base_type::TYPE_I32:
case t_base_type::TYPE_I64:
case t_base_type::TYPE_BOOL:
case t_base_type::TYPE_I8:
const_val->set_integer(constant->get_value()->get_integer());
break;
case t_base_type::TYPE_STRING:
const_val->set_string(constant->get_value()->get_string());
break;
case t_base_type::TYPE_DOUBLE:
const_val->set_double(constant->get_value()->get_double());
break;
case t_base_type::TYPE_VOID:
throw "Constants cannot be of type VOID";
}
} else if (const_type->is_map()) {
const std::map<t_const_value*, t_const_value*>& map = constant->get_value()->get_map();
std::map<t_const_value*, t_const_value*>::const_iterator v_iter;
const_val->set_map();
for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) {
const_val->add_map(v_iter->first, v_iter->second);
}
} else if (const_type->is_list()) {
const std::vector<t_const_value*>& val = constant->get_value()->get_list();
std::vector<t_const_value*>::const_iterator v_iter;
const_val->set_list();
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
const_val->add_list(*v_iter);
}
}
}
} else if (ttype->is_enum()) {
// enum constant with non-identifier value. set the enum and find the
// value's name.
t_enum* tenum = (t_enum*)ttype;
t_enum_value* enum_value = tenum->get_constant_by_value(const_val->get_integer());
if (enum_value == NULL) {
std::ostringstream valstm;
valstm << const_val->get_integer();
throw "Couldn't find a named value in enum " + tenum->get_name() + " for value "
+ valstm.str();
}
const_val->set_identifier(tenum->get_name() + "." + enum_value->get_name());
const_val->set_enum(tenum);
}
}
private:
// Map of names to types
std::map<std::string, t_type*> types_;
// Map of names to constants
std::map<std::string, t_const*> constants_;
// Map of names to services
std::map<std::string, t_service*> services_;
// to list map entries
template <typename From, typename To>
friend void plugin_output::convert(From*, To&);
};
#endif

View file

@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_SERVICE_H
#define T_SERVICE_H
#include "thrift/parse/t_function.h"
#include <vector>
class t_program;
/**
* A service consists of a set of functions.
*
*/
class t_service : public t_type {
public:
t_service(t_program* program) : t_type(program), extends_(NULL) {}
bool is_service() const { return true; }
void set_extends(t_service* extends) { extends_ = extends; }
void add_function(t_function* func) {
std::vector<t_function*>::const_iterator iter;
for (iter = functions_.begin(); iter != functions_.end(); ++iter) {
if (func->get_name() == (*iter)->get_name()) {
throw "Function " + func->get_name() + " is already defined";
}
}
functions_.push_back(func);
}
const std::vector<t_function*>& get_functions() const { return functions_; }
t_service* get_extends() { return extends_; }
const t_service* get_extends() const { return extends_; }
private:
std::vector<t_function*> functions_;
t_service* extends_;
};
#endif

View file

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_SET_H
#define T_SET_H
#include "thrift/parse/t_container.h"
/**
* A set is a lightweight container type that just wraps another data type.
*
*/
class t_set : public t_container {
public:
t_set(t_type* elem_type) : elem_type_(elem_type) {}
t_type* get_elem_type() const { return elem_type_; }
bool is_set() const { return true; }
private:
t_type* elem_type_;
};
#endif

View file

@ -0,0 +1,171 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_STRUCT_H
#define T_STRUCT_H
#include <algorithm>
#include <vector>
#include <utility>
#include <string>
#include "thrift/parse/t_type.h"
#include "thrift/parse/t_field.h"
// Forward declare that puppy
class t_program;
/**
* A struct is a container for a set of member fields that has a name. Structs
* are also used to implement exception types.
*
*/
class t_struct : public t_type {
public:
typedef std::vector<t_field*> members_type;
t_struct(t_program* program)
: t_type(program),
is_xception_(false),
is_union_(false),
members_validated(false),
members_with_value(0),
xsd_all_(false) {}
t_struct(t_program* program, const std::string& name)
: t_type(program, name),
is_xception_(false),
is_union_(false),
members_validated(false),
members_with_value(0),
xsd_all_(false) {}
void set_name(const std::string& name) {
name_ = name;
validate_union_members();
}
void set_xception(bool is_xception) { is_xception_ = is_xception; }
void validate_union_member(t_field* field) {
if (is_union_ && (!name_.empty())) {
// 1) unions can't have required fields
// 2) union members are implicitly optional, otherwise bugs like THRIFT-3650 wait to happen
if (field->get_req() != t_field::T_OPTIONAL) {
// no warning on default requiredness, but do warn on anything else that is explicitly asked for
if(field->get_req() != t_field::T_OPT_IN_REQ_OUT) {
pwarning(1,
"Union %s field %s: union members must be optional, ignoring specified requiredness.\n",
name_.c_str(),
field->get_name().c_str());
}
field->set_req(t_field::T_OPTIONAL);
}
// unions may have up to one member defaulted, but not more
if (field->get_value() != NULL) {
if (1 < ++members_with_value) {
throw "Error: Field " + field->get_name() + " provides another default value for union "
+ name_;
}
}
}
}
void validate_union_members() {
if (is_union_ && (!name_.empty()) && (!members_validated)) {
members_type::const_iterator m_iter;
for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
validate_union_member(*m_iter);
}
members_validated = true;
}
}
void set_union(bool is_union) {
is_union_ = is_union;
validate_union_members();
}
void set_xsd_all(bool xsd_all) { xsd_all_ = xsd_all; }
bool get_xsd_all() const { return xsd_all_; }
bool append(t_field* elem) {
typedef members_type::iterator iter_type;
std::pair<iter_type, iter_type> bounds = std::equal_range(members_in_id_order_.begin(),
members_in_id_order_.end(),
elem,
t_field::key_compare());
if (bounds.first != bounds.second) {
return false;
}
// returns false when there is a conflict of field names
if (get_field_by_name(elem->get_name()) != NULL) {
return false;
}
members_.push_back(elem);
members_in_id_order_.insert(bounds.second, elem);
validate_union_member(elem);
return true;
}
const members_type& get_members() const { return members_; }
const members_type& get_sorted_members() { return members_in_id_order_; }
bool is_struct() const { return !is_xception_; }
bool is_xception() const { return is_xception_; }
bool is_union() const { return is_union_; }
t_field* get_field_by_name(std::string field_name) {
members_type::const_iterator m_iter;
for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
if ((*m_iter)->get_name() == field_name) {
return *m_iter;
}
}
return NULL;
}
const t_field* get_field_by_name(std::string field_name) const {
members_type::const_iterator m_iter;
for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
if ((*m_iter)->get_name() == field_name) {
return *m_iter;
}
}
return NULL;
}
private:
members_type members_;
members_type members_in_id_order_;
bool is_xception_;
bool is_union_;
bool members_validated;
int members_with_value;
bool xsd_all_;
};
#endif

View file

@ -0,0 +1,108 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_TYPE_H
#define T_TYPE_H
#include <string>
#include <map>
#include <cstring>
#include <stdint.h>
#include "thrift/parse/t_doc.h"
class t_program;
/**
* Generic representation of a thrift type. These objects are used by the
* parser module to build up a tree of object that are all explicitly typed.
* The generic t_type class exports a variety of useful methods that are
* used by the code generator to branch based upon different handling for the
* various types.
*
*/
class t_type : public t_doc {
public:
virtual ~t_type() {}
virtual void set_name(const std::string& name) { name_ = name; }
virtual const std::string& get_name() const { return name_; }
virtual bool is_void() const { return false; }
virtual bool is_base_type() const { return false; }
virtual bool is_string() const { return false; }
virtual bool is_bool() const { return false; }
virtual bool is_typedef() const { return false; }
virtual bool is_enum() const { return false; }
virtual bool is_struct() const { return false; }
virtual bool is_xception() const { return false; }
virtual bool is_container() const { return false; }
virtual bool is_list() const { return false; }
virtual bool is_set() const { return false; }
virtual bool is_map() const { return false; }
virtual bool is_service() const { return false; }
t_program* get_program() { return program_; }
const t_program* get_program() const { return program_; }
t_type* get_true_type();
const t_type* get_true_type() const;
// This function will break (maybe badly) unless 0 <= num <= 16.
static char nybble_to_xdigit(int num) {
if (num < 10) {
return '0' + num;
} else {
return 'A' + num - 10;
}
}
static std::string byte_to_hex(uint8_t byte) {
std::string rv;
rv += nybble_to_xdigit(byte >> 4);
rv += nybble_to_xdigit(byte & 0x0f);
return rv;
}
std::map<std::string, std::string> annotations_;
protected:
t_type() : program_(NULL) { ; }
t_type(t_program* program) : program_(program) { ; }
t_type(t_program* program, std::string name) : program_(program), name_(name) { ; }
t_type(std::string name) : program_(NULL), name_(name) { ; }
t_program* program_;
std::string name_;
};
/**
* Placeholder struct for returning the key and value of an annotation
* during parsing.
*/
struct t_annotation {
std::string key;
std::string val;
};
#endif

View file

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include <cstdio>
#include "thrift/parse/t_typedef.h"
#include "thrift/parse/t_program.h"
t_type* t_typedef::get_type() const {
if (type_ == NULL) {
t_type* type = get_program()->scope()->get_type(symbolic_);
if (type == NULL) {
printf("Type \"%s\" not defined\n", symbolic_.c_str());
exit(1);
}
return type;
}
return type_;
}

View file

@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_TYPEDEF_H
#define T_TYPEDEF_H
#include <string>
#include "thrift/parse/t_type.h"
/**
* A typedef is a mapping from a symbolic name to another type. In dymanically
* typed languages (i.e. php/python) the code generator can actually usually
* ignore typedefs and just use the underlying type directly, though in C++
* the symbolic naming can be quite useful for code clarity.
*
*/
class t_typedef : public t_type {
public:
t_typedef(t_program* program, t_type* type, const std::string& symbolic)
: t_type(program, symbolic), type_(type), symbolic_(symbolic), forward_(false), seen_(false) {}
/**
* This constructor is used to refer to a type that is lazily
* resolved at a later time, like for forward declarations or
* recursive types.
*/
t_typedef(t_program* program, const std::string& symbolic, bool forward)
: t_type(program, symbolic),
type_(NULL),
symbolic_(symbolic),
forward_(forward),
seen_(false) {}
~t_typedef() {}
t_type* get_type() const;
const std::string& get_symbolic() const { return symbolic_; }
bool is_forward_typedef() const { return forward_; }
bool is_typedef() const { return true; }
private:
t_type* type_;
std::string symbolic_;
bool forward_;
mutable bool seen_;
};
#endif

View file

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/**
* define for mkdir,since the method signature
* is different for the non-POSIX MinGW
*/
#ifdef _MSC_VER
#include "thrift/windows/config.h"
#endif
#ifdef _WIN32
#include <direct.h>
#include <io.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif
#ifdef _WIN32
#define MKDIR(x) mkdir(x)
#else
#define MKDIR(x) mkdir(x, S_IRWXU | S_IRWXG | S_IRWXO)
#endif
#ifdef PATH_MAX
#define THRIFT_PATH_MAX PATH_MAX
#else
#define THRIFT_PATH_MAX MAX_PATH
#endif

View file

@ -0,0 +1,47 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
#
# Contains some contributions under the Thrift Software License.
# Please see doc/old-thrift-license.txt in the Thrift distribution for
# details.
AUTOMAKE_OPTIONS = subdir-objects
if WITH_PLUGIN
plugin_gen = plugin_types.h \
plugin_types.cpp \
plugin_constants.h \
plugin_constants.cpp
BUILT_SOURCES = $(plugin_gen)
gen.stamp: plugin.thrift $(top_builddir)/compiler/cpp/src/thrift/thrift-bootstrap
@$(RM) -f gen.tmp
@touch gen.tmp
$(top_builddir)/compiler/cpp/src/thrift/thrift-bootstrap -gen cpp -out . $<
@mv -f gen.tmp $@
$(plugin_gen): gen.stamp
@if test -f $@; then :; else \
$(RM) -f gen.stamp; \
$(MAKE) $(AM_MAKEFLAGS) gen.stamp; \
fi
clean-local:
$(RM) version.h windows/version.h $(plugin_gen)
endif

View file

@ -0,0 +1,503 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include "thrift/plugin/plugin.h"
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#endif
#include <cassert>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/smart_ptr.hpp>
#include "thrift/generate/t_generator.h"
#include "thrift/plugin/type_util.h"
#include "thrift/protocol/TBinaryProtocol.h"
#include "thrift/transport/TBufferTransports.h"
#include "thrift/transport/TFDTransport.h"
#include "thrift/plugin/plugin_types.h"
namespace apache {
namespace thrift {
namespace plugin {
using apache::thrift::protocol::TBinaryProtocol;
using apache::thrift::transport::TFDTransport;
using apache::thrift::transport::TFramedTransport;
#define THRIFT_CONVERT_FORWARD(from_type) \
template <> \
typename ToType<from_type>::type* convert_forward<from_type>(const from_type& from)
#define THRIFT_CONVERT_COMPLETE_DECL(from_type) \
template <> \
void convert(const from_type& from, ToType<from_type>::type* to)
#define THRIFT_CONVERT_UNARY_DECL(from_type) \
template <> \
typename ToType<from_type>::type* convert<from_type>(const from_type& from)
#define THRIFT_CONVERSION_DECL(from_type) \
THRIFT_CONVERT_FORWARD(from_type); \
THRIFT_CONVERT_COMPLETE_DECL(from_type); \
THRIFT_CONVERT_UNARY_DECL(from_type)
#define THRIFT_CONVERT_COMPLETE(from_type) \
THRIFT_CONVERSION_DECL(from_type) { \
ToType<from_type>::type* to = convert_forward(from); \
convert(from, to); \
return to; \
} \
THRIFT_CONVERT_COMPLETE_DECL(from_type)
#define THRIFT_CONVERSION(from_type, ...) \
THRIFT_CONVERT_FORWARD(from_type) { \
(void)from; \
return new ToType<from_type>::type(__VA_ARGS__); \
} \
THRIFT_CONVERT_COMPLETE(from_type)
#define THRIFT_ASSIGN_DOC() \
do { \
if (from.__isset.doc) \
to->set_doc(from.doc); \
} while (0)
#define THRIFT_ASSIGN_ANNOTATIONS() \
THRIFT_ASSIGN_DOC(); \
do { \
if (from.__isset.annotations) \
to->annotations_ = from.annotations; \
} while (0)
#define THRIFT_ASSIGN_METADATA() \
do { \
to->set_name(from.metadata.name); \
if (from.metadata.__isset.doc) \
to->set_doc(from.metadata.doc); \
if (from.metadata.__isset.annotations) \
to->annotations_ = from.metadata.annotations; \
} while (0)
::t_program* g_program = 0;
template <typename C, typename S>
struct TypeCache {
C* operator[](const int64_t& k) {
typename std::map<int64_t, C*>::iterator it = cache.find(k);
if (it != cache.end()) {
return it->second;
} else {
typename std::map<int64_t, S>::const_iterator cit = source->find(k);
if (cit == source->end()) {
throw ThriftPluginError("Type not found");
}
return (cache)[k] = convert_forward(cit->second);
}
}
void compileAll() {
boost::for_each(*source | boost::adaptors::map_keys,
boost::bind(&TypeCache::compile, this, _1));
}
std::map<int64_t, S> const* source;
protected:
std::map<int64_t, C*> cache;
private:
void compile(const int64_t& k) {
typename std::map<int64_t, S>::const_iterator cit = source->find(k);
if (cit == source->end()) {
throw ThriftPluginError("Type not found ");
}
convert(cit->second, (*this)[k]);
}
};
std::map<int64_t, ::t_program*> g_program_cache;
TypeCache< ::t_type, t_type> g_type_cache;
TypeCache< ::t_const, t_const> g_const_cache;
TypeCache< ::t_service, t_service> g_service_cache;
void set_global_cache(const TypeRegistry& from) {
g_type_cache.source = &from.types;
g_const_cache.source = &from.constants;
g_service_cache.source = &from.services;
g_type_cache.compileAll();
g_const_cache.compileAll();
g_service_cache.compileAll();
}
template <typename T>
T* resolve_type(int64_t name) {
return reinterpret_cast<T*>(g_type_cache[name]);
}
::t_const* resolve_const(int64_t name) {
return g_const_cache[name];
}
::t_service* resolve_service(int64_t name) {
return g_service_cache[name];
}
THRIFT_CONVERT_FORWARD(t_base_type) {
#define T_BASETYPE_CASE(type) \
case t_base::TYPE_##type: \
t = ::t_base_type::TYPE_##type; \
break
::t_base_type::t_base t = ::t_base_type::TYPE_VOID;
bool is_binary = false;
switch (from.value) {
T_BASETYPE_CASE(VOID);
T_BASETYPE_CASE(STRING);
T_BASETYPE_CASE(BOOL);
T_BASETYPE_CASE(I8);
T_BASETYPE_CASE(I16);
T_BASETYPE_CASE(I32);
T_BASETYPE_CASE(I64);
T_BASETYPE_CASE(DOUBLE);
case t_base::TYPE_BINARY:
t = ::t_base_type::TYPE_STRING;
is_binary = true;
break;
}
::t_base_type* to = new ::t_base_type(from.metadata.name, t);
to->set_binary(is_binary);
return to;
#undef T_BASETYPE_CASE
}
THRIFT_CONVERT_COMPLETE(t_base_type) {
THRIFT_ASSIGN_METADATA();
}
THRIFT_CONVERT_FORWARD(t_typedef) {
::t_typedef* to;
if (from.forward) {
to = new ::t_typedef(g_program_cache[from.metadata.program_id], from.symbolic, true);
} else {
to = new ::t_typedef(g_program_cache[from.metadata.program_id],
resolve_type< ::t_type>(from.type), from.symbolic);
}
return to;
}
THRIFT_CONVERT_COMPLETE(t_typedef) {
THRIFT_ASSIGN_METADATA();
}
THRIFT_CONVERSION(t_enum_value, from.name, from.value) {
assert(to);
THRIFT_ASSIGN_ANNOTATIONS();
}
THRIFT_CONVERSION(t_enum, g_program_cache[from.metadata.program_id]) {
assert(to);
THRIFT_ASSIGN_METADATA();
boost::for_each(from.constants | boost::adaptors::transformed(convert<t_enum_value>),
boost::bind(&::t_enum::append, to, _1));
}
THRIFT_CONVERSION(t_list, resolve_type< ::t_type>(from.elem_type)) {
assert(to);
THRIFT_ASSIGN_METADATA();
if (from.__isset.cpp_name)
to->set_cpp_name(from.cpp_name);
}
THRIFT_CONVERSION(t_set, resolve_type< ::t_type>(from.elem_type)) {
assert(to);
THRIFT_ASSIGN_METADATA();
if (from.__isset.cpp_name)
to->set_cpp_name(from.cpp_name);
}
THRIFT_CONVERSION(t_map,
resolve_type< ::t_type>(from.key_type),
resolve_type< ::t_type>(from.val_type)) {
assert(to);
THRIFT_ASSIGN_METADATA();
if (from.__isset.cpp_name)
to->set_cpp_name(from.cpp_name);
}
THRIFT_CONVERSION(t_const_value, ) {
#define T_CONST_VALUE_CASE(type) \
if (from.__isset.type##_val) \
to->set_##type(from.type##_val)
assert(to);
if (from.__isset.map_val) {
to->set_map();
for (std::map<t_const_value, t_const_value>::const_iterator it = from.map_val.begin();
it != from.map_val.end(); it++) {
to->add_map(convert(it->first), convert(it->second));
}
} else if (from.__isset.list_val) {
to->set_list();
boost::for_each(from.list_val | boost::adaptors::transformed(&convert<t_const_value>),
boost::bind(&::t_const_value::add_list, to, _1));
} else
T_CONST_VALUE_CASE(string);
else T_CONST_VALUE_CASE(integer);
else T_CONST_VALUE_CASE(double);
else {
T_CONST_VALUE_CASE(identifier);
if (from.__isset.enum_val)
to->set_enum(resolve_type< ::t_enum>(from.enum_val));
}
#undef T_CONST_VALUE_CASE
}
THRIFT_CONVERSION(t_field, resolve_type< ::t_type>(from.type), from.name, from.key) {
assert(to);
THRIFT_ASSIGN_ANNOTATIONS();
to->set_reference(from.reference);
to->set_req(static_cast< ::t_field::e_req>(from.req));
if (from.__isset.value) {
to->set_value(convert(from.value));
}
}
THRIFT_CONVERSION(t_struct, g_program_cache[from.metadata.program_id]) {
assert(to);
THRIFT_ASSIGN_METADATA();
to->set_union(from.is_union);
to->set_xception(from.is_xception);
boost::for_each(from.members | boost::adaptors::transformed(convert<t_field>),
boost::bind(&::t_struct::append, to, _1));
}
THRIFT_CONVERSION(t_const,
resolve_type< ::t_type>(from.type),
from.name,
convert<t_const_value>(from.value)) {
assert(to);
THRIFT_ASSIGN_DOC();
}
THRIFT_CONVERSION(t_function,
resolve_type< ::t_type>(from.returntype),
from.name,
resolve_type< ::t_struct>(from.arglist),
resolve_type< ::t_struct>(from.xceptions),
from.is_oneway) {
assert(to);
THRIFT_ASSIGN_DOC();
}
THRIFT_CONVERSION(t_service, g_program_cache[from.metadata.program_id]) {
assert(to);
assert(from.metadata.program_id);
assert(g_program_cache[from.metadata.program_id]);
THRIFT_ASSIGN_METADATA();
boost::for_each(from.functions | boost::adaptors::transformed(convert<t_function>),
boost::bind(&::t_service::add_function, to, _1));
if (from.__isset.extends_)
to->set_extends(resolve_service(from.extends_));
}
THRIFT_CONVERT_FORWARD(t_type) {
#define T_TYPE_CASE_FW_T(case, type) \
if (from.__isset.case##_val) \
return convert_forward<type>(from.case##_val)
#define T_TYPE_CASE_FW(case) T_TYPE_CASE_FW_T(case, t_##case)
T_TYPE_CASE_FW(base_type);
T_TYPE_CASE_FW(typedef);
T_TYPE_CASE_FW(enum);
T_TYPE_CASE_FW(struct);
T_TYPE_CASE_FW_T(xception, t_struct);
T_TYPE_CASE_FW(list);
T_TYPE_CASE_FW(set);
T_TYPE_CASE_FW(map);
T_TYPE_CASE_FW(service);
throw ThriftPluginError("Invalid data: Type union has no value.");
#undef T_TYPE_CASE_FW_T
#undef T_TYPE_CASE_FW
}
THRIFT_CONVERT_COMPLETE(t_type) {
#define T_TYPE_CASE_T(case, type) \
else if (from.__isset.case##_val) \
convert<type, ::type>(from.case##_val, reinterpret_cast< ::type*>(to))
#define T_TYPE_CASE(case) T_TYPE_CASE_T(case, t_##case)
if (false) {
}
T_TYPE_CASE(base_type);
T_TYPE_CASE(typedef);
T_TYPE_CASE(enum);
T_TYPE_CASE(struct);
T_TYPE_CASE_T(xception, t_struct);
T_TYPE_CASE(list);
T_TYPE_CASE(set);
T_TYPE_CASE(map);
T_TYPE_CASE(service);
else {
throw ThriftPluginError("Invalid data: Type union has no value.");
}
#undef T_TYPE_CASE_T
#undef T_TYPE_CASE
}
THRIFT_CONVERSION(t_scope, ) {
assert(to);
#define T_SCOPE_RESOLVE(type, name, a) \
for (std::vector<int64_t>::const_iterator it = from.name##s.begin(); it != from.name##s.end(); \
it++) { \
::t_##type* t = resolve_##type a(*it); \
to->add_##name(t->get_name(), t); \
}
T_SCOPE_RESOLVE(type, type, < ::t_type>);
T_SCOPE_RESOLVE(const, constant, );
T_SCOPE_RESOLVE(service, service, );
#undef T_SCOPE_RESOLVE
}
THRIFT_CONVERT_FORWARD(t_program) {
::t_program* to = new ::t_program(from.path, from.name);
for (std::vector<t_program>::const_iterator it = from.includes.begin(); it != from.includes.end();
it++) {
to->add_include(convert_forward(*it));
}
g_program_cache[from.program_id] = to;
return to;
}
THRIFT_CONVERT_COMPLETE(t_program) {
assert(to);
g_program = to;
convert<t_scope, ::t_scope>(from.scope, to->scope());
THRIFT_ASSIGN_DOC();
to->set_out_path(from.out_path, from.out_path_is_absolute);
boost::for_each(from.typedefs | boost::adaptors::transformed(&resolve_type< ::t_typedef>),
boost::bind(&::t_program::add_typedef, to, _1));
boost::for_each(from.enums | boost::adaptors::transformed(&resolve_type< ::t_enum>),
boost::bind(&::t_program::add_enum, to, _1));
for (std::vector<int64_t>::const_iterator it = from.objects.begin(); it != from.objects.end();
it++) {
::t_struct* t2 = resolve_type< ::t_struct>(*it);
if (t2->is_xception()) {
to->add_xception(t2);
} else {
to->add_struct(t2);
}
}
boost::for_each(from.consts | boost::adaptors::transformed(&resolve_const),
boost::bind(&::t_program::add_const, to, _1));
boost::for_each(from.services | boost::adaptors::transformed(&resolve_service),
boost::bind(&::t_program::add_service, to, _1));
for (std::vector<t_program>::const_iterator it = from.includes.begin(); it != from.includes.end();
it++) {
convert(*it, g_program_cache[it->program_id]);
}
std::for_each(from.c_includes.begin(), from.c_includes.end(),
boost::bind(&::t_program::add_c_include, to, _1));
std::for_each(from.cpp_includes.begin(), from.cpp_includes.end(),
boost::bind(&::t_program::add_cpp_include, to, _1));
for (std::map<std::string, std::string>::const_iterator it = from.namespaces.begin();
it != from.namespaces.end(); it++) {
to->set_namespace(it->first, it->second);
}
to->set_include_prefix(from.include_prefix);
to->set_namespace(from.namespace_);
}
int GeneratorPlugin::exec(int, char* []) {
#ifdef _WIN32
_setmode(fileno(stdin), _O_BINARY);
#endif
boost::shared_ptr<TFramedTransport> transport(
new TFramedTransport(boost::make_shared<TFDTransport>(fileno(stdin))));
TBinaryProtocol proto(transport);
GeneratorInput input;
try {
input.read(&proto);
} catch (std::exception& err) {
std::cerr << "Error while receiving plugin data: " << err.what() << std::endl;
return -1;
}
initGlobals();
::t_program* p = g_program = convert_forward(input.program);
set_global_cache(input.type_registry);
convert(input.program, p);
int ret = generate(p, input.parsed_options);
clearGlobals();
return ret;
}
::t_const_value::t_const_value_type const_value_case(const t_const_value& v) {
if (v.__isset.map_val)
return ::t_const_value::CV_MAP;
if (v.__isset.list_val)
return ::t_const_value::CV_LIST;
if (v.__isset.string_val)
return ::t_const_value::CV_STRING;
if (v.__isset.integer_val)
return ::t_const_value::CV_INTEGER;
if (v.__isset.double_val)
return ::t_const_value::CV_DOUBLE;
if (v.__isset.identifier_val)
return ::t_const_value::CV_IDENTIFIER;
if (v.__isset.enum_val)
return ::t_const_value::CV_IDENTIFIER;
throw ThriftPluginError("Unknown const value type");
}
bool t_const_value::operator<(const t_const_value& that) const {
::t_const_value::t_const_value_type t1 = const_value_case(*this);
::t_const_value::t_const_value_type t2 = const_value_case(that);
if (t1 != t2)
return t1 < t2;
switch (t1) {
case ::t_const_value::CV_INTEGER:
return integer_val < that.integer_val;
case ::t_const_value::CV_DOUBLE:
return double_val < that.double_val;
case ::t_const_value::CV_STRING:
return string_val < that.string_val;
case ::t_const_value::CV_MAP:
if (that.map_val.empty())
return false;
else if (map_val.empty())
return true;
else
return map_val.begin()->first < that.map_val.begin()->first;
case ::t_const_value::CV_LIST:
if (that.list_val.empty())
return false;
else if (list_val.empty())
return true;
else
return list_val.front() < that.list_val.front();
case ::t_const_value::CV_IDENTIFIER:
return integer_val < that.integer_val;
}
throw ThriftPluginError("Unknown const value type");
}
}
}
}

View file

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_PLUGIN_PLUGIN_H
#define T_PLUGIN_PLUGIN_H
#include "thrift/Thrift.h"
class t_program;
namespace apache {
namespace thrift {
namespace plugin {
struct ThriftPluginError : public apache::thrift::TException {
ThriftPluginError(const std::string& msg) : apache::thrift::TException(msg) {}
};
class GeneratorPlugin {
public:
int exec(int argc, char* argv[]);
virtual int generate(::t_program*, const std::map<std::string, std::string>&) = 0;
};
}
}
}
#endif

View file

@ -0,0 +1,202 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
namespace as3 org.apache.thrift.plugin
namespace cpp apache.thrift.plugin
namespace csharp Thrift.Plugin
namespace d thrift.plugin
namespace delphi Thrift.Plugin
namespace erl thrift.plugin
namespace go thrift
namespace haxe org.apache.thrift.plugin
namespace hs Thrift.Plugin
namespace java org.apache.thrift.plugin
namespace ocaml Thrift
namespace perl Thrift.Plugin
namespace php thrift.plugin
namespace py thrift.plugin
namespace rb Thrift
typedef i64 t_program_id
typedef i64 t_type_id
typedef i64 t_const_id
typedef i64 t_service_id
enum t_base {
TYPE_VOID
TYPE_STRING
TYPE_BOOL
TYPE_I8
TYPE_I16
TYPE_I32
TYPE_I64
TYPE_DOUBLE
TYPE_BINARY
}
struct TypeMetadata {
1: required string name
2: required t_program_id program_id
99: optional map<string, string> annotations
100: optional string doc
}
struct t_base_type {
1: required TypeMetadata metadata
2: required t_base value
}
struct t_list {
1: required TypeMetadata metadata
2: optional string cpp_name
3: required t_type_id elem_type
}
struct t_set {
1: required TypeMetadata metadata
2: optional string cpp_name
3: required t_type_id elem_type
}
struct t_map {
1: required TypeMetadata metadata
2: optional string cpp_name
3: required t_type_id key_type
4: required t_type_id val_type
}
struct t_typedef {
1: required TypeMetadata metadata
2: required t_type_id type
3: required string symbolic
4: required bool forward
}
struct t_enum_value {
1: required string name
2: required i32 value
99: optional map<string, string> annotations
100: optional string doc
}
struct t_enum {
1: required TypeMetadata metadata
2: required list<t_enum_value> constants
}
enum Requiredness {
T_REQUIRED = 0
T_OPTIONAL = 1
T_OPT_IN_REQ_OUT = 2
}
union t_const_value {
1: optional map<t_const_value, t_const_value> map_val
2: optional list<t_const_value> list_val
3: optional string string_val
4: optional i64 integer_val
5: optional double double_val
6: optional string identifier_val
7: optional t_type_id enum_val
}
struct t_const {
1: required string name
2: required t_type_id type
3: required t_const_value value
100: optional string doc
}
struct t_struct {
1: required TypeMetadata metadata
2: required list<t_field> members
3: required bool is_union
4: required bool is_xception
}
struct t_field {
1: required string name
2: required t_type_id type
3: required i32 key
4: required Requiredness req
5: optional t_const_value value
10: required bool reference
99: optional map<string, string> annotations
100: optional string doc
}
struct t_function {
1: required string name
2: required t_type_id returntype
3: required t_type_id arglist
4: required t_type_id xceptions
5: required bool is_oneway
100: optional string doc
}
struct t_service {
1: required TypeMetadata metadata
2: required list<t_function> functions
3: optional t_service_id extends_
}
union t_type {
1: optional t_base_type base_type_val
2: optional t_typedef typedef_val
3: optional t_enum enum_val
4: optional t_struct struct_val
5: optional t_struct xception_val
6: optional t_list list_val
7: optional t_set set_val
8: optional t_map map_val
9: optional t_service service_val
}
struct t_scope {
1: required list<t_type_id> types
2: required list<t_const_id> constants
3: required list<t_service_id> services
}
struct TypeRegistry {
1: required map<t_type_id, t_type> types
2: required map<t_const_id, t_const> constants
3: required map<t_service_id, t_service> services
}
struct t_program {
1: required string name
2: required t_program_id program_id
3: required string path
4: required string namespace_
5: required string out_path
6: required bool out_path_is_absolute
8: required list<t_program> includes
9: required string include_prefix
10: required t_scope scope
11: required list<t_type_id> typedefs
12: required list<t_type_id> enums
13: required list<t_const_id> consts
14: required list<t_type_id> objects
15: required list<t_service_id> services
16: required map<string, string> namespaces
17: required list<string> cpp_includes
18: required list<string> c_includes
100: optional string doc
}
struct GeneratorInput {
1: required t_program program
2: required TypeRegistry type_registry
3: required map<string, string> parsed_options
}

View file

@ -0,0 +1,410 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#ifdef _WIN32
#include <cstdio>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#define THRIFT_POPEN(cmd) _popen(cmd, "wb")
#define THRIFT_PCLOSE _pclose
#else
#define THRIFT_POPEN(cmd) popen(cmd, "w")
#define THRIFT_PCLOSE pclose
#endif
#include "thrift/plugin/plugin_output.h"
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <boost/smart_ptr.hpp>
#include "thrift/generate/t_generator.h"
#include "thrift/plugin/plugin.h"
#include "thrift/plugin/type_util.h"
#include "thrift/protocol/TBinaryProtocol.h"
#include "thrift/transport/TBufferTransports.h"
#include "thrift/transport/TFDTransport.h"
#include "thrift/plugin/plugin_types.h"
namespace plugin_output {
template <typename From>
typename apache::thrift::plugin::ToType<From>::type convert(From* from) {
typename apache::thrift::plugin::ToType<From>::type to;
convert(from, to);
return to;
}
using apache::thrift::protocol::TBinaryProtocol;
using apache::thrift::transport::TFDTransport;
using apache::thrift::transport::TFramedTransport;
using namespace apache::thrift;
#define THRIFT_CONVERSION_N(from_type, to_type) \
template <> \
void convert<from_type, to_type>(from_type * from, to_type & to)
#define THRIFT_CONVERSION(type) THRIFT_CONVERSION_N(::type, plugin::type)
#define THRIFT_ASSIGN_N(from_name, to_name, prefix) \
do { \
if (from) \
to.__set_##to_name(prefix(from->from_name)); \
} while (0)
#define THRIFT_ASSIGN(name) THRIFT_ASSIGN_N(get_##name(), name, )
#define THRIFT_ASSIGN_CONVERT(type, from_name, to_name) \
do { \
if (from && from->from_name) { \
to.__set_##to_name(convert(from->from_name)); \
} \
} while (0)
#define THRIFT_ASSIGN_OPT(name) \
do { \
if (from->has_##name()) \
THRIFT_ASSIGN(name); \
} while (0)
#define THRIFT_ASSIGN_LIST_N(type, from_name, to_name) \
do { \
if (from && !from->from_name.empty()) { \
std::transform(from->from_name.begin(), \
from->from_name.end(), \
std::back_inserter(to.to_name), \
convert< ::type>); \
} \
} while (0)
#define THRIFT_ASSIGN_METADATA() convert(reinterpret_cast<t_type*>(from), to.metadata)
// To avoid multiple instances of same type, t_type, t_const and t_service are stored in one place
// and referenced by ID.
template <typename T>
struct TypeCache {
typedef typename plugin::ToType<T>::type to_type;
std::map<int64_t, to_type> cache;
template <typename T2>
int64_t store(T2* t) {
intptr_t id = reinterpret_cast<intptr_t>(t);
if (id) {
typename std::map<int64_t, to_type>::iterator it = cache.find(id);
if (it == cache.end()) {
// HACK: fake resolve for recursive type
cache.insert(std::make_pair(id, to_type()));
// overwrite with true value
cache[id] = convert(t);
}
}
return static_cast<int64_t>(id);
}
void clear() { cache.clear(); }
};
template <typename T>
int64_t store_type(T* t);
#define T_STORE(type) \
TypeCache<t_##type> type##_cache; \
template <> \
plugin::t_##type##_id store_type<t_##type>(t_##type * t) { \
return type##_cache.store<t_##type>(t); \
}
T_STORE(type)
T_STORE(const)
T_STORE(service)
#undef T_STORE
#define THRIFT_ASSIGN_ID_N(t, from_name, to_name) \
do { \
if (from && from->from_name) \
to.__set_##to_name(store_type<t>(from->from_name)); \
} while (0)
#define THRIFT_ASSIGN_ID(name) THRIFT_ASSIGN_ID_N(t_type, get_##name(), name)
#define THRIFT_ASSIGN_LIST_ID(t, name) \
do { \
if (from && !from->get_##name##s().empty()) { \
std::transform(from->get_##name##s().begin(), \
from->get_##name##s().end(), \
std::back_inserter(to.name##s), \
&store_type<t>); \
} \
} while (0)
THRIFT_CONVERSION_N(::t_type, plugin::TypeMetadata) {
to.program_id = reinterpret_cast<int64_t>(from->get_program());
THRIFT_ASSIGN_N(annotations_, annotations, );
if (from->has_doc()) {
to.__set_doc(from->get_doc());
}
THRIFT_ASSIGN(name);
}
THRIFT_CONVERSION(t_typedef) {
THRIFT_ASSIGN_METADATA();
THRIFT_ASSIGN_ID(type);
THRIFT_ASSIGN(symbolic);
THRIFT_ASSIGN_N(is_forward_typedef(), forward, );
}
THRIFT_CONVERSION(t_enum_value) {
THRIFT_ASSIGN_OPT(doc);
THRIFT_ASSIGN(name);
THRIFT_ASSIGN(value);
}
THRIFT_CONVERSION(t_enum) {
THRIFT_ASSIGN_METADATA();
THRIFT_ASSIGN_LIST_N(t_enum_value, get_constants(), constants);
}
THRIFT_CONVERSION(t_const_value) {
switch (from->get_type()) {
case t_const_value::CV_INTEGER:
THRIFT_ASSIGN_N(get_integer(), integer_val, );
break;
case t_const_value::CV_DOUBLE:
THRIFT_ASSIGN_N(get_double(), double_val, );
break;
case t_const_value::CV_STRING:
THRIFT_ASSIGN_N(get_string(), string_val, );
break;
case t_const_value::CV_IDENTIFIER:
THRIFT_ASSIGN_ID_N(t_type, enum_, enum_val);
THRIFT_ASSIGN_N(get_identifier(), identifier_val, );
break;
case t_const_value::CV_MAP:
to.__isset.map_val = true;
if (from && !from->get_map().empty()) {
for (std::map< ::t_const_value*, ::t_const_value*>::const_iterator it
= from->get_map().begin();
it != from->get_map().end();
it++) {
to.map_val.insert(std::make_pair(convert(it->first), convert(it->second)));
}
}
break;
case t_const_value::CV_LIST:
to.__isset.list_val = true;
THRIFT_ASSIGN_LIST_N(t_const_value, get_list(), list_val);
break;
default:
throw plugin::ThriftPluginError("const value has no value");
}
}
THRIFT_CONVERSION(t_const) {
THRIFT_ASSIGN_OPT(doc);
THRIFT_ASSIGN(name);
THRIFT_ASSIGN_ID(type);
THRIFT_ASSIGN_CONVERT(t_const_value, get_value(), value);
}
THRIFT_CONVERSION(t_field) {
THRIFT_ASSIGN_OPT(doc);
THRIFT_ASSIGN(name);
THRIFT_ASSIGN(key);
THRIFT_ASSIGN_N(get_req(), req, (plugin::Requiredness::type));
THRIFT_ASSIGN(reference);
THRIFT_ASSIGN_ID(type);
THRIFT_ASSIGN_CONVERT(t_const_value, get_value(), value);
}
THRIFT_CONVERSION(t_struct) {
THRIFT_ASSIGN_METADATA();
THRIFT_ASSIGN_LIST_N(t_field, get_members(), members);
THRIFT_ASSIGN_N(is_union(), is_union, );
THRIFT_ASSIGN_N(is_xception(), is_xception, );
}
THRIFT_CONVERSION(t_function) {
THRIFT_ASSIGN_OPT(doc);
THRIFT_ASSIGN(name);
THRIFT_ASSIGN_ID(returntype);
THRIFT_ASSIGN_N(is_oneway(), is_oneway, );
THRIFT_ASSIGN_ID(arglist);
THRIFT_ASSIGN_ID(xceptions);
}
THRIFT_CONVERSION(t_list) {
THRIFT_ASSIGN_METADATA();
THRIFT_ASSIGN_OPT(cpp_name);
THRIFT_ASSIGN_ID(elem_type);
}
THRIFT_CONVERSION(t_set) {
THRIFT_ASSIGN_METADATA();
THRIFT_ASSIGN_OPT(cpp_name);
THRIFT_ASSIGN_ID(elem_type);
}
THRIFT_CONVERSION(t_map) {
THRIFT_ASSIGN_METADATA();
THRIFT_ASSIGN_OPT(cpp_name);
THRIFT_ASSIGN_ID(key_type);
THRIFT_ASSIGN_ID(val_type);
}
THRIFT_CONVERSION(t_service) {
THRIFT_ASSIGN_METADATA();
THRIFT_ASSIGN_LIST_N(t_function, get_functions(), functions);
THRIFT_ASSIGN_ID_N(t_service, get_extends(), extends_);
}
THRIFT_CONVERSION(t_base_type) {
THRIFT_ASSIGN_METADATA();
if (from->is_binary()) {
to.value = plugin::t_base::TYPE_BINARY;
} else {
switch (from->get_base()) {
#define T_BASETYPE_CASE(name) \
case t_base_type::TYPE_##name: \
to.value = plugin::t_base::TYPE_##name; \
break
T_BASETYPE_CASE(VOID);
T_BASETYPE_CASE(STRING);
T_BASETYPE_CASE(BOOL);
T_BASETYPE_CASE(I8);
T_BASETYPE_CASE(I16);
T_BASETYPE_CASE(I32);
T_BASETYPE_CASE(I64);
T_BASETYPE_CASE(DOUBLE);
default:
throw plugin::ThriftPluginError("Base type union has no value");
break;
#undef T_BASETYPE_CASE
}
}
}
THRIFT_CONVERSION(t_type) {
#define T_CONVERT_UNION_N(name, type) \
else if (from->is_##name()) { \
to.__isset.name##_val = true; \
convert(reinterpret_cast< ::type*>(from), to.name##_val); \
}
#define T_CONVERT_UNION(name) T_CONVERT_UNION_N(name, t_##name)
if (false) {
}
T_CONVERT_UNION(base_type)
T_CONVERT_UNION(typedef)
T_CONVERT_UNION(enum)
T_CONVERT_UNION(struct)
T_CONVERT_UNION_N(xception, t_struct)
T_CONVERT_UNION(list)
T_CONVERT_UNION(set)
T_CONVERT_UNION(map)
T_CONVERT_UNION(service)
else {
throw plugin::ThriftPluginError("Type union has no value");
}
#undef T_CONVERT_UNION_N
#undef T_CONVERT_UNION
}
THRIFT_CONVERSION(t_scope) {
#define T_SCOPE_ASSIGN(name, type) \
boost::copy(from->name##s_ | boost::adaptors::map_values \
| boost::adaptors::transformed(&store_type<type>), \
std::back_inserter(to.name##s))
T_SCOPE_ASSIGN(type, t_type);
T_SCOPE_ASSIGN(constant, t_const);
T_SCOPE_ASSIGN(service, t_service);
#undef T_SCOPE_ASSIGN
}
void get_global_cache(plugin::TypeRegistry& reg) {
reg.types = type_cache.cache;
reg.constants = const_cache.cache;
reg.services = service_cache.cache;
}
void clear_global_cache() {
type_cache.clear();
const_cache.clear();
service_cache.clear();
}
THRIFT_CONVERSION(t_program) {
THRIFT_ASSIGN_CONVERT(t_scope, scope(), scope);
THRIFT_ASSIGN(path);
THRIFT_ASSIGN(out_path);
THRIFT_ASSIGN(name);
THRIFT_ASSIGN(include_prefix);
THRIFT_ASSIGN(cpp_includes);
THRIFT_ASSIGN(c_includes);
THRIFT_ASSIGN(namespaces);
THRIFT_ASSIGN_N(is_out_path_absolute(), out_path_is_absolute, );
THRIFT_ASSIGN_N(get_namespace(), namespace_, );
THRIFT_ASSIGN_LIST_ID(t_type, typedef);
THRIFT_ASSIGN_LIST_ID(t_type, enum);
THRIFT_ASSIGN_LIST_ID(t_type, object);
THRIFT_ASSIGN_LIST_ID(t_const, const);
THRIFT_ASSIGN_LIST_ID(t_service, service);
THRIFT_ASSIGN_LIST_N(t_program, get_includes(), includes);
to.program_id = reinterpret_cast<plugin::t_program_id>(from);
}
PluginDelegateResult delegateToPlugin(t_program* program, const std::string& options) {
std::string language;
std::map<std::string, std::string> parsed_options;
t_generator::parse_options(options, language, parsed_options);
std::string cmd = "thrift-gen-";
if (language.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-0123456789")
!= std::string::npos) {
std::cerr << "Invalid language name" << std::endl;
return PLUGIN_FAILURE;
}
cmd.append(language);
FILE* fd = THRIFT_POPEN(cmd.c_str());
if (fd) {
#ifdef _WIN32
_setmode(fileno(fd), _O_BINARY);
#endif
boost::shared_ptr<TFramedTransport> transport(
new TFramedTransport(boost::make_shared<TFDTransport>(fileno(fd))));
TBinaryProtocol proto(transport);
plugin::GeneratorInput input;
input.__set_parsed_options(parsed_options);
clear_global_cache();
convert(program, input.program);
get_global_cache(input.type_registry);
try {
input.write(&proto);
transport->flush();
} catch (std::exception& err) {
std::cerr << "Error while sending data to plugin: " << err.what() << std::endl;
THRIFT_PCLOSE(fd);
return PLUGIN_FAILURE;
}
// TODO: be prepared for hang or crash of child process
int ret = THRIFT_PCLOSE(fd);
if (!ret) {
return PLUGIN_SUCCEESS;
} else {
std::cerr << "plugin process returned non zero exit code: " << ret << std::endl;
return PLUGIN_FAILURE;
}
}
clear_global_cache();
return PLUGIN_NOT_FOUND;
}
}

View file

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_PLUGIN_PLUGIN_OUTPUT_H
#define T_PLUGIN_PLUGIN_OUTPUT_H
#include <string>
class t_program;
namespace plugin_output {
enum PluginDelegateResult {
PLUGIN_NOT_FOUND,
PLUGIN_FAILURE,
PLUGIN_SUCCEESS,
};
PluginDelegateResult delegateToPlugin(t_program* program, const std::string& options);
}
#endif

View file

@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 T_PLUGIN_TYPE_UTIL_H
#define T_PLUGIN_TYPE_UTIL_H
namespace apache {
namespace thrift {
namespace plugin {
template <typename From>
struct ToType {};
template <typename From>
typename ToType<From>::type* convert_forward(const From&);
template <typename From, typename To>
void convert(const From&, To*);
template <typename From>
typename ToType<From>::type* convert(const From& from);
class TypeRegistry;
void set_global_cache(const TypeRegistry&);
}
}
}
// conversion from raw compiler types to plugin wire type
namespace plugin_output {
template <typename From, typename To>
void convert(From* from, To& to);
template <typename From>
typename apache::thrift::plugin::ToType<From>::type convert(From* from);
void get_global_cache(apache::thrift::plugin::TypeRegistry&);
void clear_global_cache();
}
#define THRIFT_TYPE_MAPPING(TYPE) \
class TYPE; \
namespace apache { \
namespace thrift { \
namespace plugin { \
class TYPE; \
template <> \
struct ToType< ::TYPE> { \
typedef TYPE type; \
}; \
template <> \
struct ToType<TYPE> { \
typedef ::TYPE type; \
}; \
} \
} \
}
THRIFT_TYPE_MAPPING(t_base_type)
THRIFT_TYPE_MAPPING(t_const)
THRIFT_TYPE_MAPPING(t_const_value)
THRIFT_TYPE_MAPPING(t_container)
THRIFT_TYPE_MAPPING(t_doc)
THRIFT_TYPE_MAPPING(t_enum)
THRIFT_TYPE_MAPPING(t_enum_value)
THRIFT_TYPE_MAPPING(t_field)
THRIFT_TYPE_MAPPING(t_function)
THRIFT_TYPE_MAPPING(t_list)
THRIFT_TYPE_MAPPING(t_map)
THRIFT_TYPE_MAPPING(t_program)
THRIFT_TYPE_MAPPING(t_scope)
THRIFT_TYPE_MAPPING(t_service)
THRIFT_TYPE_MAPPING(t_set)
THRIFT_TYPE_MAPPING(t_struct)
THRIFT_TYPE_MAPPING(t_type)
THRIFT_TYPE_MAPPING(t_typedef)
#undef THRIFT_TYPE_MAPPING
#endif

View file

@ -0,0 +1,463 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/**
* Thrift scanner.
*
* Tokenizes a thrift definition file.
*/
%{
/* This is redundant with some of the flags in Makefile.am, but it works
* when people override CXXFLAGS without being careful. The pragmas are
* the 'right' way to do it, but don't work on old-enough GCC (in particular
* the GCC that ship on Mac OS X 10.6.5, *counter* to what the GNU docs say)
*
* We should revert the Makefile.am changes once Apple ships a reasonable
* GCC.
*/
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-label"
#endif
#ifdef _MSC_VER
//warning C4102: 'find_rule' : unreferenced label
#pragma warning(disable:4102)
//avoid isatty redefinition
#define YY_NEVER_INTERACTIVE 1
#define YY_NO_UNISTD_H 1
#endif
#include <cassert>
#include <string>
#include <errno.h>
#include <stdlib.h>
#ifdef _MSC_VER
#include "thrift/windows/config.h"
#endif
#include "thrift/main.h"
#include "thrift/common.h"
#include "thrift/globals.h"
#include "thrift/parse/t_program.h"
/**
* Must be included AFTER parse/t_program.h, but I can't remember why anymore
* because I wrote this a while ago.
*/
#if defined(BISON_USE_PARSER_H_EXTENSION)
#include "thrift/thrifty.h"
#else
#include "thrift/thrifty.hh"
#endif
void thrift_reserved_keyword(char* keyword) {
yyerror("Cannot use reserved language keyword: \"%s\"\n", keyword);
exit(1);
}
void integer_overflow(char* text) {
yyerror("This integer is too big: \"%s\"\n", text);
exit(1);
}
void unexpected_token(char* text) {
yyerror("Unexpected token in input: \"%s\"\n", text);
exit(1);
}
%}
/**
* Provides the yylineno global, useful for debugging output
*/
%option lex-compat
/**
* Our inputs are all single files, so no need for yywrap
*/
%option noyywrap
/**
* We don't use it, and it fires up warnings at -Wall
*/
%option nounput
/**
* Helper definitions, comments, constants, and whatnot
*/
intconstant ([+-]?[0-9]+)
hexconstant ([+-]?"0x"[0-9A-Fa-f]+)
dubconstant ([+-]?[0-9]*(\.[0-9]+)?([eE][+-]?[0-9]+)?)
identifier ([a-zA-Z_](\.[a-zA-Z_0-9]|[a-zA-Z_0-9])*)
whitespace ([ \t\r\n]*)
sillycomm ("/*""*"*"*/")
multicm_begin ("/*")
doctext_begin ("/**")
comment ("//"[^\n]*)
unixcomment ("#"[^\n]*)
symbol ([:;\,\{\}\(\)\=<>\[\]])
literal_begin (['\"])
%%
{whitespace} { /* do nothing */ }
{sillycomm} { /* do nothing */ }
{doctext_begin} {
std::string parsed("/**");
int state = 0; // 0 = normal, 1 = "*" seen, "*/" seen
while(state < 2)
{
int ch = yyinput();
parsed.push_back(ch);
switch (ch) {
case EOF:
yyerror("Unexpected end of file in doc-comment at %d\n", yylineno);
exit(1);
case '*':
state = 1;
break;
case '/':
state = (state == 1) ? 2 : 0;
break;
default:
state = 0;
break;
}
}
pdebug("doctext = \"%s\"\n",parsed.c_str());
/* This does not show up in the parse tree. */
/* Rather, the parser will grab it out of the global. */
if (g_parse_mode == PROGRAM) {
clear_doctext();
g_doctext = strdup(parsed.c_str() + 3);
assert(strlen(g_doctext) >= 2);
g_doctext[strlen(g_doctext) - 2] = ' ';
g_doctext[strlen(g_doctext) - 1] = '\0';
g_doctext = clean_up_doctext(g_doctext);
g_doctext_lineno = yylineno;
if( (g_program_doctext_candidate == NULL) && (g_program_doctext_status == INVALID)){
g_program_doctext_candidate = strdup(g_doctext);
g_program_doctext_lineno = g_doctext_lineno;
g_program_doctext_status = STILL_CANDIDATE;
pdebug("%s","program doctext set to STILL_CANDIDATE");
}
}
}
{multicm_begin} { /* parsed, but thrown away */
std::string parsed("/*");
int state = 0; // 0 = normal, 1 = "*" seen, "*/" seen
while(state < 2)
{
int ch = yyinput();
parsed.push_back(ch);
switch (ch) {
case EOF:
yyerror("Unexpected end of file in multiline comment at %d\n", yylineno);
exit(1);
case '*':
state = 1;
break;
case '/':
state = (state == 1) ? 2 : 0;
break;
default:
state = 0;
break;
}
}
pdebug("multi_comm = \"%s\"\n",parsed.c_str());
}
{comment} { /* do nothing */ }
{unixcomment} { /* do nothing */ }
{symbol} { return yytext[0]; }
"*" { return yytext[0]; }
"false" { yylval.iconst=0; return tok_int_constant; }
"true" { yylval.iconst=1; return tok_int_constant; }
"namespace" { return tok_namespace; }
"cpp_namespace" { error_unsupported_namespace_decl("cpp"); /* do nothing */ }
"cpp_include" { return tok_cpp_include; }
"cpp_type" { return tok_cpp_type; }
"java_package" { error_unsupported_namespace_decl("java_package", "java"); /* do nothing */ }
"cocoa_prefix" { error_unsupported_namespace_decl("cocoa_prefix", "cocoa"); /* do nothing */ }
"csharp_namespace" { error_unsupported_namespace_decl("csharp"); /* do nothing */ }
"delphi_namespace" { error_unsupported_namespace_decl("delphi"); /* do nothing */ }
"php_namespace" { error_unsupported_namespace_decl("php"); /* do nothing */ }
"py_module" { error_unsupported_namespace_decl("py_module", "py"); /* do nothing */ }
"perl_package" { error_unsupported_namespace_decl("perl_package", "perl"); /* do nothing */ }
"ruby_namespace" { error_unsupported_namespace_decl("ruby"); /* do nothing */ }
"smalltalk_category" { error_unsupported_namespace_decl("smalltalk_category", "smalltalk.category"); /* do nothing */ }
"smalltalk_prefix" { error_unsupported_namespace_decl("smalltalk_category", "smalltalk.category"); /* do nothing */ }
"xsd_all" { return tok_xsd_all; }
"xsd_optional" { return tok_xsd_optional; }
"xsd_nillable" { return tok_xsd_nillable; }
"xsd_namespace" { error_unsupported_namespace_decl("xsd"); /* do nothing */ }
"xsd_attrs" { return tok_xsd_attrs; }
"include" { return tok_include; }
"void" { return tok_void; }
"bool" { return tok_bool; }
"byte" {
emit_byte_type_warning();
return tok_i8;
}
"i8" { return tok_i8; }
"i16" { return tok_i16; }
"i32" { return tok_i32; }
"i64" { return tok_i64; }
"double" { return tok_double; }
"string" { return tok_string; }
"binary" { return tok_binary; }
"slist" {
pwarning(0, "\"slist\" is deprecated and will be removed in a future compiler version. This type should be replaced with \"string\".\n");
return tok_slist;
}
"senum" {
pwarning(0, "\"senum\" is deprecated and will be removed in a future compiler version. This type should be replaced with \"string\".\n");
return tok_senum;
}
"map" { return tok_map; }
"list" { return tok_list; }
"set" { return tok_set; }
"oneway" { return tok_oneway; }
"typedef" { return tok_typedef; }
"struct" { return tok_struct; }
"union" { return tok_union; }
"exception" { return tok_xception; }
"extends" { return tok_extends; }
"throws" { return tok_throws; }
"service" { return tok_service; }
"enum" { return tok_enum; }
"const" { return tok_const; }
"required" { return tok_required; }
"optional" { return tok_optional; }
"async" {
pwarning(0, "\"async\" is deprecated. It is called \"oneway\" now.\n");
return tok_oneway;
}
"&" { return tok_reference; }
"BEGIN" { thrift_reserved_keyword(yytext); }
"END" { thrift_reserved_keyword(yytext); }
"__CLASS__" { thrift_reserved_keyword(yytext); }
"__DIR__" { thrift_reserved_keyword(yytext); }
"__FILE__" { thrift_reserved_keyword(yytext); }
"__FUNCTION__" { thrift_reserved_keyword(yytext); }
"__LINE__" { thrift_reserved_keyword(yytext); }
"__METHOD__" { thrift_reserved_keyword(yytext); }
"__NAMESPACE__" { thrift_reserved_keyword(yytext); }
"abstract" { thrift_reserved_keyword(yytext); }
"alias" { thrift_reserved_keyword(yytext); }
"and" { thrift_reserved_keyword(yytext); }
"args" { thrift_reserved_keyword(yytext); }
"as" { thrift_reserved_keyword(yytext); }
"assert" { thrift_reserved_keyword(yytext); }
"begin" { thrift_reserved_keyword(yytext); }
"break" { thrift_reserved_keyword(yytext); }
"case" { thrift_reserved_keyword(yytext); }
"catch" { thrift_reserved_keyword(yytext); }
"class" { thrift_reserved_keyword(yytext); }
"clone" { thrift_reserved_keyword(yytext); }
"continue" { thrift_reserved_keyword(yytext); }
"declare" { thrift_reserved_keyword(yytext); }
"def" { thrift_reserved_keyword(yytext); }
"default" { thrift_reserved_keyword(yytext); }
"del" { thrift_reserved_keyword(yytext); }
"delete" { thrift_reserved_keyword(yytext); }
"do" { thrift_reserved_keyword(yytext); }
"dynamic" { thrift_reserved_keyword(yytext); }
"elif" { thrift_reserved_keyword(yytext); }
"else" { thrift_reserved_keyword(yytext); }
"elseif" { thrift_reserved_keyword(yytext); }
"elsif" { thrift_reserved_keyword(yytext); }
"end" { thrift_reserved_keyword(yytext); }
"enddeclare" { thrift_reserved_keyword(yytext); }
"endfor" { thrift_reserved_keyword(yytext); }
"endforeach" { thrift_reserved_keyword(yytext); }
"endif" { thrift_reserved_keyword(yytext); }
"endswitch" { thrift_reserved_keyword(yytext); }
"endwhile" { thrift_reserved_keyword(yytext); }
"ensure" { thrift_reserved_keyword(yytext); }
"except" { thrift_reserved_keyword(yytext); }
"exec" { thrift_reserved_keyword(yytext); }
"finally" { thrift_reserved_keyword(yytext); }
"float" { thrift_reserved_keyword(yytext); }
"for" { thrift_reserved_keyword(yytext); }
"foreach" { thrift_reserved_keyword(yytext); }
"from" { thrift_reserved_keyword(yytext); }
"function" { thrift_reserved_keyword(yytext); }
"global" { thrift_reserved_keyword(yytext); }
"goto" { thrift_reserved_keyword(yytext); }
"if" { thrift_reserved_keyword(yytext); }
"implements" { thrift_reserved_keyword(yytext); }
"import" { thrift_reserved_keyword(yytext); }
"in" { thrift_reserved_keyword(yytext); }
"inline" { thrift_reserved_keyword(yytext); }
"instanceof" { thrift_reserved_keyword(yytext); }
"interface" { thrift_reserved_keyword(yytext); }
"is" { thrift_reserved_keyword(yytext); }
"lambda" { thrift_reserved_keyword(yytext); }
"module" { thrift_reserved_keyword(yytext); }
"native" { thrift_reserved_keyword(yytext); }
"new" { thrift_reserved_keyword(yytext); }
"next" { thrift_reserved_keyword(yytext); }
"nil" { thrift_reserved_keyword(yytext); }
"not" { thrift_reserved_keyword(yytext); }
"or" { thrift_reserved_keyword(yytext); }
"package" { thrift_reserved_keyword(yytext); }
"pass" { thrift_reserved_keyword(yytext); }
"public" { thrift_reserved_keyword(yytext); }
"print" { thrift_reserved_keyword(yytext); }
"private" { thrift_reserved_keyword(yytext); }
"protected" { thrift_reserved_keyword(yytext); }
"raise" { thrift_reserved_keyword(yytext); }
"redo" { thrift_reserved_keyword(yytext); }
"rescue" { thrift_reserved_keyword(yytext); }
"retry" { thrift_reserved_keyword(yytext); }
"register" { thrift_reserved_keyword(yytext); }
"return" { thrift_reserved_keyword(yytext); }
"self" { thrift_reserved_keyword(yytext); }
"sizeof" { thrift_reserved_keyword(yytext); }
"static" { thrift_reserved_keyword(yytext); }
"super" { thrift_reserved_keyword(yytext); }
"switch" { thrift_reserved_keyword(yytext); }
"synchronized" { thrift_reserved_keyword(yytext); }
"then" { thrift_reserved_keyword(yytext); }
"this" { thrift_reserved_keyword(yytext); }
"throw" { thrift_reserved_keyword(yytext); }
"transient" { thrift_reserved_keyword(yytext); }
"try" { thrift_reserved_keyword(yytext); }
"undef" { thrift_reserved_keyword(yytext); }
"unless" { thrift_reserved_keyword(yytext); }
"unsigned" { thrift_reserved_keyword(yytext); }
"until" { thrift_reserved_keyword(yytext); }
"use" { thrift_reserved_keyword(yytext); }
"var" { thrift_reserved_keyword(yytext); }
"virtual" { thrift_reserved_keyword(yytext); }
"volatile" { thrift_reserved_keyword(yytext); }
"when" { thrift_reserved_keyword(yytext); }
"while" { thrift_reserved_keyword(yytext); }
"with" { thrift_reserved_keyword(yytext); }
"xor" { thrift_reserved_keyword(yytext); }
"yield" { thrift_reserved_keyword(yytext); }
{intconstant} {
errno = 0;
yylval.iconst = strtoll(yytext, NULL, 10);
if (errno == ERANGE) {
integer_overflow(yytext);
}
return tok_int_constant;
}
{hexconstant} {
errno = 0;
char sign = yytext[0];
int shift = sign == '0' ? 2 : 3;
yylval.iconst = strtoll(yytext+shift, NULL, 16);
if (sign == '-') {
yylval.iconst = -yylval.iconst;
}
if (errno == ERANGE) {
integer_overflow(yytext);
}
return tok_int_constant;
}
{identifier} {
yylval.id = strdup(yytext);
return tok_identifier;
}
{dubconstant} {
/* Deliberately placed after identifier, since "e10" is NOT a double literal (THRIFT-3477) */
yylval.dconst = atof(yytext);
return tok_dub_constant;
}
{literal_begin} {
char mark = yytext[0];
std::string result;
for(;;)
{
int ch = yyinput();
switch (ch) {
case EOF:
yyerror("End of file while read string at %d\n", yylineno);
exit(1);
case '\n':
yyerror("End of line while read string at %d\n", yylineno - 1);
exit(1);
case '\\':
ch = yyinput();
switch (ch) {
case 'r':
result.push_back('\r');
continue;
case 'n':
result.push_back('\n');
continue;
case 't':
result.push_back('\t');
continue;
case '"':
result.push_back('"');
continue;
case '\'':
result.push_back('\'');
continue;
case '\\':
result.push_back('\\');
continue;
default:
yyerror("Bad escape character\n");
return -1;
}
break;
default:
if (ch == mark) {
yylval.id = strdup(result.c_str());
return tok_literal;
} else {
result.push_back(ch);
}
}
}
}
. {
unexpected_token(yytext);
}
%%
/* vim: filetype=lex
*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _THRIFT_VERSION_H_
#define _THRIFT_VERSION_H_ 1
#if defined(_MSC_VER) && (_MSC_VER > 1200)
#pragma once
#endif // _MSC_VER
#define THRIFT_VERSION "@PACKAGE_VERSION@"
#endif // _THRIFT_VERSION_H_

View file

@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _THRIFT_WINDOWS_CONFIG_H_
#define _THRIFT_WINDOWS_CONFIG_H_ 1
#if defined(_MSC_VER) && (_MSC_VER > 1200)
#pragma once
#endif // _MSC_VER
#ifndef _WIN32
#error "This is a Windows header only"
#endif
#include <io.h>
#include <stdlib.h>
#include <direct.h>
#define strtoll(begin_ptr, end_ptr, length) _strtoi64(begin_ptr, end_ptr, length)
#define PRIu64 "I64d"
#define PRIi64 "I64d"
// squelch deprecation warnings
#pragma warning(disable : 4996)
// squelch bool conversion performance warning
#pragma warning(disable : 4800)
// MSVC10 (2010) or later has stdint.h
#if _MSC_VER >= 1600
#define HAVE_STDINT_H 1
#endif
// Must be using VS2010 or later, or boost, so that C99 types are defined in the global namespace
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#include <boost/cstdint.hpp>
typedef boost::int64_t int64_t;
typedef boost::uint64_t uint64_t;
typedef boost::int32_t int32_t;
typedef boost::uint32_t uint32_t;
typedef boost::int16_t int16_t;
typedef boost::uint16_t uint16_t;
typedef boost::int8_t int8_t;
typedef boost::uint8_t uint8_t;
#endif
#endif // _THRIFT_WINDOWS_CONFIG_H_

View file

@ -0,0 +1,77 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
if(${WITH_PLUGIN})
include_directories(SYSTEM "${Boost_INCLUDE_DIRS}")
# Make sure gen-cpp files can be included
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
set(plugintest_SOURCES
plugin/conversion_test.cc
)
add_executable(plugintest ${plugintest_SOURCES})
if(WITH_SHARED_LIB AND NOT MSVC)
target_link_libraries(plugintest
thriftc
${Boost_LIBRARIES}
)
else()
target_link_libraries(plugintest
thriftc_static
thrift_static
${Boost_LIBRARIES}
)
endif()
add_test(NAME PluginUnitTest COMMAND plugintest)
set(thrift-gen-mycpp_SOURCES
../src/thrift/generate/t_cpp_generator.cc
plugin/cpp_plugin.cc
)
add_executable(thrift-gen-mycpp ${thrift-gen-mycpp_SOURCES})
if(WITH_SHARED_LIB AND NOT MSVC)
target_link_libraries(thrift-gen-mycpp thriftc)
else()
target_link_libraries(thrift-gen-mycpp thriftc_static thrift_static)
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(BUILDTYPE "Debug")
else()
# RelWithDebInfo generates binaries in "Release" directory too
set(BUILDTYPE "Release")
endif()
set_directory_properties(PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES gen-cpp
ADDITIONAL_MAKE_CLEAN_FILES gen-mycpp)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gen-cpp)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gen-mycpp)
add_test(NAME PluginIntegrationTest
COMMAND ${CMAKE_COMMAND}
-DTHRIFT_COMPILER=${THRIFT_COMPILER}
-DBINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
-DBUILDTYPE=${BUILDTYPE}
-DCURDIR=${CMAKE_CURRENT_BINARY_DIR}
-DSRCDIR=${CMAKE_CURRENT_SOURCE_DIR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cpp_plugin_test.cmake)
endif()

View file

@ -0,0 +1,51 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
#
# Contains some contributions under the Thrift Software License.
# Please see doc/old-thrift-license.txt in the Thrift distribution for
# details.
AUTOMAKE_OPTIONS = subdir-objects serial-tests
AM_CPPFLAGS = $(BOOST_CPPFLAGS) -I$(top_srcdir)/compiler/cpp/src
AM_LDFLAGS = $(BOOST_LDFLAGS)
AM_CXXFLAGS = -Wall -Wextra -pedantic
if WITH_PLUGIN
check_PROGRAMS = plugintest
noinst_PROGRAMS = thrift-gen-mycpp
AM_CPPFLAGS += -I$(top_srcdir)/lib/cpp/src -I$(top_builddir)/lib/cpp/src
plugintest_SOURCES = plugin/conversion_test.cc
plugintest_LDADD = $(top_builddir)/compiler/cpp/libthriftc.la
thrift_gen_mycpp_SOURCES = plugin/cpp_plugin.cc \
plugin/t_cpp_generator.cc
thrift_gen_mycpp_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/compiler/cpp -I$(top_srcdir)/compiler/cpp/src/generate
thrift_gen_mycpp_LDADD = $(top_builddir)/compiler/cpp/libthriftc.la
cpp_plugin_test.sh: thrift-gen-mycpp
TESTS = $(check_PROGRAMS) cpp_plugin_test.sh
clean-local:
$(RM) -rf gen-cpp gen-mycpp
endif

View file

@ -0,0 +1,45 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
file(MAKE_DIRECTORY ${CURDIR}/gen-cpp)
execute_process(COMMAND ${THRIFT_COMPILER} -r -out ${CURDIR}/gen-cpp -gen cpp ${SRCDIR}/../../../test/Include.thrift)
if(EXITCODE)
message(FATAL_ERROR "FAILED: \"${ARGV}\": \"${EXITCODE}\"")
endif()
if(WIN32)
set(ENV{PATH} "${BINDIR}/${BUILDTYPE};${BINDIR};$ENV{PATH}")
else()
set(ENV{PATH} "${BINDIR}:$ENV{PATH}")
endif()
file(MAKE_DIRECTORY ${CURDIR}/gen-mycpp)
execute_process(COMMAND ${THRIFT_COMPILER} -r -out ${CURDIR}/gen-mycpp -gen mycpp ${SRCDIR}/../../../test/Include.thrift RESULT_VARIABLE EXITCODE)
if(EXITCODE)
message(FATAL_ERROR "FAILED: \"${EXITCODE}\"")
endif()
find_program(DIFF diff)
if(DIFF)
execute_process(COMMAND ${DIFF} -urN gen-cpp gen-mycpp RESULT_VARIABLE EXITCODE)
if(EXITCODE)
message(FATAL_ERROR "FAILED: \"${EXITCODE}\"")
endif()
else()
message(WARNING "diff executable is not available. Not validating plugin-generated code.")
endif()

View file

@ -0,0 +1,27 @@
#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
# this file is intended to be invoked by make.
set -e
mkdir -p gen-cpp gen-mycpp
PATH=.:"$PATH" ../thrift -r -out gen-cpp -gen cpp ../../../test/Include.thrift
PATH=.:"$PATH" ../thrift -r -out gen-mycpp -gen mycpp ../../../test/Include.thrift
diff -urN gen-cpp gen-mycpp

View file

@ -0,0 +1,496 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include "thrift/parse/t_program.h"
#include "thrift/plugin/type_util.h"
#include "thrift/plugin/plugin_types.h"
#include <map>
#include <vector>
#include <boost/preprocessor.hpp>
#include <boost/test/included/unit_test.hpp>
#include <boost/test/parameterized_test.hpp>
using namespace apache::thrift;
using namespace boost::unit_test;
namespace test_data {
#define T_TEST_TYPES \
BOOST_PP_TUPLE_TO_LIST(14, \
(program, \
base_type, \
enum_value, \
enum, \
const_value, \
const, \
list, \
set, \
map, \
field, \
struct, \
typedef, \
function, \
service))
#define T_DELETE_TESTDATA(r, d, elem) \
for (std::vector<t_##elem*>::reverse_iterator it = elem##s.rbegin(); it != elem##s.rend(); it++) \
delete *it;
#define T_DECL_TESTDATA(r, d, elem) static std::vector< ::t_##elem*> elem##s;
BOOST_PP_LIST_FOR_EACH(T_DECL_TESTDATA, _, T_TEST_TYPES)
#undef T_DECL_TESTDATA
bool has_data = false;
void cleanup() {
if (has_data) {
has_data = false;
BOOST_PP_LIST_FOR_EACH(T_DELETE_TESTDATA, _, T_TEST_TYPES)
}
}
void init_programs() {
programs.push_back(new t_program("prog path", "prog_name"));
}
void init_base_types() {
base_types.push_back(new ::t_base_type("name0", ::t_base_type::TYPE_VOID));
base_types.push_back(new ::t_base_type("name1", ::t_base_type::TYPE_STRING));
base_types.push_back(new ::t_base_type("name2", ::t_base_type::TYPE_BOOL));
base_types.push_back(new ::t_base_type("name3", ::t_base_type::TYPE_I8));
base_types.push_back(new ::t_base_type("name4", ::t_base_type::TYPE_I16));
base_types.push_back(new ::t_base_type("name5", ::t_base_type::TYPE_I32));
base_types.push_back(new ::t_base_type("name6", ::t_base_type::TYPE_I64));
base_types.push_back(new ::t_base_type("name7", ::t_base_type::TYPE_DOUBLE));
}
void init_const_values() {
const_values.push_back(new t_const_value(42));
const_values.push_back(new t_const_value("foo"));
{
t_const_value* x = new t_const_value;
x->set_double(3.1415);
const_values.push_back(x);
}
{
t_const_value* x = new t_const_value;
x->set_identifier("bar");
x->set_enum(enums[0]);
const_values.push_back(x);
}
{
t_const_value* x = new t_const_value;
x->set_map();
x->add_map(const_values[0], const_values[1]);
x->add_map(const_values[1], const_values[0]);
const_values.push_back(x);
}
{
t_const_value* x = new t_const_value;
x->set_list();
x->add_list(const_values[0]);
x->add_list(const_values[1]);
const_values.push_back(x);
}
}
void init_consts() {
// base_type/enum indexes for this and other tests are arbitrary
consts.push_back(new t_const(base_types[2], "aaa", const_values[0]));
consts.back()->set_doc("soem doc");
consts.push_back(new t_const(base_types[3], "bbb", const_values[1]));
}
void init_enum_values() {
enum_values.push_back(new t_enum_value("VAL1", 11));
enum_values.back()->set_doc("enum doc 1");
enum_values.back()->annotations_.insert(std::make_pair("anno1", "val1"));
enum_values.push_back(new t_enum_value("VAL2", 22));
}
void init_enums() {
enums.push_back(new t_enum(programs[0]));
enums.back()->set_doc("enum doc 1");
enums.back()->annotations_.insert(std::make_pair("anno1", "val1"));
enums.back()->set_name("fooo");
enums.back()->append(enum_values[0]);
enums.back()->append(enum_values[1]);
}
void init_lists() {
lists.push_back(new t_list(enums[0]));
lists.push_back(new t_list(base_types[5]));
lists.back()->set_cpp_name("list_cpp_name_1");
}
void init_sets() {
sets.push_back(new t_set(base_types[4]));
sets.push_back(new t_set(enums[0]));
sets.back()->set_cpp_name("set_cpp_name_1");
}
void init_maps() {
maps.push_back(new t_map(base_types[4], base_types[1]));
maps.push_back(new t_map(base_types[5], enums[0]));
maps.back()->set_cpp_name("map_cpp_name_1");
}
void init_typedefs() {
typedefs.push_back(new t_typedef(programs[0], base_types[3], "VAL1"));
}
void init_fields() {
fields.push_back(new t_field(base_types[1], "f1"));
fields.back()->set_reference(false);
fields.back()->set_req(t_field::T_OPTIONAL);
fields.push_back(new t_field(base_types[2], "f2", 9));
fields.back()->set_reference(true);
fields.push_back(new t_field(base_types[3], "f3", 11));
fields.back()->set_req(t_field::T_REQUIRED);
fields.back()->set_value(const_values[0]);
}
void init_structs() {
structs.push_back(new t_struct(programs[0], "struct1"));
structs.back()->append(fields[0]);
structs.back()->append(fields[1]);
structs.push_back(new t_struct(programs[0], "union1"));
structs.back()->append(fields[0]);
structs.back()->append(fields[1]);
structs.back()->set_union(true);
structs.push_back(new t_struct(programs[0], "xcept1"));
structs.back()->set_xception(true);
}
void init_functions() {
structs.push_back(new t_struct(programs[0], "errs1"));
t_struct* errors = structs.back();
structs.push_back(new t_struct(programs[0], "args1"));
t_struct* arglist = structs.back();
functions.push_back(new t_function(base_types[0], "func1", errors, arglist, false));
functions.push_back(new t_function(base_types[0], "func2", errors, arglist, true));
}
void init_services() {
services.push_back(new t_service(programs[0]));
services.back()->set_doc("srv1 doc");
services.back()->set_name("srv1");
services.back()->add_function(functions[0]);
services.back()->add_function(functions[1]);
services.push_back(new t_service(programs[0]));
services.back()->set_name("srv2");
services.back()->set_extends(services[0]);
}
std::vector<t_type*> types;
void init_types() {
#define T_COPY_TYPES(type) std::copy(type##s.begin(), type##s.end(), std::back_inserter(types))
T_COPY_TYPES(base_type);
T_COPY_TYPES(enum);
T_COPY_TYPES(typedef);
T_COPY_TYPES(struct);
T_COPY_TYPES(list);
T_COPY_TYPES(set);
T_COPY_TYPES(map);
// T_COPY_TYPES(service);
#undef T_COPY_TYPES
}
void init() {
if (!has_data) {
has_data = true;
#define T_INIT_TESTDATA(r, d, elem) init_##elem##s();
BOOST_PP_LIST_FOR_EACH(T_INIT_TESTDATA, _, T_TEST_TYPES)
init_types();
#undef T_INIT_TESTDATA
}
}
}
struct GlobalFixture {
~GlobalFixture() { test_data::cleanup(); }
};
#if (BOOST_VERSION >= 105900)
BOOST_GLOBAL_FIXTURE(GlobalFixture);
#else
BOOST_GLOBAL_FIXTURE(GlobalFixture)
#endif
void migrate_global_cache() {
plugin::TypeRegistry reg;
plugin_output::get_global_cache(reg);
plugin::set_global_cache(reg);
plugin_output::clear_global_cache();
}
template <typename T>
T* round_trip(T* t) {
typename plugin::ToType<T>::type p;
plugin_output::convert(t, p);
migrate_global_cache();
return plugin::convert(p);
}
void test_base_type(::t_base_type* sut) {
plugin::t_base_type p;
plugin_output::convert(sut, p);
boost::scoped_ptr< ::t_base_type> sut2(plugin::convert(p));
#define THRIFT_CHECK(r, data, elem) BOOST_PP_EXPAND(BOOST_CHECK_EQUAL(data elem, sut2->elem));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(7,
(is_void(),
is_string(),
is_bool(),
is_string_list(),
is_binary(),
is_string_enum(),
is_base_type())))
}
void test_const_value(t_const_value* sut) {
boost::scoped_ptr<t_const_value> sut2(round_trip(sut));
BOOST_CHECK_EQUAL(sut->get_type(), sut2->get_type());
switch (sut->get_type()) {
#define T_CONST_VALUE_CASE(type, name) \
case t_const_value::type: \
BOOST_CHECK_EQUAL(sut->get_##name(), sut2->get_##name()); \
break
T_CONST_VALUE_CASE(CV_INTEGER, integer);
T_CONST_VALUE_CASE(CV_DOUBLE, double);
T_CONST_VALUE_CASE(CV_STRING, string);
T_CONST_VALUE_CASE(CV_IDENTIFIER, identifier);
#undef T_CONST_VALUE_CASE
case t_const_value::CV_MAP:
BOOST_CHECK_EQUAL(sut->get_map().size(), sut2->get_map().size());
{
std::map<t_const_value::t_const_value_type, t_const_value::t_const_value_type> sut_values;
for (std::map<t_const_value*, t_const_value*>::const_iterator it = sut->get_map().begin();
it != sut->get_map().end(); it++) {
sut_values[it->first->get_type()] = it->second->get_type();
}
std::map<t_const_value::t_const_value_type, t_const_value::t_const_value_type> sut2_values;
for (std::map<t_const_value*, t_const_value*>::const_iterator it = sut2->get_map().begin();
it != sut2->get_map().end(); it++) {
sut2_values[it->first->get_type()] = it->second->get_type();
}
BOOST_CHECK_EQUAL(sut_values.begin()->first, sut2_values.begin()->first);
BOOST_CHECK_EQUAL(sut_values.begin()->second, sut2_values.begin()->second);
}
break;
case t_const_value::CV_LIST:
BOOST_CHECK_EQUAL(sut->get_list().size(), sut2->get_list().size());
BOOST_CHECK_EQUAL(sut->get_list().front()->get_type(), sut2->get_list().front()->get_type());
break;
default:
BOOST_ASSERT(false);
break;
}
}
void test_const(t_const* sut) {
boost::scoped_ptr< ::t_const> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(4,
(get_type()->get_name(),
get_name(),
get_value()->get_type(),
get_doc())))
}
void test_enum_value(t_enum_value* sut) {
boost::scoped_ptr<t_enum_value> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(3, (get_name(), get_value(), get_doc())))
}
void test_enum(t_enum* sut) {
boost::scoped_ptr< ::t_enum> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(6,
(get_name(),
get_min_value()->get_value(),
get_max_value()->get_value(),
get_constant_by_value(11)->get_value(),
get_constant_by_name("VAL1")->get_value(),
get_doc())))
}
void test_list(t_list* sut) {
boost::scoped_ptr<t_list> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(4,
(get_elem_type()->get_name(),
has_cpp_name(),
get_doc(),
get_name())))
if (sut->has_cpp_name())
BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name());
}
void test_set(t_set* sut) {
boost::scoped_ptr<t_set> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(4,
(get_elem_type()->get_name(),
has_cpp_name(),
get_doc(),
get_name())))
if (sut->has_cpp_name())
BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name());
}
void test_map(t_map* sut) {
boost::scoped_ptr<t_map> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(5,
(get_key_type()->get_name(),
get_val_type()->get_name(),
has_cpp_name(),
get_doc(),
get_name())))
if (sut->has_cpp_name())
BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name());
}
void test_typedef(t_typedef* sut) {
boost::scoped_ptr<t_typedef> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(4,
(get_doc(),
get_name(),
get_symbolic(),
is_forward_typedef())))
}
void test_type(t_type* sut) {
boost::scoped_ptr<t_type> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(15,
(is_void(),
is_base_type(),
is_string(),
is_bool(),
is_typedef(),
is_enum(),
is_struct(),
is_xception(),
is_container(),
is_list(),
is_set(),
is_map(),
is_service(),
get_doc(),
get_name())))
}
void test_field(t_field* sut) {
boost::scoped_ptr<t_field> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(5,
(get_req(),
get_reference(),
get_key(),
get_doc(),
get_name())))
if (sut->get_value()) {
THRIFT_CHECK(, sut->, get_value()->get_type());
} else {
BOOST_CHECK(!sut2->get_value());
}
if (sut->get_type()) {
THRIFT_CHECK(, sut->, get_type()->get_name());
} else {
BOOST_CHECK(!sut2->get_type());
}
}
void test_struct(t_struct* sut) {
boost::scoped_ptr<t_struct> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(5,
(is_union(),
is_xception(),
is_struct(),
get_doc(),
get_name())))
}
void test_function(t_function* sut) {
boost::scoped_ptr<t_function> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(
THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(4, (get_doc(), get_name(), get_returntype()->get_name(), is_oneway())))
}
void test_service(t_service* sut) {
boost::scoped_ptr<t_service> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
sut->,
BOOST_PP_TUPLE_TO_LIST(3, (get_doc(), get_name(), get_functions().size())))
if (sut->get_extends()) {
THRIFT_CHECK(, sut->, get_extends()->get_name());
} else {
BOOST_CHECK(!sut2->get_extends());
}
}
void test_program(t_program* sut) {
boost::scoped_ptr<t_program> sut2(round_trip(sut));
BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, sut->, BOOST_PP_TUPLE_TO_LIST(2, (get_doc(), get_name())))
}
boost::unit_test::test_suite* do_init_unit_test_suite() {
test_data::init();
test_suite* ts = BOOST_TEST_SUITE("PluginConversionTest");
#define T_TEST_CASE(r, d, type) \
ts->add(BOOST_PARAM_TEST_CASE(test_##type, test_data::type##s.begin(), test_data::type##s.end()));
BOOST_PP_LIST_FOR_EACH(T_TEST_CASE, _, T_TEST_TYPES)
T_TEST_CASE(_, _, type)
#undef T_TEST_CASE
return ts;
}
#ifdef BOOST_TEST_DYN_LINK
bool init_unit_test_suite() {
framework::master_test_suite().add(do_init_unit_test_suite());
return true;
}
int main(int argc, char* argv[]) {
return ::boost::unit_test::unit_test_main(&init_unit_test_suite, argc, argv);
}
#else
boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
return do_init_unit_test_suite();
}
#endif

View file

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include "thrift/plugin/plugin.h"
#include "thrift/generate/t_generator.h"
namespace apache {
namespace thrift {
namespace plugin {
class MyCppGenerator : public GeneratorPlugin {
virtual int generate(::t_program* program,
const std::map<std::string, std::string>& parsed_options) {
t_generator* gen = t_generator_registry::get_generator(program, "cpp", parsed_options, "");
gen->generate_program();
delete gen;
return 0;
}
};
}
}
}
int main(int argc, char* argv[]) {
apache::thrift::plugin::MyCppGenerator p;
return p.exec(argc, argv);
}