mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
initial commit
This commit is contained in:
commit
c2da007f40
1610 changed files with 398047 additions and 0 deletions
55
tl/CMakeLists.txt
Normal file
55
tl/CMakeLists.txt
Normal 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> )
|
83
tl/generate/CMakeLists.txt
Normal file
83
tl/generate/CMakeLists.txt
Normal 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()
|
268
tl/generate/JavadocTlDocumentationGenerator.php
Normal file
268
tl/generate/JavadocTlDocumentationGenerator.php
Normal 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('*/', '*/', $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]);
|
323
tl/generate/TlDocumentationGenerator.php
Normal file
323
tl/generate/TlDocumentationGenerator.php
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
83
tl/generate/generate_common.cpp
Normal file
83
tl/generate/generate_common.cpp
Normal 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");
|
||||
}
|
50
tl/generate/generate_java.cpp
Normal file
50
tl/generate/generate_java.cpp
Normal 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));
|
||||
}
|
73
tl/generate/scheme/lite_api.tl
Normal file
73
tl/generate/scheme/lite_api.tl
Normal 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;
|
BIN
tl/generate/scheme/lite_api.tlo
Normal file
BIN
tl/generate/scheme/lite_api.tlo
Normal file
Binary file not shown.
553
tl/generate/scheme/ton_api.tl
Normal file
553
tl/generate/scheme/ton_api.tl
Normal 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;
|
BIN
tl/generate/scheme/ton_api.tlo
Normal file
BIN
tl/generate/scheme/ton_api.tlo
Normal file
Binary file not shown.
89
tl/generate/scheme/tonlib_api.tl
Normal file
89
tl/generate/scheme/tonlib_api.tl
Normal 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;
|
||||
|
BIN
tl/generate/scheme/tonlib_api.tlo
Normal file
BIN
tl/generate/scheme/tonlib_api.tlo
Normal file
Binary file not shown.
5
tl/generate/scheme/update-tlo.sh
Executable file
5
tl/generate/scheme/update-tlo.sh
Executable 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
|
270
tl/generate/tl_json_converter.cpp
Normal file
270
tl/generate/tl_json_converter.cpp
Normal 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
|
29
tl/generate/tl_json_converter.h
Normal file
29
tl/generate/tl_json_converter.h
Normal 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
|
698
tl/generate/tl_writer_cpp.cpp
Normal file
698
tl/generate/tl_writer_cpp.cpp
Normal 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
120
tl/generate/tl_writer_cpp.h
Normal 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
355
tl/generate/tl_writer_h.cpp
Normal 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
106
tl/generate/tl_writer_h.h
Normal 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
|
267
tl/generate/tl_writer_hpp.cpp
Normal file
267
tl/generate/tl_writer_hpp.cpp
Normal 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
121
tl/generate/tl_writer_hpp.h
Normal 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
|
465
tl/generate/tl_writer_java.cpp
Normal file
465
tl/generate/tl_writer_java.cpp
Normal 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
|
131
tl/generate/tl_writer_java.h
Normal file
131
tl/generate/tl_writer_java.h
Normal 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
|
676
tl/generate/tl_writer_jni_cpp.cpp
Normal file
676
tl/generate/tl_writer_jni_cpp.cpp
Normal 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
|
123
tl/generate/tl_writer_jni_cpp.h
Normal file
123
tl/generate/tl_writer_jni_cpp.h
Normal 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
|
204
tl/generate/tl_writer_jni_h.cpp
Normal file
204
tl/generate/tl_writer_jni_h.cpp
Normal 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
|
70
tl/generate/tl_writer_jni_h.h
Normal file
70
tl/generate/tl_writer_jni_h.h
Normal 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
|
276
tl/generate/tl_writer_td.cpp
Normal file
276
tl/generate/tl_writer_td.cpp
Normal 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
|
81
tl/generate/tl_writer_td.h
Normal file
81
tl/generate/tl_writer_td.h
Normal 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
177
tl/tl/TlObject.h
Normal 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
416
tl/tl/tl_jni_object.cpp
Normal 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
250
tl/tl/tl_jni_object.h
Normal 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
305
tl/tl/tl_json.h
Normal 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
158
tl/tl/tl_object_parse.h
Normal 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
107
tl/tl/tl_object_store.h
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue