1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

initial commit

This commit is contained in:
initial commit 2019-09-07 14:03:22 +04:00 committed by vvaltman
commit c2da007f40
1610 changed files with 398047 additions and 0 deletions

55
tl/CMakeLists.txt Normal file
View file

@ -0,0 +1,55 @@
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
add_subdirectory(generate)
set_source_files_properties(${TL_TON_API} PROPERTIES GENERATED TRUE)
add_library(tl_api STATIC
${TL_TON_API}
tl/tl_object_parse.h
tl/tl_object_store.h
tl/TlObject.h)
add_dependencies(tl_api tl_generate_common)
target_link_libraries(tl_api tdutils)
target_include_directories(tl_api PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../crypto/> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/generate>)
set_source_files_properties(${TL_LITE_API} PROPERTIES GENERATED TRUE)
add_library(tl_lite_api STATIC
${TL_LITE_API}
tl/tl_object_parse.h
tl/tl_object_store.h
tl/TlObject.h)
add_dependencies(tl_lite_api tl_generate_common)
target_link_libraries(tl_lite_api tdutils)
target_include_directories(tl_lite_api PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../crypto/> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/generate>)
if (TONLIB_ENABLE_JNI)
set(TL_JNI_OBJECT
tl/tl_jni_object.cpp
tl/tl_jni_object.h
)
else()
set(TL_JNI_OBJECT)
endif()
set_source_files_properties(${TL_TONLIB_API} PROPERTIES GENERATED TRUE)
set_source_files_properties(${TL_TONLIB_API_JSON} PROPERTIES GENERATED TRUE)
add_library(tl_tonlib_api STATIC ${TL_TONLIB_API} tl/tl_object_parse.h tl/tl_object_store.h tl/TlObject.h
${TL_JNI_OBJECT})
add_library(tl_tonlib_api_json STATIC ${TL_TONLIB_API_JSON} tl/tl_object_parse.h tl/tl_object_store.h tl/TlObject.h)
add_dependencies(tl_tonlib_api tl_generate_common)
target_link_libraries(tl_tonlib_api tdutils)
target_link_libraries(tl_tonlib_api_json tdutils tl_tonlib_api)
target_include_directories(tl_tonlib_api PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../crypto/>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/generate> )
target_include_directories(tl_tonlib_api_json PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../crypto/>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/generate> )

View file

@ -0,0 +1,83 @@
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
file(MAKE_DIRECTORY auto/tl)
set(TL_TON_API
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/ton_api.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/ton_api.h
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/ton_api.hpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/ton_api_json.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/ton_api_json.h
)
set(TL_TON_API ${TL_TON_API} PARENT_SCOPE)
set(TL_LITE_API
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/lite_api.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/lite_api.h
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/lite_api.hpp
)
set(TL_LITE_API ${TL_LITE_API} PARENT_SCOPE)
set(TL_TONLIB_API
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/tonlib_api.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/tonlib_api.h
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/tonlib_api.hpp
)
set(TL_TONLIB_API ${TL_TONLIB_API} PARENT_SCOPE)
set(TL_TONLIB_API_JSON
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/tonlib_api_json.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/tl/tonlib_api_json.h
)
set(TL_TONLIB_API_JSON ${TL_TONLIB_API_JSON} PARENT_SCOPE)
set(TL_GENERATE_COMMON_SOURCE
generate_common.cpp
tl_json_converter.cpp
tl_writer_cpp.cpp
tl_writer_h.cpp
tl_writer_hpp.cpp
tl_writer_td.cpp
tl_writer_jni_cpp.cpp
tl_writer_jni_h.cpp
tl_json_converter.h
tl_writer_cpp.h
tl_writer_h.h
tl_writer_hpp.h
tl_writer_td.h
tl_writer_jni_cpp.h
tl_writer_jni_h.h
)
set(TL_GENERATE_JAVA_SOURCE
generate_java.cpp
tl_writer_java.cpp
tl_writer_java.h
)
add_executable(tonlib_generate_java_api ${TL_GENERATE_JAVA_SOURCE})
target_link_libraries(tonlib_generate_java_api PRIVATE tdtl)
if (NOT CMAKE_CROSSCOMPILING)
find_program(PHP_EXECUTABLE php)
set(GENERATE_COMMON_CMD generate_common)
add_executable(generate_common ${TL_GENERATE_COMMON_SOURCE})
target_link_libraries(generate_common PRIVATE tdtl tdutils)
add_custom_command(
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${GENERATE_COMMON_CMD}
COMMENT "Generate common tl source files"
DEPENDS generate_common scheme/ton_api.tlo scheme/lite_api.tlo scheme/tonlib_api.tlo
OUTPUT ${TL_TON_API} ${TL_LITE_API} ${TL_TONLIB_API} ${TL_TONLIB_API_JSON}
)
add_custom_target(tl_generate_common DEPENDS ${TL_TON_API} ${TL_LITE_API} ${TL_TONLIB_API} ${TL_TONLIB_API_JSON})
if (TONLIB_ENABLE_JNI)
target_compile_definitions(generate_common PRIVATE TONLIB_ENABLE_JNI=1)
endif()
else()
add_custom_target(tl_generate_common)
endif()

View file

@ -0,0 +1,268 @@
<?php
require_once 'TlDocumentationGenerator.php';
class JavadocTlDocumentationGenerator extends TlDocumentationGenerator
{
private $nullable_type;
private $nullable_annotation;
private $java_version;
protected function escapeDocumentation($doc)
{
$doc = preg_replace_callback('/(?<!["A-Za-z_\/])[A-Za-z]*_[A-Za-z_]*/',
function ($word_matches)
{
return preg_replace_callback('/_([A-Za-z])/', function ($matches) {return strtoupper($matches[1]);}, $word_matches[0]);
}, $doc);
$doc = htmlspecialchars($doc);
$doc = str_replace('*/', '*&#47;', $doc);
return $doc;
}
protected function getFieldName($name, $class_name)
{
if (substr($name, 0, 6) === 'param_') {
$name = substr($name, 6);
}
return preg_replace_callback('/_([A-Za-z])/', function ($matches) {return strtoupper($matches[1]);}, trim($name));
}
protected function getClassName($type)
{
return implode(array_map('ucfirst', explode('.', trim($type, "\r\n ;"))));
}
protected function getTypeName($type)
{
switch ($type) {
case 'Bool':
return 'boolean';
case 'int32':
return 'int';
case 'int53':
case 'int64':
return 'long';
case 'double':
return $type;
case 'string':
return 'String';
case 'bytes':
return 'byte[]';
case 'bool':
case 'int':
case 'long':
case 'Int':
case 'Long':
case 'Int32':
case 'Int53':
case 'Int64':
case 'Double':
case 'String':
case 'Bytes':
$this->printError("Wrong type $type");
return '';
default:
if (substr($type, 0, 6) === 'vector') {
if ($type[6] !== '<' || $type[strlen($type) - 1] !== '>') {
$this->printError("Wrong vector subtype in $type");
return '';
}
return $this->getTypeName(substr($type, 7, -1)).'[]';
}
if (preg_match('/[^A-Za-z0-9.]/', $type)) {
$this->printError("Wrong type $type");
return '';
}
return $this->getClassName($type);
}
}
protected function getBaseClassName($is_function)
{
return $is_function ? 'Function' : 'Object';
}
protected function needRemoveLine($line)
{
return strpos(trim($line), '/**') === 0 || strpos(trim($line), '*') === 0 ||
($this->nullable_type && strpos($line, $this->nullable_type) > 0);
}
protected function needSkipLine($line)
{
$line = $this->fixLine(trim($line));
return (strpos($line, 'public') !== 0 && !$this->isHeaderLine($line)) || $line === 'public @interface Constructors {}';
}
protected function isHeaderLine($line)
{
return trim($line) === '@Override' || trim($line) === '@Constructors';
}
protected function extractClassName($line)
{
if (strpos($line, 'public static class ') > 0) {
return explode(' ', trim($line))[3];
}
return '';
}
protected function fixLine($line)
{
if (strpos($line, 'CONSTRUCTOR = ') > 0) {
return substr($line, 0, strpos($line, '='));
}
return $this->nullable_annotation ? str_replace($this->nullable_annotation.' ', '', $line) : $line;
}
protected function addGlobalDocumentation()
{
if ($this->nullable_type) {
$nullable_type_import = "import $this->nullable_type;".PHP_EOL;
} else {
$nullable_type_import = '';
}
$this->addDocumentation('public class TdApi {', <<<EOT
$nullable_type_import/**
* This class contains as static nested classes all other TDLib interface
* type-classes and function-classes.
* <p>
* It has no inner classes, functions or public members.
*/
EOT
);
$this->addDocumentation(' public abstract static class Object {', <<<EOT
/**
* This class is a base class for all TDLib interface classes.
*/
EOT
);
$this->addDocumentation(' public abstract int getConstructor();', <<<EOT
/**
* @return identifier uniquely determining type of the object.
*/
EOT
);
$this->addDocumentation(' public native String toString();', <<<EOT
/**
* @return string representation of the object.
*/
EOT
);
$this->addDocumentation(' public abstract static class Function extends Object {', <<<EOT
/**
* This class is a base class for all TDLib interface function-classes.
*/
EOT
);
$this->addDocumentation(' public static final int CONSTRUCTOR', <<<EOT
/**
* Identifier uniquely determining type of the object.
*/
EOT
);
$this->addDocumentation(' public int getConstructor() {', <<<EOT
/**
* @return this.CONSTRUCTOR
*/
EOT
);
}
protected function addAbstractClassDocumentation($class_name, $documentation)
{
$this->addDocumentation(" public abstract static class $class_name extends Object {", <<<EOT
/**
* This class is an abstract base class.
* $documentation
*/
EOT
);
}
protected function getFunctionReturnTypeDescription($return_type, $for_constructor)
{
$shift = $for_constructor ? ' ' : ' ';
return PHP_EOL.$shift.'*'.PHP_EOL.$shift."* <p> Returns {@link $return_type $return_type} </p>";
}
protected function addClassDocumentation($class_name, $base_class_name, $description)
{
$this->addDocumentation(" public static class $class_name extends $base_class_name {", <<<EOT
/**
* $description
*/
EOT
);
}
protected function addFieldDocumentation($class_name, $field_name, $type_name, $field_info, $may_be_null)
{
$full_line = $class_name." public $type_name $field_name;";
$this->addDocumentation($full_line, <<<EOT
/**
* $field_info
*/
EOT
);
if ($may_be_null && $this->nullable_annotation && ($this->java_version >= 8 || substr($type_name, -1) != ']')) {
$this->addLineReplacement($full_line, " $this->nullable_annotation public $type_name $field_name;".PHP_EOL);
}
}
protected function addDefaultConstructorDocumentation($class_name, $class_description)
{
$this->addDocumentation(" public $class_name() {", <<<EOT
/**
* $class_description
*/
EOT
);
}
protected function addFullConstructorDocumentation($class_name, $class_description, $known_fields, $info)
{
$full_constructor = " public $class_name(";
$colon = '';
foreach ($known_fields as $name => $type) {
$full_constructor .= $colon.$this->getTypeName($type).' '.$this->getFieldName($name, $class_name);
$colon = ', ';
}
$full_constructor .= ') {';
$full_doc = <<<EOT
/**
* $class_description
*
EOT;
foreach ($known_fields as $name => $type) {
$full_doc .= ' * @param '.$this->getFieldName($name, $class_name).' '.$info[$name].PHP_EOL;
}
$full_doc .= ' */';
$this->addDocumentation($full_constructor, $full_doc);
}
public function __construct($nullable_type, $nullable_annotation, $java_version) {
$this->nullable_type = trim($nullable_type);
$this->nullable_annotation = trim($nullable_annotation);
$this->java_version = intval($java_version);
}
}
$nullable_type = isset($argv[3]) ? $argv[3] : '';
$nullable_annotation = isset($argv[4]) ? $argv[4] : '';
$java_version = isset($argv[5]) ? intval($argv[5]) : 7;
$generator = new JavadocTlDocumentationGenerator($nullable_type, $nullable_annotation, $java_version);
$generator->generate($argv[1], $argv[2]);

View file

@ -0,0 +1,323 @@
<?php
abstract class TlDocumentationGenerator
{
private $current_line = '';
private $documentation = array();
private $line_replacement = array();
final protected function printError($error)
{
fwrite(STDERR, "$error near line \"".rtrim($this->current_line)."\"\n");
}
final protected function addDocumentation($code, $doc) {
if (isset($this->documentation[$code])) {
$this->printError("Duplicate documentation for \"$code\"");
}
$this->documentation[$code] = $doc;
// $this->printError($code);
}
final protected function addLineReplacement($line, $new_line) {
if (isset($this->line_replacement[$line])) {
$this->printError("Duplicate line replacement for \"$line\"");
}
$this->line_replacement[$line] = $new_line;
}
final protected function addDot($str) {
if (!$str) {
return '';
}
$len = strlen($str);
if ($str[$len - 1] === '.') {
return $str;
}
if ($str[$len - 1] === ')') {
// trying to place dot inside the brackets
$bracket_count = 1;
for ($pos = $len - 2; $pos >= 0; $pos--) {
if ($str[$pos] === ')') {
$bracket_count++;
}
if ($str[$pos] === '(') {
$bracket_count--;
if ($bracket_count === 0) {
break;
}
}
}
if ($bracket_count === 0) {
if (ctype_upper($str[$pos + 1])) {
return substr($str, 0, -1).'.)';
}
} else {
$this->printError("Unmatched bracket");
}
}
return $str.'.';
}
abstract protected function escapeDocumentation($doc);
abstract protected function getFieldName($name, $class_name);
abstract protected function getClassName($name);
abstract protected function getTypeName($type);
abstract protected function getBaseClassName($is_function);
abstract protected function needRemoveLine($line);
abstract protected function needSkipLine($line);
abstract protected function isHeaderLine($line);
abstract protected function extractClassName($line);
abstract protected function fixLine($line);
abstract protected function addGlobalDocumentation();
abstract protected function addAbstractClassDocumentation($class_name, $value);
abstract protected function getFunctionReturnTypeDescription($return_type, $for_constructor);
abstract protected function addClassDocumentation($class_name, $base_class_name, $description);
abstract protected function addFieldDocumentation($class_name, $field_name, $type_name, $field_info, $may_be_null);
abstract protected function addDefaultConstructorDocumentation($class_name, $class_description);
abstract protected function addFullConstructorDocumentation($class_name, $class_description, $known_fields, $info);
public function generate($tl_scheme_file, $source_file)
{
$lines = array_filter(array_map('trim', file($tl_scheme_file)));
$description = '';
$current_class = '';
$is_function = false;
$need_class_description = false;
$this->addGlobalDocumentation();
foreach ($lines as $line) {
$this->current_line = $line;
if ($line === '---types---') {
$is_function = false;
} elseif ($line === '---functions---') {
$is_function = true;
$current_class = '';
$need_class_description = false;
} elseif ($line[0] === '/') {
if ($line[1] !== '/') {
$this->printError('Wrong comment');
continue;
}
if ($line[2] === '@' || $line[2] === '-') {
$description .= trim(substr($line, 2 + intval($line[2] === '-'))).' ';
} else {
$this->printError('Unexpected comment');
}
} elseif (strpos($line, '? =') || strpos($line, ' = Vector t;') || $line === 'boolFalse = Bool;' ||
$line === 'boolTrue = Bool;' || $line === 'bytes = Bytes;' || $line === 'int32 = Int32;' ||
$line === 'int53 = Int53;'|| $line === 'int64 = Int64;') {
// skip built-in types
continue;
} else {
$description = trim($description);
if ($description[0] !== '@') {
$this->printError('Wrong description begin');
}
$docs = explode('@', $description);
array_shift($docs);
$info = array();
foreach ($docs as $doc) {
list($key, $value) = explode(' ', $doc, 2);
$value = trim($value);
if ($need_class_description) {
if ($key === 'description') {
$need_class_description = false;
$value = $this->escapeDocumentation($this->addDot($value));
$this->addAbstractClassDocumentation($current_class, $value);
continue;
} else {
$this->printError('Expected abstract class description');
}
}
if ($key === 'class') {
$current_class = $this->getClassName($value);
$need_class_description = true;
if ($is_function) {
$this->printError('Unexpected class definition');
}
} else {
if (isset($info[$key])) {
$this->printError("Duplicate info about `$key`");
}
$info[$key] = trim($value);
}
}
if (substr_count($line, '=') !== 1) {
$this->printError("Wrong '=' count");
continue;
}
list($fields, $type) = explode('=', $line);
$type = $this->getClassName($type);
$fields = explode(' ', trim($fields));
$class_name = $this->getClassName(array_shift($fields));
if ($type !== $current_class) {
$current_class = '';
$need_class_description = false;
}
if (!$is_function) {
$type_lower = strtolower($type);
$class_name_lower = strtolower($class_name);
if (empty($current_class) === ($type_lower !== $class_name_lower)) {
$this->printError('Wrong constructor name');
}
if (strpos($class_name_lower, $type_lower) !== 0) {
// $this->printError('Wrong constructor name');
}
}
$known_fields = array();
foreach ($fields as $field) {
list ($field_name, $field_type) = explode(':', $field);
if (isset($info['param_'.$field_name])) {
$known_fields['param_'.$field_name] = $field_type;
continue;
}
if (isset($info[$field_name])) {
$known_fields[$field_name] = $field_type;
continue;
}
$this->printError("Have no info about field `$field_name`");
}
foreach ($info as $name => $value) {
if (!$value) {
$this->printError("info[$name] for $class_name is empty");
} elseif (($value[0] < 'A' || $value[0] > 'Z') && ($value[0] < '0' || $value[0] > '9')) {
$this->printError("info[$name] for $class_name doesn't begins with capital letter");
}
}
foreach (array_diff_key($info, $known_fields) as $field_name => $field_info) {
if ($field_name !== 'description') {
$this->printError("Have info about unexisted field `$field_name`");
}
}
if (!$info['description']) {
$this->printError("Have no description for class `$class_name`");
}
foreach ($info as &$v) {
$v = $this->escapeDocumentation($this->addDot($v));
}
$base_class_name = $current_class ?: $this->getBaseClassName($is_function);
$class_description = $info['description'];
if ($is_function) {
$class_description .= $this->getFunctionReturnTypeDescription($this->getTypeName($type), false);
}
$this->addClassDocumentation($class_name, $base_class_name, $class_description);
foreach ($known_fields as $name => $field_type) {
$may_be_null = stripos($info[$name], 'may be null') !== false;
$field_name = $this->getFieldName($name, $class_name);
$field_type_name = $this->getTypeName($field_type);
$this->addFieldDocumentation($class_name, $field_name, $field_type_name, $info[$name], $may_be_null);
}
if ($is_function) {
$default_constructor_prefix = 'Default constructor for a function, which ';
$full_constructor_prefix = 'Creates a function, which ';
$class_description = lcfirst($info['description']);
$class_description .= $this->getFunctionReturnTypeDescription($this->getTypeName($type), true);
} else {
$default_constructor_prefix = '';
$full_constructor_prefix = '';
}
$this->addDefaultConstructorDocumentation($class_name, $default_constructor_prefix.$class_description);
if ($known_fields) {
$this->addFullConstructorDocumentation($class_name, $full_constructor_prefix.$class_description, $known_fields, $info);
}
$description = '';
}
}
$lines = file($source_file);
$result = '';
$current_class = '';
$current_headers = '';
foreach ($lines as $line) {
$this->current_line = $line;
if ($this->needRemoveLine($line)) {
continue;
}
if ($this->needSkipLine($line)) {
$result .= $current_headers.$line;
$current_headers = '';
continue;
}
if ($this->isHeaderLine($line)) {
$current_headers .= $line;
continue;
}
$current_class = $this->extractClassName($line) ?: $current_class;
$fixed_line = rtrim($this->fixLine($line));
$doc = '';
if (isset($this->documentation[$fixed_line])) {
$doc = $this->documentation[$fixed_line];
// unset($this->documentation[$fixed_line]);
} elseif (isset($this->documentation[$current_class.$fixed_line])) {
$doc = $this->documentation[$current_class.$fixed_line];
// unset($this->documentation[$current_class.$fixed_line]);
} else {
$this->printError('Have no docs for "'.$fixed_line.'"');
}
if ($doc) {
$result .= $doc."\n";
}
if (isset($this->line_replacement[$fixed_line])) {
$line = $this->line_replacement[$fixed_line];
} elseif (isset($this->line_replacement[$current_class.$fixed_line])) {
$line = $this->line_replacement[$current_class.$fixed_line];
}
$result .= $current_headers.$line;
$current_headers = '';
}
if (file_get_contents($source_file) !== $result) {
file_put_contents($source_file, $result);
}
if (count($this->documentation)) {
// $this->printError('Have unused docs '.print_r(array_keys($this->documentation), true));
}
}
}

View file

@ -0,0 +1,83 @@
/*
This file is part of TON Blockchain source code.
TON Blockchain is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
TON Blockchain is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with TON Blockchain. If not, see <http://www.gnu.org/licenses/>.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
You must obey the GNU General Public License in all respects for all
of the code used other than OpenSSL. If you modify file(s) with this
exception, you may extend this exception to your version of the file(s),
but you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tl_writer_cpp.h"
#include "tl_writer_h.h"
#include "tl_writer_hpp.h"
#include "tl_writer_jni_h.h"
#include "tl_writer_jni_cpp.h"
#include "tl_json_converter.h"
#include "td/tl/tl_config.h"
#include "td/tl/tl_generate.h"
#include <string>
#include <vector>
template <class WriterCpp = td::TD_TL_writer_cpp, class WriterH = td::TD_TL_writer_h,
class WriterHpp = td::TD_TL_writer_hpp>
static void generate_cpp(const std::string &directory, const std::string &tl_name, const std::string &string_type,
const std::string &bytes_type, const std::string &secure_string_type,
const std::string &secure_bytes_type, const std::vector<std::string> &ext_cpp_includes,
const std::vector<std::string> &ext_h_includes) {
std::string path = directory + "/" + tl_name;
td::tl::tl_config config = td::tl::read_tl_config_from_file("scheme/" + tl_name + ".tlo");
td::tl::write_tl_to_file(
config, path + ".cpp",
WriterCpp(tl_name, string_type, bytes_type, secure_string_type, secure_bytes_type, ext_cpp_includes));
td::tl::write_tl_to_file(
config, path + ".h",
WriterH(tl_name, string_type, bytes_type, secure_string_type, secure_bytes_type, ext_h_includes));
td::tl::write_tl_to_file(config, path + ".hpp",
WriterHpp(tl_name, string_type, bytes_type, secure_string_type, secure_bytes_type));
}
int main() {
generate_cpp("auto/tl", "ton_api", "std::string", "td::BufferSlice", "std::string", "td::BufferSlice",
{"\"tl/tl_object_parse.h\"", "\"tl/tl_object_store.h\"", "\"td/utils/int_types.h\"",
"\"crypto/common/bitstring.h\""},
{"<string>", "\"td/utils/buffer.h\"", "\"crypto/common/bitstring.h\""});
generate_cpp("auto/tl", "lite_api", "std::string", "td::BufferSlice", "std::string", "td::BufferSlice",
{"\"tl/tl_object_parse.h\"", "\"tl/tl_object_store.h\"", "\"td/utils/int_types.h\"",
"\"crypto/common/bitstring.h\""},
{"<string>", "\"td/utils/buffer.h\"", "\"crypto/common/bitstring.h\""});
td::gen_json_converter(td::tl::read_tl_config_from_file("scheme/ton_api.tlo"), "auto/tl/ton_api_json", "ton_api");
#ifdef TONLIB_ENABLE_JNI
generate_cpp<td::TD_TL_writer_jni_cpp, td::TD_TL_writer_jni_h>(
"auto/tl", "tonlib_api", "std::string", "std::string", "td::SecureString", "td::SecureString",
{"\"tl/tl_jni_object.h\"", "\"tl/tl_object_store.h\"", "\"td/utils/int_types.h\""},
{"<string>", "\"td/utils/SharedSlice.h\""});
#else
generate_cpp<>("auto/tl", "tonlib_api", "std::string", "std::string", "td::SecureString", "td::SecureString",
{"\"tl/tl_object_parse.h\"", "\"tl/tl_object_store.h\"", "\"td/utils/int_types.h\""},
{"<string>", "\"td/utils/SharedSlice.h\""});
#endif
td::gen_json_converter(td::tl::read_tl_config_from_file("scheme/tonlib_api.tlo"), "auto/tl/tonlib_api_json",
"tonlib_api");
}

View file

@ -0,0 +1,50 @@
/*
This file is part of TON Blockchain source code.
TON Blockchain is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
TON Blockchain is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with TON Blockchain. If not, see <http://www.gnu.org/licenses/>.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
You must obey the GNU General Public License in all respects for all
of the code used other than OpenSSL. If you modify file(s) with this
exception, you may extend this exception to your version of the file(s),
but you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tl_writer_java.h"
#include "td/tl/tl_config.h"
#include "td/tl/tl_generate.h"
#include <algorithm>
#include <string>
int main(int argc, char *argv[]) {
if (argc < 5) {
return 1;
}
std::string api_name = argv[1];
std::string source = argv[2];
std::string destination = argv[3];
std::string package = argv[4];
std::string package_name = package;
std::replace(package_name.begin(), package_name.end(), '/', '.');
destination += "/" + package + "/" + api_name + ".java";
td::tl::write_tl_to_file(td::tl::read_tl_config_from_file(source), destination,
td::TD_TL_writer_java(api_name, package_name));
}

View file

@ -0,0 +1,73 @@
int ? = Int;
long ? = Long;
double ? = Double;
string ? = String;
object ? = Object;
function ? = Function;
bytes data:string = Bytes;
true = True;
boolTrue = Bool;
boolFalse = Bool;
vector {t:Type} # [ t ] = Vector t;
int128 4*[ int ] = Int128;
int256 8*[ int ] = Int256;
tonNode.blockId workchain:int shard:long seqno:int = tonNode.BlockId;
tonNode.blockIdExt workchain:int shard:long seqno:int root_hash:int256 file_hash:int256 = tonNode.BlockIdExt;
tonNode.zeroStateIdExt workchain:int root_hash:int256 file_hash:int256 = tonNode.ZeroStateIdExt;
adnl.message.query query_id:int256 query:bytes = adnl.Message;
adnl.message.answer query_id:int256 answer:bytes = adnl.Message;
liteServer.error code:int message:string = liteServer.Error;
liteServer.accountId workchain:int id:int256 = liteServer.AccountId;
liteServer.masterchainInfo last:tonNode.blockIdExt state_root_hash:int256 init:tonNode.zeroStateIdExt = liteServer.MasterchainInfo;
liteServer.currentTime now:int = liteServer.CurrentTime;
liteServer.version mode:# version:int capabilities:long now:int = liteServer.Version;
liteServer.blockData id:tonNode.blockIdExt data:bytes = liteServer.BlockData;
liteServer.blockState id:tonNode.blockIdExt root_hash:int256 file_hash:int256 data:bytes = liteServer.BlockState;
liteServer.blockHeader id:tonNode.blockIdExt mode:# header_proof:bytes = liteServer.BlockHeader;
liteServer.sendMsgStatus status:int = liteServer.SendMsgStatus;
liteServer.accountState id:tonNode.blockIdExt shardblk:tonNode.blockIdExt shard_proof:bytes proof:bytes state:bytes = liteServer.AccountState;
liteServer.shardInfo id:tonNode.blockIdExt shardblk:tonNode.blockIdExt shard_proof:bytes shard_descr:bytes = liteServer.ShardInfo;
liteServer.allShardsInfo id:tonNode.blockIdExt proof:bytes data:bytes = liteServer.AllShardsInfo;
liteServer.transactionInfo id:tonNode.blockIdExt proof:bytes transaction:bytes = liteServer.TransactionInfo;
liteServer.transactionList ids:(vector tonNode.blockIdExt) transactions:bytes = liteServer.TransactionList;
liteServer.transactionId mode:# account:mode.0?int256 lt:mode.1?long hash:mode.2?int256 = liteServer.TransactionId;
liteServer.transactionId3 account:int256 lt:long = liteServer.TransactionId3;
liteServer.blockTransactions id:tonNode.blockIdExt req_count:# incomplete:Bool ids:(vector liteServer.transactionId) proof:bytes = liteServer.BlockTransactions;
liteServer.signature node_id_short:int256 signature:bytes = liteServer.Signature;
liteServer.signatureSet validator_set_hash:int catchain_seqno:int signatures:(vector liteServer.signature) = liteServer.SignatureSet;
liteServer.blockLinkBack to_key_block:Bool from:tonNode.blockIdExt to:tonNode.blockIdExt dest_proof:bytes shard_proof:bytes proof:bytes = liteServer.BlockLink;
liteServer.blockLinkForward to_key_block:Bool from:tonNode.blockIdExt to:tonNode.blockIdExt dest_proof:bytes config_proof:bytes signatures:liteServer.signatureSet = liteServer.BlockLink;
liteServer.partialBlockProof complete:Bool from:tonNode.blockIdExt to:tonNode.blockIdExt steps:(vector liteServer.BlockLink) = liteServer.PartialBlockProof;
liteServer.configInfo mode:# id:tonNode.blockIdExt state_proof:bytes config_proof:bytes = liteServer.ConfigInfo;
liteServer.debug.verbosity value:int = liteServer.debug.Verbosity;
---functions---
liteServer.getMasterchainInfo = liteServer.MasterchainInfo;
liteServer.getTime = liteServer.CurrentTime;
liteServer.getVersion = liteServer.Version;
liteServer.getBlock id:tonNode.blockIdExt = liteServer.BlockData;
liteServer.getState id:tonNode.blockIdExt = liteServer.BlockState;
liteServer.getBlockHeader id:tonNode.blockIdExt mode:# = liteServer.BlockHeader;
liteServer.sendMessage body:bytes = liteServer.SendMsgStatus;
liteServer.getAccountState id:tonNode.blockIdExt account:liteServer.accountId = liteServer.AccountState;
liteServer.getShardInfo id:tonNode.blockIdExt workchain:int shard:long exact:Bool = liteServer.ShardInfo;
liteServer.getAllShardsInfo id:tonNode.blockIdExt = liteServer.AllShardsInfo;
liteServer.getOneTransaction id:tonNode.blockIdExt account:liteServer.accountId lt:long = liteServer.TransactionInfo;
liteServer.getTransactions count:# account:liteServer.accountId lt:long hash:int256 = liteServer.TransactionList;
liteServer.lookupBlock mode:# id:tonNode.blockId lt:mode.1?long utime:mode.2?int = liteServer.BlockHeader;
liteServer.listBlockTransactions id:tonNode.blockIdExt mode:# count:# after:mode.7?liteServer.transactionId3 reverse_order:mode.6?true want_proof:mode.5?true = liteServer.BlockTransactions;
liteServer.getBlockProof mode:# known_block:tonNode.blockIdExt target_block:mode.0?tonNode.blockIdExt = liteServer.PartialBlockProof;
liteServer.getConfigAll mode:# id:tonNode.blockIdExt = liteServer.ConfigInfo;
liteServer.getConfigParams mode:# id:tonNode.blockIdExt param_list:(vector int) = liteServer.ConfigInfo;
liteServer.query data:bytes = Object;

Binary file not shown.

View file

@ -0,0 +1,553 @@
int ? = Int;
long ? = Long;
double ? = Double;
string ? = String;
object ? = Object;
function ? = Function;
bytes data:string = Bytes;
true = True;
boolTrue = Bool;
boolFalse = Bool;
vector {t:Type} # [ t ] = Vector t;
int128 4*[ int ] = Int128;
int256 8*[ int ] = Int256;
testObject value:int o:object f:function = TestObject;
testString value:string = TestObject;
testInt value:int = TestObject;
testVectorBytes value:(vector bytes) = TestObject;
tcp.pong random_id:long = tcp.Pong;
tcp.authentificate nonce:bytes = tcp.Message;
tcp.authentificationNonce nonce:bytes = tcp.Message;
tcp.authentificationComplete key:PublicKey signature:bytes = tcp.Message;
fec.raptorQ data_size:int symbol_size:int symbols_count:int = fec.Type;
fec.roundRobin data_size:int symbol_size:int symbols_count:int = fec.Type;
fec.online data_size:int symbol_size:int symbols_count:int = fec.Type;
---functions---
tcp.ping random_id:long = tcp.Pong;
getTestObject = TestObject;
---types---
pk.unenc data:bytes = PrivateKey;
pk.ed25519 key:int256 = PrivateKey;
pk.aes key:int256 = PrivateKey;
pk.overlay name:bytes = PrivateKey;
pub.unenc data:bytes = PublicKey;
pub.ed25519 key:int256 = PublicKey;
pub.aes key:int256 = PublicKey;
pub.overlay name:bytes = PublicKey;
---functions---
---types---
adnl.id.short id:int256 = adnl.id.Short;
adnl.proxyToFastHash ip:int port:int date:int data_hash:int256 shared_secret:int256 = adnl.ProxyTo;
adnl.proxyToFast ip:int port:int date:int signature:int256 = adnl.ProxyToSign;
adnl.proxy.none = adnl.Proxy;
adnl.proxy.fast shared_secret:bytes = adnl.Proxy;
adnl.address.udp ip:int port:int = adnl.Address;
adnl.address.udp6 ip:int128 port:int = adnl.Address;
//adnl.address.tcp ip:int port:int = adnl.Address;
//adnl.address.tcp6 ip:int128 port:int = adnl.Address;
//adnl.address.tunnel to:adnl.Address tunid: = adnl.Address;
adnl.addressList addrs:(vector adnl.Address) version:int reinit_date:int priority:int expire_at:int = adnl.AddressList;
adnl.node id:PublicKey addr_list:adnl.addressList = adnl.Node;
adnl.nodes nodes:(vector adnl.node) = adnl.Nodes;
---functions---
---types---
adnl.packetContents
rand1:bytes
flags:#
from:flags.0?PublicKey
from_short:flags.1?adnl.id.short
message:flags.2?adnl.Message
messages:flags.3?(vector adnl.Message)
address:flags.4?adnl.addressList
priority_address:flags.5?adnl.addressList
seqno:flags.6?long
confirm_seqno:flags.7?long
recv_addr_list_version:flags.8?int
recv_priority_addr_list_version:flags.9?int
reinit_date:flags.10?int
dst_reinit_date:flags.10?int
signature:flags.11?bytes
rand2:bytes
= adnl.PacketContents;
adnl.message.createChannel key:int256 date:int = adnl.Message;
adnl.message.confirmChannel key:int256 peer_key:int256 date:int = adnl.Message;
adnl.message.custom data:bytes = adnl.Message;
adnl.message.nop = adnl.Message;
adnl.message.reinit date:int = adnl.Message;
adnl.message.query query_id:int256 query:bytes = adnl.Message;
adnl.message.answer query_id:int256 answer:bytes = adnl.Message;
adnl.message.part hash:int256 total_size:int offset:int data:bytes = adnl.Message;
---functions---
---types---
adnl.db.node.key local_id:int256 peer_id:int256 = adnl.db.Key;
adnl.db.node.value date:int id:PublicKey addr_list:adnl.addressList priority_addr_list:adnl.addressList = adnl.db.node.Value;
---functions---
---types---
rldp.messagePart transfer_id:int256 fec_type:fec.Type part:int total_size:long seqno:int data:bytes = rldp.MessagePart;
rldp.confirm transfer_id:int256 part:int seqno:int = rldp.MessagePart;
rldp.complete transfer_id:int256 part:int = rldp.MessagePart;
rldp.message id:int256 data:bytes = rldp.Message;
rldp.query query_id:int256 max_answer_size:long timeout:int data:bytes = rldp.Message;
rldp.answer query_id:int256 data:bytes = rldp.Message;
---functions---
---types---
dht.node id:PublicKey addr_list:adnl.addressList version:int signature:bytes = dht.Node;
dht.nodes nodes:(vector dht.node) = dht.Nodes;
dht.key id:int256 name:bytes idx:int = dht.Key;
dht.updateRule.signature = dht.UpdateRule;
dht.updateRule.anybody = dht.UpdateRule;
dht.updateRule.overlayNodes = dht.UpdateRule;
dht.keyDescription key:dht.key id:PublicKey update_rule:dht.UpdateRule signature:bytes = dht.KeyDescription;
dht.value key:dht.keyDescription value:bytes ttl:int signature:bytes = dht.Value;
dht.pong random_id:long = dht.Pong;
dht.valueNotFound nodes:dht.nodes = dht.ValueResult;
dht.valueFound value:dht.Value = dht.ValueResult;
dht.stored = dht.Stored;
dht.message node:dht.node = dht.Message;
dht.db.bucket nodes:dht.nodes = dht.db.Bucket;
dht.db.key.bucket id:int = dht.db.Key;
---functions---
dht.ping random_id:long = dht.Pong;
dht.store value:dht.value = dht.Stored;
dht.findNode key:int256 k:int = dht.Nodes;
dht.findValue key:int256 k:int = dht.ValueResult;
dht.getSignedAddressList = dht.Node;
dht.query node:dht.node = True;
---types---
overlay.node.toSign id:adnl.id.short overlay:int256 version:int = overlay.node.ToSign;
overlay.node id:PublicKey overlay:int256 version:int signature:bytes = overlay.Node;
overlay.nodes nodes:(vector overlay.node) = overlay.Nodes;
overlay.message overlay:int256 = overlay.Message;
//overlay.randomPeers peers:(vector adnl.node) = overlay.RandomPeers;
overlay.broadcastList hashes:(vector int256) = overlay.BroadcastList;
overlay.fec.received hash:int256 = overlay.Broadcast;
overlay.fec.completed hash:int256 = overlay.Broadcast;
overlay.broadcast.id src:int256 data_hash:int256 flags:int = overlay.broadcast.Id;
overlay.broadcastFec.id src:int256 type:int256 data_hash:int256 size:int flags:int = overlay.broadcastFec.Id;
overlay.broadcastFec.partId broadcast_hash:int256 data_hash:int256 seqno:int = overlay.broadcastFec.PartId;
overlay.broadcast.toSign hash:int256 date:int = overlay.broadcast.ToSign;
overlay.certificate issued_by:PublicKey expire_at:int max_size:int signature:bytes = overlay.Certificate;
overlay.emptyCertificate = overlay.Certificate;
overlay.certificateId overlay_id:int256 node:int256 expire_at:int max_size:int = overlay.CertificateId;
overlay.unicast data:bytes = overlay.Broadcast;
overlay.broadcast src:PublicKey certificate:overlay.Certificate flags:int data:bytes date:int signature:bytes = overlay.Broadcast;
overlay.broadcastFec src:PublicKey certificate:overlay.Certificate data_hash:int256 data_size:int flags:int
data:bytes seqno:int fec:fec.Type date:int signature:bytes = overlay.Broadcast;
overlay.broadcastFecShort src:PublicKey certificate:overlay.Certificate broadcast_hash:int256 part_data_hash:int256 seqno:int signature:bytes = overlay.Broadcast;
overlay.broadcastNotFound = overlay.Broadcast;
---functions---
overlay.getRandomPeers peers:overlay.nodes = overlay.Nodes;
overlay.query overlay:int256 = True;
overlay.getBroadcast hash:int256 = overlay.Broadcast;
overlay.getBroadcastList list:overlay.broadcastList = overlay.BroadcastList;
---types---
overlay.db.nodes nodes:overlay.nodes = overlay.db.Nodes;
overlay.db.key.nodes local_id:int256 overlay:int256 = overlay.db.Key;
---functions---
---types---
catchain.block.id incarnation:int256 src:int256 height:int data_hash:int256 = catchain.block.Id;
catchain.block.dep src:int height:int data_hash:int256 signature:bytes = catchain.block.Dep;
catchain.block.data prev:catchain.block.dep deps:(vector catchain.block.dep) = catchain.block.Data;
catchain.block incarnation:int256 src:int height:int data:catchain.block.data signature:bytes = catchain.Block;
catchain.blocks blocks:(vector catchain.block) = catchain.Blocks;
catchain.blockUpdate block:catchain.block = catchain.Update;
catchain.block.data.badBlock block:catchain.block = catchain.block.inner.Data;
catchain.block.data.fork left:catchain.block.Dep right:catchain.block.Dep = catchain.block.inner.Data;
catchain.block.data.nop = catchain.block.inner.Data;
catchain.block.data.vector msgs:(vector bytes) = catchain.block.inner.Data;
//catchain.block.data.custom = catchain.block.inner.Data;
catchain.firstblock unique_hash:int256 nodes:(vector int256) = catchain.FirstBlock;
catchain.difference sent_upto:(vector int) = catchain.Difference;
catchain.differenceFork left:catchain.block.dep right:catchain.block.dep = catchain.Difference;
catchain.blockNotFound = catchain.BlockResult;
catchain.blockResult block:catchain.block = catchain.BlockResult;
catchain.sent cnt:int = catchain.Sent;
---functions---
catchain.getBlock block:int256 = catchain.BlockResult;
catchain.getBlocks blocks:(vector int256) = catchain.Sent;
catchain.getDifference rt:(vector int) = catchain.Difference;
catchain.getBlockHistory block:int256 height:long stop_if:(vector int256) = catchain.Sent;
//catchain.getForkDifference src:int fork:catchain.fork = catchain.ForkDifference;
---types---
validatorSession.round.id session:int256 height:long prev_block:int256 seqno:int = validatorSession.round.Id;
validatorSession.candidate.id round:int256 block_hash:int256 = validatorSession.tempBlock.Id;
validatorSession.message.startSession = validatorSession.Message;
validatorSession.message.finishSession = validatorSession.Message;
validatorSession.message.submittedBlock round:int root_hash:int256 file_hash:int256
collated_data_file_hash:int256 = validatorSession.round.Message;
validatorSession.message.approvedBlock round:int candidate:int256 signature:bytes = validatorSession.round.Message;
validatorSession.message.rejectedBlock round:int candidate:int256 reason:bytes = validatorSession.round.Message;
validatorSession.message.commit round:int candidate:int256 signature:bytes = validatorSession.round.Message;
validatorSession.message.vote round:int attempt:int candidate:int256 = validatorSession.round.Message;
validatorSession.message.voteFor round:int attempt:int candidate:int256 = validatorSession.round.Message;
validatorSession.message.precommit round:int attempt:int candidate:int256 = validatorSession.round.Message;
validatorSession.message.empty round:int attempt:int = validatorSession.round.Message;
validatorSession.pong hash:long = validatorSession.Pong;
validatorSession.candidateId src:int256 root_hash:int256 file_hash:int256 collated_data_file_hash:int256 = validatorSession.CandidateId;
validatorSession.blockUpdate ts:long actions:(vector validatorSession.round.Message) state:int = validatorSession.BlockUpdate;
validatorSession.candidate src:int256 round:int root_hash:int256 data:bytes collated_data:bytes = validatorSession.Candidate;
validatorSession.config catchain_idle_timeout:double catchain_max_deps:int round_candidates:int next_candidate_delay:double round_attempt_duration:int
max_round_attempts:int max_block_size:int max_collated_data_size:int = validatorSession.Config;
---functions---
validatorSession.ping hash:long = validatorSession.Pong;
validatorSession.downloadCandidate round:int id:validatorSession.candidateId = validatorSession.Candidate;
---types---
hashable.bool value:Bool = Hashable;
hashable.int32 value:int = Hashable;
hashable.int64 value:long = Hashable;
hashable.int256 value:int256 = Hashable;
hashable.bytes value:bytes = Hashable;
hashable.pair left:int right:int = Hashable;
hashable.vector value:(vector int) = Hashable;
hashable.validatorSessionOldRound seqno:int block:int signatures:int approve_signatures:int = Hashable;
hashable.validatorSessionRoundAttempt seqno:int votes:int precommitted:int vote_for_inited:int vote_for:int = Hashable;
hashable.validatorSessionRound locked_round:int locked_block:int seqno:int precommitted:Bool
first_attempt:int approved_blocks:int signatures:int attempts:int = Hashable;
hashable.blockSignature signature:int = Hashable;
hashable.sentBlock src:int root_hash:int file_hash:int collated_data_file_hash:int = Hashable;
hashable.sentBlockEmpty = Hashable;
hashable.vote block:int node:int = Hashable;
hashable.blockCandidate block:int approved:int = Hashable;
hashable.blockVoteCandidate block:int approved:int = Hashable;
hashable.blockCandidateAttempt block:int votes:int = Hashable;
hashable.cntVector data:int = Hashable;
hashable.cntSortedVector data:int = Hashable;
hashable.validatorSession ts:int old_rounds:int cur_round:int = Hashable;
---functions---
---types---
tonNode.sessionId workchain:int shard:long cc_seqno:int opts_hash:int256 = tonNode.SessionId;
tonNode.blockSignature who:int256 signature:bytes = tonNode.BlockSignature;
tonNode.blockId workchain:int shard:long seqno:int = tonNode.BlockId;
tonNode.blockIdExt workchain:int shard:long seqno:int root_hash:int256 file_hash:int256 = tonNode.BlockIdExt;
tonNode.zeroStateIdExt workchain:int root_hash:int256 file_hash:int256 = tonNode.ZeroStateIdExt;
tonNode.blockDescriptionEmpty = tonNode.BlockDescription;
tonNode.blockDescription id:tonNode.blockIdExt = tonNode.BlockDescription;
tonNode.preparedProofEmpty = tonNode.PreparedProof;
tonNode.preparedProof = tonNode.PreparedProof;
tonNode.preparedProofLink = tonNode.PreparedProof;
tonNode.preparedState = tonNode.PreparedState;
tonNode.notFoundState = tonNode.PreparedState;
tonNode.prepared = tonNode.Prepared;
tonNode.notFound = tonNode.Prepared;
tonNode.data data:bytes = tonNode.Data;
//tonNode.preparedKeyBlockProofEmpty = tonNode.PreparedKeyBlockProof;
//tonNode.preparedKeyBlockProof block_id:tonNode.blockIdExt = tonNode.PreparedKeyBlockProof;
tonNode.ihrMessage data:bytes = tonNode.IhrMessage;
tonNode.externalMessage data:bytes = tonNode.ExternalMessage;
tonNode.newShardBlock block:tonNode.blockIdExt cc_seqno:int data:bytes = tonNode.NewShardBlock;
tonNode.blockBroadcast id:tonNode.blockIdExt catchain_seqno:int validator_set_hash:int
signatures:(vector tonNode.blockSignature)
proof:bytes data:bytes = tonNode.Broadcast;
tonNode.ihrMessageBroadcast message:tonNode.ihrMessage = tonNode.Broadcast;
tonNode.externalMessageBroadcast message:tonNode.externalMessage = tonNode.Broadcast;
tonNode.newShardBlockBroadcast block:tonNode.newShardBlock = tonNode.Broadcast;
tonNode.shardPublicOverlayId workchain:int shard:long zero_state_file_hash:int256 = tonNode.ShardPublicOverlayId;
tonNode.keyBlocks blocks:(vector tonNode.blockIdExt) incomplete:Bool error:Bool = tonNode.KeyBlocks;
ton.blockId root_cell_hash:int256 file_hash:int256 = ton.BlockId;
ton.blockIdApprove root_cell_hash:int256 file_hash:int256 = ton.BlockId;
---functions---
tonNode.getNextBlockDescription prev_block:tonNode.blockIdExt = tonNode.BlockDescription;
tonNode.prepareBlockProof block:tonNode.blockIdExt allow_partial:Bool = tonNode.PreparedProof;
tonNode.prepareBlock block:tonNode.blockIdExt = tonNode.Prepared;
tonNode.preparePersistentState block:tonNode.blockIdExt masterchain_block:tonNode.blockIdExt = tonNode.PreparedState;
tonNode.prepareZeroState block:tonNode.blockIdExt = tonNode.PreparedState;
tonNode.getNextKeyBlockIds block:tonNode.blockIdExt max_size:int = tonNode.KeyBlocks;
tonNode.downloadBlock block:tonNode.blockIdExt = tonNode.Data;
tonNode.downloadPersistentState block:tonNode.blockIdExt masterchain_block:tonNode.blockIdExt = tonNode.Data;
tonNode.downloadZeroState block:tonNode.blockIdExt = tonNode.Data;
tonNode.downloadBlockProof block:tonNode.blockIdExt = tonNode.Data;
tonNode.downloadBlockProofLink block:tonNode.blockIdExt = tonNode.Data;
---types---
// bit 0 - started
// bit 1 - ready to switch
// bit 2 - switched from
// bit 3 - archived
// bit 4 - disabled
db.root.dbDescription version:int first_masterchain_block_id:tonNode.blockIdExt flags:int = db.root.DbDescription;
db.root.key.cellDb version:int = db.root.Key;
db.root.key.blockDb version:int = db.root.Key;
db.root.config celldb_version:int blockdb_version:int = db.root.Config;
db.root.key.config = db.root.Key;
db.celldb.value block_id:tonNode.blockIdExt prev:int256 next:int256 root_hash:int256 = db.celldb.Value;
db.celldb.key.value hash:int256 = db.celldb.key.Value;
db.block.info id:tonNode.blockIdExt flags:# prev_left:flags.1?tonNode.blockIdExt
prev_right:flags.2?tonNode.blockIdExt
next_left:flags.3?tonNode.blockIdExt
next_right:flags.4?tonNode.blockIdExt
lt:flags.13?long
ts:flags.14?int
state:flags.17?int256 = db.block.Info;
db.block.archivedInfo id:tonNode.blockIdExt flags:# next:flags.0?tonNode.blockIdExt = db.block.Info;
db.blockdb.value next:tonNode.blockIdExt data:bytes = db.blockdb.Value;
db.blockdb.lru id:tonNode.blockIdExt prev:int256 next:int256 = db.blockdb.Lru;
db.blockdb.key.lru id:tonNode.blockIdExt = db.blockdb.Key;
db.blockdb.key.value id:tonNode.blockIdExt = db.blockdb.Key;
db.candidate source:PublicKey id:tonNode.blockIdExt data:bytes collated_data:bytes = db.Candidate;
db.candidate.id source:PublicKey id:tonNode.blockIdExt collated_data_file_hash:int256 = db.candidate.Id;
db.filedb.key.empty = db.filedb.Key;
db.filedb.key.blockFile block_id:tonNode.blockIdExt = db.filedb.Key;
db.filedb.key.zeroStateFile block_id:tonNode.blockIdExt = db.filedb.Key;
db.filedb.key.persistentStateFile block_id:tonNode.blockIdExt masterchain_block_id:tonNode.blockIdExt = db.filedb.Key;
db.filedb.key.proof block_id:tonNode.blockIdExt = db.filedb.Key;
db.filedb.key.proofLink block_id:tonNode.blockIdExt = db.filedb.Key;
db.filedb.key.signatures block_id:tonNode.blockIdExt = db.filedb.Key;
db.filedb.key.candidate id:db.candidate.id = db.filedb.Key;
db.filedb.value key:db.filedb.Key prev:int256 next:int256 file_hash:int256 = db.filedb.Value;
db.state.destroyedSessions sessions:(vector int256) = db.state.DestroyedSessions;
db.state.initBlockId block:tonNode.blockIdExt = db.state.InitBlockId;
db.state.gcBlockId block:tonNode.blockIdExt = db.state.GcBlockId;
db.state.shardClient block:tonNode.blockIdExt = db.state.ShardClient;
db.state.asyncSerializer block:tonNode.blockIdExt last:tonNode.blockIdExt last_ts:int = db.state.AsyncSerializer;
db.state.key.destroyedSessions = db.state.Key;
db.state.key.initBlockId = db.state.Key;
db.state.key.gcBlockId = db.state.Key;
db.state.key.shardClient = db.state.Key;
db.state.key.asyncSerializer = db.state.Key;
db.lt.el.key workchain:int shard:long idx:int = db.lt.Key;
db.lt.desc.key workchain:int shard:long = db.lt.Key;
db.lt.shard.key idx:int = db.lt.Key;
db.lt.status.key = db.lt.Key;
db.lt.el.value id:tonNode.blockIdExt lt:long ts:int = db.lt.el.Value;
db.lt.desc.value first_idx:int last_idx:int last_seqno:int last_lt:long last_ts:int = db.lt.desc.Value;
db.lt.shard.value workchain:int shard:long = db.lt.shard.Value;
db.lt.status.value total_shards:int = db.lt.status.Value;
---functions---
---types---
validator.groupMember public_key_hash:int256 adnl:int256 weight:long = engine.validator.GroupMember;
validator.group workchain:int shard:long catchain_seqno:int config_hash:int256 members:(vector validator.groupMember) = validator.Group;
---functions---
---types---
id.config.local id:PrivateKey = id.config.Local;
dht.config.local id:adnl.id.short = dht.config.Local;
dht.config.random.local cnt:int = dht.config.Local;
liteserver.config.local id:PrivateKey port:int = liteserver.config.Local;
liteserver.config.random.local port:int = liteserver.config.Local;
validator.config.local id:adnl.id.short = validator.config.Local;
validator.config.random.local addr_list:adnl.addressList = validator.config.Local;
control.config.local priv:PrivateKey pub:int256 port:int = control.config.Local;
config.local local_ids:(vector id.config.local) dht:(vector dht.config.Local) validators:(vector validator.config.Local) liteservers:(vector liteserver.config.Local) control:(vector control.config.local) = config.Local;
dht.config.global static_nodes:dht.nodes k:int a:int = dht.config.Global;
adnl.config.global static_nodes:adnl.nodes = adnl.config.Global;
catchain.config.global tag:int256 nodes:(vector PublicKey) = catchain.config.Global;
dummyworkchain0.config.global zero_state_hash:int256 = dummyworkchain0.config.Global;
validator.config.global zero_state:tonNode.blockIdExt init_block:tonNode.blockIdExt hardforks:(vector tonNode.blockIdExt) = validator.config.Global;
config.global adnl:adnl.config.global dht:dht.config.global validator:validator.config.global = config.Global;
liteserver.desc id:PublicKey ip:int port:int = liteserver.Desc;
liteclient.config.global liteservers:(vector liteserver.desc) validator:validator.config.global = liteclient.config.Global;
engine.adnl id:int256 category:int = engine.Adnl;
engine.addr ip:int port:int categories:(vector int) priority_categories:(vector int) = engine.Addr;
engine.addrProxy in_ip:int in_port:int out_ip:int out_port:int
proxy_type:adnl.Proxy categories:(vector int) priority_categories:(vector int) = engine.Addr;
engine.dht id:int256 = engine.Dht;
engine.validatorTempKey key:int256 expire_at:int = engine.ValidatorTempKey;
engine.validatorAdnlAddress id:int256 expire_at:int = engine.ValidatorAdnlAddress;
engine.validator id:int256 temp_keys:(vector engine.validatorTempKey) adnl_addrs:(vector engine.validatorAdnlAddress) election_date:int expire_at:int = engine.Validator;
engine.liteServer id:int256 port:int = engine.LiteServer;
engine.controlProcess id:int256 permissions:int = engine.ControlProcess;
engine.controlInterface id:int256 port:int allowed:(vector engine.controlProcess) = engine.ControlInterface;
engine.gc ids:(vector int256) = engine.Gc;
engine.dht.config dht:(vector engine.dht) gc:engine.gc = engine.dht.Config;
engine.validator.config out_port:int addrs:(vector engine.Addr) adnl:(vector engine.adnl)
dht:(vector engine.dht)
validators:(vector engine.validator) fullnode:int256
liteservers:(vector engine.liteServer) control:(vector engine.controlInterface)
gc:engine.gc = engine.validator.Config;
---functions---
---types---
engine.adnlProxy.port in_port:int out_port:int dst_ip:int dst_port:int proxy_type:adnl.Proxy = engine.adnlProxy.Port;
engine.adnlProxy.config ports:(vector engine.adnlProxy.port) = engine.adnlProxy.Config;
---functions---
---types---
engine.validator.keyHash key_hash:int256 = engine.validator.KeyHash;
engine.validator.signature signature:bytes = engine.validator.Signature;
engine.validator.oneStat key:string value:string = engine.validator.OneStat;
engine.validator.stats stats:(vector engine.validator.oneStat) = engine.validator.Stats;
engine.validator.controlQueryError code:int message:string = engine.validator.ControlQueryError;
engine.validator.time time:int = engine.validator.Time;
engine.validator.success = engine.validator.Success;
engine.validator.jsonConfig data:string = engine.validator.JsonConfig;
engine.validator.electionBid election_date:int perm_key:int256 adnl_addr:int256 to_send_payload:bytes = engine.validator.ElectionBid;
---functions---
engine.validator.getTime = engine.validator.Time;
engine.validator.importPrivateKey key:PrivateKey = engine.validator.KeyHash;
engine.validator.exportPrivateKey key_hash:int256 = PrivateKey;
engine.validator.exportPublicKey key_hash:int256 = PublicKey;
engine.validator.generateKeyPair = engine.validator.KeyHash;
engine.validator.addAdnlId key_hash:int256 category:int = engine.validator.Success;
engine.validator.addDhtId key_hash:int256 = engine.validator.Success;
engine.validator.addValidatorPermanentKey key_hash:int256 election_date:int ttl:int = engine.validator.Success;
engine.validator.addValidatorTempKey permanent_key_hash:int256 key_hash:int256 ttl:int = engine.validator.Success;
engine.validator.addValidatorAdnlAddress permanent_key_hash:int256 key_hash:int256 ttl:int = engine.validator.Success;
engine.validator.changeFullNodeAdnlAddress adnl_id:int256 = engine.validator.Success;
engine.validator.addLiteserver key_hash:int256 port:int = engine.validator.Success;
engine.validator.addControlInterface key_hash:int256 port:int = engine.validator.Success;
engine.validator.addControlProcess key_hash:int256 port:int peer_key:int256 permissions:int = engine.validator.Success;
engine.validator.delAdnlId key_hash:int256 = engine.validator.Success;
engine.validator.delDhtId key_hash:int256 = engine.validator.Success;
engine.validator.delValidatorPermanentKey key_hash:int256 = engine.validator.Success;
engine.validator.delValidatorTempKey permanent_key_hash:int256 key_hash:int256 = engine.validator.Success;
engine.validator.delValidatorAdnlAddress permanent_key_hash:int256 key_hash:int256 = engine.validator.Success;
engine.validator.addListeningPort ip:int port:int categories:(vector int) priority_categories:(vector int) = engine.validator.Success;
engine.validator.addProxy in_ip:int in_port:int out_ip:int out_port:int proxy:adnl.Proxy categories:(vector int) priority_categories:(vector int) = engine.validator.Success;
engine.validator.delListeningPort ip:int port:int categories:(vector int) priority_categories:(vector int) = engine.validator.Success;
engine.validator.delProxy out_ip:int out_port:int categories:(vector int) priority_categories:(vector int) = engine.validator.Success;
engine.validator.sign key_hash:int256 data:bytes = engine.validator.Signature;
engine.validator.getStats = engine.validator.Stats;
engine.validator.getConfig = engine.validator.JsonConfig;
engine.validator.setVerbosity verbosity:int = engine.validator.Success;
engine.validator.createElectionBid election_date:int election_addr:string wallet:string = engine.validator.ElectionBid;
engine.validator.controlQuery data:bytes = Object;

Binary file not shown.

View file

@ -0,0 +1,89 @@
double ? = Double;
string ? = String;
int32 = Int32;
int53 = Int53;
int64 = Int64;
bytes = Bytes;
secureString = SecureString;
secureBytes = SecureBytes;
boolFalse = Bool;
boolTrue = Bool;
vector {t:Type} # [ t ] = Vector t;
error code:int32 message:string = Error;
ok = Ok;
options config:string keystore_directory:string = Options;
key public_key:bytes secret:secureBytes = Key;
inputKey key:key local_password:secureBytes = InputKey;
exportedKey word_list:vector<secureString> = ExportedKey;
exportedPemKey pem:secureString = ExportedPemKey;
exportedEncryptedKey data:secureBytes = ExportedEncryptedKey;
accountAddress account_address:string = AccountAddress;
internal.transactionId lt:int64 hash:bytes = internal.TransactionId;
raw.initialAccountState code:bytes data:bytes = raw.InitialAccountState;
raw.accountState balance:int64 code:bytes data:bytes last_transaction_id:internal.transactionId = raw.AccountState;
raw.message source:string destination:string value:int64 = raw.Message;
raw.transaction data:bytes previous_transaction_id:internal.transactionId fee:int64 in_msg:raw.message out_msgs:vector<raw.message> = raw.Transaction;
raw.transactions transactions:vector<raw.Transaction> = raw.Transactions;
testWallet.initialAccountState public_key:bytes = testWallet.InitialAccountState;
testWallet.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId = testWallet.AccountState;
testGiver.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId = testGiver.AccountState;
uninited.accountState balance:int64 = uninited.AccountState;
generic.initialAccountStateRaw initital_account_state:raw.initialAccountState = generic.InitialAccountState;
generic.initialAccountStateTestWallet initital_account_state:testWallet.initialAccountState = generic.InitialAccountState;
generic.accountStateRaw account_state:raw.accountState = generic.AccountState;
generic.accountStateTestWallet account_state:testWallet.accountState = generic.AccountState;
generic.accountStateTestGiver account_state:testGiver.accountState = generic.AccountState;
generic.accountStateUninited account_state:uninited.accountState = generic.AccountState;
---functions---
init options:options = Ok;
close = Ok;
options.setConfig config:string = Ok;
createNewKey local_password:secureBytes mnemonic_password:secureBytes = Key;
deleteKey public_key:bytes = Ok;
exportKey input_key:inputKey = ExportedKey;
exportPemKey input_key:inputKey key_password:secureBytes = ExportedPemKey;
exportEncryptedKey input_key:inputKey key_password:secureBytes = ExportedEncryptedKey;
importKey local_password:secureBytes mnemonic_password:secureBytes exported_key:exportedKey = Key;
importPemKey local_password:secureBytes key_password:secureBytes exported_key:exportedPemKey = Key;
importEncryptedKey local_password:secureBytes key_password:secureBytes exported_encrypted_key:exportedEncryptedKey = Key;
changeLocalPassword input_key:inputKey new_local_password:secureBytes = Key;
//raw.init initial_account_state:raw.initialAccountState = Ok;
raw.getAccountAddress initital_account_state:raw.initialAccountState = AccountAddress;
raw.getAccountState account_address:accountAddress = raw.AccountState;
raw.sendMessage destination:accountAddress initial_account_state:bytes data:bytes = Ok;
raw.getTransactions account_address:accountAddress from_transaction_id:internal.transactionId = raw.Transactions;
testWallet.init private_key:inputKey = Ok;
testWallet.getAccountAddress initital_account_state:testWallet.initialAccountState = AccountAddress;
testWallet.getAccountState account_address:accountAddress = testWallet.AccountState;
testWallet.sendGrams private_key:inputKey destination:accountAddress seqno:int32 amount:int64 = Ok;
testGiver.getAccountState = testGiver.AccountState;
testGiver.getAccountAddress = AccountAddress;
testGiver.sendGrams destination:accountAddress seqno:int32 amount:int64 = Ok;
//generic.getAccountAddress initital_account_state:generic.InitialAccountState = AccountAddress;
generic.getAccountState account_address:accountAddress = generic.AccountState;
generic.sendGrams private_key:inputKey source:accountAddress destination:accountAddress amount:int64 = Ok;
runTests dir:string = Ok;

Binary file not shown.

View file

@ -0,0 +1,5 @@
#!/bin/sh
cd $(dirname $0)
tl-parser -e ton_api.tlo ton_api.tl
tl-parser -e tonlib_api.tlo tonlib_api.tl
tl-parser -e lite_api.tlo lite_api.tl

View file

@ -0,0 +1,270 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tl_json_converter.h"
#include "td/tl/tl_simple.h"
#include "td/utils/buffer.h"
#include "td/utils/filesystem.h"
#include "td/utils/logging.h"
#include "td/utils/Slice.h"
#include "td/utils/StringBuilder.h"
#include <utility>
namespace td {
namespace {
std::string tl_name = "ton_api";
}
template <class T>
void gen_to_json_constructor(StringBuilder &sb, const T *constructor, bool is_header) {
sb << "void to_json(JsonValueScope &jv, "
<< "const " << tl_name << "::" << tl::simple::gen_cpp_name(constructor->name) << " &object)";
if (is_header) {
sb << ";\n";
return;
}
sb << " {\n";
sb << " auto jo = jv.enter_object();\n";
sb << " jo << ctie(\"@type\", \"" << constructor->name << "\");\n";
for (auto &arg : constructor->args) {
auto field = tl::simple::gen_cpp_field_name(arg.name);
// TODO: or as null
bool is_custom = arg.type->type == tl::simple::Type::Custom;
if (is_custom) {
sb << " if (object." << field << ") {\n ";
}
auto object = PSTRING() << "object." << tl::simple::gen_cpp_field_name(arg.name);
if (arg.type->type == tl::simple::Type::Bytes || arg.type->type == tl::simple::Type::SecureBytes) {
object = PSTRING() << "JsonBytes{" << object << "}";
} else if (arg.type->type == tl::simple::Type::Int64) {
object = PSTRING() << "JsonInt64{" << object << "}";
} else if (arg.type->type == tl::simple::Type::Vector &&
(arg.type->vector_value_type->type == tl::simple::Type::Bytes ||
arg.type->vector_value_type->type == tl::simple::Type::SecureBytes)) {
object = PSTRING() << "JsonVectorBytes(" << object << ")";
} else if (arg.type->type == tl::simple::Type::Vector &&
arg.type->vector_value_type->type == tl::simple::Type::Int64) {
object = PSTRING() << "JsonVectorInt64{" << object << "}";
}
sb << " jo << ctie(\"" << arg.name << "\", ToJson(" << object << "));\n";
if (is_custom) {
sb << " }\n";
}
}
sb << "}\n";
}
void gen_to_json(StringBuilder &sb, const tl::simple::Schema &schema, bool is_header) {
for (auto *custom_type : schema.custom_types) {
if (custom_type->constructors.size() > 1) {
auto type_name = tl::simple::gen_cpp_name(custom_type->name);
sb << "void to_json(JsonValueScope &jv, const " << tl_name << "::" << type_name << " &object)";
if (is_header) {
sb << ";\n";
} else {
sb << " {\n"
<< " " << tl_name << "::downcast_call(const_cast<" << tl_name << "::" << type_name
<< " &>(object), [&jv](const auto &object) { "
"to_json(jv, object); });\n"
<< "}\n";
}
}
for (auto *constructor : custom_type->constructors) {
gen_to_json_constructor(sb, constructor, is_header);
}
}
for (auto *function : schema.functions) {
gen_to_json_constructor(sb, function, is_header);
}
if (is_header) {
sb << "inline void to_json(JsonValueScope &jv, const ton::" << tl_name
<< "::Object &object) {\n"
" ton::"
<< tl_name << "::downcast_call(const_cast<ton::" << tl_name
<< "::Object &>(object),[&jv](const auto &object) { "
"to_json(jv, object); });\n"
<< "}\n";
sb << "inline void to_json(JsonValueScope &jv, const ton::" << tl_name << "::Function &object) {\n"
<< " ton::" << tl_name << "::downcast_call(const_cast<ton::" << tl_name
<< "::Function &>(object), [&jv](const auto &object) { "
"to_json(jv, object); });\n"
<< "}\n";
}
}
template <class T>
void gen_from_json_constructor(StringBuilder &sb, const T *constructor, bool is_header) {
sb << "Status from_json(" << tl_name << "::" << tl::simple::gen_cpp_name(constructor->name)
<< " &to, JsonObject &from)";
if (is_header) {
sb << ";\n";
} else {
sb << " {\n";
for (auto &arg : constructor->args) {
sb << " {\n";
sb << " TRY_RESULT(value, get_json_object_field(from, \"" << tl::simple::gen_cpp_name(arg.name)
<< "\", JsonValue::Type::Null, true));\n";
sb << " if (value.type() != JsonValue::Type::Null) {\n";
if (arg.type->type == tl::simple::Type::Bytes) {
sb << " TRY_STATUS(from_json_bytes(to." << tl::simple::gen_cpp_field_name(arg.name) << ", value));\n";
} else if (arg.type->type == tl::simple::Type::Vector &&
arg.type->vector_value_type->type == tl::simple::Type::Bytes) {
sb << " TRY_STATUS(from_json_vector_bytes(to." << tl::simple::gen_cpp_field_name(arg.name)
<< ", value));\n";
} else {
sb << " TRY_STATUS(from_json(to." << tl::simple::gen_cpp_field_name(arg.name) << ", value));\n";
}
sb << " }\n";
sb << " }\n";
}
sb << " return Status::OK();\n";
sb << "}\n";
}
}
void gen_from_json(StringBuilder &sb, const tl::simple::Schema &schema, bool is_header) {
for (auto *custom_type : schema.custom_types) {
for (auto *constructor : custom_type->constructors) {
gen_from_json_constructor(sb, constructor, is_header);
}
}
for (auto *function : schema.functions) {
gen_from_json_constructor(sb, function, is_header);
}
}
using Vec = std::vector<std::pair<int32, std::string>>;
void gen_tl_constructor_from_string(StringBuilder &sb, Slice name, const Vec &vec, bool is_header) {
sb << "Result<int32> tl_constructor_from_string(" << tl_name << "::" << name << " *object, const std::string &str)";
if (is_header) {
sb << ";\n";
return;
}
sb << " {\n";
sb << " static const std::unordered_map<Slice, int32, SliceHash> m = {\n";
bool is_first = true;
for (auto &p : vec) {
if (is_first) {
is_first = false;
} else {
sb << ",\n";
}
sb << " {\"" << p.second << "\", " << p.first << "}";
}
sb << "\n };\n";
sb << " auto it = m.find(str);\n";
sb << " if (it == m.end()) {\n"
<< " return Status::Error(str + \"Unknown class\");\n"
<< " }\n"
<< " return it->second;\n";
sb << "}\n";
}
void gen_tl_constructor_from_string(StringBuilder &sb, const tl::simple::Schema &schema, bool is_header) {
Vec vec_for_nullary;
for (auto *custom_type : schema.custom_types) {
Vec vec;
for (auto *constructor : custom_type->constructors) {
vec.push_back(std::make_pair(constructor->id, constructor->name));
vec_for_nullary.push_back(vec.back());
}
if (vec.size() > 1) {
gen_tl_constructor_from_string(sb, tl::simple::gen_cpp_name(custom_type->name), vec, is_header);
}
}
gen_tl_constructor_from_string(sb, "Object", vec_for_nullary, is_header);
Vec vec_for_function;
for (auto *function : schema.functions) {
vec_for_function.push_back(std::make_pair(function->id, function->name));
}
gen_tl_constructor_from_string(sb, "Function", vec_for_function, is_header);
}
void gen_json_converter_file(const tl::simple::Schema &schema, const std::string &file_name_base, bool is_header) {
auto file_name = is_header ? file_name_base + ".h" : file_name_base + ".cpp";
//file_name = "auto/" + file_name;
auto old_file_content = [&] {
auto r_content = read_file(file_name);
if (r_content.is_error()) {
return BufferSlice();
}
return r_content.move_as_ok();
}();
std::string buf(2000000, ' ');
StringBuilder sb(MutableSlice{buf});
if (is_header) {
sb << "#pragma once\n\n";
sb << "#include \"auto/tl/" << tl_name << ".h\"\n\n";
sb << "#include \"auto/tl/" << tl_name << ".hpp\"\n\n";
sb << "#include \"td/utils/JsonBuilder.h\"\n";
sb << "#include \"td/utils/Status.h\"\n\n";
sb << "#include \"crypto/common/bitstring.h\"\n";
} else {
sb << "#include \"" << file_name_base << ".h\"\n\n";
sb << "#include \"auto/tl/" << tl_name << ".h\"\n";
sb << "#include \"auto/tl/" << tl_name << ".hpp\"\n\n";
sb << "#include \"tl/tl_json.h\"\n\n";
sb << "#include \"td/utils/base64.h\"\n";
sb << "#include \"td/utils/common.h\"\n";
sb << "#include \"td/utils/Slice.h\"\n\n";
sb << "#include <unordered_map>\n\n";
}
sb << "namespace ton {\n";
sb << "namespace " << tl_name << "{\n";
sb << " using namespace td;\n";
gen_tl_constructor_from_string(sb, schema, is_header);
gen_from_json(sb, schema, is_header);
gen_to_json(sb, schema, is_header);
sb << "} // namespace " << tl_name << "\n";
sb << "} // namespace ton\n";
CHECK(!sb.is_error());
buf.resize(sb.as_cslice().size());
auto new_file_content = std::move(buf);
if (new_file_content != old_file_content.as_slice()) {
write_file(file_name, new_file_content).ensure();
}
}
void gen_json_converter(const tl::tl_config &config, const std::string &file_name, const std::string &new_tl_name) {
tl_name = new_tl_name;
tl::simple::Schema schema(config);
gen_json_converter_file(schema, file_name, true);
gen_json_converter_file(schema, file_name, false);
}
} // namespace td

View file

@ -0,0 +1,29 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include <string>
#include "td/tl/tl_config.h"
namespace td {
void gen_json_converter(const tl::tl_config &config, const std::string &file_name, const std::string &tl_name);
} // namespace td

View file

@ -0,0 +1,698 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tl_writer_cpp.h"
#include <cassert>
namespace td {
std::string TD_TL_writer_cpp::gen_output_begin() const {
std::string ext_include_str;
for (auto &it : ext_include) {
ext_include_str += "#include " + it + "\n";
}
if (!ext_include_str.empty()) {
ext_include_str += "\n";
}
return "#include \"" + tl_name + ".h\"\n\n" + ext_include_str +
"#include \"td/utils/common.h\"\n"
"#include \"td/utils/format.h\"\n"
"#include \"td/utils/logging.h\"\n"
"#include \"td/utils/tl_parsers.h\"\n"
"#include \"td/utils/tl_storers.h\"\n\n"
"namespace ton {\n"
"namespace " +
tl_name +
" {\n\n"
"std::string to_string(const BaseObject &value) {\n"
" td::TlStorerToString storer;\n"
" value.store(storer, \"\");\n"
" return storer.str();\n"
"}\n";
}
std::string TD_TL_writer_cpp::gen_output_end() const {
return "} // namespace " + tl_name +
"\n"
"} // namespace ton\n";
}
std::string TD_TL_writer_cpp::gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const {
return "";
}
std::string TD_TL_writer_cpp::gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const {
for (std::size_t i = 0; i < vars.size(); i++) {
vars[i].index = static_cast<int>(i);
vars[i].is_stored = false;
vars[i].is_type = false;
vars[i].parameter_num = -1;
vars[i].function_arg_num = -1;
}
if (result_type != nullptr) {
assert(result_type->children.empty());
}
for (std::size_t i = 0; i < t->args.size(); i++) {
const tl::arg &a = t->args[i];
int arg_type = a.type->get_type();
if (arg_type == tl::NODE_TYPE_VAR_TYPE) {
const tl::tl_tree_var_type *var_type = static_cast<const tl::tl_tree_var_type *>(a.type);
assert(a.flags & tl::FLAG_EXCL);
assert(var_type->var_num < static_cast<int>(vars.size()));
assert(var_type->var_num >= 0);
assert(!vars[var_type->var_num].is_type);
vars[var_type->var_num].is_type = true;
vars[var_type->var_num].function_arg_num = static_cast<int>(i);
}
}
std::string res;
for (std::size_t i = 0; i < vars.size(); i++) {
if (!vars[i].is_type) {
assert(vars[i].parameter_num == -1);
assert(vars[i].function_arg_num == -1);
assert(vars[i].is_stored == false);
res += " " + gen_class_name("#") + " " + gen_var_name(vars[i]) + ";\n";
}
}
return res;
}
std::string TD_TL_writer_cpp::gen_function_vars(const tl::tl_combinator *t,
std::vector<tl::var_description> &vars) const {
for (std::size_t i = 0; i < vars.size(); i++) {
vars[i].index = static_cast<int>(i);
vars[i].is_stored = false;
vars[i].is_type = false;
vars[i].parameter_num = -1;
vars[i].function_arg_num = -1;
}
for (std::size_t i = 0; i < t->args.size(); i++) {
const tl::arg &a = t->args[i];
int arg_type = a.type->get_type();
if (arg_type == tl::NODE_TYPE_VAR_TYPE) {
const tl::tl_tree_var_type *var_type = static_cast<const tl::tl_tree_var_type *>(a.type);
assert(a.flags & tl::FLAG_EXCL);
assert(var_type->var_num >= 0);
assert(!vars[var_type->var_num].is_type);
vars[var_type->var_num].is_type = true;
vars[var_type->var_num].function_arg_num = static_cast<int>(i);
}
}
return "";
}
std::string TD_TL_writer_cpp::gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const {
assert(result_type->children.empty());
return "";
}
std::string TD_TL_writer_cpp::gen_constructor_id_store_raw(const std::string &id) const {
return "s.store_binary(" + id + ");";
}
std::string TD_TL_writer_cpp::gen_constructor_id_store(std::int32_t id, int storer_type) const {
if (storer_type == 1) {
return "";
}
return " " + gen_constructor_id_store_raw(int_to_string(id)) + "\n";
}
std::string TD_TL_writer_cpp::gen_fetch_class_name(const tl::tl_tree_type *tree_type) const {
const tl::tl_type *t = tree_type->type;
const std::string &name = t->name;
if (name == "#" || name == "Int32") {
return "TlFetchInt";
}
if (name == "Int53" || name == "Int64") {
return "TlFetchLong";
}
if (name == "True" || name == "Bool" || name == "Int" || name == "Long" || name == "Double" || name == "Int128" ||
name == "Int256") {
return "TlFetch" + name;
}
if (name == "String" || name == "SecureString") {
return "TlFetchString<" + string_type + ">";
}
if (name == "Bytes" || name == "SecureBytes") {
return "TlFetchBytes<" + bytes_type + ">";
}
if (name == "Object") {
return "TlFetchObject<" + gen_base_type_class_name(0) + ">";
}
if (name == "Function") {
return "TlFetchObject<" + gen_base_function_class_name() + ">";
}
if (name == "Vector") {
assert(t->arity == 1);
assert(tree_type->children.size() == 1);
assert(tree_type->children[0]->get_type() == tl::NODE_TYPE_TYPE);
const tl::tl_tree_type *child = static_cast<const tl::tl_tree_type *>(tree_type->children[0]);
return "TlFetchVector<" + gen_full_fetch_class_name(child) + ">";
}
assert(!is_built_in_simple_type(name) && !is_built_in_complex_type(name));
for (std::size_t i = 0; i < tree_type->children.size(); i++) {
assert(tree_type->children[i]->get_type() == tl::NODE_TYPE_NAT_CONST);
}
assert(tree_type->children.empty());
return "TlFetchObject<" + gen_main_class_name(t) + ">";
}
std::string TD_TL_writer_cpp::gen_full_fetch_class_name(const tl::tl_tree_type *tree_type) const {
const tl::tl_type *t = tree_type->type;
const std::string &name = t->name;
assert(!(t->flags & tl::FLAG_DEFAULT_CONSTRUCTOR)); // Not supported yet
std::int32_t expected_constructor_id = 0;
if (tree_type->flags & tl::FLAG_BARE) {
assert(is_type_bare(t));
} else {
if (is_type_bare(t)) {
for (std::size_t i = 0; i < t->constructors_num; i++) {
if (is_built_in_complex_type(name) || is_combinator_supported(t->constructors[i])) {
assert(expected_constructor_id == 0);
expected_constructor_id = t->constructors[i]->id;
assert(expected_constructor_id != 0);
}
}
}
}
if (expected_constructor_id == 0) {
return gen_fetch_class_name(tree_type);
}
return "TlFetchBoxed<" + gen_fetch_class_name(tree_type) + ", " + int_to_string(expected_constructor_id) + ">";
}
std::string TD_TL_writer_cpp::gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const {
return gen_full_fetch_class_name(tree_type) + "::parse(p)";
}
std::string TD_TL_writer_cpp::gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars,
bool flat, int parser_type) const {
assert(parser_type >= 0);
std::string field_name = (parser_type == 0 ? (field_num == 0 ? ": " : ", ") : "res->") + gen_field_name(a.name);
if (a.type->get_type() == tl::NODE_TYPE_VAR_TYPE) {
assert(parser_type == 1);
const tl::tl_tree_var_type *t = static_cast<const tl::tl_tree_var_type *>(a.type);
assert(a.flags == tl::FLAG_EXCL);
assert(a.var_num == -1);
assert(a.exist_var_num == -1);
assert(t->var_num >= 0);
assert(vars[t->var_num].is_type);
assert(!vars[t->var_num].is_stored);
vars[t->var_num].is_stored = true;
return " " + field_name + " = " + gen_base_function_class_name() + "::fetch(p);\n";
}
assert(!(a.flags & tl::FLAG_EXCL));
assert(!(a.flags & tl::FLAG_OPT_VAR));
std::string res = " ";
if (a.exist_var_num != -1) {
assert(0 <= a.exist_var_num && a.exist_var_num < static_cast<int>(vars.size()));
assert(vars[a.exist_var_num].is_stored);
res += "if (" + gen_var_name(vars[a.exist_var_num]) + " & " + int_to_string(1 << a.exist_var_bit) + ") { ";
}
if (flat) {
// TODO
// return gen_field_fetch(const tl::arg &a, std::vector<tl::var_description> &vars, int num, bool flat);
}
bool store_to_var_num = false;
if (a.var_num >= 0) {
assert(a.type->get_type() == tl::NODE_TYPE_TYPE);
assert(static_cast<const tl::tl_tree_type *>(a.type)->type->id == tl::ID_VAR_NUM);
assert(0 <= a.var_num && a.var_num < static_cast<int>(vars.size()));
if (!vars[a.var_num].is_stored) {
res += "if ((" + gen_var_name(vars[a.var_num]) + " = ";
store_to_var_num = true;
} else {
assert(false);
}
vars[a.var_num].is_stored = true;
}
res += field_name + (parser_type == 0 ? "(" : " = ");
assert(a.type->get_type() == tl::NODE_TYPE_TYPE);
const tl::tl_tree_type *tree_type = static_cast<tl::tl_tree_type *>(a.type);
res += gen_type_fetch(field_name, tree_type, vars, parser_type);
if (store_to_var_num) {
res += ") < 0) { FAIL(\"Variable of type # can't be negative\"); }";
} else {
res += (parser_type == 0 ? ")" : ";");
}
if (a.exist_var_num >= 0) {
res += " }";
if (store_to_var_num) {
res += " else { " + gen_var_name(vars[a.var_num]) + " = 0; }";
}
}
res += "\n";
return res;
}
std::string TD_TL_writer_cpp::gen_var_type_fetch(const tl::arg &a) const {
assert(false);
return "";
}
std::string TD_TL_writer_cpp::get_pretty_field_name(std::string field_name) const {
if (!field_name.empty() && field_name.back() == ']') {
return "";
}
auto equals_pos = field_name.find('=');
if (equals_pos != std::string::npos && equals_pos + 3 < field_name.size()) {
field_name = field_name.substr(equals_pos + 2);
if (field_name.back() == ')') {
field_name.pop_back();
}
}
while (!field_name.empty() && field_name.back() == '_') {
field_name.pop_back();
}
return field_name;
}
std::string TD_TL_writer_cpp::get_pretty_class_name(std::string class_name) const {
return class_name;
}
std::string TD_TL_writer_cpp::gen_vector_store(const std::string &field_name, const tl::tl_tree_type *t,
const std::vector<tl::var_description> &vars, int storer_type) const {
std::string num = field_name.back() == ']' ? "2" : "";
return "{ const std::vector<" + gen_type_name(t) + "> &v" + num + " = " + field_name +
"; const std::uint32_t multiplicity" + num + " = static_cast<std::uint32_t>(v" + num +
".size()); const auto vector_name" + num + " = \"" + get_pretty_class_name("vector") +
"[\" + td::to_string(multiplicity" + num + ")+ \"]\"; s.store_class_begin(\"" +
get_pretty_field_name(field_name) + "\", vector_name" + num +
".c_str()); "
"for (std::uint32_t i" +
num + " = 0; i" + num + " < multiplicity" + num + "; i" + num + "++) { " +
gen_type_store("v" + num + "[i" + num + "]", t, vars, storer_type) + " } s.store_class_end(); }";
}
std::string TD_TL_writer_cpp::gen_store_class_name(const tl::tl_tree_type *tree_type) const {
const tl::tl_type *t = tree_type->type;
const std::string &name = t->name;
if (name == "#" || name == "Int" || name == "Long" || name == "Int32" || name == "Int53" || name == "Int64" ||
name == "Double" || name == "Int128" || name == "Int256") {
return "TlStoreBinary";
}
if (name == "Bool") {
return "TlStoreBool";
}
if (name == "True") {
return "TlStoreTrue";
}
if (name == "String" || name == "Bytes" || name == "SecureString" || name == "SecureBytes") {
return "TlStoreString";
}
if (name == "Object" || name == "Function") {
return "TlStoreObject";
}
if (name == "Vector") {
assert(t->arity == 1);
assert(tree_type->children.size() == 1);
assert(tree_type->children[0]->get_type() == tl::NODE_TYPE_TYPE);
const tl::tl_tree_type *child = static_cast<const tl::tl_tree_type *>(tree_type->children[0]);
return "TlStoreVector<" + gen_full_store_class_name(child) + ">";
}
assert(!is_built_in_simple_type(name) && !is_built_in_complex_type(name));
for (std::size_t i = 0; i < tree_type->children.size(); i++) {
assert(tree_type->children[i]->get_type() == tl::NODE_TYPE_NAT_CONST);
}
assert(tree_type->children.empty());
return "TlStoreObject";
}
std::string TD_TL_writer_cpp::gen_full_store_class_name(const tl::tl_tree_type *tree_type) const {
const tl::tl_type *t = tree_type->type;
assert(!(t->flags & tl::FLAG_DEFAULT_CONSTRUCTOR)); // Not supported yet
if ((tree_type->flags & tl::FLAG_BARE) != 0 || t->name == "#" || t->name == "Bool") {
return gen_store_class_name(tree_type);
}
if (is_built_in_complex_type(t->name)) {
return "TlStoreBoxed<" + gen_store_class_name(tree_type) + ", " + int_to_string(t->constructors[0]->id) + ">";
}
if (!is_type_bare(t)) {
return "TlStoreBoxedUnknown<" + gen_store_class_name(tree_type) + ">";
}
for (std::size_t i = 0; i < t->constructors_num; i++) {
if (is_combinator_supported(t->constructors[i])) {
return "TlStoreBoxed<" + gen_store_class_name(tree_type) + ", " + int_to_string(t->constructors[i]->id) + ">";
}
}
assert(false);
return "";
}
std::string TD_TL_writer_cpp::gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const {
if (storer_type == 0) {
return gen_full_store_class_name(tree_type) + "::store(" + field_name + ", s);";
}
const tl::tl_type *t = tree_type->type;
const std::string &name = t->name;
assert(!(t->flags & tl::FLAG_DEFAULT_CONSTRUCTOR)); // Not supported yet
if (name == "#" || name == "Int" || name == "Long" || name == "Int32" || name == "Int53" || name == "Int64" ||
name == "Double" || name == "Bool" || name == "String" || name == "SecureString" || name == "Int128" ||
name == "Int256") {
return "s.store_field(\"" + get_pretty_field_name(field_name) + "\", " + field_name + ");";
} else if (name == "True") {
// currently nothing to do
return "";
} else if (name == "Bytes" || name == "SecureBytes") {
return "s.store_bytes_field(\"" + get_pretty_field_name(field_name) + "\", " + field_name + ");";
} else if (name == "Vector") {
const tl::tl_tree_type *child = static_cast<const tl::tl_tree_type *>(tree_type->children[0]);
return gen_vector_store(field_name, child, vars, storer_type);
} else {
assert(tree_type->children.empty());
return "if (" + field_name + " == nullptr) { s.store_field(\"" + get_pretty_field_name(field_name) +
"\", \"null\"); } else { " + field_name + "->store(s, \"" + get_pretty_field_name(field_name) + "\"); }";
}
}
std::string TD_TL_writer_cpp::gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int storer_type) const {
std::string field_name = gen_field_name(a.name);
std::string res = storer_type == 1 ? " " : " ";
if (a.type->get_type() == tl::NODE_TYPE_VAR_TYPE) {
const tl::tl_tree_var_type *t = static_cast<const tl::tl_tree_var_type *>(a.type);
assert(a.flags == tl::FLAG_EXCL);
assert(a.var_num == -1);
assert(a.exist_var_num == -1);
assert(t->var_num >= 0);
assert(!vars[t->var_num].is_stored);
vars[t->var_num].is_stored = true;
assert(vars[t->var_num].is_type);
return res + field_name + "->store(s);\n";
}
assert(!(a.flags & tl::FLAG_EXCL));
if (a.flags & tl::FLAG_OPT_VAR) {
assert(false);
assert(a.exist_var_num == -1);
assert(0 <= a.var_num && a.var_num < static_cast<int>(vars.size()));
assert(a.type->get_type() == tl::NODE_TYPE_TYPE);
assert(static_cast<const tl::tl_tree_type *>(a.type)->type->id == tl::ID_VAR_NUM);
assert(vars[a.var_num].is_stored);
assert(!vars[a.var_num].is_type);
return "";
}
if (a.exist_var_num >= 0) {
assert(a.exist_var_num < static_cast<int>(vars.size()));
assert(vars[a.exist_var_num].is_stored);
res += "if (" + gen_var_name(vars[a.exist_var_num]) + " & " + int_to_string(1 << a.exist_var_bit) + ") { ";
}
if (flat) {
// TODO
// return gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat, int storer_type);
}
if (a.var_num >= 0) {
assert(a.type->get_type() == tl::NODE_TYPE_TYPE);
assert(static_cast<const tl::tl_tree_type *>(a.type)->type->id == tl::ID_VAR_NUM);
assert(a.var_num < static_cast<int>(vars.size()));
if (!vars[a.var_num].is_stored) {
field_name = "(" + gen_var_name(vars[a.var_num]) + " = " + field_name + ")";
vars[a.var_num].is_stored = true;
} else {
assert(false); // need to check value of stored var
field_name = gen_var_name(vars[a.var_num]);
}
}
assert(a.type->get_type() == tl::NODE_TYPE_TYPE);
const tl::tl_tree_type *tree_type = static_cast<tl::tl_tree_type *>(a.type);
res += gen_type_store(field_name, tree_type, vars, storer_type);
if (a.exist_var_num >= 0) {
res += " }";
}
res += "\n";
return res;
}
std::string TD_TL_writer_cpp::gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const {
return "";
}
std::string TD_TL_writer_cpp::gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const {
return "";
}
std::string TD_TL_writer_cpp::gen_class_end() const {
return "";
}
std::string TD_TL_writer_cpp::gen_class_alias(const std::string &class_name, const std::string &alias_name) const {
return "";
}
std::string TD_TL_writer_cpp::gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const {
if (is_proxy) {
return "";
}
return "\nconst std::int32_t " + class_name + "::ID;\n";
}
std::string TD_TL_writer_cpp::gen_function_result_type(const tl::tl_tree *result) const {
return "";
}
std::string TD_TL_writer_cpp::gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity,
std::vector<tl::var_description> &vars, int parser_type) const {
for (std::size_t i = 0; i < vars.size(); i++) {
assert(vars[i].is_stored == false);
}
std::string fetched_type = "object_ptr<" + class_name + "> ";
std::string returned_type = "object_ptr<" + parent_class_name + "> ";
assert(arity == 0);
if (parser_type == 0) {
return "\n" + returned_type + class_name + "::fetch(" + parser_name +
" &p) {\n"
" return make_object<" +
class_name +
">(p);\n"
"}\n\n" +
class_name + "::" + class_name + "(" + parser_name +
" &p)\n"
"#define FAIL(error) p.set_error(error)\n";
}
return "\n" + returned_type + class_name + "::fetch(" + parser_name +
" &p) {\n"
"#define FAIL(error) p.set_error(error); return nullptr;\n" +
(parser_type == -1 ? "" : " " + fetched_type + "res = make_object<" + class_name + ">();\n");
}
std::string TD_TL_writer_cpp::gen_fetch_function_end(bool has_parent, int field_num,
const std::vector<tl::var_description> &vars,
int parser_type) const {
for (std::size_t i = 0; i < vars.size(); i++) {
assert(vars[i].is_stored);
}
if (parser_type == 0) {
return "#undef FAIL\n"
"{" +
(field_num == 0 ? "\n (void)p;\n" : std::string()) + "}\n";
}
if (parser_type == -1) {
return "#undef FAIL\n"
"}\n";
}
return " if (p.get_error()) { FAIL(\"\"); }\n"
" return " +
std::string(has_parent ? "std::move(res)" : "res") +
";\n"
"#undef FAIL\n"
"}\n";
}
std::string TD_TL_writer_cpp::gen_fetch_function_result_begin(const std::string &parser_name,
const std::string &class_name,
const tl::tl_tree *result) const {
return "\n" + class_name + "::ReturnType " + class_name + "::fetch_result(" + parser_name +
" &p) {\n"
"#define FAIL(error) p.set_error(error); return ReturnType()\n"
" return ";
}
std::string TD_TL_writer_cpp::gen_fetch_function_result_end() const {
return ";\n"
"#undef FAIL\n"
"}\n";
}
std::string TD_TL_writer_cpp::gen_fetch_function_result_any_begin(const std::string &parser_name,
const std::string &class_name, bool is_proxy) const {
return "";
}
std::string TD_TL_writer_cpp::gen_fetch_function_result_any_end(bool is_proxy) const {
return "";
}
std::string TD_TL_writer_cpp::gen_store_function_begin(const std::string &storer_name, const std::string &class_name,
int arity, std::vector<tl::var_description> &vars,
int storer_type) const {
for (std::size_t i = 0; i < vars.size(); i++) {
vars[i].is_stored = false;
}
if (storer_type == -1) {
return "";
}
assert(arity == 0);
return "\n"
"void " +
class_name + "::store(" + storer_name + " &s" +
std::string(storer_type <= 0 ? "" : ", const char *field_name") + ") const {\n" +
(storer_type <= 0 ? " (void)sizeof(s);\n"
: " if (!LOG_IS_STRIPPED(ERROR)) {\n"
" s.store_class_begin(field_name, \"" +
get_pretty_class_name(class_name) + "\");\n");
}
std::string TD_TL_writer_cpp::gen_store_function_end(const std::vector<tl::var_description> &vars,
int storer_type) const {
for (std::size_t i = 0; i < vars.size(); i++) {
assert(vars[i].is_stored);
}
if (storer_type == -1) {
return "";
}
return (storer_type <= 0 ? std::string()
: " s.store_class_end();\n"
" }\n") +
"}\n";
}
std::string TD_TL_writer_cpp::gen_fetch_switch_begin() const {
return " int constructor = p.fetch_int();\n"
" switch (constructor) {\n";
}
std::string TD_TL_writer_cpp::gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const {
assert(arity == 0);
return " case " + gen_class_name(t->name) +
"::ID:\n"
" return " +
gen_class_name(t->name) + "::fetch(p);\n";
}
std::string TD_TL_writer_cpp::gen_fetch_switch_end() const {
return " default:\n"
" FAIL(PSTRING() << \"Unknown constructor found \" << td::format::as_hex(constructor));\n"
" }\n";
}
std::string TD_TL_writer_cpp::gen_constructor_begin(int fields_num, const std::string &class_name,
bool is_default) const {
return "\n" + class_name + "::" + class_name + "(";
}
std::string TD_TL_writer_cpp::gen_constructor_field_init(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const {
std::string field_type = gen_field_type(a);
if (field_type.empty()) {
return "";
}
std::string move_begin;
std::string move_end;
if ((field_type == bytes_type || field_type == secure_bytes_type || field_type == secure_string_type ||
field_type.compare(0, 11, "std::vector") == 0 || field_type.compare(0, 10, "object_ptr") == 0) &&
!is_default) {
move_begin = "std::move(";
move_end = ")";
}
return (field_num == 0 ? ")\n : " : " , ") + gen_field_name(a.name) + "(" + move_begin +
(is_default ? "" : gen_field_name(a.name)) + move_end + ")\n";
}
std::string TD_TL_writer_cpp::gen_constructor_end(const tl::tl_combinator *t, int fields_num, bool is_default) const {
if (fields_num == 0) {
return ") {\n"
"}\n";
}
return "{}\n";
}
} // namespace td

120
tl/generate/tl_writer_cpp.h Normal file
View file

@ -0,0 +1,120 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "tl_writer_td.h"
#include <cstdint>
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_cpp : public TD_TL_writer {
std::string gen_constructor_id_store_raw(const std::string &id) const;
std::string gen_fetch_class_name(const tl::tl_tree_type *tree_type) const;
std::string gen_full_fetch_class_name(const tl::tl_tree_type *tree_type) const;
std::string gen_store_class_name(const tl::tl_tree_type *tree_type) const;
std::string gen_full_store_class_name(const tl::tl_tree_type *tree_type) const;
std::vector<std::string> ext_include;
protected:
std::string gen_vector_store(const std::string &field_name, const tl::tl_tree_type *t,
const std::vector<tl::var_description> &vars, int storer_type) const;
virtual std::string get_pretty_field_name(std::string field_name) const;
virtual std::string get_pretty_class_name(std::string class_name) const;
public:
TD_TL_writer_cpp(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type,
const std::string &secure_string_type, const std::string &secure_bytes_type,
const std::vector<std::string> &ext_include)
: TD_TL_writer(tl_name, string_type, bytes_type, secure_string_type, secure_bytes_type)
, ext_include(ext_include) {
}
std::string gen_output_begin() const override;
std::string gen_output_end() const override;
std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const override;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const override;
std::string gen_class_end() const override;
std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const override;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const override;
std::string gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const override;
std::string gen_function_vars(const tl::tl_combinator *t, std::vector<tl::var_description> &vars) const override;
std::string gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const override;
std::string gen_constructor_id_store(std::int32_t id, int storer_type) const override;
std::string gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int parser_type) const override;
std::string gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int storer_type) const override;
std::string gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_var_type_fetch(const tl::arg &a) const override;
std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const override;
std::string gen_function_result_type(const tl::tl_tree *result) const override;
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity,
std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_fetch_function_end(bool has_parent, int field_num, const std::vector<tl::var_description> &vars,
int parser_type) const override;
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
const tl::tl_tree *result) const override;
std::string gen_fetch_function_result_end() const override;
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
bool is_proxy) const override;
std::string gen_fetch_function_result_any_end(bool is_proxy) const override;
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_store_function_end(const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_fetch_switch_begin() const override;
std::string gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const override;
std::string gen_fetch_switch_end() const override;
std::string gen_constructor_begin(int fields_num, const std::string &class_name, bool is_default) const override;
std::string gen_constructor_field_init(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const override;
std::string gen_constructor_end(const tl::tl_combinator *t, int fields_num, bool is_default) const override;
};
} // namespace td

355
tl/generate/tl_writer_h.cpp Normal file
View file

@ -0,0 +1,355 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tl_writer_h.h"
#include <cassert>
#include <utility>
namespace td {
std::string TD_TL_writer_h::forward_declaration(std::string type) {
std::string prefix;
std::string suffix;
do {
std::size_t pos = type.find("::");
if (pos == std::string::npos) {
return prefix + "class " + type + ";\n" + suffix;
}
std::string namespace_name = type.substr(0, pos);
type = type.substr(pos + 2);
prefix += "namespace " + namespace_name + " {\n";
suffix += "} // namespace " + namespace_name + "\n";
} while (true);
assert(false);
return "";
}
std::string TD_TL_writer_h::gen_output_begin() const {
std::string ext_include_str;
for (auto &it : ext_include) {
ext_include_str += "#include " + it + "\n";
}
if (!ext_include_str.empty()) {
ext_include_str += "\n";
}
std::string ext_forward_declaration;
for (auto &storer_name : get_storers()) {
ext_forward_declaration += forward_declaration(storer_name);
}
for (auto &parser_name : get_parsers()) {
ext_forward_declaration += forward_declaration(parser_name);
}
if (!ext_forward_declaration.empty()) {
ext_forward_declaration += "\n";
}
return "#pragma once\n\n"
"#include \"tl/TlObject.h\"\n\n"
"#include \"td/utils/int_types.h\"\n\n" +
ext_include_str +
"#include <cstdint>\n"
"#include <memory>\n"
"#include <utility>\n"
"#include <vector>\n\n" +
ext_forward_declaration + "namespace ton {\n" + "namespace " + tl_name + "{\n" +
"using BaseObject = ::ton::TlObject;\n\n"
"template <class Type>\n"
"using object_ptr = ::ton::tl_object_ptr<Type>;\n\n"
"template <class Type, class... Args>\n"
"object_ptr<Type> make_object(Args &&... args) {\n"
" return object_ptr<Type>(new Type(std::forward<Args>(args)...));\n"
"}\n\n"
"template <class ToType, class FromType>\n"
"object_ptr<ToType> move_object_as(FromType &&from) {\n"
" return object_ptr<ToType>(static_cast<ToType *>(from.release()));\n"
"}\n\n"
"std::string to_string(const BaseObject &value);\n\n"
"template <class T>\n"
"std::string to_string(const object_ptr<T> &value) {\n"
" if (value == nullptr) {\n"
" return \"null\";\n"
" }\n"
"\n"
" return to_string(*value);\n"
"}\n\n";
}
std::string TD_TL_writer_h::gen_output_end() const {
return "} // namespace " + tl_name +
"\n"
"} // namespace ton\n";
}
std::string TD_TL_writer_h::gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const {
return " " + type_name + (type_name.empty() || type_name[type_name.size() - 1] == ' ' ? "" : " ") + field_name +
";\n";
}
std::string TD_TL_writer_h::gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const {
return "";
}
std::string TD_TL_writer_h::gen_function_vars(const tl::tl_combinator *t,
std::vector<tl::var_description> &vars) const {
for (std::size_t i = 0; i < vars.size(); i++) {
vars[i].index = static_cast<int>(i);
vars[i].is_stored = false;
vars[i].is_type = false;
vars[i].parameter_num = -1;
vars[i].function_arg_num = -1;
}
for (std::size_t i = 0; i < t->args.size(); i++) {
const tl::arg &a = t->args[i];
int arg_type = a.type->get_type();
if (arg_type == tl::NODE_TYPE_VAR_TYPE) {
const tl::tl_tree_var_type *var_type = static_cast<const tl::tl_tree_var_type *>(a.type);
assert(a.flags & tl::FLAG_EXCL);
assert(var_type->var_num >= 0);
assert(!vars[var_type->var_num].is_type);
vars[var_type->var_num].is_type = true;
vars[var_type->var_num].function_arg_num = static_cast<int>(i);
}
}
std::string res;
for (std::size_t i = 0; i < vars.size(); i++) {
if (!vars[i].is_type) {
assert(vars[i].parameter_num == -1);
assert(vars[i].function_arg_num == -1);
assert(vars[i].is_stored == false);
res += " mutable " + gen_class_name("#") + " " + gen_var_name(vars[i]) + ";\n";
}
}
return res;
}
std::string TD_TL_writer_h::gen_flags_definitions(const tl::tl_combinator *t) const {
std::vector<std::pair<std::string, std::int32_t>> flags;
for (std::size_t i = 0; i < t->args.size(); i++) {
const tl::arg &a = t->args[i];
if (a.exist_var_num != -1) {
auto name = a.name;
for (auto &c : name) {
c = to_upper(c);
}
flags.push_back(std::make_pair(name, a.exist_var_bit));
}
}
std::string res;
if (!flags.empty()) {
res += " enum Flags : std::int32_t {";
bool first = true;
for (auto &p : flags) {
if (first) {
first = false;
} else {
res += ", ";
}
res += p.first + "_MASK = " + int_to_string(1 << p.second);
}
res += "};\n";
}
return res;
}
std::string TD_TL_writer_h::gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const {
return "";
}
std::string TD_TL_writer_h::gen_constructor_id_store(std::int32_t id, int storer_type) const {
return "";
}
std::string TD_TL_writer_h::gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars,
bool flat, int parser_type) const {
return "";
}
std::string TD_TL_writer_h::gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int storer_type) const {
return "";
}
std::string TD_TL_writer_h::gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const {
return "";
}
std::string TD_TL_writer_h::gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const {
return "";
}
std::string TD_TL_writer_h::gen_var_type_fetch(const tl::arg &a) const {
assert(false);
return "";
}
std::string TD_TL_writer_h::gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const {
return "class " + class_name + ";\n\n";
}
std::string TD_TL_writer_h::gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const {
return "class " + class_name + (!is_proxy ? " final " : "") + ": public " + base_class_name +
" {\n"
" public:\n";
}
std::string TD_TL_writer_h::gen_class_end() const {
return "};\n\n";
}
std::string TD_TL_writer_h::gen_class_alias(const std::string &class_name, const std::string &alias_name) const {
return "";
// return "typedef " + class_name + " " + alias_name + ";\n\n\n";
}
std::string TD_TL_writer_h::gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const {
if (is_proxy) {
if (class_name == gen_base_tl_class_name()) {
return "\n virtual std::int32_t get_id() const = 0;\n";
}
return "";
}
return "\n"
" static const std::int32_t ID = " +
int_to_string(id) +
";\n"
" std::int32_t get_id() const final {\n"
" return ID;\n"
" }\n";
}
std::string TD_TL_writer_h::gen_function_result_type(const tl::tl_tree *result) const {
assert(result->get_type() == tl::NODE_TYPE_TYPE);
const tl::tl_tree_type *result_type = static_cast<const tl::tl_tree_type *>(result);
std::string fetched_type = gen_type_name(result_type);
if (!fetched_type.empty() && fetched_type[fetched_type.size() - 1] == ' ') {
fetched_type.pop_back();
}
return "\n"
" using ReturnType = " +
fetched_type + ";\n";
}
std::string TD_TL_writer_h::gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity,
std::vector<tl::var_description> &vars, int parser_type) const {
std::string returned_type = "object_ptr<" + parent_class_name + "> ";
if (parser_type == 0) {
return "\n"
" static " +
returned_type + "fetch(" + parser_name + " &p);\n\n" + " explicit " + class_name + "(" + parser_name +
" &p);\n";
}
assert(arity == 0);
return "\n"
" static " +
returned_type + "fetch(" + parser_name + " &p);\n";
}
std::string TD_TL_writer_h::gen_fetch_function_end(bool has_parent, int field_num,
const std::vector<tl::var_description> &vars,
int parser_type) const {
return "";
}
std::string TD_TL_writer_h::gen_fetch_function_result_begin(const std::string &parser_name,
const std::string &class_name,
const tl::tl_tree *result) const {
return "\n"
" static ReturnType fetch_result(" +
parser_name + " &p);\n";
}
std::string TD_TL_writer_h::gen_fetch_function_result_end() const {
return "";
}
std::string TD_TL_writer_h::gen_fetch_function_result_any_begin(const std::string &parser_name,
const std::string &class_name, bool is_proxy) const {
return "";
}
std::string TD_TL_writer_h::gen_fetch_function_result_any_end(bool is_proxy) const {
return "";
}
std::string TD_TL_writer_h::gen_store_function_begin(const std::string &storer_name, const std::string &class_name,
int arity, std::vector<tl::var_description> &vars,
int storer_type) const {
assert(arity == 0);
if (storer_type == -1) {
return "";
}
return "\n"
" void store(" +
storer_name + " &s" + std::string(storer_type == 0 ? "" : ", const char *field_name") + ") const final;\n";
}
std::string TD_TL_writer_h::gen_store_function_end(const std::vector<tl::var_description> &vars,
int storer_type) const {
return "";
}
std::string TD_TL_writer_h::gen_fetch_switch_begin() const {
return "";
}
std::string TD_TL_writer_h::gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const {
return "";
}
std::string TD_TL_writer_h::gen_fetch_switch_end() const {
return "";
}
std::string TD_TL_writer_h::gen_constructor_begin(int fields_num, const std::string &class_name,
bool is_default) const {
return "\n"
" " +
std::string(fields_num == 1 ? "explicit " : "") + class_name + "(";
}
std::string TD_TL_writer_h::gen_constructor_field_init(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const {
return "";
}
std::string TD_TL_writer_h::gen_constructor_end(const tl::tl_combinator *t, int fields_num, bool is_default) const {
return ");\n";
}
} // namespace td

106
tl/generate/tl_writer_h.h Normal file
View file

@ -0,0 +1,106 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "tl_writer_td.h"
#include <cstdint>
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_h : public TD_TL_writer {
protected:
const std::vector<std::string> ext_include;
static std::string forward_declaration(std::string type);
public:
TD_TL_writer_h(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type,
const std::string &secure_string_type, const std::string &secure_bytes_type,
const std::vector<std::string> &ext_include)
: TD_TL_writer(tl_name, string_type, bytes_type, secure_string_type, secure_bytes_type)
, ext_include(ext_include) {
}
std::string gen_output_begin() const override;
std::string gen_output_end() const override;
std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const override;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const override;
std::string gen_class_end() const override;
std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const override;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const override;
std::string gen_flags_definitions(const tl::tl_combinator *t) const override;
std::string gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const override;
std::string gen_function_vars(const tl::tl_combinator *t, std::vector<tl::var_description> &vars) const override;
std::string gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const override;
std::string gen_constructor_id_store(std::int32_t id, int storer_type) const override;
std::string gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int parser_type) const override;
std::string gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int storer_type) const override;
std::string gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_var_type_fetch(const tl::arg &a) const override;
std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const override;
std::string gen_function_result_type(const tl::tl_tree *result) const override;
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity,
std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_fetch_function_end(bool has_parent, int field_num, const std::vector<tl::var_description> &vars,
int parser_type) const override;
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
const tl::tl_tree *result) const override;
std::string gen_fetch_function_result_end() const override;
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
bool is_proxy) const override;
std::string gen_fetch_function_result_any_end(bool is_proxy) const override;
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_store_function_end(const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_fetch_switch_begin() const override;
std::string gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const override;
std::string gen_fetch_switch_end() const override;
std::string gen_constructor_begin(int fields_num, const std::string &class_name, bool is_default) const override;
std::string gen_constructor_field_init(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const override;
std::string gen_constructor_end(const tl::tl_combinator *t, int fields_num, bool is_default) const override;
};
} // namespace td

View file

@ -0,0 +1,267 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tl_writer_hpp.h"
#include <cassert>
namespace td {
bool TD_TL_writer_hpp::is_documentation_generated() const {
return true;
}
int TD_TL_writer_hpp::get_additional_function_type(const std::string &additional_function_name) const {
assert(additional_function_name == "downcast_call");
return 2;
}
std::vector<std::string> TD_TL_writer_hpp::get_additional_functions() const {
std::vector<std::string> additional_functions;
additional_functions.push_back("downcast_call");
return additional_functions;
}
std::string TD_TL_writer_hpp::gen_base_type_class_name(int arity) const {
assert(arity == 0);
return "Object";
}
std::string TD_TL_writer_hpp::gen_base_tl_class_name() const {
return "BaseObject";
}
std::string TD_TL_writer_hpp::gen_output_begin() const {
return "#pragma once\n"
"\n"
"#include \"" +
tl_name +
".h\"\n"
"\n"
"namespace ton {\n"
"namespace " +
tl_name + " {\n\n";
}
std::string TD_TL_writer_hpp::gen_output_end() const {
return "} // namespace " + tl_name +
"\n"
"} // namespace ton \n";
}
std::string TD_TL_writer_hpp::gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const {
return "";
}
std::string TD_TL_writer_hpp::gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const {
return "";
}
std::string TD_TL_writer_hpp::gen_function_vars(const tl::tl_combinator *t,
std::vector<tl::var_description> &vars) const {
return "";
}
std::string TD_TL_writer_hpp::gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const {
return "";
}
std::string TD_TL_writer_hpp::gen_constructor_id_store(std::int32_t id, int storer_type) const {
return "";
}
std::string TD_TL_writer_hpp::gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars,
bool flat, int parser_type) const {
return "";
}
std::string TD_TL_writer_hpp::gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int storer_type) const {
return "";
}
std::string TD_TL_writer_hpp::gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const {
return "";
}
std::string TD_TL_writer_hpp::gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const {
return "";
}
std::string TD_TL_writer_hpp::gen_var_type_fetch(const tl::arg &a) const {
assert(false);
return "";
}
std::string TD_TL_writer_hpp::gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const {
return "";
}
std::string TD_TL_writer_hpp::gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const {
return "";
}
std::string TD_TL_writer_hpp::gen_class_end() const {
return "";
}
std::string TD_TL_writer_hpp::gen_class_alias(const std::string &class_name, const std::string &alias_name) const {
return "";
}
std::string TD_TL_writer_hpp::gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const {
return "";
}
std::string TD_TL_writer_hpp::gen_function_result_type(const tl::tl_tree *result) const {
return "";
}
std::string TD_TL_writer_hpp::gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity,
std::vector<tl::var_description> &vars, int parser_type) const {
return "";
}
std::string TD_TL_writer_hpp::gen_fetch_function_end(bool has_parent, int field_num,
const std::vector<tl::var_description> &vars,
int parser_type) const {
return "";
}
std::string TD_TL_writer_hpp::gen_fetch_function_result_begin(const std::string &parser_name,
const std::string &class_name,
const tl::tl_tree *result) const {
return "";
}
std::string TD_TL_writer_hpp::gen_fetch_function_result_end() const {
return "";
}
std::string TD_TL_writer_hpp::gen_fetch_function_result_any_begin(const std::string &parser_name,
const std::string &class_name, bool is_proxy) const {
return "";
}
std::string TD_TL_writer_hpp::gen_fetch_function_result_any_end(bool is_proxy) const {
return "";
}
std::string TD_TL_writer_hpp::gen_store_function_begin(const std::string &storer_name, const std::string &class_name,
int arity, std::vector<tl::var_description> &vars,
int storer_type) const {
return "";
}
std::string TD_TL_writer_hpp::gen_store_function_end(const std::vector<tl::var_description> &vars,
int storer_type) const {
return "";
}
std::string TD_TL_writer_hpp::gen_fetch_switch_begin() const {
return "";
}
std::string TD_TL_writer_hpp::gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const {
return "";
}
std::string TD_TL_writer_hpp::gen_fetch_switch_end() const {
return "";
}
std::string TD_TL_writer_hpp::gen_additional_function(const std::string &function_name, const tl::tl_combinator *t,
bool is_function) const {
assert(function_name == "downcast_call");
return "";
}
std::string TD_TL_writer_hpp::gen_additional_proxy_function_begin(const std::string &function_name,
const tl::tl_type *type,
const std::string &class_name, int arity,
bool is_function) const {
assert(function_name == "downcast_call");
return "/**\n"
" * Calls specified function object with the specified object downcasted to the most-derived type.\n"
" * \\param[in] obj Object to pass as an argument to the function object.\n"
" * \\param[in] func Function object to which the object will be passed.\n"
" * \\returns whether function object call has happened. Should always return true for correct parameters.\n"
" */\n"
"template <class T>\n"
"bool downcast_call(" +
class_name +
" &obj, const T &func) {\n"
" switch (obj.get_id()) {\n";
}
std::string TD_TL_writer_hpp::gen_additional_proxy_function_case(const std::string &function_name,
const tl::tl_type *type, const std::string &class_name,
int arity) const {
assert(function_name == "downcast_call");
assert(false);
return "";
}
std::string TD_TL_writer_hpp::gen_additional_proxy_function_case(const std::string &function_name,
const tl::tl_type *type, const tl::tl_combinator *t,
int arity, bool is_function) const {
assert(function_name == "downcast_call");
return " case " + gen_class_name(t->name) +
"::ID:\n"
" func(static_cast<" +
gen_class_name(t->name) +
" &>(obj));\n"
" return true;\n";
}
std::string TD_TL_writer_hpp::gen_additional_proxy_function_end(const std::string &function_name,
const tl::tl_type *type, bool is_function) const {
assert(function_name == "downcast_call");
return " default:\n"
" return false;\n"
" }\n"
"}\n\n";
}
std::string TD_TL_writer_hpp::gen_constructor_begin(int fields_num, const std::string &class_name,
bool is_default) const {
return "";
}
std::string TD_TL_writer_hpp::gen_constructor_parameter(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const {
return "";
}
std::string TD_TL_writer_hpp::gen_constructor_field_init(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const {
return "";
}
std::string TD_TL_writer_hpp::gen_constructor_end(const tl::tl_combinator *t, int fields_num, bool is_default) const {
return "";
}
} // namespace td

121
tl/generate/tl_writer_hpp.h Normal file
View file

@ -0,0 +1,121 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "tl_writer_td.h"
#include <cstdint>
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_hpp : public TD_TL_writer {
public:
TD_TL_writer_hpp(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type,
const std::string &secure_string_type, const std::string &secure_bytes_type)
: TD_TL_writer(tl_name, string_type, bytes_type, secure_string_type, secure_bytes_type) {
}
bool is_documentation_generated() const override;
int get_additional_function_type(const std::string &additional_function_name) const override;
std::vector<std::string> get_additional_functions() const override;
std::string gen_base_type_class_name(int arity) const override;
std::string gen_base_tl_class_name() const override;
std::string gen_output_begin() const override;
std::string gen_output_end() const override;
std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const override;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const override;
std::string gen_class_end() const override;
std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const override;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const override;
std::string gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const override;
std::string gen_function_vars(const tl::tl_combinator *t, std::vector<tl::var_description> &vars) const override;
std::string gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const override;
std::string gen_constructor_id_store(std::int32_t id, int storer_type) const override;
std::string gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int parser_type) const override;
std::string gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int storer_type) const override;
std::string gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_var_type_fetch(const tl::arg &a) const override;
std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const override;
std::string gen_function_result_type(const tl::tl_tree *result) const override;
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity,
std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_fetch_function_end(bool has_parent, int field_num, const std::vector<tl::var_description> &vars,
int parser_type) const override;
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
const tl::tl_tree *result) const override;
std::string gen_fetch_function_result_end() const override;
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
bool is_proxy) const override;
std::string gen_fetch_function_result_any_end(bool is_proxy) const override;
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_store_function_end(const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_fetch_switch_begin() const override;
std::string gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const override;
std::string gen_fetch_switch_end() const override;
std::string gen_constructor_begin(int fields_num, const std::string &class_name, bool is_default) const override;
std::string gen_constructor_parameter(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const override;
std::string gen_constructor_field_init(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const override;
std::string gen_constructor_end(const tl::tl_combinator *t, int fields_num, bool is_default) const override;
std::string gen_additional_function(const std::string &function_name, const tl::tl_combinator *t,
bool is_function) const override;
std::string gen_additional_proxy_function_begin(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity,
bool is_function) const override;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity) const override;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const tl::tl_combinator *t, int arity,
bool is_function) const override;
std::string gen_additional_proxy_function_end(const std::string &function_name, const tl::tl_type *type,
bool is_function) const override;
};
} // namespace td

View file

@ -0,0 +1,465 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tl_writer_java.h"
#include <cassert>
namespace td {
const int TD_TL_writer_java::MAX_ARITY;
const std::string TD_TL_writer_java::base_type_class_names[MAX_ARITY + 1] = {"Object"};
const std::string TD_TL_writer_java::base_tl_class_name = "Object";
const std::string TD_TL_writer_java::base_function_class_name = "Function";
int TD_TL_writer_java::get_max_arity() const {
return MAX_ARITY;
}
bool TD_TL_writer_java::is_built_in_simple_type(const std::string &name) const {
return name == "Bool" || name == "Int32" || name == "Int53" || name == "Int64" || name == "Double" ||
name == "String" || name == "Bytes" || name == "SecureString" || name == "SecureBytes";
}
bool TD_TL_writer_java::is_built_in_complex_type(const std::string &name) const {
return name == "Vector";
}
bool TD_TL_writer_java::is_type_bare(const tl::tl_type *t) const {
return t->simple_constructors == 1 || (is_built_in_simple_type(t->name) && t->name != "Bool") ||
is_built_in_complex_type(t->name);
}
bool TD_TL_writer_java::is_combinator_supported(const tl::tl_combinator *constructor) const {
if (!TL_writer::is_combinator_supported(constructor)) {
return false;
}
for (std::size_t i = 0; i < constructor->args.size(); i++) {
if (constructor->args[i].type->get_type() == tl::NODE_TYPE_VAR_TYPE) {
return false;
}
}
return true;
}
int TD_TL_writer_java::get_parser_type(const tl::tl_combinator *t, const std::string &parser_name) const {
return 0;
}
int TD_TL_writer_java::get_storer_type(const tl::tl_combinator *t, const std::string &storer_name) const {
return 0;
}
std::vector<std::string> TD_TL_writer_java::get_parsers() const {
std::vector<std::string> parsers;
parsers.push_back("<inlined>");
return parsers;
}
std::vector<std::string> TD_TL_writer_java::get_storers() const {
return std::vector<std::string>();
}
std::string TD_TL_writer_java::gen_base_tl_class_name() const {
return base_tl_class_name;
}
std::string TD_TL_writer_java::gen_base_type_class_name(int arity) const {
assert(arity == 0);
return base_type_class_names[arity];
}
std::string TD_TL_writer_java::gen_base_function_class_name() const {
return base_function_class_name;
}
std::string TD_TL_writer_java::gen_class_name(std::string name) const {
if (name == "Object" || name == "#") {
assert(false);
}
bool next_to_upper = true;
std::string result;
for (std::size_t i = 0; i < name.size(); i++) {
if (!is_alnum(name[i])) {
next_to_upper = true;
continue;
}
if (next_to_upper) {
result += to_upper(name[i]);
next_to_upper = false;
} else {
result += name[i];
}
}
return result;
}
std::string TD_TL_writer_java::gen_field_name(std::string name) const {
assert(name.size() > 0);
assert(is_alnum(name.back()));
bool next_to_upper = false;
std::string result;
for (std::size_t i = 0; i < name.size(); i++) {
if (!is_alnum(name[i])) {
next_to_upper = true;
continue;
}
if (next_to_upper) {
result += to_upper(name[i]);
next_to_upper = false;
} else {
result += name[i];
}
}
return result;
}
std::string TD_TL_writer_java::gen_var_name(const tl::var_description &desc) const {
assert(false);
return std::string();
}
std::string TD_TL_writer_java::gen_parameter_name(int index) const {
assert(false);
return std::string();
}
std::string TD_TL_writer_java::gen_type_name(const tl::tl_tree_type *tree_type) const {
const tl::tl_type *t = tree_type->type;
const std::string &name = t->name;
if (name == "#") {
assert(false);
}
if (name == "Bool") {
return "boolean";
}
if (name == "Int32") {
return "int";
}
if (name == "Int53" || name == "Int64") {
return "long";
}
if (name == "Double") {
return "double";
}
if (name == "String" || name == "SecureString") {
return "String";
}
if (name == "Bytes" || name == "SecureBytes") {
return "byte[]";
}
if (name == "Vector") {
assert(t->arity == 1);
assert(tree_type->children.size() == 1);
assert(tree_type->children[0]->get_type() == tl::NODE_TYPE_TYPE);
const tl::tl_tree_type *child = static_cast<const tl::tl_tree_type *>(tree_type->children[0]);
return gen_type_name(child) + "[]";
}
assert(!is_built_in_simple_type(name) && !is_built_in_complex_type(name));
for (std::size_t i = 0; i < tree_type->children.size(); i++) {
assert(tree_type->children[i]->get_type() == tl::NODE_TYPE_NAT_CONST);
}
return gen_main_class_name(t);
}
std::string TD_TL_writer_java::gen_array_type_name(const tl::tl_tree_array *arr, const std::string &field_name) const {
assert(false);
return std::string();
}
std::string TD_TL_writer_java::gen_var_type_name() const {
return gen_base_function_class_name();
}
std::string TD_TL_writer_java::gen_int_const(const tl::tl_tree *tree_c,
const std::vector<tl::var_description> &vars) const {
assert(false);
return std::string();
}
std::string TD_TL_writer_java::gen_output_begin() const {
return "package " + package_name +
";\n\n"
"public class " +
tl_name + " {\n";
}
std::string TD_TL_writer_java::gen_output_end() const {
return "}\n";
}
std::string TD_TL_writer_java::gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const {
return "";
}
std::string TD_TL_writer_java::gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const {
std::string full_class_name = "static class " + class_name;
if (class_name != gen_base_tl_class_name()) {
full_class_name += " extends " + base_class_name;
}
std::string result = " public " + std::string(is_proxy ? "abstract " : "") + full_class_name + " {\n";
if (class_name == gen_base_tl_class_name() || class_name == gen_base_function_class_name()) {
result += " public native String toString();\n";
}
return result;
}
std::string TD_TL_writer_java::gen_class_end() const {
return " }\n\n";
}
std::string TD_TL_writer_java::gen_class_alias(const std::string &class_name, const std::string &alias_name) const {
return "";
}
std::string TD_TL_writer_java::gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const {
return " public " + type_name + " " + field_name + ";\n";
}
std::string TD_TL_writer_java::gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const {
for (std::size_t i = 0; i < vars.size(); i++) {
vars[i].index = static_cast<int>(i);
vars[i].is_stored = false;
vars[i].is_type = false;
vars[i].parameter_num = -1;
vars[i].function_arg_num = -1;
}
if (result_type != nullptr) {
assert(result_type->children.empty());
}
for (std::size_t i = 0; i < t->args.size(); i++) {
assert(t->args[i].type->get_type() != tl::NODE_TYPE_VAR_TYPE);
}
for (std::size_t i = 0; i < vars.size(); i++) {
assert(vars[i].is_type);
}
return "";
}
std::string TD_TL_writer_java::gen_function_vars(const tl::tl_combinator *t,
std::vector<tl::var_description> &vars) const {
for (std::size_t i = 0; i < vars.size(); i++) {
vars[i].index = static_cast<int>(i);
vars[i].is_stored = false;
vars[i].is_type = false;
vars[i].parameter_num = -1;
vars[i].function_arg_num = -1;
}
for (std::size_t i = 0; i < t->args.size(); i++) {
assert(t->args[i].type->get_type() != tl::NODE_TYPE_VAR_TYPE);
}
for (std::size_t i = 0; i < vars.size(); i++) {
assert(vars[i].is_type);
}
return "";
}
std::string TD_TL_writer_java::gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const {
assert(result_type->children.empty());
return "";
}
std::string TD_TL_writer_java::gen_constructor_id_store(std::int32_t id, int storer_type) const {
return "";
}
std::string TD_TL_writer_java::gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars,
bool flat, int parser_type) const {
assert(parser_type >= 0);
assert(a.exist_var_num == -1);
assert(a.type->get_type() != tl::NODE_TYPE_VAR_TYPE);
assert(!(a.flags & tl::FLAG_EXCL));
assert(!(a.flags & tl::FLAG_OPT_VAR));
if (flat) {
// TODO
// return gen_field_fetch(const tl::arg &a, std::vector<tl::var_description> &vars, int num, bool flat);
}
assert(a.var_num == -1);
assert(a.type->get_type() == tl::NODE_TYPE_TYPE);
return "";
}
std::string TD_TL_writer_java::gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int storer_type) const {
return "";
}
std::string TD_TL_writer_java::gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const {
return "";
}
std::string TD_TL_writer_java::gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const {
return "";
}
std::string TD_TL_writer_java::gen_var_type_fetch(const tl::arg &a) const {
assert(false);
return "";
}
std::string TD_TL_writer_java::gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const {
if (is_proxy) {
return class_name == gen_base_tl_class_name() ? "\n public abstract int getConstructor();\n" : "";
}
return "\n"
" public static final int CONSTRUCTOR = " +
int_to_string(id) +
";\n\n"
" @Override\n"
" public int getConstructor() {\n"
" return CONSTRUCTOR;\n"
" }\n";
}
std::string TD_TL_writer_java::gen_function_result_type(const tl::tl_tree *result) const {
return "";
}
std::string TD_TL_writer_java::gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity,
std::vector<tl::var_description> &vars, int parser_type) const {
return "";
}
std::string TD_TL_writer_java::gen_fetch_function_end(bool has_parent, int field_num,
const std::vector<tl::var_description> &vars,
int parser_type) const {
return "";
}
std::string TD_TL_writer_java::gen_fetch_function_result_begin(const std::string &parser_name,
const std::string &class_name,
const tl::tl_tree *result) const {
return "";
}
std::string TD_TL_writer_java::gen_fetch_function_result_end() const {
return "";
}
std::string TD_TL_writer_java::gen_fetch_function_result_any_begin(const std::string &parser_name,
const std::string &class_name, bool is_proxy) const {
return "";
}
std::string TD_TL_writer_java::gen_fetch_function_result_any_end(bool is_proxy) const {
return "";
}
std::string TD_TL_writer_java::gen_store_function_begin(const std::string &storer_name, const std::string &class_name,
int arity, std::vector<tl::var_description> &vars,
int storer_type) const {
assert(false);
return "";
}
std::string TD_TL_writer_java::gen_store_function_end(const std::vector<tl::var_description> &vars,
int storer_type) const {
assert(false);
return "";
}
std::string TD_TL_writer_java::gen_fetch_switch_begin() const {
return "";
}
std::string TD_TL_writer_java::gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const {
assert(arity == 0);
return "";
}
std::string TD_TL_writer_java::gen_fetch_switch_end() const {
return "";
}
std::string TD_TL_writer_java::gen_constructor_begin(int fields_num, const std::string &class_name,
bool is_default) const {
return "\n"
" public " +
class_name + "(";
}
std::string TD_TL_writer_java::gen_constructor_parameter(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const {
if (is_default) {
return "";
}
std::string field_type = gen_field_type(a);
if (field_type.empty()) {
return "";
}
if (field_type[field_type.size() - 1] != ' ') {
field_type += ' ';
}
return (field_num == 0 ? "" : ", ") + field_type + gen_field_name(a.name);
}
std::string TD_TL_writer_java::gen_constructor_field_init(int field_num, const std::string &class_name,
const tl::arg &a, bool is_default) const {
std::string field_type = gen_field_type(a);
if (field_type.empty()) {
return "";
}
if (is_default) {
return (field_num == 0 ? ") {\n" : "");
}
return std::string(field_num == 0 ? ") {\n" : "") + " this." + gen_field_name(a.name) + " = " +
gen_field_name(a.name) + ";\n";
}
std::string TD_TL_writer_java::gen_constructor_end(const tl::tl_combinator *t, int fields_num, bool is_default) const {
if (fields_num == 0) {
return ") {\n"
" }\n";
}
return " }\n";
}
} // namespace td

View file

@ -0,0 +1,131 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "td/tl/tl_writer.h"
#include <cstdint>
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_java : public tl::TL_writer {
static const int MAX_ARITY = 0;
static const std::string base_type_class_names[MAX_ARITY + 1];
static const std::string base_tl_class_name;
static const std::string base_function_class_name;
const std::string package_name;
public:
TD_TL_writer_java(const std::string &tl_name, const std::string &package_name)
: TL_writer(tl_name), package_name(package_name) {
}
int get_max_arity() const override;
bool is_built_in_simple_type(const std::string &name) const override;
bool is_built_in_complex_type(const std::string &name) const override;
bool is_type_bare(const tl::tl_type *t) const override;
bool is_combinator_supported(const tl::tl_combinator *constructor) const override;
int get_parser_type(const tl::tl_combinator *t, const std::string &parser_name) const override;
int get_storer_type(const tl::tl_combinator *t, const std::string &storer_name) const override;
std::vector<std::string> get_parsers() const override;
std::vector<std::string> get_storers() const override;
std::string gen_base_tl_class_name() const override;
std::string gen_base_type_class_name(int arity) const override;
std::string gen_base_function_class_name() const override;
std::string gen_class_name(std::string name) const override;
std::string gen_field_name(std::string name) const override;
std::string gen_var_name(const tl::var_description &desc) const override;
std::string gen_parameter_name(int index) const override;
std::string gen_type_name(const tl::tl_tree_type *tree_type) const override;
std::string gen_array_type_name(const tl::tl_tree_array *arr, const std::string &field_name) const override;
std::string gen_var_type_name() const override;
std::string gen_int_const(const tl::tl_tree *tree_c, const std::vector<tl::var_description> &vars) const override;
std::string gen_output_begin() const override;
std::string gen_output_end() const override;
std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const override;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const override;
std::string gen_class_end() const override;
std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const override;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const override;
std::string gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const override;
std::string gen_function_vars(const tl::tl_combinator *t, std::vector<tl::var_description> &vars) const override;
std::string gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const override;
std::string gen_constructor_id_store(std::int32_t id, int storer_type) const override;
std::string gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int parser_type) const override;
std::string gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int storer_type) const override;
std::string gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_var_type_fetch(const tl::arg &a) const override;
std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const override;
std::string gen_function_result_type(const tl::tl_tree *result) const override;
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity,
std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_fetch_function_end(bool has_parent, int field_num, const std::vector<tl::var_description> &vars,
int parser_type) const override;
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
const tl::tl_tree *result) const override;
std::string gen_fetch_function_result_end() const override;
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
bool is_proxy) const override;
std::string gen_fetch_function_result_any_end(bool is_proxy) const override;
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_store_function_end(const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_fetch_switch_begin() const override;
std::string gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const override;
std::string gen_fetch_switch_end() const override;
std::string gen_constructor_begin(int fields_num, const std::string &class_name, bool is_default) const override;
std::string gen_constructor_parameter(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const override;
std::string gen_constructor_field_init(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const override;
std::string gen_constructor_end(const tl::tl_combinator *t, int fields_num, bool is_default) const override;
};
} // namespace td

View file

@ -0,0 +1,676 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tl_writer_jni_cpp.h"
#include <cassert>
#include <cstdio>
namespace td {
bool TD_TL_writer_jni_cpp::is_built_in_simple_type(const std::string &name) const {
return name == "Bool" || name == "Int32" || name == "Int53" || name == "Int64" || name == "Double" ||
name == "String" || name == "Bytes" || name == "SecureString" || name == "SecureBytes";
}
bool TD_TL_writer_jni_cpp::is_built_in_complex_type(const std::string &name) const {
return name == "Vector";
}
int TD_TL_writer_jni_cpp::get_parser_type(const tl::tl_combinator *t, const std::string &parser_name) const {
return 1;
}
int TD_TL_writer_jni_cpp::get_additional_function_type(const std::string &additional_function_name) const {
return 1;
}
std::vector<std::string> TD_TL_writer_jni_cpp::get_parsers() const {
std::vector<std::string> parsers;
parsers.push_back("JNIEnv *env, jobject");
return parsers;
}
std::vector<std::string> TD_TL_writer_jni_cpp::get_storers() const {
std::vector<std::string> storers;
storers.push_back("JNIEnv *env, jobject");
storers.push_back("td::TlStorerToString");
return storers;
}
std::vector<std::string> TD_TL_writer_jni_cpp::get_additional_functions() const {
std::vector<std::string> additional_functions;
additional_functions.push_back("init_jni_vars");
return additional_functions;
}
std::string TD_TL_writer_jni_cpp::gen_base_type_class_name(int arity) const {
assert(arity == 0);
return "Object";
}
std::string TD_TL_writer_jni_cpp::gen_base_tl_class_name() const {
return "Object";
}
std::string TD_TL_writer_jni_cpp::gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const {
return "\n"
"jclass " +
class_name + "::Class;\n";
}
std::string TD_TL_writer_jni_cpp::gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const {
return "jfieldID " + class_name + "::" + field_name + "fieldID;\n";
}
std::string TD_TL_writer_jni_cpp::gen_constructor_id_store(std::int32_t id, int storer_type) const {
return "";
}
std::string TD_TL_writer_jni_cpp::gen_vector_fetch(std::string field_name, const tl::tl_tree_type *t,
const std::vector<tl::var_description> &vars,
int parser_type) const {
std::string vector_type = gen_type_name(t);
if (vector_type == "bool") {
assert(false); // TODO
}
std::string fetch_object = "td::jni::fetch_object(env, p, " + field_name + "fieldID)";
std::string array_type;
if (vector_type == "std::int32_t") {
array_type = "jintArray";
}
if (vector_type == "std::int64_t") {
array_type = "jlongArray";
}
if (vector_type == "double") {
array_type = "jdoubleArray";
}
if (!array_type.empty()) {
return "td::jni::fetch_vector(env, (" + array_type + ")" + fetch_object + ");";
}
std::string template_type;
if (vector_type == string_type) {
template_type = "std::string";
} else if (vector_type == secure_string_type) {
template_type = secure_string_type;
} else if (vector_type.compare(0, 11, "std::vector") == 0) {
const tl::tl_tree_type *child = static_cast<const tl::tl_tree_type *>(t->children[0]);
template_type = gen_type_name(child);
if (template_type.compare(0, 10, "object_ptr") == 0) {
template_type = gen_main_class_name(child->type);
}
template_type = "std::vector<" + template_type + ">";
} else if (vector_type == bytes_type) {
std::fprintf(stderr, "Vector of Bytes is not supported\n");
assert(false);
} else {
assert(vector_type.compare(0, 10, "object_ptr") == 0);
template_type = gen_main_class_name(t->type);
}
return "td::jni::FetchVector<" + template_type + ">::fetch(env, (jobjectArray)" + fetch_object + ");";
}
std::string TD_TL_writer_jni_cpp::gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const {
const tl::tl_type *t = tree_type->type;
const std::string &name = t->name;
assert(!(t->flags & tl::FLAG_DEFAULT_CONSTRUCTOR));
assert(parser_type == 1);
if (!(tree_type->flags & tl::FLAG_BARE)) {
if (is_type_bare(t)) {
if (field_name != "") {
std::fprintf(stderr, "Do not use non-bare fields with bare type %s\n", name.c_str());
// assert(false);
}
}
} else {
assert(is_type_bare(t));
}
std::string res_begin;
if (!field_name.empty()) {
res_begin = field_name + " = ";
}
std::string res;
assert(name != "#");
if (field_name.empty()) {
if (name == "Bool") {
return "env->CallObjectMethod(p, td::jni::BooleanGetValueMethodID)";
} else if (name == "Int32") {
return "env->CallObjectMethod(p, td::jni::IntegerGetValueMethodID)";
} else if (name == "Int53" || name == "Int64") {
return "env->CallObjectMethod(p, td::jni::LongGetValueMethodID)";
} else if (name == "Double") {
return "env->CallObjectMethod(p, td::jni::DoubleGetValueMethodID)";
} else if (name == "String") {
return "td::jni::from_jstring(env, (jstring)p)";
} else if (name == "Bytes") {
return "td::jni::from_bytes(env, (jbyteArray)p)";
} else if (name == "SecureString") {
return "td::jni::from_jstring_secure(env, (jstring)p)";
} else if (name == "SecureBytes") {
return "td::jni::from_bytes_secure(env, (jbyteArray)p)";
}
}
if (name == "Bool") {
res = "(env->GetBooleanField(p, " + field_name + "fieldID) != 0)";
} else if (name == "Int32") {
res = "env->GetIntField(p, " + field_name + "fieldID)";
} else if (name == "Int53" || name == "Int64") {
res = "env->GetLongField(p, " + field_name + "fieldID)";
} else if (name == "Double") {
res = "env->GetDoubleField(p, " + field_name + "fieldID)";
} else if (name == "String") {
res = "td::jni::fetch_string(env, p, " + field_name + "fieldID)";
} else if (name == "Bytes") {
res = "td::jni::from_bytes(env, (jbyteArray)td::jni::fetch_object(env, p, " + field_name + "fieldID))";
} else if (name == "SecureString") {
res = "td::jni::fetch_string_secure(env, p, " + field_name + "fieldID)";
} else if (name == "SecureBytes") {
res = "td::jni::from_bytes_secure(env, (jbyteArray)td::jni::fetch_object(env, p, " + field_name + "fieldID))";
} else if (name == "Vector") {
const tl::tl_tree_type *child = static_cast<const tl::tl_tree_type *>(tree_type->children[0]);
res = gen_vector_fetch(field_name, child, vars, parser_type);
} else {
if (field_name == "") {
return gen_main_class_name(tree_type->type) + "::fetch(env, p)";
}
res = "td::jni::fetch_tl_object<" + gen_main_class_name(tree_type->type) + ">(env, td::jni::fetch_object(env, p, " +
field_name + "fieldID));";
}
return res_begin + res;
}
std::string TD_TL_writer_jni_cpp::gen_field_fetch(int field_num, const tl::arg &a,
std::vector<tl::var_description> &vars, bool flat,
int parser_type) const {
assert(parser_type >= 0);
std::string field_name = (parser_type == 0 ? (field_num == 0 ? ": " : ", ") : "res->") + gen_field_name(a.name);
assert(a.exist_var_num == -1);
if (a.type->get_type() == tl::NODE_TYPE_VAR_TYPE) {
assert(parser_type == 1);
const tl::tl_tree_var_type *t = static_cast<const tl::tl_tree_var_type *>(a.type);
assert(a.flags == tl::FLAG_EXCL);
assert(a.var_num == -1);
assert(t->var_num >= 0);
assert(vars[t->var_num].is_type);
assert(!vars[t->var_num].is_stored);
vars[t->var_num].is_stored = true;
assert(false && "not supported");
return " " + field_name + " = " + gen_base_function_class_name() + "::fetch(env, p);\n";
}
assert(!(a.flags & tl::FLAG_EXCL));
assert(!(a.flags & tl::FLAG_OPT_VAR));
if (flat) {
// TODO
// return gen_field_fetch(const tl::arg &a, std::vector<tl::var_description> &vars, int num, bool flat);
}
assert(a.var_num == -1);
assert(a.type->get_type() == tl::NODE_TYPE_TYPE);
const tl::tl_tree_type *tree_type = static_cast<tl::tl_tree_type *>(a.type);
assert(parser_type != 0);
return " " + gen_type_fetch(field_name, tree_type, vars, parser_type) + ";\n";
}
std::string TD_TL_writer_jni_cpp::get_pretty_field_name(std::string field_name) const {
return gen_java_field_name(TD_TL_writer_cpp::get_pretty_field_name(field_name));
}
std::string TD_TL_writer_jni_cpp::get_pretty_class_name(std::string class_name) const {
if (class_name == "vector") {
return "Array";
}
return gen_basic_java_class_name(class_name);
}
std::string TD_TL_writer_jni_cpp::gen_vector_store(const std::string &field_name, const tl::tl_tree_type *t,
const std::vector<tl::var_description> &vars,
int storer_type) const {
if (storer_type == 1) {
return TD_TL_writer_cpp::gen_vector_store(field_name, t, vars, storer_type);
}
std::string vector_type = gen_type_name(t);
if (vector_type == "bool") {
assert(false); // TODO
}
if (vector_type == "std::int32_t" || vector_type == "std::int64_t" || vector_type == "double" ||
vector_type == string_type || vector_type == secure_string_type ||
vector_type.compare(0, 11, "std::vector") == 0 || vector_type.compare(0, 10, "object_ptr") == 0) {
return "{ "
"auto arr_tmp_ = td::jni::store_vector(env, " +
field_name +
"); "
"if (arr_tmp_) { "
"env->SetObjectField(s, " +
field_name +
"fieldID, arr_tmp_); "
"env->DeleteLocalRef(arr_tmp_); "
"} }";
}
if (vector_type == bytes_type) {
std::fprintf(stderr, "Vector of Bytes is not supported\n");
assert(false);
}
assert(false);
return "";
}
std::string TD_TL_writer_jni_cpp::gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const {
const tl::tl_type *t = tree_type->type;
const std::string &name = t->name;
assert(!field_name.empty());
assert(!(t->flags & tl::FLAG_DEFAULT_CONSTRUCTOR));
if (!(tree_type->flags & tl::FLAG_BARE)) {
if (storer_type == 0) {
if (is_type_bare(t)) {
std::fprintf(stderr, "Do not use non-bare fields with bare type %s\n", name.c_str());
// assert(false);
}
}
} else {
assert(is_type_bare(t));
}
std::string res;
if (name == "Int32" || name == "Int53" || name == "Int64" || name == "Double" || name == "Bool" || name == "String" ||
name == "SecureString") {
if (storer_type == 1) {
res = "s.store_field(\"" + get_pretty_field_name(field_name) + "\", " + field_name + ");";
} else if (name == "Bool") {
res = "env->SetBooleanField(s, " + field_name + "fieldID, " + field_name + ");";
} else if (name == "Int32") {
res = "env->SetIntField(s, " + field_name + "fieldID, " + field_name + ");";
} else if (name == "Int53" || name == "Int64") {
res = "env->SetLongField(s, " + field_name + "fieldID, " + field_name + ");";
} else if (name == "Double") {
res = "env->SetDoubleField(s, " + field_name + "fieldID, " + field_name + ");";
} else if (name == "String") {
res = "{ jstring nextString = td::jni::to_jstring(env, " + field_name +
"); if (nextString) { env->SetObjectField(s, " + field_name +
"fieldID, nextString); env->DeleteLocalRef(nextString); } }";
} else if (name == "SecureString") {
res = "{ jstring nextString = td::jni::to_jstring_secure(env, " + field_name +
"); if (nextString) { env->SetObjectField(s, " + field_name +
"fieldID, nextString); env->DeleteLocalRef(nextString); } }";
} else {
assert(false);
}
} else if (name == "Bytes") {
if (storer_type == 1) {
res = "s.store_bytes_field(\"" + get_pretty_field_name(field_name) + "\", " + field_name + ");";
} else {
res = "{ jbyteArray nextBytes = td::jni::to_bytes(env, " + field_name +
"); if (nextBytes) { env->SetObjectField(s, " + field_name +
"fieldID, nextBytes); env->DeleteLocalRef(nextBytes); } }";
}
} else if (name == "SecureBytes") {
if (storer_type == 1) {
res = "s.store_bytes_field(\"" + get_pretty_field_name(field_name) + "\", " + field_name + ");";
} else {
res = "{ jbyteArray nextBytes = td::jni::to_bytes_secure(env, " + field_name +
"); if (nextBytes) { env->SetObjectField(s, " + field_name +
"fieldID, nextBytes); env->DeleteLocalRef(nextBytes); } }";
}
} else if (name == "Vector") {
const tl::tl_tree_type *child = static_cast<const tl::tl_tree_type *>(tree_type->children[0]);
res = gen_vector_store(field_name, child, vars, storer_type);
} else {
if (storer_type == 1) {
res = "if (" + field_name + " == nullptr) { s.store_field(\"" + get_pretty_field_name(field_name) +
"\", \"null\"); } else { " + field_name + "->store(s, \"" + get_pretty_field_name(field_name) + "\"); }";
} else {
res = "if (" + field_name + " != nullptr) { jobject next; " + field_name +
"->store(env, next); if (next) { env->SetObjectField(s, " + field_name +
"fieldID, next); env->DeleteLocalRef(next); } }";
}
assert(tree_type->children.empty());
}
return res;
}
std::string TD_TL_writer_jni_cpp::gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int storer_type) const {
std::string field_name = gen_field_name(a.name);
std::string shift = storer_type == 1 ? " " : " ";
assert(a.exist_var_num == -1);
if (a.type->get_type() == tl::NODE_TYPE_VAR_TYPE) {
const tl::tl_tree_var_type *t = static_cast<const tl::tl_tree_var_type *>(a.type);
assert(a.flags == tl::FLAG_EXCL);
assert(a.var_num == -1);
assert(t->var_num >= 0);
assert(!vars[t->var_num].is_stored);
vars[t->var_num].is_stored = true;
assert(vars[t->var_num].is_type);
assert(false && "not supported");
return shift + field_name + "->store(env, s);\n";
}
assert(!(a.flags & tl::FLAG_EXCL));
assert(!(a.flags & tl::FLAG_OPT_VAR));
if (flat) {
// TODO
// return gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat, int storer_type);
}
assert(a.var_num == -1);
assert(a.type->get_type() == tl::NODE_TYPE_TYPE);
const tl::tl_tree_type *tree_type = static_cast<tl::tl_tree_type *>(a.type);
return shift + gen_type_store(field_name, tree_type, vars, storer_type) + "\n";
}
std::string TD_TL_writer_jni_cpp::gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const {
if (is_proxy) {
return "";
}
return "\nconst std::int32_t " + class_name + "::ID;\n";
}
std::string TD_TL_writer_jni_cpp::gen_fetch_function_begin(const std::string &parser_name,
const std::string &class_name,
const std::string &parent_class_name, int arity,
std::vector<tl::var_description> &vars,
int parser_type) const {
for (std::size_t i = 0; i < vars.size(); i++) {
assert(vars[i].is_stored == false);
}
std::string fetched_type = "object_ptr<" + class_name + "> ";
std::string returned_type = "object_ptr<" + parent_class_name + "> ";
assert(arity == 0);
assert(parser_type != 0);
return "\n" + returned_type + class_name + "::fetch(" + parser_name + " &p) {\n" +
(parser_type == -1 ? ""
: " if (p == nullptr) return nullptr;\n"
" " +
fetched_type + "res = make_object<" + class_name + ">();\n");
}
std::string TD_TL_writer_jni_cpp::gen_fetch_function_end(bool has_parent, int field_num,
const std::vector<tl::var_description> &vars,
int parser_type) const {
for (std::size_t i = 0; i < vars.size(); i++) {
assert(vars[i].is_stored);
}
assert(parser_type != 0);
if (parser_type == -1) {
return "}\n";
}
return " return " + std::string(has_parent ? "std::move(res)" : "res") +
";\n"
"}\n";
}
std::string TD_TL_writer_jni_cpp::gen_fetch_function_result_begin(const std::string &parser_name,
const std::string &class_name,
const tl::tl_tree *result) const {
return "\n" + class_name + "::ReturnType " + class_name + "::fetch_result(" + parser_name +
" &p) {\n"
" if (p == nullptr) return ReturnType();\n" +
" return ";
}
std::string TD_TL_writer_jni_cpp::gen_fetch_function_result_end() const {
return ";\n"
"}\n";
}
std::string TD_TL_writer_jni_cpp::gen_fetch_function_result_any_begin(const std::string &parser_name,
const std::string &class_name,
bool is_proxy) const {
return "";
}
std::string TD_TL_writer_jni_cpp::gen_fetch_function_result_any_end(bool is_proxy) const {
return "";
}
std::string TD_TL_writer_jni_cpp::gen_store_function_begin(const std::string &storer_name,
const std::string &class_name, int arity,
std::vector<tl::var_description> &vars,
int storer_type) const {
for (std::size_t i = 0; i < vars.size(); i++) {
vars[i].is_stored = false;
}
if (storer_type == -1) {
return "";
}
assert(arity == 0);
return "\n"
"void " +
class_name + "::store(" + storer_name + " &s" +
std::string(storer_type <= 0 ? "" : ", const char *field_name") + ") const {\n" +
(storer_type <= 0 ? " s = env->AllocObject(Class);\n"
" if (!s) { return; }\n"
: " if (!LOG_IS_STRIPPED(ERROR)) {\n"
" s.store_class_begin(field_name, \"" +
get_pretty_class_name(class_name) + "\");\n");
}
std::string TD_TL_writer_jni_cpp::gen_fetch_switch_begin() const {
return " if (p == nullptr) { return nullptr; }\n"
" auto id = env->CallIntMethod(p, td::jni::GetConstructorID);\n"
" switch (id) {\n";
}
std::string TD_TL_writer_jni_cpp::gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const {
assert(arity == 0);
return " case " + gen_class_name(t->name) +
"::ID:\n"
" return " +
gen_class_name(t->name) + "::fetch(env, p);\n";
}
std::string TD_TL_writer_jni_cpp::gen_fetch_switch_end() const {
return " default:\n"
" LOG(WARNING) << \"Unknown constructor found: \" << id;\n"
" return nullptr;\n"
" }\n";
}
std::string TD_TL_writer_jni_cpp::gen_java_field_name(std::string name) const {
std::string result;
bool next_to_upper = false;
for (std::size_t i = 0; i < name.size(); i++) {
if (!is_alnum(name[i])) {
next_to_upper = true;
continue;
}
if (next_to_upper) {
result += to_upper(name[i]);
next_to_upper = false;
} else {
result += name[i];
}
}
return result;
}
std::string TD_TL_writer_jni_cpp::gen_basic_java_class_name(std::string name) const {
std::string result;
bool next_to_upper = true;
for (std::size_t i = 0; i < name.size(); i++) {
if (!is_alnum(name[i])) {
next_to_upper = true;
continue;
}
if (next_to_upper) {
result += to_upper(name[i]);
next_to_upper = false;
} else {
result += name[i];
}
}
return result;
}
std::string TD_TL_writer_jni_cpp::gen_java_class_name(std::string name) const {
return "(PSLICE() << package_name << \"/TonApi$" + gen_basic_java_class_name(name) + "\").c_str()";
}
std::string TD_TL_writer_jni_cpp::gen_type_signature(const tl::tl_tree_type *tree_type) const {
const tl::tl_type *t = tree_type->type;
const std::string &name = t->name;
assert(name != "#");
assert(name != gen_base_tl_class_name());
if (name == "Bool") {
return "Z";
} else if (name == "Int32") {
return "I";
} else if (name == "Int53" || name == "Int64") {
return "J";
} else if (name == "Double") {
return "D";
} else if (name == "String" || name == "SecureString") {
return "Ljava/lang/String;";
} else if (name == "Bytes" || name == "SecureBytes") {
return "[B";
} else if (name == "Vector") {
const tl::tl_tree_type *child = static_cast<const tl::tl_tree_type *>(tree_type->children[0]);
return "[" + gen_type_signature(child);
} else {
return "L%PACKAGE_NAME%/TonApi$" + gen_basic_java_class_name(gen_main_class_name(t)) + ";";
}
assert(false);
return "";
}
std::string TD_TL_writer_jni_cpp::gen_additional_function(const std::string &function_name, const tl::tl_combinator *t,
bool is_function) const {
assert(function_name == "init_jni_vars");
std::string class_name = gen_class_name(t->name);
std::string class_name_class = "Class";
std::string res =
"\n"
"void " +
class_name + "::" + function_name +
"(JNIEnv *env, const char *package_name) {\n"
" " +
class_name_class + " = td::jni::get_jclass(env, " + gen_java_class_name(gen_class_name(t->name)) + ");\n";
if (t->args.size()) {
for (std::size_t i = 0; i < t->args.size(); i++) {
const tl::arg &a = t->args[i];
assert(a.type->get_type() == tl::NODE_TYPE_TYPE);
const tl::tl_tree_type *tree_type = static_cast<tl::tl_tree_type *>(a.type);
std::string field_name = gen_field_name(a.name);
assert(field_name.size());
std::string java_field_name = gen_java_field_name(std::string(field_name, 0, field_name.size() - 1));
std::string type_signature = gen_type_signature(tree_type);
if (type_signature.find("%PACKAGE_NAME%") == std::string::npos) {
type_signature = '"' + type_signature + '"';
} else {
std::string new_type_signature = "(PSLICE()";
std::size_t pos = type_signature.find("%PACKAGE_NAME%");
while (pos != std::string::npos) {
new_type_signature += " << \"" + type_signature.substr(0, pos) + "\" << package_name";
type_signature = type_signature.substr(pos + 14);
pos = type_signature.find("%PACKAGE_NAME%");
}
if (!type_signature.empty()) {
new_type_signature += " << \"" + type_signature + "\"";
}
type_signature = new_type_signature + ").c_str()";
}
res += " " + field_name + "fieldID = td::jni::get_field_id(env, " + class_name_class + ", \"" + java_field_name +
"\", " + type_signature + ");\n";
}
}
res += "}\n";
return res;
}
std::string TD_TL_writer_jni_cpp::gen_additional_proxy_function_begin(const std::string &function_name,
const tl::tl_type *type,
const std::string &class_name, int arity,
bool is_function) const {
assert(function_name == "init_jni_vars");
assert(arity == 0);
return "\n"
"void " +
class_name + "::" + function_name +
"(JNIEnv *env, const char *package_name) {\n"
" Class = td::jni::get_jclass(env, " +
gen_java_class_name(class_name) + ");\n";
}
std::string TD_TL_writer_jni_cpp::gen_additional_proxy_function_case(const std::string &function_name,
const tl::tl_type *type,
const std::string &class_name, int arity) const {
assert(function_name == "init_jni_vars");
assert(arity == 0);
return " " + class_name + "::" + function_name + "(env, package_name);\n";
}
std::string TD_TL_writer_jni_cpp::gen_additional_proxy_function_case(const std::string &function_name,
const tl::tl_type *type,
const tl::tl_combinator *t, int arity,
bool is_function) const {
assert(function_name == "init_jni_vars");
assert(arity == 0);
return " " + gen_class_name(t->name) + "::" + function_name + "(env, package_name);\n";
}
std::string TD_TL_writer_jni_cpp::gen_additional_proxy_function_end(const std::string &function_name,
const tl::tl_type *type, bool is_function) const {
assert(function_name == "init_jni_vars");
return "}\n";
}
} // namespace td

View file

@ -0,0 +1,123 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "tl_writer_cpp.h"
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_jni_cpp : public TD_TL_writer_cpp {
std::string gen_vector_fetch(std::string field_name, const tl::tl_tree_type *t,
const std::vector<tl::var_description> &vars, int parser_type) const;
std::string gen_vector_store(const std::string &field_name, const tl::tl_tree_type *t,
const std::vector<tl::var_description> &vars, int storer_type) const;
std::string package_name;
std::string gen_java_field_name(std::string name) const;
std::string gen_basic_java_class_name(std::string name) const;
std::string gen_java_class_name(std::string name) const;
std::string gen_type_signature(const tl::tl_tree_type *tree_type) const;
std::string get_pretty_field_name(std::string field_name) const override;
std::string get_pretty_class_name(std::string class_name) const override;
public:
TD_TL_writer_jni_cpp(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type,
const std::string &secure_string_type, const std::string &secure_bytes_type,
const std::vector<std::string> &ext_include)
: TD_TL_writer_cpp(tl_name, string_type, bytes_type, secure_string_type, secure_bytes_type, ext_include) {
}
bool is_built_in_simple_type(const std::string &name) const override;
bool is_built_in_complex_type(const std::string &name) const override;
int get_parser_type(const tl::tl_combinator *t, const std::string &parser_name) const override;
int get_additional_function_type(const std::string &additional_function_name) const override;
std::vector<std::string> get_parsers() const override;
std::vector<std::string> get_storers() const override;
std::vector<std::string> get_additional_functions() const override;
std::string gen_base_type_class_name(int arity) const override;
std::string gen_base_tl_class_name() const override;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const override;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const override;
std::string gen_constructor_id_store(std::int32_t id, int storer_type) const override;
std::string gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int parser_type) const override;
std::string gen_field_store(const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int storer_type) const override;
std::string gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const override;
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity,
std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_fetch_function_end(bool has_parent, int field_num, const std::vector<tl::var_description> &vars,
int parser_type) const override;
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
const tl::tl_tree *result) const override;
std::string gen_fetch_function_result_end() const override;
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
bool is_proxy) const override;
std::string gen_fetch_function_result_any_end(bool is_proxy) const override;
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_fetch_switch_begin() const override;
std::string gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const override;
std::string gen_fetch_switch_end() const override;
std::string gen_additional_function(const std::string &function_name, const tl::tl_combinator *t,
bool is_function) const override;
std::string gen_additional_proxy_function_begin(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity,
bool is_function) const override;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity) const override;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const tl::tl_combinator *t, int arity,
bool is_function) const override;
std::string gen_additional_proxy_function_end(const std::string &function_name, const tl::tl_type *type,
bool is_function) const override;
};
} // namespace td

View file

@ -0,0 +1,204 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tl_writer_jni_h.h"
#include <cassert>
namespace td {
bool TD_TL_writer_jni_h::is_built_in_simple_type(const std::string &name) const {
return name == "Bool" || name == "Int32" || name == "Int53" || name == "Int64" || name == "Double" ||
name == "String" || name == "Bytes" || name == "SecureString" || name == "SecureBytes";
}
bool TD_TL_writer_jni_h::is_built_in_complex_type(const std::string &name) const {
return name == "Vector";
}
int TD_TL_writer_jni_h::get_additional_function_type(const std::string &additional_function_name) const {
if (additional_function_name == "init_jni_vars") {
return 1;
}
return TD_TL_writer_h::get_additional_function_type(additional_function_name);
}
int TD_TL_writer_jni_h::get_parser_type(const tl::tl_combinator *t, const std::string &parser_name) const {
return 1;
}
std::vector<std::string> TD_TL_writer_jni_h::get_parsers() const {
std::vector<std::string> parsers;
parsers.push_back("JNIEnv *env, jobject");
return parsers;
}
std::vector<std::string> TD_TL_writer_jni_h::get_storers() const {
std::vector<std::string> storers;
storers.push_back("JNIEnv *env, jobject");
storers.push_back("td::TlStorerToString");
return storers;
}
std::vector<std::string> TD_TL_writer_jni_h::get_additional_functions() const {
std::vector<std::string> additional_functions = TD_TL_writer_h::get_additional_functions();
additional_functions.push_back("init_jni_vars");
return additional_functions;
}
std::string TD_TL_writer_jni_h::gen_base_type_class_name(int arity) const {
assert(arity == 0);
return "Object";
}
std::string TD_TL_writer_jni_h::gen_base_tl_class_name() const {
return "Object";
}
std::string TD_TL_writer_jni_h::gen_output_begin() const {
std::string ext_include_str;
for (auto &it : ext_include) {
ext_include_str += "#include " + it + "\n";
}
return "#pragma once\n\n"
"#include \"tl/TlObject.h\"\n\n"
"#include <cstdint>\n"
"#include <utility>\n"
"#include <vector>\n\n"
"#include <jni.h>\n\n" +
ext_include_str +
"\n"
"namespace td {\n" +
forward_declaration("TlStorerToString") + "}\n" +
"namespace ton {\n" + "namespace " + tl_name +
" {\n\n"
"class " +
gen_base_tl_class_name() +
";\n"
"using BaseObject = " +
gen_base_tl_class_name() +
";\n\n"
"template <class Type>\n"
"using object_ptr = ::ton::tl_object_ptr<Type>;\n\n"
"template <class Type, class... Args>\n"
"object_ptr<Type> make_object(Args &&... args) {\n"
" return object_ptr<Type>(new Type(std::forward<Args>(args)...));\n"
"}\n\n"
"template <class ToType, class FromType>\n"
"object_ptr<ToType> move_object_as(FromType &&from) {\n"
" return object_ptr<ToType>(static_cast<ToType *>(from.release()));\n"
"}\n\n"
"std::string to_string(const BaseObject &value);\n\n"
"template <class T>\n"
"std::string to_string(const object_ptr<T> &value) {\n"
" if (value == nullptr) {\n"
" return \"null\";\n"
" }\n"
"\n"
" return to_string(*value);\n"
"}\n\n";
}
std::string TD_TL_writer_jni_h::gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const {
if (class_name == gen_base_tl_class_name()) {
return "class " + class_name +
" {\n"
" public:\n"
" virtual ~" +
class_name +
"() {\n"
" }\n\n" +
" virtual void store(JNIEnv *env, jobject &s) const {\n"
" }\n\n"
" virtual void store(td::TlStorerToString &s, const char *field_name) const = 0;\n\n"
" static jclass Class;\n";
}
return "class " + class_name + (!is_proxy ? " final " : "") + ": public " + base_class_name +
" {\n"
" public:\n"
" static jclass Class;\n";
}
std::string TD_TL_writer_jni_h::gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const {
return TD_TL_writer_h::gen_field_definition(class_name, type_name, field_name) + " static jfieldID " + field_name +
"fieldID;\n";
}
std::string TD_TL_writer_jni_h::gen_additional_function(const std::string &function_name, const tl::tl_combinator *t,
bool is_function) const {
if (function_name == "init_jni_vars") {
return "\n"
" static void " +
function_name + "(JNIEnv *env, const char *package_name);\n";
}
return TD_TL_writer_h::gen_additional_function(function_name, t, is_function);
}
std::string TD_TL_writer_jni_h::gen_additional_proxy_function_begin(const std::string &function_name,
const tl::tl_type *type,
const std::string &class_name, int arity,
bool is_function) const {
if (function_name == "init_jni_vars") {
return "\n"
" static void " +
function_name + "(JNIEnv *env, const char *package_name);\n";
}
return TD_TL_writer_h::gen_additional_proxy_function_begin(function_name, type, class_name, arity, is_function);
}
std::string TD_TL_writer_jni_h::gen_additional_proxy_function_case(const std::string &function_name,
const tl::tl_type *type,
const std::string &class_name, int arity) const {
if (function_name == "init_jni_vars") {
return "";
}
return TD_TL_writer_h::gen_additional_proxy_function_case(function_name, type, class_name, arity);
}
std::string TD_TL_writer_jni_h::gen_additional_proxy_function_case(const std::string &function_name,
const tl::tl_type *type, const tl::tl_combinator *t,
int arity, bool is_function) const {
if (function_name == "init_jni_vars") {
return "";
}
return TD_TL_writer_h::gen_additional_proxy_function_case(function_name, type, t, arity, is_function);
}
std::string TD_TL_writer_jni_h::gen_additional_proxy_function_end(const std::string &function_name,
const tl::tl_type *type, bool is_function) const {
if (function_name == "init_jni_vars") {
return "";
}
return TD_TL_writer_h::gen_additional_proxy_function_end(function_name, type, is_function);
}
} // namespace td

View file

@ -0,0 +1,70 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "tl_writer_h.h"
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_jni_h : public TD_TL_writer_h {
public:
TD_TL_writer_jni_h(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type,
const std::string &secure_string_type, const std::string &secure_bytes_type,
const std::vector<std::string> &ext_include)
: TD_TL_writer_h(tl_name, string_type, bytes_type, secure_string_type, secure_bytes_type, ext_include) {
}
bool is_built_in_simple_type(const std::string &name) const override;
bool is_built_in_complex_type(const std::string &name) const override;
int get_parser_type(const tl::tl_combinator *t, const std::string &parser_name) const override;
int get_additional_function_type(const std::string &additional_function_name) const override;
std::vector<std::string> get_parsers() const override;
std::vector<std::string> get_storers() const override;
std::vector<std::string> get_additional_functions() const override;
std::string gen_base_type_class_name(int arity) const override;
std::string gen_base_tl_class_name() const override;
std::string gen_output_begin() const override;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name,
bool is_proxy) const override;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const override;
std::string gen_additional_function(const std::string &function_name, const tl::tl_combinator *t,
bool is_function) const override;
std::string gen_additional_proxy_function_begin(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity,
bool is_function) const override;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity) const override;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const tl::tl_combinator *t, int arity,
bool is_function) const override;
std::string gen_additional_proxy_function_end(const std::string &function_name, const tl::tl_type *type,
bool is_function) const override;
};
} // namespace td

View file

@ -0,0 +1,276 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tl_writer_td.h"
#include <iostream>
#include <cassert>
namespace td {
const int TD_TL_writer::MAX_ARITY;
const std::string TD_TL_writer::base_type_class_names[MAX_ARITY + 1] = {"Object"};
const std::string TD_TL_writer::base_tl_class_name = "TlObject";
const std::string TD_TL_writer::base_function_class_name = "Function";
int TD_TL_writer::get_max_arity() const {
return MAX_ARITY;
}
bool TD_TL_writer::is_built_in_simple_type(const std::string &name) const {
return name == "True" || name == "Bool" || name == "Int" || name == "Long" || name == "Double" || name == "String" ||
name == "Int32" || name == "Int53" || name == "Int64" || name == "Int128" || name == "Int256" ||
name == "Bytes" || name == "SecureString" || name == "SecureBytes" || name == "Function" || name == "Object";
}
bool TD_TL_writer::is_built_in_complex_type(const std::string &name) const {
return name == "Vector";
}
bool TD_TL_writer::is_type_bare(const tl::tl_type *t) const {
return t->simple_constructors <= 1 || (is_built_in_simple_type(t->name) && t->name != "Bool") ||
is_built_in_complex_type(t->name);
}
bool TD_TL_writer::is_combinator_supported(const tl::tl_combinator *constructor) const {
if (!TL_writer::is_combinator_supported(constructor)) {
return false;
}
for (std::size_t i = 0; i < constructor->args.size(); i++) {
if (constructor->args[i].type->get_type() == tl::NODE_TYPE_VAR_TYPE) {
return false;
}
}
return true;
}
int TD_TL_writer::get_storer_type(const tl::tl_combinator *t, const std::string &storer_name) const {
return storer_name == "td::TlStorerToString" || storer_name == "TlStorerToString";
}
tl::TL_writer::Mode TD_TL_writer::get_parser_mode(int type) const {
if (tl_name == "tonlib_api") {
#ifndef TD_ENABLE_JNI // we need to parse all types in order to implement toString
return Server;
#endif
}
return All;
}
tl::TL_writer::Mode TD_TL_writer::get_storer_mode(int type) const {
if (type == 1) {
return All;
}
if (tl_name == "td_api") {
return Server;
}
if (tl_name == "telegram_api") {
return Client;
}
return All;
}
std::vector<std::string> TD_TL_writer::get_parsers() const {
std::vector<std::string> parsers;
if (tl_name == "ton_api" || tl_name == "lite_api") {
parsers.push_back("td::TlParser");
}
return parsers;
}
std::vector<std::string> TD_TL_writer::get_storers() const {
std::vector<std::string> storers;
if (tl_name == "ton_api" || tl_name == "lite_api") {
storers.push_back("td::TlStorerCalcLength");
storers.push_back("td::TlStorerUnsafe");
}
storers.push_back("td::TlStorerToString");
return storers;
}
std::string TD_TL_writer::gen_base_tl_class_name() const {
return base_tl_class_name;
}
std::string TD_TL_writer::gen_base_type_class_name(int arity) const {
assert(arity == 0);
return base_type_class_names[arity];
}
std::string TD_TL_writer::gen_base_function_class_name() const {
return base_function_class_name;
}
std::string TD_TL_writer::gen_class_name(std::string name) const {
if (name == "Object") {
//assert(false);
}
if (name == "#") {
return "std::int32_t";
}
for (std::size_t i = 0; i < name.size(); i++) {
if (!is_alnum(name[i])) {
name[i] = '_';
}
}
return name;
}
std::string TD_TL_writer::gen_field_name(std::string name) const {
for (std::size_t i = 0; i < name.size(); i++) {
if (!is_alnum(name[i])) {
name[i] = '_';
}
}
assert(name.size() > 0);
assert(name[name.size() - 1] != '_');
return name + "_";
}
std::string TD_TL_writer::gen_var_name(const tl::var_description &desc) const {
assert(!desc.is_type);
if (desc.parameter_num != -1) {
assert(false);
}
return "var" + int_to_string(desc.index);
}
std::string TD_TL_writer::gen_parameter_name(int index) const {
assert(false);
return std::string();
}
std::string TD_TL_writer::gen_type_name(const tl::tl_tree_type *tree_type) const {
const tl::tl_type *t = tree_type->type;
const std::string &name = t->name;
if (name == "#") {
return "std::int32_t";
}
if (name == "True") {
return "bool";
}
if (name == "Bool") {
return "bool";
}
if (name == "Int" || name == "Int32") {
return "std::int32_t";
}
if (name == "Long" || name == "Int53" || name == "Int64") {
return "std::int64_t";
}
if (name == "Double") {
return "double";
}
if (name == "String") {
return string_type;
}
if (name == "Int128") {
return "td::Bits128";
}
if (name == "Int256") {
return "td::Bits256";
}
if (name == "Bytes") {
return bytes_type;
}
if (name == "SecureString") {
return secure_string_type;
}
if (name == "SecureBytes") {
return secure_bytes_type;
}
if (name == "Object") {
return "object_ptr<" + gen_base_type_class_name(0) + ">";
}
if (name == "Function") {
return "object_ptr<" + gen_base_function_class_name() + ">";
}
if (name == "Vector") {
assert(t->arity == 1);
assert(tree_type->children.size() == 1);
assert(tree_type->children[0]->get_type() == tl::NODE_TYPE_TYPE);
const tl::tl_tree_type *child = static_cast<const tl::tl_tree_type *>(tree_type->children[0]);
return "std::vector<" + gen_type_name(child) + ">";
}
assert(!is_built_in_simple_type(name) && !is_built_in_complex_type(name));
for (std::size_t i = 0; i < tree_type->children.size(); i++) {
assert(tree_type->children[i]->get_type() == tl::NODE_TYPE_NAT_CONST);
}
return "object_ptr<" + gen_main_class_name(t) + ">";
}
std::string TD_TL_writer::gen_array_type_name(const tl::tl_tree_array *arr, const std::string &field_name) const {
assert(false);
return std::string();
}
std::string TD_TL_writer::gen_var_type_name() const {
return "object_ptr<" + gen_base_function_class_name() + ">";
}
std::string TD_TL_writer::gen_int_const(const tl::tl_tree *tree_c, const std::vector<tl::var_description> &vars) const {
assert(false);
return std::string();
}
std::string TD_TL_writer::gen_constructor_parameter(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const {
if (is_default) {
return "";
}
std::string field_type = gen_field_type(a);
if (field_type.empty()) {
return "";
}
if (field_type[field_type.size() - 1] != ' ') {
field_type += ' ';
}
std::string res = (field_num == 0 ? "" : ", ");
if (field_type == "bool " || field_type == "std::int32_t " || field_type == "std::int64_t " ||
field_type == "double ") {
res += field_type;
} else if (field_type == "td::Bits128 " || field_type == "td::Bits256 " || field_type == string_type + " ") {
res += field_type + "const &";
} else if (field_type.compare(0, 11, "std::vector") == 0 || field_type == bytes_type + " " ||
field_type == secure_string_type + " " || field_type == secure_bytes_type + " ") {
res += field_type + "&&";
} else if (field_type.compare(0, 10, "object_ptr") == 0) {
res += field_type + "&&";
} else {
std::cerr << field_type << "\n";
assert(false && "unreachable");
}
return res + gen_field_name(a.name);
}
} // namespace td

View file

@ -0,0 +1,81 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "td/tl/tl_writer.h"
#include <string>
#include <vector>
namespace td {
class TD_TL_writer : public tl::TL_writer {
static const int MAX_ARITY = 0;
static const std::string base_type_class_names[MAX_ARITY + 1];
static const std::string base_tl_class_name;
static const std::string base_function_class_name;
protected:
const std::string string_type;
const std::string bytes_type;
const std::string secure_string_type;
const std::string secure_bytes_type;
public:
TD_TL_writer(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type,
const std::string &secure_string_type, const std::string &secure_bytes_type)
: TL_writer(tl_name)
, string_type(string_type)
, bytes_type(bytes_type)
, secure_string_type(secure_string_type)
, secure_bytes_type(secure_bytes_type) {
}
int get_max_arity() const override;
bool is_built_in_simple_type(const std::string &name) const override;
bool is_built_in_complex_type(const std::string &name) const override;
bool is_type_bare(const tl::tl_type *t) const override;
bool is_combinator_supported(const tl::tl_combinator *constructor) const override;
int get_storer_type(const tl::tl_combinator *t, const std::string &storer_name) const override;
Mode get_parser_mode(int type) const override;
Mode get_storer_mode(int type) const override;
std::vector<std::string> get_parsers() const override;
std::vector<std::string> get_storers() const override;
std::string gen_base_tl_class_name() const override;
std::string gen_base_type_class_name(int arity) const override;
std::string gen_base_function_class_name() const override;
std::string gen_class_name(std::string name) const override;
std::string gen_field_name(std::string name) const override;
std::string gen_var_name(const tl::var_description &desc) const override;
std::string gen_parameter_name(int index) const override;
std::string gen_type_name(const tl::tl_tree_type *tree_type) const override;
std::string gen_array_type_name(const tl::tl_tree_array *arr, const std::string &field_name) const override;
std::string gen_var_type_name() const override;
std::string gen_int_const(const tl::tl_tree *tree_c, const std::vector<tl::var_description> &vars) const override;
std::string gen_constructor_parameter(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const override;
};
} // namespace td

177
tl/tl/TlObject.h Normal file
View file

@ -0,0 +1,177 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
/**
* \file
* Contains declarations of a base class for all TL-objects and some helper methods
*/
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
namespace td {
class TlStorerCalcLength;
class TlStorerUnsafe;
class TlStorerToString;
} // namespace td
namespace ton {
/**
* This class is a base class for all TL-objects.
*/
class TlObject {
public:
/**
* Returns identifier uniquely determining TL-type of the object.
*/
virtual std::int32_t get_id() const = 0;
/**
* Appends object to the storer serializing object to a buffer of fixed length.
* \param[in] s Storer to which object will be appended.
*/
virtual void store(td::TlStorerUnsafe &s) const {
}
/**
* Appends object to the storer calculating TL-length of the serialized object.
* \param[in] s Storer to which object will be appended.
*/
virtual void store(td::TlStorerCalcLength &s) const {
}
/**
* Helper function for to_string method. Appends string representation of the object to the storer.
* \param[in] s Storer to which object string representation will be appended.
* \param[in] field_name Object field_name if applicable.
*/
virtual void store(td::TlStorerToString &s, const char *field_name) const = 0;
/**
* Default constructor.
*/
TlObject() = default;
/**
* Deleted copy constructor.
*/
TlObject(const TlObject &) = delete;
/**
* Deleted copy assignment operator.
*/
TlObject &operator=(const TlObject &) = delete;
/**
* Default move constructor.
*/
TlObject(TlObject &&) = default;
/**
* Default move assignment operator.
*/
TlObject &operator=(TlObject &&) = default;
/**
* Virtual desctructor.
*/
virtual ~TlObject() = default;
};
/**
* A smart wrapper to store a pointer to a TL-object.
*/
template <class Type>
using tl_object_ptr = std::unique_ptr<Type>;
/**
* A function to create a dynamically allocated TL-object. Can be treated as an analogue of std::make_unique.
* Examples of usage:
* \code
* auto get_auth_state_request = td::create_tl_object<td::td_api::getAuthState>();
* auto send_message_request = td::create_tl_object<td::td_api::sendMessage>(chat_id, 0, false, false, nullptr,
* td::create_tl_object<td::td_api::inputMessageText>("Hello, world!!!", false, true, {}, nullptr));
* \endcode
*
* \tparam Type Type of a TL-object to construct.
* \param[in] args Arguments to pass to the object constructor.
* \return Wrapped pointer to the created TL-object.
*/
template <class Type, class... Args>
tl_object_ptr<Type> create_tl_object(Args &&... args) {
return tl_object_ptr<Type>(new Type(std::forward<Args>(args)...));
}
/**
* A function to downcast a wrapped pointer to TL-object to a pointer to its subclass.
* It is undefined behaviour to cast an object to the wrong type.
* Examples of usage:
* \code
* td::tl_object_ptr<td::td_api::AuthState> auth_state = ...;
* switch (auth_state->get_id()) {
* case td::td_api::authStateWaitPhoneNumber::ID: {
* auto state = td::move_tl_object_as<td::td_api::authStateWaitPhoneNumber>(auth_state);
* // use state
* break;
* }
* case td::td_api::authStateWaitCode::ID: {
* auto state = td::move_tl_object_as<td::td_api::authStateWaitCode>(auth_state);
* // use state
* break;
* }
* case td::td_api::authStateWaitPassword::ID: {
* auto state = td::move_tl_object_as<td::td_api::authStateWaitPassword>(auth_state);
* // use state
* break;
* }
* case td::td_api::authStateOk::ID: {
* auto state = td::move_tl_object_as<td::td_api::authStateOk>(auth_state);
* // use state
* break;
* }
* case td::td_api::authStateLoggingOut::ID: {
* auto state = td::move_tl_object_as<td::td_api::authStateLoggingOut>(auth_state);
* // use state
* break;
* }
* }
* \endcode
*
* \tparam ToT Type of a TL-object to move to.
* \tparam FromT Type of a TL-object to move from, auto-deduced.
* \param[in] from Wrapped pointer to a TL-object.
*/
template <class ToT, class FromT>
tl_object_ptr<ToT> move_tl_object_as(tl_object_ptr<FromT> &from) {
return tl_object_ptr<ToT>(static_cast<ToT *>(from.release()));
}
/**
* \overload
*/
template <class ToT, class FromT>
tl_object_ptr<ToT> move_tl_object_as(tl_object_ptr<FromT> &&from) {
return tl_object_ptr<ToT>(static_cast<ToT *>(from.release()));
}
} // namespace ton

416
tl/tl/tl_jni_object.cpp Normal file
View file

@ -0,0 +1,416 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tl_jni_object.h"
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include <memory>
namespace td {
namespace jni {
thread_local bool parse_error;
static jclass BooleanClass;
static jclass IntegerClass;
static jclass LongClass;
static jclass DoubleClass;
static jclass StringClass;
static jclass ObjectClass;
jmethodID GetConstructorID;
jmethodID BooleanGetValueMethodID;
jmethodID IntegerGetValueMethodID;
jmethodID LongGetValueMethodID;
jmethodID DoubleGetValueMethodID;
static void fatal_error(JNIEnv *env, CSlice error) {
LOG(ERROR) << error;
env->FatalError(error.c_str());
}
jclass get_jclass(JNIEnv *env, const char *class_name) {
jclass clazz = env->FindClass(class_name);
if (!clazz) {
fatal_error(env, PSLICE() << "Can't find class [" << class_name << "]");
}
jclass clazz_global = (jclass)env->NewGlobalRef(clazz);
env->DeleteLocalRef(clazz);
if (!clazz_global) {
fatal_error(env, PSLICE() << "Can't create global reference to [" << class_name << "]");
}
return clazz_global;
}
jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name, const char *signature) {
jmethodID res = env->GetMethodID(clazz, name, signature);
if (!res) {
fatal_error(env, PSLICE() << "Can't find method [" << name << "] with signature [" << signature << "]");
}
return res;
}
jfieldID get_field_id(JNIEnv *env, jclass clazz, const char *name, const char *signature) {
jfieldID res = env->GetFieldID(clazz, name, signature);
if (!res) {
fatal_error(env, PSLICE() << "Can't find field [" << name << "] with signature [" << signature << "]");
}
return res;
}
void register_native_method(JNIEnv *env, jclass clazz, std::string name, std::string signature, void *function_ptr) {
JNINativeMethod native_method{&name[0], &signature[0], function_ptr};
if (env->RegisterNatives(clazz, &native_method, 1) != 0) {
fatal_error(env, PSLICE() << "RegisterNatives failed for " << name << " with signature " << signature);
}
}
std::unique_ptr<JNIEnv, JvmThreadDetacher> get_jni_env(JavaVM *java_vm, jint jni_version) {
JNIEnv *env = nullptr;
if (java_vm->GetEnv(reinterpret_cast<void **>(&env), jni_version) == JNI_EDETACHED) {
#ifdef JDK1_2 // if not Android JNI
auto p_env = reinterpret_cast<void **>(&env);
#else
auto p_env = &env;
#endif
java_vm->AttachCurrentThread(p_env, nullptr);
} else {
java_vm = nullptr;
}
return std::unique_ptr<JNIEnv, JvmThreadDetacher>(env, JvmThreadDetacher(java_vm));
}
void init_vars(JNIEnv *env, const char *td_api_java_package) {
BooleanClass = get_jclass(env, "java/lang/Boolean");
IntegerClass = get_jclass(env, "java/lang/Integer");
LongClass = get_jclass(env, "java/lang/Long");
DoubleClass = get_jclass(env, "java/lang/Double");
StringClass = get_jclass(env, "java/lang/String");
ObjectClass = get_jclass(env, (PSLICE() << td_api_java_package << "/TonApi$Object").c_str());
GetConstructorID = get_method_id(env, ObjectClass, "getConstructor", "()I");
BooleanGetValueMethodID = get_method_id(env, BooleanClass, "booleanValue", "()Z");
IntegerGetValueMethodID = get_method_id(env, IntegerClass, "intValue", "()I");
LongGetValueMethodID = get_method_id(env, LongClass, "longValue", "()J");
DoubleGetValueMethodID = get_method_id(env, DoubleClass, "doubleValue", "()D");
}
static size_t get_utf8_from_utf16_length(const jchar *p, jsize len) {
size_t result = 0;
for (jsize i = 0; i < len; i++) {
unsigned int cur = p[i];
if ((cur & 0xF800) == 0xD800) {
if (i < len) {
unsigned int next = p[++i];
if ((next & 0xFC00) == 0xDC00 && (cur & 0x400) == 0) {
result += 4;
continue;
}
}
// TODO wrong UTF-16, it is possible
return 0;
}
result += 1 + (cur >= 0x80) + (cur >= 0x800);
}
return result;
}
static void utf16_to_utf8(const jchar *p, jsize len, char *res) {
for (jsize i = 0; i < len; i++) {
unsigned int cur = p[i];
// TODO conversion unsigned int -> signed char is implementation defined
if (cur <= 0x7f) {
*res++ = static_cast<char>(cur);
} else if (cur <= 0x7ff) {
*res++ = static_cast<char>(0xc0 | (cur >> 6));
*res++ = static_cast<char>(0x80 | (cur & 0x3f));
} else if ((cur & 0xF800) != 0xD800) {
*res++ = static_cast<char>(0xe0 | (cur >> 12));
*res++ = static_cast<char>(0x80 | ((cur >> 6) & 0x3f));
*res++ = static_cast<char>(0x80 | (cur & 0x3f));
} else {
// correctness is already checked
unsigned int next = p[++i];
unsigned int val = ((cur - 0xD800) << 10) + next - 0xDC00 + 0x10000;
*res++ = static_cast<char>(0xf0 | (val >> 18));
*res++ = static_cast<char>(0x80 | ((val >> 12) & 0x3f));
*res++ = static_cast<char>(0x80 | ((val >> 6) & 0x3f));
*res++ = static_cast<char>(0x80 | (val & 0x3f));
}
}
}
static jsize get_utf16_from_utf8_length(const char *p, size_t len, jsize *surrogates) {
// UTF-8 correctness is supposed
jsize result = 0;
for (size_t i = 0; i < len; i++) {
result += ((p[i] & 0xc0) != 0x80);
*surrogates += ((p[i] & 0xf8) == 0xf0);
}
return result;
}
static void utf8_to_utf16(const char *p, size_t len, jchar *res) {
// UTF-8 correctness is supposed
for (size_t i = 0; i < len;) {
unsigned int a = static_cast<unsigned char>(p[i++]);
if (a >= 0x80) {
unsigned int b = static_cast<unsigned char>(p[i++]);
if (a >= 0xe0) {
unsigned int c = static_cast<unsigned char>(p[i++]);
if (a >= 0xf0) {
unsigned int d = static_cast<unsigned char>(p[i++]);
unsigned int val = ((a & 0x07) << 18) + ((b & 0x3f) << 12) + ((c & 0x3f) << 6) + (d & 0x3f) - 0x10000;
*res++ = static_cast<jchar>(0xD800 + (val >> 10));
*res++ = static_cast<jchar>(0xDC00 + (val & 0x3ff));
} else {
*res++ = static_cast<jchar>(((a & 0x0f) << 12) + ((b & 0x3f) << 6) + (c & 0x3f));
}
} else {
*res++ = static_cast<jchar>(((a & 0x1f) << 6) + (b & 0x3f));
}
} else {
*res++ = static_cast<jchar>(a);
}
}
}
std::string fetch_string(JNIEnv *env, jobject o, jfieldID id) {
jstring s = (jstring)env->GetObjectField(o, id);
if (s == nullptr) {
// treat null as an empty string
return std::string();
}
std::string res = from_jstring(env, s);
env->DeleteLocalRef(s);
return res;
}
SecureString fetch_string_secure(JNIEnv *env, jobject o, jfieldID id) {
jstring s = (jstring)env->GetObjectField(o, id);
if (s == nullptr) {
// treat null as an empty string
return {};
}
auto res = from_jstring_secure(env, s);
env->DeleteLocalRef(s);
return res;
}
template <class T>
T do_from_jstring(JNIEnv *env, jstring s) {
if (!s) {
return T{};
}
jsize s_len = env->GetStringLength(s);
const jchar *p = env->GetStringChars(s, nullptr);
if (p == nullptr) {
parse_error = true;
return T{};
}
size_t len = get_utf8_from_utf16_length(p, s_len);
T res(len, '\0');
if (len) {
utf16_to_utf8(p, s_len, as_mutable_slice(res).begin());
}
env->ReleaseStringChars(s, p);
return res;
}
std::string from_jstring(JNIEnv *env, jstring s) {
return do_from_jstring<std::string>(env, s);
}
jstring do_to_jstring(JNIEnv *env, CSlice s) {
jsize surrogates = 0;
jsize unicode_len = get_utf16_from_utf8_length(s.c_str(), s.size(), &surrogates);
if (surrogates == 0) {
// TODO '\0'
return env->NewStringUTF(s.c_str());
}
jsize result_len = surrogates + unicode_len;
if (result_len <= 256) {
jchar result[256];
utf8_to_utf16(s.c_str(), s.size(), result);
return env->NewString(result, result_len);
}
auto result = std::make_unique<jchar[]>(result_len);
utf8_to_utf16(s.c_str(), s.size(), result.get());
return env->NewString(result.get(), result_len);
}
jstring to_jstring(JNIEnv *env, const std::string &s) {
return do_to_jstring(env, s);
}
template <class T>
T do_from_bytes(JNIEnv *env, jbyteArray arr) {
T b;
if (arr != nullptr) {
jsize length = env->GetArrayLength(arr);
if (length != 0) {
b = T(narrow_cast<size_t>(length), '\0');
env->GetByteArrayRegion(arr, 0, length, reinterpret_cast<jbyte *>(as_mutable_slice(b).begin()));
}
env->DeleteLocalRef(arr);
}
return b;
}
std::string from_bytes(JNIEnv *env, jbyteArray arr) {
return do_from_bytes<std::string>(env, arr);
}
jbyteArray to_bytes(JNIEnv *env, Slice b) {
static_assert(sizeof(char) == sizeof(jbyte), "Mismatched jbyte size");
jsize length = narrow_cast<jsize>(b.size());
jbyteArray arr = env->NewByteArray(length);
if (arr != nullptr && length != 0) {
env->SetByteArrayRegion(arr, 0, length, reinterpret_cast<const jbyte *>(b.data()));
}
return arr;
}
SecureString from_jstring_secure(JNIEnv *env, jstring s) {
return do_from_jstring<SecureString>(env, s);
}
jstring to_jstring_secure(JNIEnv *env, Slice s) {
SecureString cstr(s.size() + 1);
cstr.as_mutable_slice().copy_from(s);
cstr.as_mutable_slice().back() = 0;
return do_to_jstring(env, CSlice(cstr.data(), cstr.data() + s.size()));
}
SecureString from_bytes_secure(JNIEnv *env, jbyteArray arr) {
return do_from_bytes<SecureString>(env, arr);
}
jbyteArray to_bytes_secure(JNIEnv *env, Slice b) {
return to_bytes(env, b);
}
jintArray store_vector(JNIEnv *env, const std::vector<std::int32_t> &v) {
static_assert(sizeof(std::int32_t) == sizeof(jint), "Mismatched jint size");
jsize length = narrow_cast<jsize>(v.size());
jintArray arr = env->NewIntArray(length);
if (arr != nullptr && length != 0) {
env->SetIntArrayRegion(arr, 0, length, reinterpret_cast<const jint *>(&v[0]));
}
return arr;
}
jlongArray store_vector(JNIEnv *env, const std::vector<std::int64_t> &v) {
static_assert(sizeof(std::int64_t) == sizeof(jlong), "Mismatched jlong size");
jsize length = narrow_cast<jsize>(v.size());
jlongArray arr = env->NewLongArray(length);
if (arr != nullptr && length != 0) {
env->SetLongArrayRegion(arr, 0, length, reinterpret_cast<const jlong *>(&v[0]));
}
return arr;
}
jdoubleArray store_vector(JNIEnv *env, const std::vector<double> &v) {
static_assert(sizeof(double) == sizeof(jdouble), "Mismatched jdouble size");
jsize length = narrow_cast<jsize>(v.size());
jdoubleArray arr = env->NewDoubleArray(length);
if (arr != nullptr && length != 0) {
env->SetDoubleArrayRegion(arr, 0, length, reinterpret_cast<const jdouble *>(&v[0]));
}
return arr;
}
jobjectArray store_vector(JNIEnv *env, const std::vector<std::string> &v) {
jsize length = narrow_cast<jsize>(v.size());
jobjectArray arr = env->NewObjectArray(length, StringClass, 0);
if (arr != nullptr) {
for (jsize i = 0; i < length; i++) {
jstring str = to_jstring(env, v[i]);
if (str) {
env->SetObjectArrayElement(arr, i, str);
env->DeleteLocalRef(str);
}
}
}
return arr;
}
jobjectArray store_vector(JNIEnv *env, const std::vector<SecureString> &v) {
jsize length = narrow_cast<jsize>(v.size());
jobjectArray arr = env->NewObjectArray(length, StringClass, 0);
if (arr != nullptr) {
for (jsize i = 0; i < length; i++) {
jstring str = to_jstring_secure(env, v[i]);
if (str) {
env->SetObjectArrayElement(arr, i, str);
env->DeleteLocalRef(str);
}
}
}
return arr;
}
std::vector<std::int32_t> fetch_vector(JNIEnv *env, jintArray arr) {
std::vector<std::int32_t> result;
if (arr != nullptr) {
jsize length = env->GetArrayLength(arr);
if (length != 0) {
result.resize(length);
env->GetIntArrayRegion(arr, 0, length, reinterpret_cast<jint *>(&result[0]));
}
env->DeleteLocalRef(arr);
}
return result;
}
std::vector<std::int64_t> fetch_vector(JNIEnv *env, jlongArray arr) {
std::vector<std::int64_t> result;
if (arr != nullptr) {
jsize length = env->GetArrayLength(arr);
if (length != 0) {
result.resize(length);
env->GetLongArrayRegion(arr, 0, length, reinterpret_cast<jlong *>(&result[0]));
}
env->DeleteLocalRef(arr);
}
return result;
}
std::vector<double> fetch_vector(JNIEnv *env, jdoubleArray arr) {
std::vector<double> result;
if (arr != nullptr) {
jsize length = env->GetArrayLength(arr);
if (length != 0) {
result.resize(length);
env->GetDoubleArrayRegion(arr, 0, length, reinterpret_cast<jdouble *>(&result[0]));
}
env->DeleteLocalRef(arr);
}
return result;
}
} // namespace jni
} // namespace td

250
tl/tl/tl_jni_object.h Normal file
View file

@ -0,0 +1,250 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include <jni.h>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "td/utils/Slice.h"
#include "td/utils/SharedSlice.h"
namespace td {
namespace jni {
extern thread_local bool parse_error;
extern jmethodID GetConstructorID;
extern jmethodID BooleanGetValueMethodID;
extern jmethodID IntegerGetValueMethodID;
extern jmethodID LongGetValueMethodID;
extern jmethodID DoubleGetValueMethodID;
jclass get_jclass(JNIEnv *env, const char *class_name);
jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name, const char *signature);
jfieldID get_field_id(JNIEnv *env, jclass clazz, const char *name, const char *signature);
void register_native_method(JNIEnv *env, jclass clazz, std::string name, std::string signature, void *function_ptr);
class JvmThreadDetacher {
JavaVM *java_vm_;
void detach() {
if (java_vm_ != nullptr) {
java_vm_->DetachCurrentThread();
java_vm_ = nullptr;
}
}
public:
explicit JvmThreadDetacher(JavaVM *java_vm) : java_vm_(java_vm) {
}
JvmThreadDetacher(const JvmThreadDetacher &other) = delete;
JvmThreadDetacher &operator=(const JvmThreadDetacher &other) = delete;
JvmThreadDetacher(JvmThreadDetacher &&other) : java_vm_(other.java_vm_) {
other.java_vm_ = nullptr;
}
JvmThreadDetacher &operator=(JvmThreadDetacher &&other) = delete;
~JvmThreadDetacher() {
detach();
}
void operator()(JNIEnv *env) {
detach();
}
};
std::unique_ptr<JNIEnv, JvmThreadDetacher> get_jni_env(JavaVM *java_vm, jint jni_version);
std::string fetch_string(JNIEnv *env, jobject o, jfieldID id);
SecureString fetch_string_secure(JNIEnv *env, jobject o, jfieldID id);
inline jobject fetch_object(JNIEnv *env, const jobject &o, const jfieldID &id) {
// null return object is implicitly allowed
return env->GetObjectField(o, id);
}
inline bool have_parse_error() {
return parse_error;
}
inline void reset_parse_error() {
parse_error = false;
}
std::string from_jstring(JNIEnv *env, jstring s);
SecureString from_jstring_secure(JNIEnv *env, jstring s);
jstring to_jstring(JNIEnv *env, const std::string &s);
jstring to_jstring_secure(JNIEnv *env, Slice s);
std::string from_bytes(JNIEnv *env, jbyteArray arr);
SecureString from_bytes_secure(JNIEnv *env, jbyteArray arr);
jbyteArray to_bytes(JNIEnv *env, Slice b);
jbyteArray to_bytes_secure(JNIEnv *env, Slice b);
void init_vars(JNIEnv *env, const char *td_api_java_package);
jintArray store_vector(JNIEnv *env, const std::vector<std::int32_t> &v);
jlongArray store_vector(JNIEnv *env, const std::vector<std::int64_t> &v);
jdoubleArray store_vector(JNIEnv *env, const std::vector<double> &v);
jobjectArray store_vector(JNIEnv *env, const std::vector<std::string> &v);
jobjectArray store_vector(JNIEnv *env, const std::vector<SecureString> &v);
template <class T>
jobjectArray store_vector(JNIEnv *env, const std::vector<T> &v) {
jint length = static_cast<jint>(v.size());
jobjectArray arr = env->NewObjectArray(length, T::element_type::Class, jobject());
if (arr != nullptr) {
for (jint i = 0; i < length; i++) {
if (v[i] != nullptr) {
jobject stored_object;
v[i]->store(env, stored_object);
if (stored_object) {
env->SetObjectArrayElement(arr, i, stored_object);
env->DeleteLocalRef(stored_object);
}
}
}
}
return arr;
}
template <class T>
class get_array_class {
static jclass get();
};
template <class T>
jobjectArray store_vector(JNIEnv *env, const std::vector<std::vector<T>> &v) {
jint length = static_cast<jint>(v.size());
jobjectArray arr = env->NewObjectArray(length, get_array_class<typename T::element_type>::get(), 0);
if (arr != nullptr) {
for (jint i = 0; i < length; i++) {
auto stored_array = store_vector(env, v[i]);
if (stored_array) {
env->SetObjectArrayElement(arr, i, stored_array);
env->DeleteLocalRef(stored_array);
}
}
}
return arr;
}
template <class T>
auto fetch_tl_object(JNIEnv *env, jobject obj) {
decltype(T::fetch(env, obj)) result;
if (obj != nullptr) {
result = T::fetch(env, obj);
env->DeleteLocalRef(obj);
}
return result;
}
std::vector<std::int32_t> fetch_vector(JNIEnv *env, jintArray arr);
std::vector<std::int64_t> fetch_vector(JNIEnv *env, jlongArray arr);
std::vector<double> fetch_vector(JNIEnv *env, jdoubleArray arr);
template <class T>
struct FetchVector {
static auto fetch(JNIEnv *env, jobjectArray arr) {
std::vector<decltype(fetch_tl_object<T>(env, jobject()))> result;
if (arr != nullptr) {
jsize length = env->GetArrayLength(arr);
result.reserve(length);
for (jsize i = 0; i < length; i++) {
result.push_back(fetch_tl_object<T>(env, env->GetObjectArrayElement(arr, i)));
}
env->DeleteLocalRef(arr);
}
return result;
}
};
template <>
struct FetchVector<std::string> {
static std::vector<std::string> fetch(JNIEnv *env, jobjectArray arr) {
std::vector<std::string> result;
if (arr != nullptr) {
jsize length = env->GetArrayLength(arr);
result.reserve(length);
for (jsize i = 0; i < length; i++) {
jstring str = (jstring)env->GetObjectArrayElement(arr, i);
result.push_back(jni::from_jstring(env, str));
if (str) {
env->DeleteLocalRef(str);
}
}
env->DeleteLocalRef(arr);
}
return result;
}
};
template <>
struct FetchVector<SecureString> {
static std::vector<SecureString> fetch(JNIEnv *env, jobjectArray arr) {
std::vector<SecureString> result;
if (arr != nullptr) {
jsize length = env->GetArrayLength(arr);
result.reserve(length);
for (jsize i = 0; i < length; i++) {
jstring str = (jstring)env->GetObjectArrayElement(arr, i);
result.push_back(jni::from_jstring_secure(env, str));
if (str) {
env->DeleteLocalRef(str);
}
}
env->DeleteLocalRef(arr);
}
return result;
}
};
template <class T>
struct FetchVector<std::vector<T>> {
static auto fetch(JNIEnv *env, jobjectArray arr) {
std::vector<decltype(FetchVector<T>::fetch(env, jobjectArray()))> result;
if (arr != nullptr) {
jsize length = env->GetArrayLength(arr);
result.reserve(length);
for (jsize i = 0; i < length; i++) {
result.push_back(FetchVector<T>::fetch(env, (jobjectArray)env->GetObjectArrayElement(arr, i)));
}
env->DeleteLocalRef(arr);
}
return result;
}
};
} // namespace jni
} // namespace td

305
tl/tl/tl_json.h Normal file
View file

@ -0,0 +1,305 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "td/utils/base64.h"
#include "td/utils/buffer.h"
#include "td/utils/format.h"
#include "td/utils/JsonBuilder.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SharedSlice.h"
#include "td/utils/Status.h"
#include "td/utils/tl_storers.h"
#include <type_traits>
namespace td {
struct JsonInt64 {
int64 value;
};
inline void to_json(JsonValueScope &jv, const JsonInt64 json_int64) {
jv << JsonString(PSLICE() << json_int64.value);
}
struct JsonVectorInt64 {
const std::vector<int64> &value;
};
inline void to_json(JsonValueScope &jv, const JsonVectorInt64 &vec) {
auto ja = jv.enter_array();
for (auto &value : vec.value) {
ja.enter_value() << ToJson(JsonInt64{value});
}
}
struct JsonBytes {
td::Slice bytes;
};
inline void to_json(JsonValueScope &jv, const JsonBytes json_bytes) {
jv << JsonString(PSLICE() << base64_encode(json_bytes.bytes));
}
template <class T>
struct JsonVectorBytesImpl {
const std::vector<T> &value;
};
template <class T>
auto JsonVectorBytes(const std::vector<T> &value) {
return JsonVectorBytesImpl<T>{value};
}
template <class T>
void to_json(JsonValueScope &jv, const JsonVectorBytesImpl<T> &vec) {
auto ja = jv.enter_array();
for (auto &value : vec.value) {
ja.enter_value() << ToJson(JsonBytes{value});
}
}
template <unsigned size>
inline void to_json(JsonValueScope &jv, const td::BitArray<size> &vec) {
to_json(jv, base64_encode(as_slice(vec)));
}
template <class T>
void to_json(JsonValueScope &jv, const ton::tl_object_ptr<T> &value) {
if (value) {
to_json(jv, *value);
} else {
jv << JsonNull();
}
}
template <class T>
void to_json(JsonValueScope &jv, const std::vector<T> &v) {
auto ja = jv.enter_array();
for (auto &value : v) {
ja.enter_value() << ToJson(value);
}
}
inline Status from_json(std::int32_t &to, JsonValue &from) {
if (from.type() != JsonValue::Type::Number && from.type() != JsonValue::Type::String) {
return Status::Error(PSLICE() << "Expected number, got " << from.type());
}
Slice number = from.type() == JsonValue::Type::String ? from.get_string() : from.get_number();
TRY_RESULT(res, to_integer_safe<int32>(number));
to = res;
return Status::OK();
}
inline Status from_json(bool &to, JsonValue &from) {
if (from.type() != JsonValue::Type::Boolean) {
int32 x;
auto status = from_json(x, from);
if (status.is_ok()) {
to = x != 0;
return Status::OK();
}
return Status::Error(PSLICE() << "Expected bool, got " << from.type());
}
to = from.get_boolean();
return Status::OK();
}
inline Status from_json(std::int64_t &to, JsonValue &from) {
if (from.type() != JsonValue::Type::Number && from.type() != JsonValue::Type::String) {
return Status::Error(PSLICE() << "Expected number, got " << from.type());
}
Slice number = from.type() == JsonValue::Type::String ? from.get_string() : from.get_number();
TRY_RESULT(res, to_integer_safe<int64>(number));
to = res;
return Status::OK();
}
inline Status from_json(double &to, JsonValue &from) {
if (from.type() != JsonValue::Type::Number) {
return Status::Error(PSLICE() << "Expected number, got " << from.type());
}
to = to_double(from.get_number().str());
return Status::OK();
}
inline Status from_json(string &to, JsonValue &from) {
if (from.type() != JsonValue::Type::String) {
return Status::Error(PSLICE() << "Expected string, got " << from.type());
}
to = from.get_string().str();
return Status::OK();
}
inline Status from_json(SecureString &to, JsonValue &from) {
if (from.type() != JsonValue::Type::String) {
return Status::Error(PSLICE() << "Expected string, got " << from.type());
}
to = SecureString(from.get_string().str());
return Status::OK();
}
inline Status from_json(Slice &to, JsonValue &from) {
if (from.type() != JsonValue::Type::String) {
return Status::Error(PSLICE() << "Expected string, got " << from.type());
}
to = from.get_string();
return Status::OK();
}
inline Status from_json_bytes(string &to, JsonValue &from) {
if (from.type() != JsonValue::Type::String) {
return Status::Error(PSLICE() << "Expected string, got " << from.type());
}
TRY_RESULT(decoded, base64_decode(from.get_string()));
to = std::move(decoded);
return Status::OK();
}
inline Status from_json_bytes(SecureString &to, JsonValue &from) {
if (from.type() != JsonValue::Type::String) {
return Status::Error(PSLICE() << "Expected string, got " << from.type());
}
TRY_RESULT(decoded, base64_decode_secure(from.get_string()));
to = std::move(decoded);
return Status::OK();
}
inline Status from_json_bytes(BufferSlice &to, JsonValue &from) {
if (from.type() != JsonValue::Type::String) {
return Status::Error(PSLICE() << "Expected string, got " << from.type());
}
TRY_RESULT(decoded, base64_decode(from.get_string()));
to = BufferSlice(decoded);
return Status::OK();
}
inline Status from_json_bytes(Slice &to, JsonValue &from) {
if (from.type() != JsonValue::Type::String) {
return Status::Error(PSLICE() << "Expected string, got " << from.type());
}
TRY_RESULT(decoded, base64_decode(from.get_string()));
from.get_string().copy_from(decoded);
from.get_string().truncate(decoded.size());
to = from.get_string();
return Status::OK();
}
template <unsigned size>
inline Status from_json(td::BitArray<size> &to, JsonValue &from) {
string raw;
TRY_STATUS(from_json_bytes(raw, from));
auto S = to.as_slice();
if (raw.size() != S.size()) {
return Status::Error("Wrong length for UInt");
}
S.copy_from(raw);
return Status::OK();
}
template <class T>
Status from_json(std::vector<T> &to, JsonValue &from) {
if (from.type() != JsonValue::Type::Array) {
return Status::Error(PSLICE() << "Expected array, got " << from.type());
}
to = std::vector<T>(from.get_array().size());
size_t i = 0;
for (auto &value : from.get_array()) {
TRY_STATUS(from_json(to[i], value));
i++;
}
return Status::OK();
}
template <class T>
inline Status from_json_vector_bytes(std::vector<T> &to, JsonValue &from) {
if (from.type() != JsonValue::Type::Array) {
return Status::Error(PSLICE() << "Expected array, got " << from.type());
}
to = std::vector<T>(from.get_array().size());
size_t i = 0;
for (auto &value : from.get_array()) {
TRY_STATUS(from_json_bytes(to[i], value));
i++;
}
return Status::OK();
}
template <class T>
class DowncastHelper : public T {
public:
explicit DowncastHelper(int32 constructor) : constructor_(constructor) {
}
int32 get_id() const override {
return constructor_;
}
void store(TlStorerToString &s, const char *field_name) const override {
}
private:
int32 constructor_{0};
};
template <class T>
std::enable_if_t<!std::is_constructible<T>::value, Status> from_json(ton::tl_object_ptr<T> &to, JsonValue &from) {
if (from.type() != JsonValue::Type::Object) {
if (from.type() == JsonValue::Type::Null) {
to = nullptr;
return Status::OK();
}
return Status::Error(PSLICE() << "Expected object, got " << from.type());
}
auto &object = from.get_object();
TRY_RESULT(constructor_value, get_json_object_field(object, "@type", JsonValue::Type::Null, false));
int32 constructor = 0;
if (constructor_value.type() == JsonValue::Type::Number) {
constructor = to_integer<int32>(constructor_value.get_number());
} else if (constructor_value.type() == JsonValue::Type::String) {
TRY_RESULT(t_constructor, tl_constructor_from_string(to.get(), constructor_value.get_string().str()));
constructor = t_constructor;
} else {
return Status::Error(PSLICE() << "Expected string or int, got " << constructor_value.type());
}
DowncastHelper<T> helper(constructor);
Status status;
bool ok = downcast_call(static_cast<T &>(helper), [&](auto &dummy) {
auto result = ton::create_tl_object<std::decay_t<decltype(dummy)>>();
status = from_json(*result, object);
to = std::move(result);
});
TRY_STATUS(std::move(status));
if (!ok) {
return Status::Error(PSLICE() << "Unknown constructor " << format::as_hex(constructor));
}
return Status::OK();
}
template <class T>
std::enable_if_t<std::is_constructible<T>::value, Status> from_json(ton::tl_object_ptr<T> &to, JsonValue &from) {
if (from.type() != JsonValue::Type::Object) {
if (from.type() == JsonValue::Type::Null) {
to = nullptr;
return Status::OK();
}
return Status::Error(PSLICE() << "Expected object, got " << from.type());
}
to = ton::create_tl_object<T>();
return from_json(*to, from.get_object());
}
} // namespace td

158
tl/tl/tl_object_parse.h Normal file
View file

@ -0,0 +1,158 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "tl/TlObject.h"
#include "td/utils/int_types.h"
#include "crypto/common/bitstring.h"
namespace ton {
template <class Func, std::int32_t constructor_id>
class TlFetchBoxed {
public:
template <class Parser>
static auto parse(Parser &p) -> decltype(Func::parse(p)) {
if (p.fetch_int() != constructor_id) {
p.set_error("Wrong constructor found");
return decltype(Func::parse(p))();
}
return Func::parse(p);
}
};
class TlFetchTrue {
public:
template <class Parser>
static bool parse(Parser &p) {
return true;
}
};
class TlFetchBool {
public:
template <class Parser>
static bool parse(Parser &p) {
constexpr std::int32_t ID_BOOL_FALSE = 0xbc799737;
constexpr std::int32_t ID_BOOL_TRUE = 0x997275b5;
std::int32_t c = p.fetch_int();
if (c == ID_BOOL_TRUE) {
return true;
}
if (c != ID_BOOL_FALSE) {
p.set_error("Bool expected");
}
return false;
}
};
class TlFetchInt {
public:
template <class Parser>
static std::int32_t parse(Parser &p) {
return p.fetch_int();
}
};
class TlFetchLong {
public:
template <class Parser>
static std::int64_t parse(Parser &p) {
return p.fetch_long();
}
};
class TlFetchDouble {
public:
template <class Parser>
static double parse(Parser &p) {
return p.fetch_double();
}
};
class TlFetchInt128 {
public:
template <class Parser>
static td::Bits128 parse(Parser &p) {
return p.template fetch_binary<td::Bits128>();
}
};
class TlFetchInt256 {
public:
template <class Parser>
static td::Bits256 parse(Parser &p) {
return p.template fetch_binary<td::Bits256>();
}
};
template <class T>
class TlFetchString {
public:
template <class Parser>
static T parse(Parser &p) {
return p.template fetch_string<T>();
}
};
template <class T>
class TlFetchBytes {
public:
template <class Parser>
static T parse(Parser &p) {
return p.template fetch_string<T>();
}
};
template <class Func>
class TlFetchVector {
public:
template <class Parser>
static auto parse(Parser &p) -> std::vector<decltype(Func::parse(p))> {
const std::uint32_t multiplicity = p.fetch_int();
std::vector<decltype(Func::parse(p))> v;
if (p.get_left_len() < multiplicity) {
p.set_error("Wrong vector length");
} else {
v.reserve(multiplicity);
for (std::uint32_t i = 0; i < multiplicity; i++) {
v.push_back(Func::parse(p));
}
}
return v;
}
};
template <class T>
class TlFetchObject {
public:
template <class Parser>
static tl_object_ptr<T> parse(Parser &p) {
return move_tl_object_as<T>(T::fetch(p));
}
};
} // namespace ton

107
tl/tl/tl_object_store.h Normal file
View file

@ -0,0 +1,107 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "tl/TlObject.h"
#include "td/utils/misc.h"
namespace ton {
template <class Func, std::int32_t constructor_id>
class TlStoreBoxed {
public:
template <class T, class Storer>
static void store(const T &x, Storer &s) {
s.store_binary(constructor_id);
Func::store(x, s);
}
};
template <class Func>
class TlStoreBoxedUnknown {
public:
template <class T, class Storer>
static void store(const T &x, Storer &s) {
s.store_binary(x->get_id());
Func::store(x, s);
}
};
class TlStoreBool {
public:
template <class Storer>
static void store(const bool &x, Storer &s) {
constexpr std::int32_t ID_BOOL_FALSE = 0xbc799737;
constexpr std::int32_t ID_BOOL_TRUE = 0x997275b5;
s.store_binary(x ? ID_BOOL_TRUE : ID_BOOL_FALSE);
}
};
class TlStoreTrue {
public:
template <class Storer>
static void store(const bool &x, Storer &s) {
// currently nothing to do
}
};
class TlStoreBinary {
public:
template <class T, class Storer>
static void store(const T &x, Storer &s) {
s.store_binary(x);
}
};
class TlStoreString {
public:
template <class T, class Storer>
static void store(const T &x, Storer &s) {
s.store_string(x);
}
};
template <class Func>
class TlStoreVector {
public:
template <class T, class Storer>
static void store(const T &vec, Storer &s) {
s.store_binary(td::narrow_cast<td::int32>(vec.size()));
for (auto &val : vec) {
Func::store(val, s);
}
}
};
class TlStoreObject {
public:
template <class T, class Storer>
static void store(const tl_object_ptr<T> &obj, Storer &s) {
return obj->store(s);
}
};
} // namespace ton