diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..ce341760f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +build/* diff --git a/CMakeLists.txt b/CMakeLists.txt index 7cc3fd5f47..7e5b9c24af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,32 +1,31 @@ cmake_minimum_required(VERSION 3.5) -project(eosio_wasm_sdk VERSION 1.0.0) +project(eosio_wasm_sdk) -include(GNUInstallDirs) +set(VERSION_MAJOR 1) +set(VERSION_MINOR 1) +set(VERSION_PATCH 0) -set(SDK_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/eosio.wasmsdk) - -if(NOT ${NO_WASM_COMPILER} STREQUAL "") - string(TOLOWER ${NO_WASM_COMPILER} no_wasm_comp) - if(NOT ${no_wasm_comp} STREQUAL "true") - ### include eosio clang 7 as external project - include(ClangExternalProject.txt) - else(NOT ${no_wasm_comp} STREQUAL "true") - add_custom_target(EosioClang) - endif() -else(NOT ${NO_WASM_COMPILER} STREQUAL "") - set(no_wasm_comp "false") - include(ClangExternalProject.txt) +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + message(WARNING "CMAKE_INSTALL_PREFIX is set to default path of ${CMAKE_INSTALL_PREFIX}, resetting to ${CMAKE_INSTALL_PREFIX}/eosio.wasmsdk") + set(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/eosio.wasmsdk") +elseif ("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr/local") + message(WARNING "CMAKE_INSTALL_PREFIX is explicitly set to /usr/local. This is not recommended.") endif() -#include(ToolingExternalProject.txt) + +include(GNUInstallDirs) + +include(ClangExternalProject.txt) add_subdirectory(external) set(WASM_SDK_BUILD true) -configure_file(${CMAKE_SOURCE_DIR}/eosio.imports.in ${CMAKE_BINARY_DIR}/eosio.imports) +configure_file(${CMAKE_SOURCE_DIR}/modules/EosioWasmToolchainBuild.cmake.in ${CMAKE_BINARY_DIR}/lib/cmake/EosioWasmToolchain.cmake @ONLY) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}/lib/cmake") +include(EosioWasmToolchain) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/modules") -include(EosioWasmToolchainBuild) if ("${CORE_SYMBOL_NAME}" STREQUAL "") set( CORE_SYMBOL_NAME "SYS" ) @@ -41,30 +40,14 @@ endif() add_subdirectory(libraries) -if ( ${no_wasm_comp} STREQUAL "false" ) - include(InstallClang.txt) -endif() +include(InstallClang.txt) message( STATUS "Using '${CORE_SYMBOL_NAME}' as CORE symbol name" ) # install examples -install(DIRECTORY examples DESTINATION "${SDK_INSTALL_PREFIX}") - -install(EXPORT EosioLib DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) - -set(INCLUDE_INSTALL_DIR ${SDK_INSTALL_PREFIX}/include) -include(CMakePackageConfigHelpers) -write_basic_package_version_file(EosioLibConfigVersion.cmake - COMPATIBILITY SameMajorVersion) - -configure_package_config_file(${CMAKE_SOURCE_DIR}/modules/EosioLibConfig.cmake.in EosioLibConfig.cmake - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/" - PATH_VARS INCLUDE_INSTALL_DIR) +#install(DIRECTORY examples DESTINATION "${CMAKE_INSTALL_PREFIX}") -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/EosioLibConfigVersion.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/EosioLibConfig.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) configure_file(${CMAKE_SOURCE_DIR}/modules/EosioWasmToolchain.cmake.in ${CMAKE_BINARY_DIR}/modules/EosioWasmToolchain.cmake @ONLY) -install(FILES ${CMAKE_BINARY_DIR}/modules/EosioWasmToolchain.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) -install(FILES ${CMAKE_BINARY_DIR}/eosio.imports DESTINATION ${SDK_INSTALL_PREFIX}) +install(FILES ${CMAKE_BINARY_DIR}/modules/EosioWasmToolchain.cmake DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/cmake) +configure_file(${CMAKE_SOURCE_DIR}/eosio.imports.in ${CMAKE_BINARY_DIR}/eosio.imports COPYONLY) +install(FILES ${CMAKE_BINARY_DIR}/eosio.imports DESTINATION ${CMAKE_INSTALL_PREFIX}) diff --git a/ClangExternalProject.txt b/ClangExternalProject.txt index f4821ab2fc..e8faad8a08 100644 --- a/ClangExternalProject.txt +++ b/ClangExternalProject.txt @@ -4,11 +4,12 @@ include(GNUInstallDirs) ExternalProject_Add( EosioClang - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${SDK_INSTALL_PREFIX}/llvm -DBOOST_ROOT=${BOOST_ROOT} -DEOSIO_INSTALL=${SDK_INSTALL_PREFIX} + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/llvm -DCMAKE_BUILD_TYPE=Release -DBOOST_ROOT=${BOOST_ROOT} -DSDK_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DEOSIO_VER_MAJOR=${VERSION_MAJOR} -DEOSIO_VER_MINOR=${VERSION_MINOR} -DEOSIO_VER_REVISION=${VERSION_PATCH} -DEOSIO_STACK_SIZE=8192 SOURCE_DIR "${CMAKE_SOURCE_DIR}/eosio_llvm" UPDATE_COMMAND "" PATCH_COMMAND "" TEST_COMMAND "" INSTALL_COMMAND "" + BUILD_ALWAYS 1 ) diff --git a/InstallClang.txt b/InstallClang.txt index 6eaa585114..05f3eb260c 100644 --- a/InstallClang.txt +++ b/InstallClang.txt @@ -1,78 +1,60 @@ -macro(install_symlink from to) - install(CODE - "execute_process(COMMAND mkdir -p ${SDK_INSTALL_PREFIX}/bin) - execute_process(COMMAND mkdir -p ${CMAKE_INSTALL_PREFIX}/bin) - execute_process(COMMAND ln -sf ${SDK_INSTALL_PREFIX}/bin/${from} ${CMAKE_INSTALL_PREFIX}/bin/${to})") -endmacro() - -install_symlink(llvm-ranlib eosio.ranlib) - # install clang and llvm set(CLANG_BIN_DIR ${CMAKE_BINARY_DIR}/EosioClang-prefix/src/EosioClang-build/bin) install(FILES ${CLANG_BIN_DIR}/llvm-ranlib - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/llvm-ar - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/llvm-nm - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/llvm-objcopy - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/llvm-readobj - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/llvm-objdump - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/llvm-readelf - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/opt - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/llc - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/lld - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/llvm-strip - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/clang-7 - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/wasm-ld - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/eosio-cc - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/eosio-cpp - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/eosio-ld - DESTINATION ${SDK_INSTALL_PREFIX}/bin + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CLANG_BIN_DIR}/../lib/LLVMEosioApply${CMAKE_SHARED_LIBRARY_SUFFIX} - DESTINATION ${SDK_INSTALL_PREFIX}/bin) - -install_symlink(llvm-ranlib eosio-ranlib) -install_symlink(llvm-ar eosio-ar) -install_symlink(llvm-objdump eosio-objdump) -install_symlink(llvm-readelf eosio-readelf) -install_symlink(eosio-cc eosio-cc) -install_symlink(eosio-cpp eosio-cpp) -install_symlink(eosio-ld eosio-ld) - + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}) install(CODE " execute_process(COMMAND ln -sf - ${SDK_INSTALL_PREFIX}/bin/clang-7 - ${SDK_INSTALL_PREFIX}/bin/clang)") + ${CMAKE_INSTALL_FULL_BINDIR}/clang-7 + ${CMAKE_INSTALL_FULL_BINDIR}/clang)") install(CODE " execute_process(COMMAND ln -sf - ${SDK_INSTALL_PREFIX}/bin/clang-7 - ${SDK_INSTALL_PREFIX}/bin/clang++)") + ${CMAKE_INSTALL_FULL_BINDIR}/clang-7 + ${CMAKE_INSTALL_FULL_BINDIR}/clang++)") diff --git a/LICENSE b/LICENSE index bf31410ba2..55e80764e3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -MIT License +Copyright (c) 2018, Respective Authors all rights reserved. -Copyright (c) 2018 EOSIO +The MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md index b94c98f6c4..97b1ebe859 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # WasmSDK -## Version : 1.0.0 +## Version : 1.1.0 WasmSDK is a toolchain for WebAssembly (WASM). In addition to being a general purpose WebAssembly toolchain, [EOSIO](https://github.com/eosio/eos) specific optimizations are available to support building EOSIO smart contracts. This new toolchain is built around [Clang 7](https://github.com/eosio/llvm), which means that the SDK has the most currently available optimizations and analyses from LLVM, but as the WASM target is still considered experimental, some optimizations are not available or incomplete. @@ -30,35 +30,7 @@ $ ./build.sh Finally, install the build *This install will install the core to ```/usr/local/eosio.wasmsdk``` and symlinks to the top level tools (compiler, ld, etc.) to ```/usr/local/bin``` ```sh -$ cd build -$ sudo make install -``` - -### Manual Installation -`WasmSDK requires CMake v3.5+ and Boost 1.67.0 to run.` - -First clone the repo and create a build directory - -```sh -$ git clone --recursive https://github.com/eosio/wasmsdk -$ cd wasmsdk -$ mkdir build && cd build -``` - -Then configure with cmake to install to ```/usr/local/eosio.wasmsdk``` - -```sh -$ cmake .. -``` - -or configure cmake to install to a specific path -```sh -$ cmake -DCMAKE_INSTALL_PREFIX= .. -``` - -Then to install, simply -```sh -$ make && make install +$ sudo ./install.sh ``` ### Installed Tools @@ -66,7 +38,7 @@ $ make && make install * [eosio-cpp](#eosio-cpp) * [eosio-cc](#eosio-cc) * [eosio-ld](#eosio-ld) -* eosio-pp (only strips all zeroed initialized data segments for now, currently runs automatically with cpp/cc and ld) +* eosio-pp (post processing pass for WASM, automatically runs with eosio-cpp and eosio-ld) * eosio-ranlib * eosio-ar * eosio-objdump @@ -179,6 +151,8 @@ eosio.ld options: -L= - Add directory to library search path -fno-cfl-aa - Disable CFL Alias Analysis -fno-lto - Disable LTO + -fno-post-pass - Don't run post processing pass + -fno-stack-first - Don't set the stack first in memory -l= - Root name of library to link -lto-opt= - LTO Optimization level (O0-O3) -o= - Write output to diff --git a/build.sh b/build.sh index af188cb86e..6317f237c1 100755 --- a/build.sh +++ b/build.sh @@ -4,6 +4,9 @@ printf "\t=========== Building eosio.wasmsdk ===========\n\n" RED='\033[0;31m' NC='\033[0m' +txtbld=$(tput bold) +bldred=${txtbld}$(tput setaf 1) +txtrst=$(tput sgr0) export DISK_MIN=10 export TEMP_DIR="/tmp" @@ -55,11 +58,41 @@ if [ $# -ge 1 ]; then CORE_SYMBOL=$1 fi +if [[ `uname` == 'Darwin' ]]; then + FREE_MEM=`vm_stat | grep "Pages free:"` + read -ra FREE_MEM <<< "$FREE_MEM" + FREE_MEM=$((${FREE_MEM[2]%?}*(4096))) # free pages * page size +else + FREE_MEM=`free | grep "Mem:" | awk '{print $4}'` +fi + +CORES_AVAIL=`getconf _NPROCESSORS_ONLN` +MEM_CORES=$(( ${FREE_MEM}/4000000 )) # 4 gigabytes per core +CORES=$(( $CORES_AVAIL < $MEM_CORES ? $CORES_AVAIL : $MEM_CORES )) -CORES=`getconf _NPROCESSORS_ONLN` mkdir -p build pushd build &> /dev/null -cmake -DBOOST_ROOT="${BOOST}" -DCORE_SYMBOL_NAME="${CORE_SYMBOL}" ../ +cmake -DCMAKE_INSTALL_PREFIX=/usr/local/eosio.wasmsdk -DBOOST_ROOT="${BOOST}" -DCORE_SYMBOL_NAME="${CORE_SYMBOL}" ../ +if [ $? -ne 0 ]; then + exit -1; +fi make -j${CORES} +if [ $? -ne 0 ]; then + exit -1; +fi popd &> /dev/null +printf "\n${bldred}\t ___ ___ ___ ___\n" +printf "\t / /\\ / /\\ / /\\ ___ / /\\ \n" +printf "\t / /:/_ / /::\\ / /:/_ / /\\ / /::\\ \n" +printf "\t / /:/ /\\ / /:/\\:\\ / /:/ /\\ / /:/ / /:/\\:\\ \n" +printf "\t / /:/ /:/_ / /:/ \\:\\ / /:/ /::\\ /__/::\\ / /:/ \\:\\ \n" +printf "\t /__/:/ /:/ /\\ /__/:/ \\__\\:\\ /__/:/ /:/\\:\\ \\__\\/\\:\\__ /__/:/ \\__\\:\\ \n" +printf "\t \\ \\:\\/:/ /:/ \\ \\:\\ / /:/ \\ \\:\\/:/~/:/ \\ \\:\\/\\ \\ \\:\\ / /:/ \n" +printf "\t \\ \\::/ /:/ \\ \\:\\ /:/ \\ \\::/ /:/ \\__\\::/ \\ \\:\\ /:/ \n" +printf "\t \\ \\:\\/:/ \\ \\:\\/:/ \\__\\/ /:/ /__/:/ \\ \\:\\/:/ \n" +printf "\t \\ \\::/ \\ \\::/ /__/:/ \\__\\/ \\ \\::/ \n" +printf "\t \\__\\/ \\__\\/ \\__\\/ \\__\\/ \n${txtrst}" + +printf "\\tFor more information:\\n" +printf "\\tEOSIO website: https://eos.io\\n" diff --git a/eosio_llvm b/eosio_llvm index 530a62bbb5..0cfb48ff09 160000 --- a/eosio_llvm +++ b/eosio_llvm @@ -1 +1 @@ -Subproject commit 530a62bbb52a013b4c8209961e089188bfb58eef +Subproject commit 0cfb48ff090fc6c4c45f09ad37afcbc89f14a1ae diff --git a/examples/exchange/CMakeLists.txt b/examples/exchange/CMakeLists.txt index 09e09f9924..2e01df4a73 100644 --- a/examples/exchange/CMakeLists.txt +++ b/examples/exchange/CMakeLists.txt @@ -2,12 +2,12 @@ cmake_minimum_required(VERSION 3.5) project(exchange_example VERSION 1.0.0) # if no wasm root is given use default path -if(WASM_ROOT STREQUAL "" OR NOT WASM_ROOT) - set(WASM_ROOT ${CMAKE_INSTALL_PREFIX}) +if(EOSIO_WASMSDK_ROOT STREQUAL "" OR NOT EOSIO_WASMSDK_ROOT) + set(EOSIO_WASMSDK_ROOT ${CMAKE_INSTALL_PREFIX}) endif() # append the path to the module to include -list(APPEND CMAKE_MODULE_PATH ${WASM_ROOT}/lib/cmake) +list(APPEND CMAKE_MODULE_PATH ${EOSIO_WASMSDK_ROOT}/lib/cmake) #include the toolchain cmake include(EosioWasmToolchain) @@ -20,4 +20,4 @@ target_include_directories( exchange_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../ add_executable(exchange exchange.cpp ) target_include_directories( exchange PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../ ) -target_link_libraries( exchange exchange_lib) \ No newline at end of file +target_link_libraries( exchange exchange_lib) diff --git a/examples/hello/CMakeLists.txt b/examples/hello/CMakeLists.txt index 45f9774ddc..7ac7e434e4 100644 --- a/examples/hello/CMakeLists.txt +++ b/examples/hello/CMakeLists.txt @@ -2,12 +2,12 @@ cmake_minimum_required(VERSION 3.5) project(hello_example VERSION 1.0.0) # if no wasm root is given use default path -if(WASM_ROOT STREQUAL "" OR NOT WASM_ROOT) - set(WASM_ROOT ${CMAKE_INSTALL_PREFIX}) +if(EOSIO_WASMSDK_ROOT STREQUAL "" OR NOT EOSIO_WASMSDK_ROOT) + set(EOSIO_WASMSDK_ROOT ${CMAKE_INSTALL_PREFIX}) endif() # append the path to the module to include -list(APPEND CMAKE_MODULE_PATH ${WASM_ROOT}/lib/cmake) +list(APPEND CMAKE_MODULE_PATH ${EOSIO_WASMSDK_ROOT}/lib/cmake) #include the toolchain cmake include(EosioWasmToolchain) diff --git a/examples/template/CMakeLists.txt b/examples/template/CMakeLists.txt index 07a8ccd75d..0b8063a72e 100644 --- a/examples/template/CMakeLists.txt +++ b/examples/template/CMakeLists.txt @@ -2,12 +2,12 @@ cmake_minimum_required(VERSION 3.5) project(hello_example VERSION 1.0.0) # if no wasm root is given use default path -if(WASM_ROOT STREQUAL "" OR NOT WASM_ROOT) - set(WASM_ROOT ${CMAKE_INSTALL_PREFIX}) +if(EOSIO_WASMSDK_ROOT STREQUAL "" OR NOT EOSIO_WASMSDK_ROOT) + set(EOSIO_WASMSDK_ROOT ${CMAKE_INSTALL_PREFIX}) endif() # append the path to the module to include -list(APPEND CMAKE_MODULE_PATH ${WASM_ROOT}/lib/cmake) +list(APPEND CMAKE_MODULE_PATH ${EOSIO_WASMSDK_ROOT}/lib/cmake) #include the toolchain cmake include(EosioWasmToolchain) diff --git a/external/wabt/CMakeLists.txt b/external/wabt/CMakeLists.txt index bfe4867faa..6869d27458 100644 --- a/external/wabt/CMakeLists.txt +++ b/external/wabt/CMakeLists.txt @@ -289,8 +289,8 @@ if (NOT EMSCRIPTEN) set(WABT_EXECUTABLES ${WABT_EXECUTABLES} PARENT_SCOPE) add_custom_target(${name}-copy-to-bin ALL - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_INSTALL_BINDIR} - COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_INSTALL_BINDIR} + COMMAND ${CMAKE_COMMAND} -E make_directory \$ENV{DESTDIR}${CMAKE_INSTALL_BINDIR} + COMMAND ${CMAKE_COMMAND} -E copy $ \$ENV{DESTDIR}${CMAKE_INSTALL_BINDIR} DEPENDS ${name} ) endfunction() @@ -393,10 +393,9 @@ if (NOT EMSCRIPTEN) # install #install(TARGETS ${WABT_EXECUTABLES} DESTINATION bin) - install(TARGETS eosio-pp DESTINATION ${SDK_INSTALL_PREFIX}/bin) - install(FILES ${SDK_INSTALL_PREFIX}/bin/eosio-pp - DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME eosio-pp - PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + install(TARGETS wat2wasm DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}) + install(TARGETS wasm2wat DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}) + install(TARGETS eosio-pp DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}) else () # emscripten stuff diff --git a/install.sh b/install.sh new file mode 100755 index 0000000000..8f7f5ad069 --- /dev/null +++ b/install.sh @@ -0,0 +1,102 @@ +#!/bin/bash +########################################################################## +# This is the EOSIO automated install script for Linux and Mac OS. +# This file was downloaded from https://github.com/EOSIO/eos +# +# Copyright (c) 2017, Respective Authors all rights reserved. +# +# After June 1, 2018 this software is available under the following terms: +# +# The MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# https://github.com/EOSIO/eos/blob/master/LICENSE.txt +########################################################################## + + + CWD="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + if [ "${CWD}" != "${PWD}" ]; then + printf "\\n\\tPlease cd into directory %s to run this script.\\n \\tExiting now.\\n\\n" "${CWD}" + exit 1 + fi + + BUILD_DIR="${PWD}/build" + CMAKE_BUILD_TYPE=Release + TIME_BEGIN=$( date -u +%s ) + INSTALL_PREFIX="/usr/local/eosio.wasmsdk" + VERSION=1.2 + + txtbld=$(tput bold) + bldred=${txtbld}$(tput setaf 1) + txtrst=$(tput sgr0) + + create_symlink() { + pushd /usr/local/bin &> /dev/null + ln -sf ../eosio.wasmsdk/bin/$1 $2 + popd &> /dev/null + } + + install_symlinks() { + printf "\\n\\tInstalling EOSIO.WasmSDK Binary Symlinks\\n\\n" + create_symlink "llvm-ranlib eosio-ranlib" + create_symlink "llvm-ar eosio-ar" + create_symlink "llvm-objdump eosio-objdump" + create_symlink "llvm-readelf eosio-readelf" + create_symlink "eosio-cc eosio-cc" + create_symlink "eosio-cpp eosio-cpp" + create_symlink "eosio-ld eosio-ld" + create_symlink "eosio-pp eosio-pp" + create_symlink "wasm2wat eosio-wasm2wast" + create_symlink "wat2wasm eosio-wast2wasm" + } + + if [ ! -d "${BUILD_DIR}" ]; then + printf "\\n\\tError, build.sh has not ran. Please run ./build.sh first!\\n\\n" + exit -1 + fi + + if ! pushd "${BUILD_DIR}" + then + printf "Unable to enter build directory %s.\\n Exiting now.\\n" "${BUILD_DIR}" + exit 1; + fi + + if ! make install + then + printf "\\n\\t>>>>>>>>>>>>>>>>>>>> MAKE installing EOSIO has exited with the above error.\\n\\n" + exit -1 + fi + popd &> /dev/null + + install_symlinks + printf "\n${bldred}\t ___ ___ ___ ___\n" + printf "\t / /\\ / /\\ / /\\ ___ / /\\ \n" + printf "\t / /:/_ / /::\\ / /:/_ / /\\ / /::\\ \n" + printf "\t / /:/ /\\ / /:/\\:\\ / /:/ /\\ / /:/ / /:/\\:\\ \n" + printf "\t / /:/ /:/_ / /:/ \\:\\ / /:/ /::\\ /__/::\\ / /:/ \\:\\ \n" + printf "\t /__/:/ /:/ /\\ /__/:/ \\__\\:\\ /__/:/ /:/\\:\\ \\__\\/\\:\\__ /__/:/ \\__\\:\\ \n" + printf "\t \\ \\:\\/:/ /:/ \\ \\:\\ / /:/ \\ \\:\\/:/~/:/ \\ \\:\\/\\ \\ \\:\\ / /:/ \n" + printf "\t \\ \\::/ /:/ \\ \\:\\ /:/ \\ \\::/ /:/ \\__\\::/ \\ \\:\\ /:/ \n" + printf "\t \\ \\:\\/:/ \\ \\:\\/:/ \\__\\/ /:/ /__/:/ \\ \\:\\/:/ \n" + printf "\t \\ \\::/ \\ \\::/ /__/:/ \\__\\/ \\ \\::/ \n" + printf "\t \\__\\/ \\__\\/ \\__\\/ \\__\\/ \n${txtrst}" + + printf "\\tFor more information:\\n" + printf "\\tEOSIO website: https://eos.io\\n" diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index b3b429dacc..dc30f7e760 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -1,3 +1,6 @@ +set(CMAKE_C_FLAGS " ${CMAKE_C_FLAGS} -O3 -Wall ") +set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -O3 -Wall ") + add_subdirectory(libc) add_subdirectory(libc++) add_subdirectory(eosiolib) diff --git a/libraries/boost/CMakeLists.txt b/libraries/boost/CMakeLists.txt index eeea70e307..c569761ab3 100644 --- a/libraries/boost/CMakeLists.txt +++ b/libraries/boost/CMakeLists.txt @@ -1 +1 @@ -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include DESTINATION ${SDK_INSTALL_PREFIX}/include/../) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/../) diff --git a/libraries/eosiolib/CMakeLists.txt b/libraries/eosiolib/CMakeLists.txt index 8ac4b89aa9..ce30e36fa0 100644 --- a/libraries/eosiolib/CMakeLists.txt +++ b/libraries/eosiolib/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB HEADERS "*.hpp" "*.h") -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/core_symbol.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/core_symbol.hpp) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/core_symbol.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/core_symbol.hpp) add_library(eosio eosiolib.cpp @@ -9,12 +9,13 @@ add_library(eosio target_include_directories(eosio PUBLIC "$" - $) + $) target_link_libraries( eosio c c++ ) install(TARGETS eosio EXPORT EosioLib - LIBRARY DESTINATION ${SDK_INSTALL_PREFIX}/lib/ - ARCHIVE DESTINATION ${SDK_INSTALL_PREFIX}/lib/) + LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../eosiolib DESTINATION ${SDK_INSTALL_PREFIX}/include) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../eosiolib DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp") +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/core_symbol.hpp DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/eosiolib) diff --git a/libraries/eosiolib/action.h b/libraries/eosiolib/action.h index 7356c65dab..3e686fe469 100644 --- a/libraries/eosiolib/action.h +++ b/libraries/eosiolib/action.h @@ -9,14 +9,14 @@ extern "C" { /** * @defgroup actionapi Action API * @ingroup contractdev - * @brief Define API for querying action properties + * @brief Defines API for for querying action and sending action * */ /** * @defgroup actioncapi Action C API * @ingroup actionapi - * @brief Define API for querying action properties + * @brief Defines API for querying action and sending action * * * A EOS.IO action has the following abstract structure: @@ -68,16 +68,19 @@ extern "C" { /** * Copy up to @ref len bytes of current action data to the specified location + * * @brief Copy current action data to the specified location * @param msg - a pointer where up to @ref len bytes of the current action data will be copied * @param len - len of the current action data to be copied, 0 to report required size * @return the number of bytes copied to msg, or number of bytes that can be copied if len==0 passed + * @pre `msg` is a valid pointer to a range of memory at least `len` bytes long + * @post `msg` is filled with packed action data */ uint32_t read_action_data( void* msg, uint32_t len ); /** - * Get the length of the current action's data field - * This method is useful for dynamically sized actions + * Get the length of the current action's data field. This method is useful for dynamically sized actions + * * @brief Get the length of current action's data field * @return the length of the current action's data field */ @@ -85,21 +88,31 @@ extern "C" { /** * Add the specified account to set of accounts to be notified + * * @brief Add the specified account to set of accounts to be notified * @param name - name of the account to be verified */ void require_recipient( account_name name ); /** - * Verifies that @ref name exists in the set of provided auths on a action. Throws if not found + * Verifies that @ref name exists in the set of provided auths on a action. Throws if not found. + * * @brief Verify specified account exists in the set of provided auths * @param name - name of the account to be verified */ void require_auth( account_name name ); + + /** + * Verifies that @ref name has auth. + * + * @brief Verifies that @ref name has auth. + * @param name - name of the account to be verified + */ bool has_auth( account_name name ); /** - * Verifies that @ref name exists in the set of provided auths on a action. Throws if not found + * Verifies that @ref name exists in the set of provided auths on a action. Throws if not found. + * * @brief Verify specified account exists in the set of provided auths * @param name - name of the account to be verified * @param permission - permission level to be verified @@ -110,15 +123,19 @@ extern "C" { /** * Send an inline action in the context of this action's parent transaction - * @param serialized_action - serialized action - * @param size - size of serialized action in bytes + * + * @param serialized_action - serialized action + * @param size - size of serialized action in bytes + * @pre `serialized_action` is a valid pointer to an array at least `size` bytes long */ void send_inline(char *serialized_action, size_t size); /** * Send an inline context free action in the context of this action's parent transaction - * @param serialized_action - serialized action - * @param size - size of serialized action in bytes + * + * @param serialized_action - serialized action + * @param size - size of serialized action in bytes + * @pre `serialized_action` is a valid pointer to an array at least `size` bytes long */ void send_context_free_inline(char *serialized_action, size_t size); diff --git a/libraries/eosiolib/action.hpp b/libraries/eosiolib/action.hpp index e6963178e3..fcbb40b749 100644 --- a/libraries/eosiolib/action.hpp +++ b/libraries/eosiolib/action.hpp @@ -17,7 +17,7 @@ namespace eosio { /** * @defgroup actioncppapi Action C++ API * @ingroup actionapi - * @brief Type-safe C++ wrapers for Action C API + * @brief Defines type-safe C++ wrapers for querying action and sending action * * @note There are some methods from the @ref actioncapi that can be used directly from C++ * @@ -28,9 +28,11 @@ namespace eosio { * * This method unpacks the current action at type T. * - * @brief Interpret the action body as type T + * @brief Interpret the action body as type T. + * @return Unpacked action data casted as T. * * Example: + * * @code * struct dummy_action { * char a; //1 @@ -62,9 +64,12 @@ namespace eosio { * * @note action.code is also considered as part of the set of notified accounts * - * @brief Verify specified accounts exist in the set of notified accounts + * @brief Notify an account for this action + * @param name account to be notified + * @param remaining_accounts accounts to be notified * * Example: + * * @code * require_recipient(N(Account1), N(Account2), N(Account3)); // throws exception if any of them not in set. * @endcode @@ -75,13 +80,50 @@ namespace eosio { require_recipient( remaining_accounts... ); } + /** + * Packed representation of a permission level (Authorization) + * + * @brief Packed representation of a permission level (Authorization) + */ struct permission_level { + /** + * Construct a new permission level object with actor name and permission name + * + * @brief Construct a new permission level object + * @param a - Name of the account who owns this authorization + * @param p - Name of the permission + */ permission_level( account_name a, permission_name p ):actor(a),permission(p){} + + /** + * Default Constructor + * + * @brief Construct a new permission level object + */ permission_level(){} + /** + * Name of the account who owns this permission + * + * @brief Name of the account who owns this permission + */ account_name actor; + /** + * Name of the permission + * + * @brief Name of the permission + */ permission_name permission; + /** + * Check equality of two permissions + * + * @brief Check equality of two permissions + * @param a - first permission to compare + * @param b - second permission to compare + * @return true if equal + * @return false if unequal + */ friend bool operator == ( const permission_level& a, const permission_level& b ) { return std::tie( a.actor, a.permission ) == std::tie( b.actor, b.permission ); } @@ -89,25 +131,66 @@ namespace eosio { EOSLIB_SERIALIZE( permission_level, (actor)(permission) ) }; - void require_auth(const permission_level& level) { + /** + * Require the specified authorization for this action. If this action doesn't contain the specified auth, it will fail. + * + * @brief Require the specified authorization for this action + * + * @param level - Authorization to be required + */ + inline void require_auth(const permission_level& level) { require_auth2( level.actor, level.permission ); } /** * This is the packed representation of an action along with * meta-data about the authorization levels. + * + * @brief Packed representation of an action */ struct action { + /** + * Name of the account the action is intended for + * + * @brief Name of the account the action is intended for + */ account_name account; + + /** + * Name of the action + * + * @brief Name of the action + */ action_name name; + + /** + * List of permissions that authorize this action + * + * @brief List of permissions that authorize this action + */ vector authorization; + + /** + * Payload data + * + * @brief Payload data + */ bytes data; + /** + * Default Constructor + * + * @brief Construct a new action object + */ action() = default; /** - * @tparam Action - a type derived from action_meta - * @param value - will be serialized via pack into data + * Construct a new action object with the given permission and action struct + * + * @brief Construct a new action object with the given permission and action struct + * @tparam Action - Type of action struct + * @param auth - The permission that authorizes this action + * @param value - The action struct that will be serialized via pack into data */ template action( vector&& auth, const Action& value ) { @@ -118,8 +201,12 @@ namespace eosio { } /** - * @tparam Action - a type derived from action_meta - * @param value - will be serialized via pack into data + * Construct a new action object with the given list of permissions and action struct + * + * @brief Construct a new action object with the given list of permissions and action struct + * @tparam Action - Type of action struct + * @param auth - The list of permissions that authorizes this action + * @param value - The action struct that will be serialized via pack into data */ template action( const permission_level& auth, const Action& value ) @@ -129,9 +216,13 @@ namespace eosio { data = pack(value); } + /** - * @tparam Action - a type derived from action_meta - * @param value - will be serialized via pack into data + * Construct a new action object with the given action struct + * + * @brief Construct a new action object with the given action struct + * @tparam Action - Type of action struct + * @param value - The action struct that will be serialized via pack into data */ template action( const Action& value ) { @@ -141,22 +232,28 @@ namespace eosio { } /** - * @tparam T - the type of the action data - * @param auth - a single permission_level to be used as the authorization of the action - * @param a - name of the contract account - * @param n - name of the action - * @param value - will be serialized via pack into data + * Construct a new action object with the given action struct + * + * @brief Construct a new action object with the given permission, action receiver, action name, action struct + * @tparam T - Type of action struct, must be serializable by `pack(...)` + * @param auth - The permissions that authorizes this action + * @param a - The name of the account this action is intended for (action receiver) + * @param n - The name of the action + * @param value - The action struct that will be serialized via pack into data */ template action( const permission_level& auth, account_name a, action_name n, T&& value ) :account(a), name(n), authorization(1,auth), data(pack(std::forward(value))) {} /** - * @tparam T - the type of the action data - * @param auths - vector permission_levels defining the authorizations of the action - * @param a - name of the contract account - * @param n - name of the action - * @param value - will be serialized via pack into data + * Construct a new action object with the given action struct + * + * @brief Construct a new action object with the given list of permissions, action receiver, action name, action struct + * @tparam T - Type of action struct, must be serializable by `pack(...)` + * @param auths - The list of permissions that authorize this action + * @param a - The name of the account this action is intended for (action receiver) + * @param n - The name of the action + * @param value - The action struct that will be serialized via pack into data */ template action( vector auths, account_name a, action_name n, T&& value ) @@ -164,11 +261,22 @@ namespace eosio { EOSLIB_SERIALIZE( action, (account)(name)(authorization)(data) ) + /** + * Send the action as inline action + * + * @brief Send the action as inline action + */ void send() const { auto serialize = pack(*this); ::send_inline(serialize.data(), serialize.size()); } + /** + * Send the action as inline context free action + * + * @brief Send the action as inline context free action + * @pre This action should not contain any authorizations + */ void send_context_free() const { eosio_assert( authorization.size() == 0, "context free actions cannot have authorizations"); auto serialize = pack(*this); @@ -177,6 +285,8 @@ namespace eosio { /** * Retrieve the unpacked data as T + * + * @brief Retrieve the unpacked data as T * @tparam T expected type of data * @return the action data */ @@ -189,12 +299,33 @@ namespace eosio { }; + /** + * Base class to derive a new defined action from so it can take advantage of the dispatcher + * + * @brief Base class to derive a new defined action from + * @tparam Account - The account this action is intended for + * @tparam Name - The name of the action + */ template struct action_meta { + /** + * Get the account this action is intended for + * + * @brief Get the account this action is intended for + * @return uint64_t The account this action is intended for + */ static uint64_t get_account() { return Account; } + /** + * Get the name of this action + * + * @brief Get the name of this action + * @return uint64_t Name of the action + */ static uint64_t get_name() { return Name; } }; + ///@} actioncpp api + template void dispatch_inline( account_name code, action_name act, vector perms, @@ -202,9 +333,11 @@ namespace eosio { action( perms, code, act, std::move(args) ).send(); } + template struct inline_dispatcher; + template struct inline_dispatcher { static void call(account_name code, const permission_level& perm, std::tuple args) { @@ -215,7 +348,6 @@ namespace eosio { } }; - ///@} actioncpp api } // namespace eosio @@ -227,9 +359,31 @@ INLINE_ACTION_SENDER3( CONTRACT_CLASS, NAME, ::eosio::string_to_name(#NAME) ) #define INLINE_ACTION_SENDER(...) BOOST_PP_OVERLOAD(INLINE_ACTION_SENDER,__VA_ARGS__)(__VA_ARGS__) +/** + * @addtogroup actioncppapi + * Additional documentation for group + * @{ + */ + +/** + * Send inline action + * + * @brief Send inline action + * @param CONTRACT - The account this action is intended for + * @param NAME - The name of the action + * @param ... - The member of the action specified as ("action_member1_name", action_member1_value)("action_member2_name", action_member2_value) + */ #define SEND_INLINE_ACTION( CONTRACT, NAME, ... )\ INLINE_ACTION_SENDER(std::decay_t, NAME)( (CONTRACT).get_self(),\ BOOST_PP_TUPLE_ENUM(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__)) ); - +/** + * Extend a new defined action with theaction meta, so it can work with the dispatcher + * + * @brief Extend a new defined action with the action meta + * @param CODE - The account this action is intended for + * @param NAME - The name of the action + */ #define ACTION( CODE, NAME ) struct NAME : ::eosio::action_meta + + /// @} diff --git a/libraries/eosiolib/asset.hpp b/libraries/eosiolib/asset.hpp index b208e35cb7..ce9db086e6 100644 --- a/libraries/eosiolib/asset.hpp +++ b/libraries/eosiolib/asset.hpp @@ -8,12 +8,54 @@ namespace eosio { + /** + * @defgroup assetapi Asset API + * @brief Defines API for managing assets + * @ingroup contractdev + */ + + /** + * @defgroup assetcppapi Asset CPP API + * @brief Defines %CPP API for managing assets + * @ingroup assetapi + * @{ + */ + + /** + * \struct Stores information for owner of asset + * + * @brief Stores information for owner of asset + */ + struct asset { + /** + * The amount of the asset + * + * @brief The amount of the asset + */ int64_t amount; + + /** + * The symbol name of the asset + * + * @brief The symbol name of the asset + */ symbol_type symbol; + /** + * Maximum amount possible for this asset. It's capped to 2^62 - 1 + * + * @brief Maximum amount possible for this asset + */ static constexpr int64_t max_amount = (1LL << 62) - 1; + /** + * Construct a new asset given the symbol name and the amount + * + * @brief Construct a new asset object + * @param a - The amount of the asset + * @param s - THe name of the symbol, default to CORE_SYMBOL + */ explicit asset( int64_t a = 0, symbol_type s = CORE_SYMBOL ) :amount(a),symbol{s} { @@ -21,20 +63,55 @@ namespace eosio { eosio_assert( symbol.is_valid(), "invalid symbol name" ); } + /** + * Check if the amount doesn't exceed the max amount + * + * @brief Check if the amount doesn't exceed the max amount + * @return true - if the amount doesn't exceed the max amount + * @return false - otherwise + */ bool is_amount_within_range()const { return -max_amount <= amount && amount <= max_amount; } + + /** + * Check if the asset is valid. %A valid asset has its amount <= max_amount and its symbol name valid + * + * @brief Check if the asset is valid + * @return true - if the asset is valid + * @return false - otherwise + */ bool is_valid()const { return is_amount_within_range() && symbol.is_valid(); } + /** + * Set the amount of the asset + * + * @brief Set the amount of the asset + * @param a - New amount for the asset + */ void set_amount( int64_t a ) { amount = a; eosio_assert( is_amount_within_range(), "magnitude of asset amount must be less than 2^62" ); } + /** + * Unary minus operator + * + * @brief Unary minus operator + * @return asset - New asset with its amount is the negative amount of this asset + */ asset operator-()const { asset r = *this; r.amount = -r.amount; return r; } + /** + * Subtraction assignment operator + * + * @brief Subtraction assignment operator + * @param a - Another asset to subtract this asset with + * @return asset& - Reference to this asset + * @post The amount of this asset is subtracted by the amount of asset a + */ asset& operator-=( const asset& a ) { eosio_assert( a.symbol == symbol, "attempt to subtract asset with different symbol" ); amount -= a.amount; @@ -43,6 +120,14 @@ namespace eosio { return *this; } + /** + * Addition Assignment operator + * + * @brief Addition Assignment operator + * @param a - Another asset to subtract this asset with + * @return asset& - Reference to this asset + * @post The amount of this asset is added with the amount of asset a + */ asset& operator+=( const asset& a ) { eosio_assert( a.symbol == symbol, "attempt to add asset with different symbol" ); amount += a.amount; @@ -51,83 +136,214 @@ namespace eosio { return *this; } + /** + * Addition operator + * + * @brief Addition operator + * @param a - The first asset to be added + * @param b - The second asset to be added + * @return asset - New asset as the result of addition + */ inline friend asset operator+( const asset& a, const asset& b ) { asset result = a; result += b; return result; } + /** + * Subtraction operator + * + * @brief Subtraction operator + * @param a - The asset to be subtracted + * @param b - The asset used to subtract + * @return asset - New asset as the result of subtraction of a with b + */ inline friend asset operator-( const asset& a, const asset& b ) { asset result = a; result -= b; return result; } + /** + * Multiplication assignment operator. Multiply the amount of this asset with a number and then assign the value to itself. + * + * @brief Multiplication assignment operator, with a number + * @param a - The multiplier for the asset's amount + * @return asset - Reference to this asset + * @post The amount of this asset is multiplied by a + */ asset& operator*=( int64_t a ) { eosio_assert( a == 0 || (amount * a) / a == amount, "multiplication overflow or underflow" ); + amount *= a; eosio_assert( -max_amount <= amount, "multiplication underflow" ); eosio_assert( amount <= max_amount, "multiplication overflow" ); - amount *= a; return *this; } + /** + * Multiplication operator, with a number proceeding + * + * @brief Multiplication operator, with a number proceeding + * @param a - The asset to be multiplied + * @param b - The multiplier for the asset's amount + * @return asset - New asset as the result of multiplication + */ friend asset operator*( const asset& a, int64_t b ) { asset result = a; result *= b; return result; } + + /** + * Multiplication operator, with a number preceeding + * + * @brief Multiplication operator, with a number preceeding + * @param a - The multiplier for the asset's amount + * @param b - The asset to be multiplied + * @return asset - New asset as the result of multiplication + */ friend asset operator*( int64_t b, const asset& a ) { asset result = a; result *= b; return result; } + /** + * Division assignment operator. Divide the amount of this asset with a number and then assign the value to itself. + * + * @brief Division assignment operator, with a number + * @param a - The divisor for the asset's amount + * @return asset - Reference to this asset + * @post The amount of this asset is divided by a + */ asset& operator/=( int64_t a ) { amount /= a; return *this; } + /** + * Division operator, with a number proceeding + * + * @brief Division operator, with a number proceeding + * @param a - The asset to be divided + * @param b - The divisor for the asset's amount + * @return asset - New asset as the result of division + */ friend asset operator/( const asset& a, int64_t b ) { asset result = a; result /= b; return result; } + /** + * Division operator, with another asset + * + * @brief Division operator, with another asset + * @param a - The asset which amount acts as the dividend + * @param b - The asset which amount acts as the divisor + * @return int64_t - the resulted amount after the division + * @pre Both asset must have the same symbol + */ friend int64_t operator/( const asset& a, const asset& b ) { eosio_assert( a.symbol == b.symbol, "comparison of assets with different symbols is not allowed" ); return a.amount / b.amount; } + /** + * Equality operator + * + * @brief Equality operator + * @param a - The first asset to be compared + * @param b - The second asset to be compared + * @return true - if both asset has the same amount + * @return false - otherwise + * @pre Both asset must have the same symbol + */ friend bool operator==( const asset& a, const asset& b ) { eosio_assert( a.symbol == b.symbol, "comparison of assets with different symbols is not allowed" ); return a.amount == b.amount; } + /** + * Inequality operator + * + * @brief Inequality operator + * @param a - The first asset to be compared + * @param b - The second asset to be compared + * @return true - if both asset doesn't have the same amount + * @return false - otherwise + * @pre Both asset must have the same symbol + */ friend bool operator!=( const asset& a, const asset& b ) { return !( a == b); } + /** + * Less than operator + * + * @brief Less than operator + * @param a - The first asset to be compared + * @param b - The second asset to be compared + * @return true - if the first asset's amount is less than the second asset amount + * @return false - otherwise + * @pre Both asset must have the same symbol + */ friend bool operator<( const asset& a, const asset& b ) { eosio_assert( a.symbol == b.symbol, "comparison of assets with different symbols is not allowed" ); return a.amount < b.amount; } + /** + * Less or equal to operator + * + * @brief Less or equal to operator + * @param a - The first asset to be compared + * @param b - The second asset to be compared + * @return true - if the first asset's amount is less or equal to the second asset amount + * @return false - otherwise + * @pre Both asset must have the same symbol + */ friend bool operator<=( const asset& a, const asset& b ) { eosio_assert( a.symbol == b.symbol, "comparison of assets with different symbols is not allowed" ); return a.amount <= b.amount; } + /** + * Greater than operator + * + * @brief Greater than operator + * @param a - The first asset to be compared + * @param b - The second asset to be compared + * @return true - if the first asset's amount is greater than the second asset amount + * @return false - otherwise + * @pre Both asset must have the same symbol + */ friend bool operator>( const asset& a, const asset& b ) { eosio_assert( a.symbol == b.symbol, "comparison of assets with different symbols is not allowed" ); return a.amount > b.amount; } + /** + * Greater or equal to operator + * + * @brief Greater or equal to operator + * @param a - The first asset to be compared + * @param b - The second asset to be compared + * @return true - if the first asset's amount is greater or equal to the second asset amount + * @return false - otherwise + * @pre Both asset must have the same symbol + */ friend bool operator>=( const asset& a, const asset& b ) { eosio_assert( a.symbol == b.symbol, "comparison of assets with different symbols is not allowed" ); return a.amount >= b.amount; } + /** + * %Print the asset + * + * @brief %Print the asset + */ void print()const { int64_t p = (int64_t)symbol.precision(); int64_t p10 = 1; @@ -154,30 +370,93 @@ namespace eosio { EOSLIB_SERIALIZE( asset, (amount)(symbol) ) }; + /** + * \struct Extended asset which stores the information of the owner of the asset + * + * @brief Extended asset which stores the information of the owner of the asset + */ struct extended_asset : public asset { + /** + * The owner of the asset + * + * @brief The owner of the asset + */ account_name contract; + /** + * Get the extended symbol of the asset + * + * @brief Get the extended symbol of the asset + * @return extended_symbol - The extended symbol of the asset + */ extended_symbol get_extended_symbol()const { return extended_symbol( symbol, contract ); } + + /** + * Default constructor + * + * @brief Construct a new extended asset object + */ extended_asset() = default; + + /** + * Construct a new extended asset given the amount and extended symbol + * + * @brief Construct a new extended asset object + */ extended_asset( int64_t v, extended_symbol s ):asset(v,s),contract(s.contract){} + /** + * Construct a new extended asset given the asset and owner name + * + * @brief Construct a new extended asset object + */ extended_asset( asset a, account_name c ):asset(a),contract(c){} + /** + * %Print the extended asset + * + * @brief %Print the extended asset + */ void print()const { asset::print(); prints("@"); printn(contract); } + + /** + * Unary minus operator + * + * @brief Unary minus operator + * @return extended_asset - New extended asset with its amount is the negative amount of this extended asset + */ extended_asset operator-()const { asset r = this->asset::operator-(); return {r, contract}; } + /** + * Subtraction operator. This subtracts the amount of the extended asset. + * + * @brief Subtraction operator + * @param a - The extended asset to be subtracted + * @param b - The extended asset used to subtract + * @return extended_asset - New extended asset as the result of subtraction + * @pre The owner of both extended asset need to be the same + */ friend extended_asset operator - ( const extended_asset& a, const extended_asset& b ) { eosio_assert( a.contract == b.contract, "type mismatch" ); asset r = static_cast(a) - static_cast(b); return {r, a.contract}; } + /** + * Addition operator. This adds the amount of the extended asset. + * + * @brief Addition operator + * @param a - The extended asset to be added + * @param b - The extended asset to be added + * @return extended_asset - New extended asset as the result of addition + * @pre The owner of both extended asset need to be the same + */ friend extended_asset operator + ( const extended_asset& a, const extended_asset& b ) { eosio_assert( a.contract == b.contract, "type mismatch" ); asset r = static_cast(a) + static_cast(b); @@ -187,5 +466,5 @@ namespace eosio { EOSLIB_SERIALIZE( extended_asset, (amount)(symbol)(contract) ) }; - +/// @} asset type } /// namespace eosio diff --git a/libraries/eosiolib/chain.h b/libraries/eosiolib/chain.h index 3da7cb47f1..8477968be9 100644 --- a/libraries/eosiolib/chain.h +++ b/libraries/eosiolib/chain.h @@ -8,32 +8,38 @@ /** * @defgroup chainapi Chain API - * @brief Define API for querying internal chain state + * @brief Defines API for querying internal chain state * @ingroup contractdev */ /** * @defgroup chaincapi Chain C API - * @brief C API for querying internal chain state + * @brief Defines %C API for querying internal chain state * @ingroup chainapi * @{ */ extern "C" { - /** - * Return the set of active producers - * @param producers - a pointer to an buffer of account_names - * @param datalen - byte length of buffer, 0 to report required size - * @return the number of bytes actually populated, or number of bytes that can be copied if datalen==0 passed - * - * Example: - * @code - * account_name producers[21]; - * uint32_t bytes_populated = get_active_producers(producers, sizeof(account_name)*21); - * @endcode - */ + /** + * Gets the set of active producers. + * @brief Gets the set of active producers. + * + * @param producers - Pointer to a buffer of account names + * @param datalen - Byte length of buffer, when passed 0 will return the size required to store full output. + * + * @return uint32_t - Number of bytes actually populated + * @pre `producers` is a pointer to a range of memory at least `datalen` bytes long + * @post the passed in `producers` pointer gets the array of active producers. + * + * Example: + * + * @code + * account_name producers[21]; + * uint32_t bytes_populated = get_active_producers(producers, sizeof(account_name)*21); + * @endcode + */ - uint32_t get_active_producers( account_name* producers, uint32_t datalen ); + uint32_t get_active_producers( account_name* producers, uint32_t datalen ); ///@ } chaincapi } diff --git a/libraries/eosiolib/compiler_builtins.h b/libraries/eosiolib/compiler_builtins.h index cd69d1dee8..62e2ff2515 100644 --- a/libraries/eosiolib/compiler_builtins.h +++ b/libraries/eosiolib/compiler_builtins.h @@ -8,65 +8,424 @@ extern "C" { /** - * @defgroup compiler builtins API + * @defgroup compilerbuiltinsapi Compiler Builtins API + * @ingroup mathapi * @brief Declares int128 helper builtins generated by the toolchain. - * @ingroup compilerbuiltinsapi - * + * * @{ */ /** - * Multiply two 128 bit integers split as two unsigned 64 bit integers and assign the value to the first parameter. + * Multiply two 128 bit integers split as two 64 bit unsigned integers and assign the value to the first parameter. * @brief Multiply two 128 unsigned bit integers (which are represented as two 64 bit unsigned integers. * @param res It will be replaced with the result product. * @param la Low 64 bits of the first 128 bit factor. * @param ha High 64 bits of the first 128 bit factor. * @param lb Low 64 bits of the second 128 bit factor. * @param hb High 64 bits of the second 128 bit factor. + * @post `res` is replaced with the result of multiplication * Example: * @code * __int128 res = 0; * __int128 a = 100; * __int128 b = 100; * __multi3(res, a, (a >> 64), b, (b >> 64)); - * printi128(res); // Output: 10000 + * printi128(&res); // Output: 10000 * @endcode */ void __multi3(__int128& res, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb); + /** + * Divide two 128 bit integers split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Divide two 128 bit integers (which are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @post `res` is replaced with the result of division + * Example: + * @code + * __int128 res = 0; + * __int128 a = 100; + * __int128 b = 100; + * __divti3(res, a, (a >> 64), b, (b >> 64)); + * printi128(&res); // Output: 1 + * @endcode + */ void __divti3(__int128& res, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb); + + /** + * Divide two 128 bit unsigned integers split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Divide two 128 unsigned bit integers (which are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * Example: + * @code + * unsigned __int128 res = 0; + * unsigned __int128 a = 100; + * unsigned __int128 b = 100; + * __udivti3(res, a, (a >> 64), b, (b >> 64)); + * printi128(&res); // Output: 1 + * @endcode + */ void __udivti3(unsigned __int128& res, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb); + /** + * Perform modular arithmetic on two 128 bit integers split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Perform modular arithmetic on two 128 bit integers (which are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @post `res` is replaced with the result of modulus + * Example: + * @code + * __int128 res = 0; + * __int128 a = 100; + * __int128 b = 3; + * __modti3(res, a, (a >> 64), b, (b >> 64)); + * printi128(&res); // Output: 1 + * @endcode + */ void __modti3(__int128& res, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb); + + /** + * Perform modular arithmetic on two 128 unsigned bit integers split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Perform modular arithmetic on two 128 unsigned bit integers (which are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @post `res` is replaced with the result of modulus + * Example: + * @code + * unsigned __int128 res = 0; + * unsigned __int128 a = 100; + * unsigned __int128 b = 3; + * __umodti3(res, a, (a >> 64), b, (b >> 64)); + * printi128(&res); // Output: 1 + * @endcode + */ void __umodti3(unsigned __int128& res, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb); +/** + * Perform logical shift left on a 128 bit integer split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Perform logical shift left on a 128 bit integer (which is represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param lo Low 64 bits of the 128 bit factor. + * @param hi High 64 bits of the 128 bit factor. + * @param shift Number of bits to shift. + * @post `res` is replaced with the result of the operation + * Example: + * @code + * __int128 res = 0; + * __int128 a = 8; + * __lshlti3(res, a, (a >> 64), 1); + * printi128(&res); // Output: 16 + * @endcode + */ void __lshlti3(__int128& res, uint64_t lo, uint64_t hi, uint32_t shift); + + /** + * Perform logical shift right on a 128 bit integer split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Perform logical shift right on a 128 bit integer (which is represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param lo Low 64 bits of the 128 bit factor. + * @param hi High 64 bits of the 128 bit factor. + * @param shift Number of bits to shift. + * @post `res` is replaced with the result of the operation + * Example: + * @code + * __int128 res = 0; + * __int128 a = 8; + * __lshrti3(res, a, (a >> 64), 1); + * printi128(&res); // Output: 4 + * @endcode + */ void __lshrti3(__int128& res, uint64_t lo, uint64_t hi, uint32_t shift); +/** + * Perform arithmetic shift left on a 128 bit integer split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Perform arithmetic shift left on a 128 bit integer (which is represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param lo Low 64 bits of the 128 bit factor. + * @param hi High 64 bits of the 128 bit factor. + * @param shift Number of bits to shift. + * @post `res` is replaced with the result of the operation + * Example: + * @code + * __int128 res = 0; + * __int128 a = 8; + * __ashlti3(res, a, (a >> 64), 1); + * printi128(&res); // Output: 16 + * @endcode + */ void __ashlti3(__int128& res, uint64_t lo, uint64_t hi, uint32_t shift); + + /** + * Perform arithmetic shift right on a 128 bit integer split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Perform arithmetic shift right on a 128 bit integer (which is represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param lo Low 64 bits of the 128 bit factor. + * @param hi High 64 bits of the 128 bit factor. + * @param shift Number of bits to shift. + * @post `res` is replaced with the result of the operation + * Example: + * @code + * __int128 res = 0; + * __int128 a = -8; + * __ashrti3(res, a, (a >> 64), 1); + * printi128(&res); // Output: -4 + * @endcode + */ void __ashrti3(__int128& res, uint64_t lo, uint64_t hi, uint32_t shift); + /** + * Add two long doubles split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Add two long doubles (which are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @post `ret` is replaced with the result of the operation + */ void __addtf3( long double& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + /** + * Subtract two long doubles split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Subtract two long doubles (which are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @post `ret` is replaced with the result of the operation + */ void __subtf3( long double& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + /** + * Multiply two long doubles split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Multiply two long doubles (which are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @post `ret` is replaced with the result of the operation + */ void __multf3( long double& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + /** + * Divide two long doubles split as two 64 bit unsigned integers and assign the value to the first parameter. + * @brief Divide two long doubles (which are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @post `ret` is replaced with the result of the operation + */ void __divtf3( long double& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + /** + * Check equality between two doubles split as two 64 bit unsigned integers + * @brief Check equality between two doubles (which are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @return 1 if a greater than b + * @return 0 if a equal to b + * @return -1 if a less than b + * @return 1 if either a or b is NaN + */ int __eqtf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + /** + * Check inequality between two doubles split as two 64 bit unsigned integers + * @brief Check inequality between two doubles (which are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @return 1 if a greater than b + * @return 0 if a equal to b + * @return -1 if a less than b + * @return1 if either a or b is NaN + */ int __netf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + + /** + * Check if the first double is greater or equal to the second double, the doubles are split as two 64 bit unsigned integers + * @brief Check if the first double is greater or equal to the second double, (the doubles are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @return 1 if a greater than b + * @return 0 if a equal to b + * @return -1 if a less than b + * @return -1 if either a or b is NaN + */ int __getf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + /** + * Check if the first double is greater than the second double, the doubles are split as two 64 bit unsigned integers + * @brief Check if the first double is greater than the second double, (the doubles are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @return 1 if a greater than b + * @return 0 if a equal to b + * @return -1 if a less than b + * @return 0 if either a or b is NaN + */ int __gttf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + /** + * Check if the first double is less or equal to the second double, the doubles are split as two 64 bit unsigned integers + * @brief Check if the first double is less or equal to the second double, (the doubles are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @return 1 if a greater than b + * @return 0 if a equal to b + * @return -1 if a less than b + * @return 1 if either a or b is NaN + */ int __letf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + /** + * Check if the first double is less than the second double, the doubles are split as two 64 bit unsigned integers + * @brief Check if the first double is less than the second double, (the doubles are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @return 1 if a greater than b + * @return 0 if a equal to b + * @return -1 if a less than b + * @return 0 if either a or b is NaN + */ int __lttf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + /** + * Compare two doubles which are split as two 64 bit unsigned integers + * @brief Compare two doubles (the doubles are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @return 1 if a greater than b + * @return 0 if a equal to b + * @return -1 if a less than b + * @return 1 if either a or b is NaN + */ int __cmptf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + /** + * Check if either of the doubles is NaN, the doubles are split as two 64 bit unsigned integers + * @brief Check if either of the doubles is NaN, (the doubles are represented as two 64 bit unsigned integers) + * @param res It will be replaced with the result product. + * @param la Low 64 bits of the first 128 bit factor. + * @param ha High 64 bits of the first 128 bit factor. + * @param lb Low 64 bits of the second 128 bit factor. + * @param hb High 64 bits of the second 128 bit factor. + * @return 1 if either a or b is NaN + * @return 0 if either a or b is not NaN + */ int __unordtf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ); + + /** + * Extend float to long double + * @brief Extend float to long double + * @param ret It will be replaced with the result product. + * @param f Input float to be extended + * @post `ret` is replaced with the extended float + */ void __extendsftf2( long double& ret, float f ); + + /** + * Extend double to long double + * @brief Extend float to long double + * @param ret It will be replaced with the result product. + * @param f Input float to be extended + * @post `ret` is replaced with the extended float + */ void __extenddftf2( long double& ret, double f ); + + /** + * Convert long double (which are split as two 64 bit unsigned integers) into 64 bit integer + * @brief Convert long double (which are split as two 64 bit unsigned integers) into 64 bit integer + * @param l Low 64 bits of the first 128 bit factor. + * @param h High 64 bits of the first 128 bit factor. + * @return the converted 64 bit integer. + */ int64_t __fixtfdi( uint64_t l, uint64_t h ); + + /** + * Convert long double (which are split as two 64 bit unsigned integers) into 32 bit integer + * @brief Convert long double (which are split as two 64 bit unsigned integers) into 32 bit integer + * @param l Low 64 bits of the first 128 bit factor. + * @param h High 64 bits of the first 128 bit factor. + * @return the converted 32 bit integer. + */ int32_t __fixtfsi( uint64_t l, uint64_t h ); + + /** + * Convert long double (which are split as two 64 bit unsigned integers) into 64 bit unsigned integer + * @brief Convert long double (which are split as two 64 bit unsigned integers) into 64 bit unsigned integer + * @param l Low 64 bits of the first 128 bit factor. + * @param h High 64 bits of the first 128 bit factor. + * @return the converted 64 bit unsigned integer. + */ uint64_t __fixunstfdi( uint64_t l, uint64_t h ); + + /** + * Convert long double (which are split as two 64 bit unsigned integers) into 32 bit unsigned integer + * @brief Convert long double (which are split as two 64 bit unsigned integers) into 32 bit unsigned integer + * @param l Low 64 bits of the first 128 bit factor. + * @param h High 64 bits of the first 128 bit factor. + * @return the converted 32 bit unsigned integer. + */ uint32_t __fixunstfsi( uint64_t l, uint64_t h ); + + /** + * Truncate long double (which are split as two 64 bit unsigned integers) into double + * @brief Convert long double (which are split as two 64 bit unsigned integers) into double + * @param l Low 64 bits of the first 128 bit factor. + * @param h High 64 bits of the first 128 bit factor. + * @return the converted double + */ double __trunctfdf2( uint64_t l, uint64_t h ); + + /** + * Truncate long double (which are split as two 64 bit unsigned integers) into float + * @brief Convert long double (which are split as two 64 bit unsigned integers) into float + * @param l Low 64 bits of the first 128 bit factor. + * @param h High 64 bits of the first 128 bit factor. + * @return the converted float + */ float __trunctfsf2( uint64_t l, uint64_t h ); void __break_point(); +/// @} } // extern "C" diff --git a/libraries/eosiolib/contract.hpp b/libraries/eosiolib/contract.hpp index 4e88dae342..307731bd72 100644 --- a/libraries/eosiolib/contract.hpp +++ b/libraries/eosiolib/contract.hpp @@ -2,14 +2,46 @@ namespace eosio { +/** + * @defgroup contracttype Contract Type + * @ingroup types + * @brief Defines contract type which is %base class for every EOSIO contract + * + * @{ + * + */ + +/** + * @brief %Base class for EOSIO contract. + * @details %Base class for EOSIO contract. %A new contract should derive from this class, so it can make use of EOSIO_ABI macro. + */ class contract { public: + /** + * Construct a new contract given the contract name + * + * @brief Construct a new contract object. + * @param n - The name of this contract + */ contract( account_name n ):_self(n){} + /** + * + * Get this contract name + * + * @brief Get this contract name. + * @return account_name - The name of this contract + */ inline account_name get_self()const { return _self; } protected: + /** + * The name of this contract + * + * @brief The name of this contract. + */ account_name _self; }; +/// @} contracttype } /// namespace eosio diff --git a/libraries/eosiolib/core_symbol.hpp b/libraries/eosiolib/core_symbol.hpp deleted file mode 100644 index b4b86071f7..0000000000 --- a/libraries/eosiolib/core_symbol.hpp +++ /dev/null @@ -1,7 +0,0 @@ -/** @file - * @copyright defined in eos/LICENSE.txt - * - * \warning This file is machine generated. DO NOT EDIT. See core_symbol.hpp.in for changes. - */ - -#define CORE_SYMBOL S(4,SYS) diff --git a/libraries/eosiolib/core_symbol.hpp.in b/libraries/eosiolib/core_symbol.hpp.in index 84311cac62..4a60220b6a 100644 --- a/libraries/eosiolib/core_symbol.hpp.in +++ b/libraries/eosiolib/core_symbol.hpp.in @@ -4,4 +4,4 @@ * \warning This file is machine generated. DO NOT EDIT. See core_symbol.hpp.in for changes. */ -#define CORE_SYMBOL S(4,${CORE_SYMBOL_NAME}) +#define CORE_SYMBOL S(4,${CORE_SYMBOL_NAME}) \ No newline at end of file diff --git a/libraries/eosiolib/crypto.h b/libraries/eosiolib/crypto.h index cae78328e1..4fd9b04e50 100644 --- a/libraries/eosiolib/crypto.h +++ b/libraries/eosiolib/crypto.h @@ -5,85 +5,236 @@ #pragma once #include extern "C" { + +/** + * @defgroup cryptoapi Chain API + * @brief Defines API for calculating and checking hash + * @ingroup contractdev + */ + +/** + * @defgroup cryptocapi Chain C API + * @brief Defines %C API for calculating and checking hash + * @ingroup chainapi + * @{ + */ + /** - * This method is implemented as: + * Tests if the sha256 hash generated from data matches the provided checksum. + * This method is optimized to a NO-OP when in fast evaluation mode. + * @brief Tests if the sha256 hash generated from data matches the provided checksum. * - * checksum calc_hash; - * sha256( data, length, &calc_hash ); - * eosio_assert( calc_hash == hash, "invalid hash" ); + * @param data - Data you want to hash + * @param length - Data length + * @param hash - `checksum256*` hash to compare to * - * This method is optimized to a NO-OP when in fast evaluation mode + * @pre **assert256 hash** of `data` equals provided `hash` parameter. + * @post Executes next statement. If was not `true`, hard return. + * + * Example: +* + * @code + * checksum hash; + * char data; + * uint32_t length; + * assert_sha256( data, length, hash ) + * //If the sha256 hash generated from data does not equal provided hash, anything below will never fire. + * eosio::print("sha256 hash generated from data equals provided hash"); + * @endcode */ void assert_sha256( char* data, uint32_t length, const checksum256* hash ); /** - * This method is implemented as: + * Tests if the sha1 hash generated from data matches the provided checksum. + * This method is optimized to a NO-OP when in fast evaluation mode. + * @brief Tests if the sha1 hash generated from data matches the provided checksum. * - * checksum calc_hash; - * sha1( data, length, &calc_hash ); - * eos_assert( calc_hash == hash, "invalid hash" ); + * @param data - Data you want to hash + * @param length - Data length + * @param hash - `checksum160*` hash to compare to + * + * @pre **sha1 hash** of `data` equals provided `hash` parameter. + * @post Executes next statement. If was not `true`, hard return. * - * This method is optimized to a NO-OP when in fast evaluation mode + * Example: +* + * @code + * checksum hash; + * char data; + * uint32_t length; + * assert_sha1( data, length, hash ) + * //If the sha1 hash generated from data does not equal provided hash, anything below will never fire. + * eosio::print("sha1 hash generated from data equals provided hash"); + * @endcode */ void assert_sha1( char* data, uint32_t length, const checksum160* hash ); /** - * This method is implemented as: + * Tests if the sha512 hash generated from data matches the provided checksum. + * This method is optimized to a NO-OP when in fast evaluation mode. + * @brief Tests if the sha512 hash generated from data matches the provided checksum. * - * checksum calc_hash; - * sha512( data, length, &calc_hash ); - * eos_assert( calc_hash == hash, "invalid hash" ); + * @param data - Data you want to hash + * @param length - Data length + * @param hash - `checksum512*` hash to compare to + * + * @pre **assert512 hash** of `data` equals provided `hash` parameter. + * @post Executes next statement. If was not `true`, hard return. * - * This method is optimized to a NO-OP when in fast evaluation mode + * Example: +* + * @code + * checksum hash; + * char data; + * uint32_t length; + * assert_sha512( data, length, hash ) + * //If the sha512 hash generated from data does not equal provided hash, anything below will never fire. + * eosio::print("sha512 hash generated from data equals provided hash"); + * @endcode */ void assert_sha512( char* data, uint32_t length, const checksum512* hash ); /** - * This method is implemented as: + * Tests if the ripemod160 hash generated from data matches the provided checksum. + * @brief Tests if the ripemod160 hash generated from data matches the provided checksum. * - * checksum calc_hash; - * ripemd160( data, length, &calc_hash ); - * eos_assert( calc_hash == hash, "invalid hash" ); + * @param data - Data you want to hash + * @param length - Data length + * @param hash - `checksum160*` hash to compare to + * + * @pre **assert160 hash** of `data` equals provided `hash` parameter. + * @post Executes next statement. If was not `true`, hard return. * - * This method is optimized to a NO-OP when in fast evaluation mode + * Example: +* + * @code + * checksum hash; + * char data; + * uint32_t length; + * assert_ripemod160( data, length, hash ) + * //If the ripemod160 hash generated from data does not equal provided hash, anything below will never fire. + * eosio::print("ripemod160 hash generated from data equals provided hash"); + * @endcode */ void assert_ripemd160( char* data, uint32_t length, const checksum160* hash ); /** - * Calculates sha256( data,length) and stores result in memory pointed to by hash - * `hash` should be checksum<256> + * Hashes `data` using `sha256` and stores result in memory pointed to by hash. + * @brief Hashes `data` using `sha256` and stores result in memory pointed to by hash. + * + * @param data - Data you want to hash + * @param length - Data length + * @param hash - Hash pointer + * + * Example: +* + * @code + * checksum calc_hash; + * sha256( data, length, &calc_hash ); + * eos_assert( calc_hash == hash, "invalid hash" ); + * @endcode */ void sha256( char* data, uint32_t length, checksum256* hash ); /** - * Calculates sha1( data,length) and stores result in memory pointed to by hash - * `hash` should be checksum<160> + * Hashes `data` using `sha1` and stores result in memory pointed to by hash. + * @brief Hashes `data` using `sha1` and stores result in memory pointed to by hash. + * + * @param data - Data you want to hash + * @param length - Data length + * @param hash - Hash pointer + * + * Example: +* + * @code + * checksum calc_hash; + * sha1( data, length, &calc_hash ); + * eos_assert( calc_hash == hash, "invalid hash" ); + * @endcode */ void sha1( char* data, uint32_t length, checksum160* hash ); /** - * Calculates sha512( data,length) and stores result in memory pointed to by hash - * `hash` should be checksum<512> + * Hashes `data` using `sha512` and stores result in memory pointed to by hash. + * @brief Hashes `data` using `sha512` and stores result in memory pointed to by hash. + * + * @param data - Data you want to hash + * @param length - Data length + * @param hash - Hash pointer + * + * Example: +* + * @code + * checksum calc_hash; + * sha512( data, length, &calc_hash ); + * eos_assert( calc_hash == hash, "invalid hash" ); + * @endcode */ void sha512( char* data, uint32_t length, checksum512* hash ); /** - * Calculates ripemd160( data,length) and stores result in memory pointed to by hash - * `hash` should be checksum<160> + * Hashes `data` using `ripemod160` and stores result in memory pointed to by hash. + * @brief Hashes `data` using `ripemod160` and stores result in memory pointed to by hash. + * + * @param data - Data you want to hash + * @param length - Data length + * @param hash - Hash pointer + * + * Example: +* + * @code + * checksum calc_hash; + * ripemod160( data, length, &calc_hash ); + * eos_assert( calc_hash == hash, "invalid hash" ); + * @endcode */ void ripemd160( char* data, uint32_t length, checksum160* hash ); /** - * Calculates the public key used for a given signature and hash used to create a message and places it in `pub` - * returns the number of bytes read into pub - * `digest` should be checksum<256> + * Calculates the public key used for a given signature and hash used to create a message. + * @brief Calculates the public key used for a given signature and hash used to create a message. + * + * @param digest - Hash used to create a message + * @param sig - Signature + * @param siglen - Signature length + * @param pub - Public key + * @param publen - Public key length + * + * Example: +* + * @code + * @endcode */ int recover_key( const checksum256* digest, const char* sig, size_t siglen, char* pub, size_t publen ); /** - * Tests a given public key with the generated key from digest and the signature - * `digest` should be checksum<256> + * Tests a given public key with the generated key from digest and the signature. + * @brief Tests a given public key with the generated key from digest and the signature. + * + * @param digest - What the key will be generated from + * @param sig - Signature + * @param siglen - Signature length + * @param pub - Public key + * @param publen - Public key length + * + * @pre **assert recovery key** of `pub` equals the key generated from the `digest` parameter + * @post Executes next statement. If was not `true`, hard return. + * + * Example: +* + * @code + * checksum digest; + * char sig; + * size_t siglen; + * char pub; + * size_t publen; + * assert_recover_key( digest, sig, siglen, pub, publen ) + * // If the given public key does not match with the generated key from digest and the signature, anything below will never fire. + * eosio::print("pub key matches the pub key generated from digest"); + * @endcode */ void assert_recover_key( const checksum256* digest, const char* sig, size_t siglen, const char* pub, size_t publen ); +/// }@cryptocapi + } diff --git a/libraries/eosiolib/currency.hpp b/libraries/eosiolib/currency.hpp index 2a5dced3ae..1328c49387 100644 --- a/libraries/eosiolib/currency.hpp +++ b/libraries/eosiolib/currency.hpp @@ -9,7 +9,7 @@ namespace eosio { /** * This contract enables the creation, issuance, and transfering of many different tokens. - * + * @deprecated This class is deprecated in favor of eosio.token in Dawn 3.0 */ class currency { public: diff --git a/libraries/eosiolib/datastream.hpp b/libraries/eosiolib/datastream.hpp index 7287903a9a..65666e78cc 100644 --- a/libraries/eosiolib/datastream.hpp +++ b/libraries/eosiolib/datastream.hpp @@ -22,28 +22,47 @@ namespace eosio { +/** + * @defgroup datastream Data Stream + * @brief Defines data stream for reading and writing data in the form of bytes + * @ingroup serialize + * @{ + */ /** - * @brief A data stream for reading and writing data in the form of bytes + * %A data stream for reading and writing data in the form of bytes + * + * @brief %A data stream for reading and writing data in the form of bytes. + * @tparam T - Type of the datastream buffer */ template class datastream { public: + /** + * Construct a new datastream object given the size of the buffer and start position of the buffer + * + * @brief Construct a new datastream object + * @param start - The start position of the buffer + * @param s - The size of the buffer + */ datastream( T start, size_t s ) :_start(start),_pos(start),_end(start+s){} /** * Skips a specified number of bytes from this stream + * * @brief Skips a specific number of bytes from this stream - * @param s The number of bytes to skip + * @param s - The number of bytes to skip */ inline void skip( size_t s ){ _pos += s; } /** * Reads a specified number of bytes from the stream into a buffer + * * @brief Reads a specified number of bytes from this stream into a buffer - * @param d pointer to the destination buffer - * @param s the number of bytes to read + * @param d - The pointer to the destination buffer + * @param s - the number of bytes to read + * @return true */ inline bool read( char* d, size_t s ) { eosio_assert( size_t(_end - _pos) >= (size_t)s, "read" ); @@ -54,9 +73,11 @@ class datastream { /** * Writes a specified number of bytes into the stream from a buffer + * * @brief Writes a specified number of bytes into the stream from a buffer - * @param d pointer to the source buffer - * @param s The number of bytes to write + * @param d - The pointer to the source buffer + * @param s - The number of bytes to write + * @return true */ inline bool write( const char* d, size_t s ) { eosio_assert( _end - _pos >= (int32_t)s, "write" ); @@ -67,8 +88,10 @@ class datastream { /** * Writes a byte into the stream + * * @brief Writes a byte into the stream * @param c byte to write + * @return true */ inline bool put(char c) { eosio_assert( _pos < _end, "put" ); @@ -79,10 +102,20 @@ class datastream { /** * Reads a byte from the stream + * * @brief Reads a byte from the stream - * @param c reference to destination byte + * @param c - The reference to destination byte + * @return true */ inline bool get( unsigned char& c ) { return get( *(char*)&c ); } + + /** + * Reads a byte from the stream + * + * @brief Reads a byte from the stream + * @param c - The reference to destination byte + * @return true + */ inline bool get( char& c ) { eosio_assert( _pos < _end, "get" ); @@ -93,72 +126,164 @@ class datastream { /** * Retrieves the current position of the stream + * * @brief Retrieves the current position of the stream - * @return the current position of the stream + * @return T - The current position of the stream */ T pos()const { return _pos; } inline bool valid()const { return _pos <= _end && _pos >= _start; } /** * Sets the position within the current stream + * * @brief Sets the position within the current stream - * @param p offset relative to the origin + * @param p - The offset relative to the origin + * @return true if p is within the range + * @return false if p is not within the rawnge */ inline bool seekp(size_t p) { _pos = _start + p; return _pos <= _end; } /** * Gets the position within the current stream + * * @brief Gets the position within the current stream - * @return p the position within the current stream + * @return p - The position within the current stream */ inline size_t tellp()const { return size_t(_pos - _start); } /** * Returns the number of remaining bytes that can be read/skipped + * * @brief Returns the number of remaining bytes that can be read/skipped - * @return number of remaining bytes + * @return size_t - The number of remaining bytes */ inline size_t remaining()const { return _end - _pos; } private: + /** + * The start position of the buffer + * + * @brief The start position of the buffer + */ T _start; + /** + * The current position of the buffer + * + * @brief The current position of the buffer + */ T _pos; + /** + * The end position of the buffer + * + * @brief The end position of the buffer + */ T _end; }; /** - * @brief Specialization of datastream used to help determine the final size of a serialized value + * @brief Specialization of datastream used to help determine the final size of a serialized value. + * Specialization of datastream used to help determine the final size of a serialized value */ template<> class datastream { public: + /** + * Construct a new specialized datastream object given the initial size + * + * @brief Construct a new specialized datastream object + * @param init_size - The initial size + */ datastream( size_t init_size = 0):_size(init_size){} + + /** + * Increment the size by s. This behaves the same as write( const char* ,size_t s ). + * + * @brief Increase the size by s + * @param s - The amount of size to increase + * @return true + */ inline bool skip( size_t s ) { _size += s; return true; } + + /** + * Increment the size by s. This behaves the same as skip( size_t s ) + * + * @brief Increase the size by s + * @param s - The amount of size to increase + * @return true + */ inline bool write( const char* ,size_t s ) { _size += s; return true; } + + /** + * Increment the size by one + * + * @brief Increase the size by one + * @return true + */ inline bool put(char ) { ++_size; return true; } + + /** + * Check validity. It's always valid + * + * @brief Check validity + * @return true + */ inline bool valid()const { return true; } + + /** + * Set new size + * + * @brief Set new size + * @param p - The new size + * @return true + */ inline bool seekp(size_t p) { _size = p; return true; } + + /** + * Get the size + * + * @brief Get the size + * @return size_t - The size + */ inline size_t tellp()const { return _size; } + + /** + * Always returns 0 + * + * @brief Always returns 0 + * @return size_t - 0 + */ inline size_t remaining()const { return 0; } private: + /** + * The size used to determine the final size of a serialized value. + * + * @brief The size used to determine the final size of a serialized value. + */ size_t _size; }; /** * Serialize a public_key into a stream + * * @brief Serialize a public_key - * @param ds stream to write - * @param pubkey value to serialize + * @param ds - The stream to write + * @param pubkey - The value to serialize + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream */ template inline datastream& operator<<(datastream& ds, const public_key pubkey) { ds.write( (const char*)&pubkey, sizeof(pubkey)); return ds; } + /** * Deserialize a public_key from a stream + * * @brief Deserialize a public_key - * @param ds stream to read - * @param pubkey destination for deserialized value + * @param ds - The stream to read + * @param pubkey - The destination for deserialized value + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream */ template inline datastream& operator>>(datastream& ds, public_key& pubkey) { @@ -168,20 +293,27 @@ inline datastream& operator>>(datastream& ds, public_key& pubkey /** * Serialize a key256 into a stream + * * @brief Serialize a key256 - * @param ds stream to write - * @param d value to serialize + * @param ds - The stream to write + * @param d - The value to serialize + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream */ template inline datastream& operator<<(datastream& ds, const key256& d) { ds.write( (const char*)d.data(), d.size() ); return ds; } + /** * Deserialize a key256 from a stream + * * @brief Deserialize a key256 - * @param ds stream to read - * @param d destination for deserialized value + * @param ds - The stream to read + * @param d - The destination for deserialized value + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream */ template inline datastream& operator>>(datastream& ds, key256& d) { @@ -189,10 +321,29 @@ inline datastream& operator>>(datastream& ds, key256& d) { return ds; } +/** + * Serialize a bool into a stream + * + * @brief Serialize a bool into a stream + * @param ds - The stream to read + * @param d - The value to serialize + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream + */ template inline datastream& operator<<(datastream& ds, const bool& d) { return ds << uint8_t(d); } + +/** + * Deserialize a bool from a stream + * + * @brief Deserialize a bool + * @param ds - The stream to read + * @param d - The destination for deserialized value + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream + */ template inline datastream& operator>>(datastream& ds, bool& d) { uint8_t t; @@ -203,20 +354,27 @@ inline datastream& operator>>(datastream& ds, bool& d) { /** * Serialize a checksum256 into a stream + * * @brief Serialize a checksum256 - * @param ds stream to write - * @param d value to serialize + * @param ds - The stream to write + * @param d - The value to serialize + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream */ template inline datastream& operator<<(datastream& ds, const checksum256& d) { ds.write( (const char*)&d.hash[0], sizeof(d.hash) ); return ds; } + /** * Deserialize a checksum256 from a stream + * * @brief Deserialize a checksum256 - * @param ds stream to read - * @param d destination for deserialized value + * @param ds - The stream to read + * @param d - The destination for deserialized value + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream */ template inline datastream& operator>>(datastream& ds, checksum256& d) { @@ -224,6 +382,15 @@ inline datastream& operator>>(datastream& ds, checksum256& d) { return ds; } +/** + * Serialize a string into a stream + * + * @brief Serialize a string + * @param ds - The stream to write + * @param v - The value to serialize + * @tparam DataStream - Type of datastream + * @return DataStream& - Reference to the datastream + */ template DataStream& operator << ( DataStream& ds, const std::string& v ) { ds << unsigned_int( v.size() ); @@ -232,6 +399,15 @@ DataStream& operator << ( DataStream& ds, const std::string& v ) { return ds; } +/** + * Deserialize a string from a stream + * + * @brief Deserialize a string + * @param ds - The stream to read + * @param v - The destination for deserialized value + * @tparam DataStream - Type of datastream + * @return DataStream& - Reference to the datastream + */ template DataStream& operator >> ( DataStream& ds, std::string& v ) { std::vector tmp; @@ -243,6 +419,17 @@ DataStream& operator >> ( DataStream& ds, std::string& v ) { return ds; } +/** + * Serialize a fixed size array into a stream + * + * @brief Serialize a fixed size array + * @param ds - The stream to write + * @param v - The value to serialize + * @tparam DataStream - Type of datastream + * @tparam T - Type of the object contained in the array + * @tparam N - Size of the array + * @return DataStream& - Reference to the datastream + */ template DataStream& operator << ( DataStream& ds, const std::array& v ) { for( const auto& i : v ) @@ -250,6 +437,18 @@ DataStream& operator << ( DataStream& ds, const std::array& v ) { return ds; } + +/** + * Deserialize a fixed size array from a stream + * + * @brief Deserialize a fixed size array + * @param ds - The stream to read + * @param v - The destination for deserialized value + * @tparam DataStream - Type of datastream + * @tparam T - Type of the object contained in the array + * @tparam N - Size of the array + * @return DataStream& - Reference to the datastream + */ template DataStream& operator >> ( DataStream& ds, std::array& v ) { for( auto& i : v ) @@ -258,6 +457,14 @@ DataStream& operator >> ( DataStream& ds, std::array& v ) { } namespace _datastream_detail { + /** + * Check if type T is a pointer + * + * @brief Check if type T is a pointer + * @tparam T - The type to be checked + * @return true if T is a pointer + * @return false otherwise + */ template constexpr bool is_pointer() { return std::is_pointer::value || @@ -265,6 +472,14 @@ namespace _datastream_detail { std::is_member_pointer::value; } + /** + * Check if type T is a primitive type + * + * @brief Check if type T is a primitive type + * @tparam T - The type to be checked + * @return true if T is a primitive type + * @return false otherwise + */ template constexpr bool is_primitive() { return std::is_arithmetic::value || @@ -272,12 +487,32 @@ namespace _datastream_detail { } } +/** + * Pointer should not be serialized, so this function will always throws an error + * + * @brief Deserialize a a pointer + * @param ds - The stream to read + * @tparam DataStream - Type of datastream + * @tparam T - Type of the pointer + * @return DataStream& - Reference to the datastream + * @post Throw an exception if it is a pointer + */ template()>* = nullptr> DataStream& operator >> ( DataStream& ds, T ) { static_assert(!_datastream_detail::is_pointer(), "Pointers should not be serialized" ); return ds; } +/** + * Serialize a fixed size array of non-primitive and non-pointer type + * + * @brief Serialize a fixed size array of non-primitive and non-pointer type + * @param ds - The stream to write + * @param v - The value to serialize + * @tparam DataStream - Type of datastream + * @tparam T - Type of the pointer + * @return DataStream& - Reference to the datastream + */ template() && !_datastream_detail::is_pointer()>* = nullptr> @@ -288,6 +523,16 @@ DataStream& operator << ( DataStream& ds, const T (&v)[N] ) { return ds; } +/** + * Serialize a fixed size array of non-primitive type + * + * @brief Serialize a fixed size array of non-primitive type + * @param ds - The stream to write + * @param v - The value to serialize + * @tparam DataStream - Type of datastream + * @tparam T - Type of the pointer + * @return DataStream& - Reference to the datastream + */ template()>* = nullptr> DataStream& operator << ( DataStream& ds, const T (&v)[N] ) { @@ -296,6 +541,17 @@ DataStream& operator << ( DataStream& ds, const T (&v)[N] ) { return ds; } +/** + * Deserialize a fixed size array of non-primitive and non-pointer type + * + * @brief Deserialize a fixed size array of non-primitive and non-pointer type + * @param ds - The stream to read + * @param v - The destination for deserialized value + * @tparam T - Type of the object contained in the array + * @tparam N - Size of the array + * @tparam DataStream - Type of datastream + * @return DataStream& - Reference to the datastream + */ template() && !_datastream_detail::is_pointer()>* = nullptr> @@ -308,6 +564,17 @@ DataStream& operator >> ( DataStream& ds, T (&v)[N] ) { return ds; } +/** + * Deserialize a fixed size array of non-primitive type + * + * @brief Deserialize a fixed size array of non-primitive type + * @param ds - The stream to read + * @param v - The destination for deserialized value + * @tparam T - Type of the object contained in the array + * @tparam N - Size of the array + * @tparam DataStream - Type of datastream + * @return DataStream& - Reference to the datastream + */ template()>* = nullptr> DataStream& operator >> ( DataStream& ds, T (&v)[N] ) { @@ -318,6 +585,15 @@ DataStream& operator >> ( DataStream& ds, T (&v)[N] ) { return ds; } +/** + * Serialize a vector of char + * + * @brief Serialize a vector of char + * @param ds - The stream to write + * @param v - The value to serialize + * @tparam DataStream - Type of datastream + * @return DataStream& - Reference to the datastream + */ template DataStream& operator << ( DataStream& ds, const vector& v ) { ds << unsigned_int( v.size() ); @@ -325,6 +601,16 @@ DataStream& operator << ( DataStream& ds, const vector& v ) { return ds; } +/** + * Serialize a vector + * + * @brief Serialize a vector + * @param ds - The stream to write + * @param v - The value to serialize + * @tparam DataStream - Type of datastream + * @tparam T - Type of the object contained in the vector + * @return DataStream& - Reference to the datastream + */ template DataStream& operator << ( DataStream& ds, const vector& v ) { ds << unsigned_int( v.size() ); @@ -333,6 +619,15 @@ DataStream& operator << ( DataStream& ds, const vector& v ) { return ds; } +/** + * Deserialize a vector of char + * + * @brief Deserialize a vector of char + * @param ds - The stream to read + * @param v - The destination for deserialized value + * @tparam DataStream - Type of datastream + * @return DataStream& - Reference to the datastream + */ template DataStream& operator >> ( DataStream& ds, vector& v ) { unsigned_int s; @@ -342,6 +637,16 @@ DataStream& operator >> ( DataStream& ds, vector& v ) { return ds; } +/** + * Deserialize a vector + * + * @brief Deserialize a vector + * @param ds - The stream to read + * @param v - The destination for deserialized value + * @tparam DataStream - Type of datastream + * @tparam T - Type of the object contained in the vector + * @return DataStream& - Reference to the datastream + */ template DataStream& operator >> ( DataStream& ds, vector& v ) { unsigned_int s; @@ -374,6 +679,17 @@ DataStream& operator >> ( DataStream& ds, std::set& s ) { return ds; } +/** + * Serialize a map + * + * @brief Serialize a map + * @param ds - The stream to write + * @param m - The value to serialize + * @tparam DataStream - Type of datastream + * @tparam K - Type of the key contained in the map + * @tparam V - Type of the value contained in the map + * @return DataStream& - Reference to the datastream + */ template DataStream& operator << ( DataStream& ds, const std::map& m ) { ds << unsigned_int( m.size() ); @@ -383,6 +699,17 @@ DataStream& operator << ( DataStream& ds, const std::map& m ) { return ds; } +/** + * Deserialize a map + * + * @brief Deserialize a map + * @param ds - The stream to read + * @param m - The destination for deserialized value + * @tparam DataStream - Type of datastream + * @tparam K - Type of the key contained in the map + * @tparam V - Type of the value contained in the map + * @return DataStream& - Reference to the datastream + */ template DataStream& operator >> ( DataStream& ds, std::map& m ) { m.clear(); @@ -418,6 +745,18 @@ DataStream& operator >> ( DataStream& ds, boost::container::flat_set& s ) { return ds; } + +/** + * Serialize a flat map + * + * @brief Serialize a flat map + * @param ds - The stream to write + * @param m - The value to serialize + * @tparam DataStream - Type of datastream + * @tparam K - Type of the key contained in the flat map + * @tparam V - Type of the value contained in the flat map + * @return DataStream& - Reference to the datastream + */ template DataStream& operator<<( DataStream& ds, const boost::container::flat_map& m ) { ds << unsigned_int( m.size() ); @@ -426,6 +765,17 @@ DataStream& operator<<( DataStream& ds, const boost::container::flat_map& m return ds; } +/** + * Deserialize a flat map + * + * @brief Deserialize a flat map + * @param ds - The stream to read + * @param m - The destination for deserialized value + * @tparam DataStream - Type of datastream + * @tparam K - Type of the key contained in the flat map + * @tparam V - Type of the value contained in the flat map + * @return DataStream& - Reference to the datastream + */ template DataStream& operator>>( DataStream& ds, boost::container::flat_map& m ) { m.clear(); @@ -439,6 +789,16 @@ DataStream& operator>>( DataStream& ds, boost::container::flat_map& m ) { return ds; } +/** + * Serialize a tuple + * + * @brief Serialize a tuple + * @param ds - The stream to write + * @param t - The value to serialize + * @tparam DataStream - Type of datastream + * @tparam Args - Type of the objects contained in the tuple + * @return DataStream& - Reference to the datastream + */ template DataStream& operator<<( DataStream& ds, const std::tuple& t ) { boost::fusion::for_each( t, [&]( const auto& i ) { @@ -447,6 +807,16 @@ DataStream& operator<<( DataStream& ds, const std::tuple& t ) { return ds; } +/** + * Deserialize a tuple + * + * @brief Deserialize a tuple + * @param ds - The stream to read + * @param t - The destination for deserialized value + * @tparam DataStream - Type of datastream + * @tparam Args - Type of the objects contained in the tuple + * @return DataStream& - Reference to the datastream + */ template DataStream& operator>>( DataStream& ds, std::tuple& t ) { boost::fusion::for_each( t, [&]( auto& i ) { @@ -455,6 +825,16 @@ DataStream& operator>>( DataStream& ds, std::tuple& t ) { return ds; } +/** + * Serialize a class + * + * @brief Serialize a class + * @param ds - The stream to write + * @param v - The value to serialize + * @tparam DataStream - Type of datastream + * @tparam T - Type of class + * @return DataStream& - Reference to the datastream + */ template::value>* = nullptr> DataStream& operator<<( DataStream& ds, const T& v ) { boost::pfr::for_each_field(v, [&](const auto& field) { @@ -462,6 +842,17 @@ DataStream& operator<<( DataStream& ds, const T& v ) { }); return ds; } + +/** + * Deserialize a class + * + * @brief Deserialize a class + * @param ds - The stream to read + * @param v - The destination for deserialized value + * @tparam DataStream - Type of datastream + * @tparam T - Type of class + * @return DataStream& - Reference to the datastream + */ template::value>* = nullptr> DataStream& operator>>( DataStream& ds, T& v ) { boost::pfr::for_each_field(v, [&](auto& field) { @@ -470,18 +861,47 @@ DataStream& operator>>( DataStream& ds, T& v ) { return ds; } +/** + * Serialize a primitive type + * + * @brief Serialize a primitive type + * @param ds - The stream to write + * @param v - The value to serialize + * @tparam DataStream - Type of datastream + * @tparam T - Type of the primitive type + * @return DataStream& - Reference to the datastream + */ template()>* = nullptr> DataStream& operator<<( DataStream& ds, const T& v ) { ds.write( (const char*)&v, sizeof(T) ); return ds; } +/** + * Deserialize a primitive type + * + * @brief Deserialize a primitive type + * @param ds - The stream to read + * @param v - The destination for deserialized value + * @tparam DataStream - Type of datastream + * @tparam T - Type of the primitive type + * @return DataStream& - Reference to the datastream + */ template()>* = nullptr> DataStream& operator>>( DataStream& ds, T& v ) { ds.read( (char*)&v, sizeof(T) ); return ds; } +/** + * Unpack data inside a fixed size buffer as T + * + * @brief Unpack data inside a fixed size buffer as T + * @tparam T - Type of the unpacked data + * @param buffer - Pointer to the buffer + * @param len - Length of the buffer + * @return T - The unpacked data + */ template T unpack( const char* buffer, size_t len ) { T result; @@ -490,11 +910,27 @@ T unpack( const char* buffer, size_t len ) { return result; } +/** + * Unpack data inside a variable size buffer as T + * + * @brief Unpack data inside a variable size buffer as T + * @tparam T - Type of the unpacked data + * @param bytes - Buffer + * @return T - The unpacked data + */ template T unpack( const vector& bytes ) { return unpack( bytes.data(), bytes.size() ); } +/** + * Get the size of the packed data + * + * @brief Get the size of the packed data + * @tparam T - Type of the data to be packed + * @param value - Data to be packed + * @return size_t - Size of the packed data + */ template size_t pack_size( const T& value ) { datastream ps; @@ -502,6 +938,14 @@ size_t pack_size( const T& value ) { return ps.tellp(); } +/** + * Get packed data + * + * @brief Get packed data + * @tparam T - Type of the data to be packed + * @param value - Data to be packed + * @return bytes - The packed data + */ template bytes pack( const T& value ) { bytes result; @@ -512,28 +956,64 @@ bytes pack( const T& value ) { return result; } +/** + * Serialize a checksum160 type + * + * @brief Serialize a checksum160 type + * @param ds - The stream to write + * @param cs - The value to serialize + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream + */ template inline datastream& operator<<(datastream& ds, const checksum160& cs) { ds.write((const char*)&cs.hash[0], sizeof(cs.hash)); return ds; } +/** + * Deserialize a checksum160 type + * + * @brief Deserialize a checksum160 type + * @param ds - The stream to read + * @param cs - The destination for deserialized value + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream + */ template inline datastream& operator>>(datastream& ds, checksum160& cs) { ds.read((char*)&cs.hash[0], sizeof(cs.hash)); return ds; } +/** + * Serialize a checksum512 type + * + * @brief Serialize a checksum512 type + * @param ds - The stream to write + * @param cs - The value to serialize + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream + */ template inline datastream& operator<<(datastream& ds, const checksum512& cs) { ds.write((const char*)&cs.hash[0], sizeof(cs.hash)); return ds; } +/** + * Deserialize a checksum512 type + * + * @brief Deserialize a checksum512 type + * @param ds - The stream to read + * @param cs - The destination for deserialized value + * @tparam Stream - Type of datastream buffer + * @return datastream& - Reference to the datastream + */ template inline datastream& operator>>(datastream& ds, checksum512& cs) { ds.read((char*)&cs.hash[0], sizeof(cs.hash)); return ds; } - +/// @} datastream } diff --git a/libraries/eosiolib/db.h b/libraries/eosiolib/db.h index 4074a87e42..d2c01b6b15 100644 --- a/libraries/eosiolib/db.h +++ b/libraries/eosiolib/db.h @@ -9,105 +9,932 @@ extern "C" { /** * @defgroup database Database API - * @brief APIs that store and retreive data on the blockchain + * @brief Defines APIs that store and retrieve data on the blockchain * @ingroup contractdev * - * EOS.IO organizes data according to the following broad structure: + * @defgroup databasecpp Database C++ API + * @brief Defines an interface to EOSIO database + * @ingroup database * + * @details + * EOSIO organizes data according to the following broad structure: * - **code** - the account name which has write permission - * - **scope** - an account where the data is stored + * - **scope** - an area where the data is stored * - **table** - a name for the table that is being stored * - **record** - a row in the table - * - * Every transaction specifies the set of valid scopes that may be read and/or written - * to. The code that is running determines what can be written to; therefore, write operations - * do not allow you to specify/configure the code. - * - * @note Attempts to read and/or write outside the valid scope and/or code sections will - * cause your transaction to fail. - * - * - * @section tabletypes table Types - * These are the supported table types identified by the number and - * size of the index: - * - * 1. @ref dbi64 - * - * The @ref databaseCpp provides a simple interface for storing any fixed-size struct as - * a database row. - * */ /** - * @defgroup databaseC Database C API - * @brief C APIs for interfacing with the database. + * @defgroup databasec Database C API + * @brief Defines %C APIs for interfacing with the database. * @ingroup database + * + * @details Database C API provides low level interface to EOSIO database. + * + * @section tabletypes Supported Table Types + * Following are the table types supported by the C API: + * 1. Primary Table + * - 64-bit integer key + * 2. Secondary Index Table + * - 64-bit integer key + * - 128-bit integer key + * - 256-bit integer key + * - double key + * - long double key + * @{ */ +/** + * + * Store a record in a primary 64-bit integer index table + * + * @brief Store a record in a primary 64-bit integer index table + * @param scope - The scope where the table resides (implied to be within the code of the current receiver) + * @param table - The table name + * @param payer - The account that pays for the storage costs + * @param id - ID of the entry + * @param data - Record to store + * @param len - Size of data + * @pre `data` is a valid pointer to a range of memory at least `len` bytes long + * @pre `*((uint64_t*)data)` stores the primary key + * @return iterator to the newly created table row + * @post a new entry is created in the table + */ int32_t db_store_i64(account_name scope, table_name table, account_name payer, uint64_t id, const void* data, uint32_t len); + +/** + * + * Update a record in a primary 64-bit integer index table + * + * @brief Update a record in a primary 64-bit integer index table + * @param iterator - Iterator to the table row containing the record to update + * @param payer - The account that pays for the storage costs (use 0 to continue using current payer) + * @param data - New updated record + * @param len - Size of data + * @pre `data` is a valid pointer to a range of memory at least `len` bytes long + * @pre `*((uint64_t*)data)` stores the primary key + * @pre `iterator` points to an existing table row in the table + * @post the record contained in the table row pointed to by `iterator` is replaced with the new updated record + */ void db_update_i64(int32_t iterator, account_name payer, const void* data, uint32_t len); + +/** + * + * Remove a record from a primary 64-bit integer index table + * + * @brief Remove a record from a primary 64-bit integer index table + * @param iterator - Iterator to the table row to remove + * @pre `iterator` points to an existing table row in the table + * @post the table row pointed to by `iterator` is removed and the associated storage costs are refunded to the payer + * + * Example: + * + * @code + * int32_t itr = db_find_i64(receiver, receiver, table1, N(alice)); + * eosio_assert(itr >= 0, "Alice cannot be removed since she was already not found in the table"); + * db_remove_i64(itr); + * @endcode + */ void db_remove_i64(int32_t iterator); + +/** + * + * Get a record in a primary 64-bit integer index table + * + * @brief Get a record in a primary 64-bit integer index table + * @param iterator - The iterator to the table row containing the record to retrieve + * @param data - Pointer to the buffer which will be filled with the retrieved record + * @param len - Size of the buffer + * @return size of the data copied into the buffer if `len > 0`, or size of the retrieved record if `len == 0`. + * @pre `iterator` points to an existing table row in the table + * @pre `data` is a valid pointer to a range of memory at least `len` bytes long + * @post `data` will be filled with the retrieved record (truncated to the first `len` bytes if necessary) + * + * Example: + * + * @code + * char value[50]; + * auto len = db_get_i64(itr, value, 0); + * eosio_assert(len <= 50, "buffer to small to store retrieved record"); + * db_get_i64(itr, value, len); + * @endcode + */ int32_t db_get_i64(int32_t iterator, const void* data, uint32_t len); + +/** + * + * Find the table row following the referenced table row in a primary 64-bit integer index table + * + * @brief Find the table row following the referenced table row in a primary 64-bit integer index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the next table row + * @return iterator to the table row following the referenced table row (or the end iterator of the table if the referenced table row is the last one in the table) + * @pre `iterator` points to an existing table row in the table + * @post `*primary` will be replaced with the primary key of the table row following the referenced table row if it exists, otherwise `*primary` will be left untouched + * + * Example: + * + * @code + * int32_t charlie_itr = db_find_i64(receiver, receiver, table1, N(charlie)); + * // expect nothing after charlie + * uint64_t prim = 0 + * int32_t end_itr = db_next_i64(charlie_itr, &prim); + * eosio_assert(end_itr < -1, "Charlie was not the last entry in the table"); + * @endcode + */ int32_t db_next_i64(int32_t iterator, uint64_t* primary); + +/** + * + * Find the table row preceding the referenced table row in a primary 64-bit integer index table + * + * @brief Find the table row preceding the referenced table row in a primary 64-bit integer index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the previous table row + * @return iterator to the table row preceding the referenced table row assuming one exists (it will return -1 if the referenced table row is the first one in the table) + * @pre `iterator` points to an existing table row in the table or it is the end iterator of the table + * @post `*primary` will be replaced with the primary key of the table row preceding the referenced table row if it exists, otherwise `*primary` will be left untouched + * + * Example: + * + * @code + * uint64_t prim = 0; + * int32_t itr_prev = db_previous_i64(itr, &prim); + * @endcode + */ int32_t db_previous_i64(int32_t iterator, uint64_t* primary); + +/** + * + * Find a table row in a primary 64-bit integer index table by primary key + * + * @brief Find a table row in a primary 64-bit integer index table by primary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param id - The primary key of the table row to look up + * @return iterator to the table row with a primary key equal to `id` or the end iterator of the table if the table row could not be found + * + * Example: + * + * @code + * int itr = db_find_i64(receiver, receiver, table1, N(charlie)); + * @endcode + */ int32_t db_find_i64(account_name code, account_name scope, table_name table, uint64_t id); + +/** + * + * Find the table row in a primary 64-bit integer index table that matches the lowerbound condition for a given primary key + * The table row that matches the lowerbound condition is the first table row in the table with the lowest primary key that is >= the given key + * + * @brief Find the table row in a primary 64-bit integer index table that matches the lowerbound condition for a given primary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param id - The primary key used to determine the lowerbound + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ int32_t db_lowerbound_i64(account_name code, account_name scope, table_name table, uint64_t id); + +/** + * + * Find the table row in a primary 64-bit integer index table that matches the upperbound condition for a given primary key + * The table row that matches the upperbound condition is the first table row in the table with the lowest primary key that is > the given key + * + * @brief Find the table row in a primary 64-bit integer index table that matches the upperbound condition for a given primary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param id - The primary key used to determine the upperbound + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ int32_t db_upperbound_i64(account_name code, account_name scope, table_name table, uint64_t id); + +/** + * + * Get an iterator representing just-past-the-end of the last table row of a primary 64-bit integer index table + * + * @brief Get an iterator representing just-past-the-end of the last table row of a primary 64-bit integer index table + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @return end iterator of the table + */ int32_t db_end_i64(account_name code, account_name scope, table_name table); +/** + * + * Store an association of a 64-bit integer secondary key to a primary key in a secondary 64-bit integer index table + * + * @brief Store an association of a 64-bit integer secondary key to a primary key in a secondary 64-bit integer index table + * @param scope - The scope where the table resides (implied to be within the code of the current receiver) + * @param table - The table name + * @param payer - The account that pays for the storage costs + * @param id - The primary key to which to associate the secondary key + * @param secondary - Pointer to the secondary key + * @return iterator to the newly created table row + * @post new secondary key association between primary key `id` and secondary key `*secondary` is created in the secondary 64-bit integer index table + */ int32_t db_idx64_store(account_name scope, table_name table, account_name payer, uint64_t id, const uint64_t* secondary); + +/** + * + * Update an association for a 64-bit integer secondary key to a primary key in a secondary 64-bit integer index table + * + * @brief Update an association for a 64-bit integer secondary key to a primary key in a secondary 64-bit integer index table + * @param iterator - The iterator to the table row containing the secondary key association to update + * @param payer - The account that pays for the storage costs (use 0 to continue using current payer) + * @param secondary - Pointer to the **new** secondary key that will replace the existing one of the association + * @pre `iterator` points to an existing table row in the table + * @post the secondary key of the table row pointed to by `iterator` is replaced by `*secondary` + */ void db_idx64_update(int32_t iterator, account_name payer, const uint64_t* secondary); + +/** + * + * Remove a table row from a secondary 64-bit integer index table + * + * @brief Remove a table row from a secondary 64-bit integer index table + * @param iterator - Iterator to the table row to remove + * @pre `iterator` points to an existing table row in the table + * @post the table row pointed to by `iterator` is removed and the associated storage costs are refunded to the payer + */ void db_idx64_remove(int32_t iterator); + +/** + * + * Find the table row following the referenced table row in a secondary 64-bit integer index table + * + * @brief Find the table row following the referenced table row in a secondary 64-bit integer index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the next table row + * @return iterator to the table row following the referenced table row (or the end iterator of the table if the referenced table row is the last one in the table) + * @pre `iterator` points to an existing table row in the table + * @post `*primary` will be replaced with the primary key of the table row following the referenced table row if it exists, otherwise `*primary` will be left untouched + */ int32_t db_idx64_next(int32_t iterator, uint64_t* primary); + +/** + * + * Find the table row preceding the referenced table row in a secondary 64-bit integer index table + * + * @brief Find the table row preceding the referenced table row in a secondary 64-bit integer index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the previous table row + * @return iterator to the table row preceding the referenced table row assuming one exists (it will return -1 if the referenced table row is the first one in the table) + * @pre `iterator` points to an existing table row in the table or it is the end iterator of the table + * @post `*primary` will be replaced with the primary key of the table row preceding the referenced table row if it exists, otherwise `*primary` will be left untouched + */ int32_t db_idx64_previous(int32_t iterator, uint64_t* primary); + +/** + * + * Find a table row in a secondary 64-bit integer index table by primary key + * + * @brief Find a table row in a secondary 64-bit integer index table by primary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to a `uint64_t` variable which will have its value set to the secondary key of the found table row + * @param primary - The primary key of the table row to look up + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @return iterator to the table row with a primary key equal to `id` or the end iterator of the table if the table row could not be found + */ int32_t db_idx64_find_primary(account_name code, account_name scope, table_name table, uint64_t* secondary, uint64_t primary); + +/** + * + * Find a table row in a secondary 64-bit integer index table by secondary key + * + * @brief Find a table row in a secondary 64-bit integer index table by secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key used to lookup the table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the first table row with a secondary key equal to `*secondary` or the end iterator of the table if the table row could not be found + */ int32_t db_idx64_find_secondary(account_name code, account_name scope, table_name table, const uint64_t* secondary, uint64_t* primary); + +/** + * + * Find the table row in a secondary 64-bit integer index table that matches the lowerbound condition for a given secondary key + * The table row that matches the lowerbound condition is the first table row in the table with the lowest secondary key that is >= the given key + * + * @brief Find the table row in a secondary 64-bit integer index table that matches the lowerbound condition for a given secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key first used to determine the lowerbound and which is then replaced with the secondary key of the found table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ int32_t db_idx64_lowerbound(account_name code, account_name scope, table_name table, uint64_t* secondary, uint64_t* primary); + +/** + * + * Find the table row in a secondary 64-bit integer index table that matches the upperbound condition for a given secondary key + * The table row that matches the upperbound condition is the first table row in the table with the lowest secondary key that is > the given key + * + * @brief Find the table row in a secondary 64-bit integer index table that matches the upperbound condition for a given secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key first used to determine the upperbound and which is then replaced with the secondary key of the found table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ int32_t db_idx64_upperbound(account_name code, account_name scope, table_name table, uint64_t* secondary, uint64_t* primary); + +/** + * + * Get an end iterator representing just-past-the-end of the last table row of a secondary 64-bit integer index table + * + * @brief Get an end iterator representing just-past-the-end of the last table row of a secondary 64-bit integer index table + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @return end iterator of the table + */ int32_t db_idx64_end(account_name code, account_name scope, table_name table); + + +/** + * + * Store an association of a 128-bit integer secondary key to a primary key in a secondary 128-bit integer index table + * + * @brief Store an association of a 128-bit integer secondary key to a primary key in a secondary 128-bit integer index table + * @param scope - The scope where the table resides (implied to be within the code of the current receiver) + * @param table - The table name + * @param payer - The account that pays for the storage costs + * @param id - The primary key to which to associate the secondary key + * @param secondary - Pointer to the secondary key + * @return iterator to the newly created table row + * @post new secondary key association between primary key `id` and secondary key `*secondary` is created in the secondary 128-bit integer index table + */ int32_t db_idx128_store(account_name scope, table_name table, account_name payer, uint64_t id, const uint128_t* secondary); + +/** + * + * Update an association for a 128-bit integer secondary key to a primary key in a secondary 128-bit integer index table + * + * @brief Update an association for a 128-bit integer secondary key to a primary key in a secondary 128-bit integer index table + * @param iterator - The iterator to the table row containing the secondary key association to update + * @param payer - The account that pays for the storage costs (use 0 to continue using current payer) + * @param secondary - Pointer to the **new** secondary key that will replace the existing one of the association + * @pre `iterator` points to an existing table row in the table + * @post the secondary key of the table row pointed to by `iterator` is replaced by `*secondary` + */ void db_idx128_update(int32_t iterator, account_name payer, const uint128_t* secondary); + +/** + * + * Remove a table row from a secondary 128-bit integer index table + * + * @brief Remove a table row from a secondary 128-bit integer index table + * @param iterator - Iterator to the table row to remove + * @pre `iterator` points to an existing table row in the table + * @post the table row pointed to by `iterator` is removed and the associated storage costs are refunded to the payer + */ void db_idx128_remove(int32_t iterator); + +/** + * + * Find the table row following the referenced table row in a secondary 128-bit integer index table + * + * @brief Find the table row following the referenced table row in a secondary 128-bit integer index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the next table row + * @return iterator to the table row following the referenced table row (or the end iterator of the table if the referenced table row is the last one in the table) + * @pre `iterator` points to an existing table row in the table + * @post `*primary` will be replaced with the primary key of the table row following the referenced table row if it exists, otherwise `*primary` will be left untouched + */ int32_t db_idx128_next(int32_t iterator, uint64_t* primary); + +/** + * + * Find the table row preceding the referenced table row in a secondary 128-bit integer index table + * + * @brief Find the table row preceding the referenced table row in a secondary 128-bit integer index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the previous table row + * @return iterator to the table row preceding the referenced table row assuming one exists (it will return -1 if the referenced table row is the first one in the table) + * @pre `iterator` points to an existing table row in the table or it is the end iterator of the table + * @post `*primary` will be replaced with the primary key of the table row preceding the referenced table row if it exists, otherwise `*primary` will be left untouched + */ int32_t db_idx128_previous(int32_t iterator, uint64_t* primary); + +/** + * + * Find a table row in a secondary 128-bit integer index table by primary key + * + * @brief Find a table row in a secondary 128-bit integer index table by primary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to a `uint128_t` variable which will have its value set to the secondary key of the found table row + * @param primary - The primary key of the table row to look up + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @return iterator to the table row with a primary key equal to `id` or the end iterator of the table if the table row could not be found + */ int32_t db_idx128_find_primary(account_name code, account_name scope, table_name table, uint128_t* secondary, uint64_t primary); + +/** + * + * Find a table row in a secondary 128-bit integer index table by secondary key + * + * @brief Find a table row in a secondary 128-bit integer index table by secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key used to lookup the table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the first table row with a secondary key equal to `*secondary` or the end iterator of the table if the table row could not be found + */ int32_t db_idx128_find_secondary(account_name code, account_name scope, table_name table, const uint128_t* secondary, uint64_t* primary); + +/** + * + * Find the table row in a secondary 128-bit integer index table that matches the lowerbound condition for a given secondary key + * The table row that matches the lowerbound condition is the first table row in the table with the lowest secondary key that is >= the given key + * + * @brief Find the table row in a secondary 128-bit integer index table that matches the lowerbound condition for a given secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key first used to determine the lowerbound and which is then replaced with the secondary key of the found table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ int32_t db_idx128_lowerbound(account_name code, account_name scope, table_name table, uint128_t* secondary, uint64_t* primary); + +/** + * + * Find the table row in a secondary 128-bit integer index table that matches the upperbound condition for a given secondary key + * The table row that matches the upperbound condition is the first table row in the table with the lowest secondary key that is > the given key + * + * @brief Find the table row in a secondary 128-bit integer index table that matches the upperbound condition for a given secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key first used to determine the upperbound and which is then replaced with the secondary key of the found table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ int32_t db_idx128_upperbound(account_name code, account_name scope, table_name table, uint128_t* secondary, uint64_t* primary); + +/** + * + * Get an end iterator representing just-past-the-end of the last table row of a secondary 128-bit integer index table + * + * @brief Get an end iterator representing just-past-the-end of the last table row of a secondary 128-bit integer index table + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @return end iterator of the table + */ int32_t db_idx128_end(account_name code, account_name scope, table_name table); -int32_t db_idx256_store(account_name scope, table_name table, account_name payer, uint64_t id, const void* data, uint32_t data_len ); -void db_idx256_update(int32_t iterator, account_name payer, const void* data, uint32_t data_len); +/** + * + * Store an association of a 256-bit secondary key to a primary key in a secondary 256-bit index table + * + * @brief Store an association of a 256-bit secondary key to a primary key in a secondary 256-bit index table + * @param scope - The scope where the table resides (implied to be within the code of the current receiver) + * @param table - The table name + * @param payer - The account that pays for the storage costs + * @param id - The primary key to which to associate the secondary key + * @param data - Pointer to the secondary key data stored as an array of 2 `uint128_t` integers + * @param data_len - Must be set to 2 + * @return iterator to the newly created table row + * @post new secondary key association between primary key `id` and the specified secondary key is created in the secondary 256-bit index table + */ +int32_t db_idx256_store(account_name scope, table_name table, account_name payer, uint64_t id, const uint128_t* data, uint32_t data_len ); + +/** + * + * Update an association for a 256-bit secondary key to a primary key in a secondary 256-bit index table + * + * @brief Update an association for a 256-bit secondary key to a primary key in a secondary 256-bit index table + * @param iterator - The iterator to the table row containing the secondary key association to update + * @param payer - The account that pays for the storage costs (use 0 to continue using current payer) + * @param data - Pointer to the **new** secondary key data (which is stored as an array of 2 `uint128_t` integers) that will replace the existing one of the association + * @param data_len - Must be set to 2 + * @pre `iterator` points to an existing table row in the table + * @post the secondary key of the table row pointed to by `iterator` is replaced by the specified secondary key + */ +void db_idx256_update(int32_t iterator, account_name payer, const uint128_t* data, uint32_t data_len); + +/** + * + * Remove a table row from a secondary 256-bit index table + * + * @brief Remove a table row from a secondary 256-bit index table + * @param iterator - Iterator to the table row to remove + * @pre `iterator` points to an existing table row in the table + * @post the table row pointed to by `iterator` is removed and the associated storage costs are refunded to the payer + */ void db_idx256_remove(int32_t iterator); + +/** + * + * Find the table row following the referenced table row in a secondary 256-bit index table + * + * @brief Find the table row following the referenced table row in a secondary 256-bit index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the next table row + * @return iterator to the table row following the referenced table row (or the end iterator of the table if the referenced table row is the last one in the table) + * @pre `iterator` points to an existing table row in the table + * @post `*primary` will be replaced with the primary key of the table row following the referenced table row if it exists, otherwise `*primary` will be left untouched + */ int32_t db_idx256_next(int32_t iterator, uint64_t* primary); + +/** + * + * Find the table row preceding the referenced table row in a secondary 256-bit index table + * + * @brief Find the table row preceding the referenced table row in a secondary 256-bit index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the previous table row + * @return iterator to the table row preceding the referenced table row assuming one exists (it will return -1 if the referenced table row is the first one in the table) + * @pre `iterator` points to an existing table row in the table or it is the end iterator of the table + * @post `*primary` will be replaced with the primary key of the table row preceding the referenced table row if it exists, otherwise `*primary` will be left untouched + */ int32_t db_idx256_previous(int32_t iterator, uint64_t* primary); -int32_t db_idx256_find_primary(account_name code, account_name scope, table_name table, void* data, uint32_t data_len, uint64_t primary); -int32_t db_idx256_find_secondary(account_name code, account_name scope, table_name table, const void* data, uint32_t data_len, uint64_t* primary); -int32_t db_idx256_lowerbound(account_name code, account_name scope, table_name table, void* data, uint32_t data_len, uint64_t* primary); -int32_t db_idx256_upperbound(account_name code, account_name scope, table_name table, void* data, uint32_t data_len, uint64_t* primary); + +/** + * + * Find a table row in a secondary 256-bit index table by primary key + * + * @brief Find a table row in a secondary 128-bit integer index table by primary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param data - Pointer to the an array of 2 `uint128_t` integers which will act as the buffer to hold the retrieved secondary key of the found table row + * @param data_len - Must be set to 2 + * @param primary - The primary key of the table row to look up + * @post If and only if the table row is found, the buffer pointed to by `data` will be filled with the secondary key of the found table row + * @return iterator to the table row with a primary key equal to `id` or the end iterator of the table if the table row could not be found + */ +int32_t db_idx256_find_primary(account_name code, account_name scope, table_name table, uint128_t* data, uint32_t data_len, uint64_t primary); + +/** + * + * Find a table row in a secondary 256-bit index table by secondary key + * + * @brief Find a table row in a secondary 256-bit index table by secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param data - Pointer to the secondary key data (which is stored as an array of 2 `uint128_t` integers) used to lookup the table row + * @param data_len - Must be set to 2 + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the first table row with a secondary key equal to the specified secondary key or the end iterator of the table if the table row could not be found + */ +int32_t db_idx256_find_secondary(account_name code, account_name scope, table_name table, const uint128_t* data, uint32_t data_len, uint64_t* primary); + +/** + * + * Find the table row in a secondary 256-bit index table that matches the lowerbound condition for a given secondary key + * The table row that matches the lowerbound condition is the first table row in the table with the lowest secondary key that is >= the given key (uses lexicographical ordering on the 256-bit keys) + * + * @brief Find the table row in a secondary 256-bit index table that matches the lowerbound condition for a given secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param data - Pointer to the secondary key data (which is stored as an array of 2 `uint128_t` integers) first used to determine the lowerbound and which is then replaced with the secondary key of the found table row + * @param data_len - Must be set to 2 + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, the buffer pointed to by `data` will be filled with the secondary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ +int32_t db_idx256_lowerbound(account_name code, account_name scope, table_name table, uint128_t* data, uint32_t data_len, uint64_t* primary); + +/** + * + * Find the table row in a secondary 256-bit index table that matches the upperbound condition for a given secondary key + * The table row that matches the upperbound condition is the first table row in the table with the lowest secondary key that is > the given key (uses lexicographical ordering on the 256-bit keys) + * + * @brief Find the table row in a secondary 256-bit index table that matches the upperbound condition for a given secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param data - Pointer to the secondary key data (which is stored as an array of 2 `uint128_t` integers) first used to determine the upperbound and which is then replaced with the secondary key of the found table row + * @param data_len - Must be set to 2 + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, the buffer pointed to by `data` will be filled with the secondary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ +int32_t db_idx256_upperbound(account_name code, account_name scope, table_name table, uint128_t* data, uint32_t data_len, uint64_t* primary); + +/** + * + * Get an end iterator representing just-past-the-end of the last table row of a secondary 256-bit index table + * + * @brief Get an end iterator representing just-past-the-end of the last table row of a secondary 256-bit index table + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @return end iterator of the table + */ int32_t db_idx256_end(account_name code, account_name scope, table_name table); +/** + * + * Store an association of a double-precision floating-point secondary key to a primary key in a secondary double-precision floating-point index table + * + * @brief Store an association of a double-precision floating-point secondary key to a primary key in a secondary double-precision floating-point index table + * @param scope - The scope where the table resides (implied to be within the code of the current receiver) + * @param table - The table name + * @param payer - The account that pays for the storage costs + * @param id - The primary key to which to associate the secondary key + * @param secondary - Pointer to the secondary key + * @return iterator to the newly created table row + * @post new secondary key association between primary key `id` and secondary key `*secondary` is created in the secondary double-precision floating-point index table + */ int32_t db_idx_double_store(account_name scope, table_name table, account_name payer, uint64_t id, const double* secondary); + +/** + * + * Update an association for a double-precision floating-point secondary key to a primary key in a secondary double-precision floating-point index table + * + * @brief Update an association for a double-precision floating-point secondary key to a primary key in a secondary double-precision floating-point index table + * @param iterator - The iterator to the table row containing the secondary key association to update + * @param payer - The account that pays for the storage costs (use 0 to continue using current payer) + * @param secondary - Pointer to the **new** secondary key that will replace the existing one of the association + * @pre `iterator` points to an existing table row in the table + * @post the secondary key of the table row pointed to by `iterator` is replaced by `*secondary` + */ void db_idx_double_update(int32_t iterator, account_name payer, const double* secondary); + +/** + * + * Remove a table row from a secondary double-precision floating-point index table + * + * @brief Remove a table row from a secondary double-precision floating-point index table + * @param iterator - Iterator to the table row to remove + * @pre `iterator` points to an existing table row in the table + * @post the table row pointed to by `iterator` is removed and the associated storage costs are refunded to the payer + */ void db_idx_double_remove(int32_t iterator); + +/** + * + * Find the table row following the referenced table row in a secondary double-precision floating-point index table + * + * @brief Find the table row following the referenced table row in a secondary double-precision floating-point index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the next table row + * @return iterator to the table row following the referenced table row (or the end iterator of the table if the referenced table row is the last one in the table) + * @pre `iterator` points to an existing table row in the table + * @post `*primary` will be replaced with the primary key of the table row following the referenced table row if it exists, otherwise `*primary` will be left untouched + */ int32_t db_idx_double_next(int32_t iterator, uint64_t* primary); + +/** + * + * Find the table row preceding the referenced table row in a secondary double-precision floating-point index table + * + * @brief Find the table row preceding the referenced table row in a secondary double-precision floating-point index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the previous table row + * @return iterator to the table row preceding the referenced table row assuming one exists (it will return -1 if the referenced table row is the first one in the table) + * @pre `iterator` points to an existing table row in the table or it is the end iterator of the table + * @post `*primary` will be replaced with the primary key of the table row preceding the referenced table row if it exists, otherwise `*primary` will be left untouched + */ int32_t db_idx_double_previous(int32_t iterator, uint64_t* primary); + +/** + * + * Find a table row in a secondary double-precision floating-point index table by primary key + * + * @brief Find a table row in a secondary double-precision floating-point index table by primary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to a `double` variable which will have its value set to the secondary key of the found table row + * @param primary - The primary key of the table row to look up + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @return iterator to the table row with a primary key equal to `id` or the end iterator of the table if the table row could not be found + */ int32_t db_idx_double_find_primary(account_name code, account_name scope, table_name table, double* secondary, uint64_t primary); + +/** + * + * Find a table row in a secondary double-precision floating-point index table by secondary key + * + * @brief Find a table row in a secondary double-precision floating-point index table by secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key used to lookup the table row + * @param primary - Pointer to a `double` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the first table row with a secondary key equal to `*secondary` or the end iterator of the table if the table row could not be found + */ int32_t db_idx_double_find_secondary(account_name code, account_name scope, table_name table, const double* secondary, uint64_t* primary); + +/** + * + * Find the table row in a secondary double-precision floating-point index table that matches the lowerbound condition for a given secondary key + * The table row that matches the lowerbound condition is the first table row in the table with the lowest secondary key that is >= the given key + * + * @brief Find the table row in a secondary double-precision floating-point index table that matches the lowerbound condition for a given secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key first used to determine the lowerbound and which is then replaced with the secondary key of the found table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ int32_t db_idx_double_lowerbound(account_name code, account_name scope, table_name table, double* secondary, uint64_t* primary); + +/** + * + * Find the table row in a secondary double-precision floating-point index table that matches the upperbound condition for a given secondary key + * The table row that matches the upperbound condition is the first table row in the table with the lowest secondary key that is > the given key + * + * @brief Find the table row in a secondary double-precision floating-point index table that matches the upperbound condition for a given secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key first used to determine the upperbound and which is then replaced with the secondary key of the found table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ int32_t db_idx_double_upperbound(account_name code, account_name scope, table_name table, double* secondary, uint64_t* primary); + +/** + * + * Get an end iterator representing just-past-the-end of the last table row of a secondary double-precision floating-point index table + * + * @brief Get an end iterator representing just-past-the-end of the last table row of a secondary double-precision floating-point index table + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @return end iterator of the table + */ int32_t db_idx_double_end(account_name code, account_name scope, table_name table); +/** + * + * Store an association of a quadruple-precision floating-point secondary key to a primary key in a secondary quadruple-precision floating-point index table + * + * @brief Store an association of a quadruple-precision floating-point secondary key to a primary key in a secondary quadruple-precision floating-point index table + * @param scope - The scope where the table resides (implied to be within the code of the current receiver) + * @param table - The table name + * @param payer - The account that pays for the storage costs + * @param id - The primary key to which to associate the secondary key + * @param secondary - Pointer to the secondary key + * @return iterator to the newly created table row + * @post new secondary key association between primary key `id` and secondary key `*secondary` is created in the secondary quadruple-precision floating-point index table + */ int32_t db_idx_long_double_store(account_name scope, table_name table, account_name payer, uint64_t id, const long double* secondary); + +/** + * + * Update an association for a quadruple-precision floating-point secondary key to a primary key in a secondary quadruple-precision floating-point index table + * + * @brief Update an association for a quadruple-precision floating-point secondary key to a primary key in a secondary quadruple-precision floating-point index table + * @param iterator - The iterator to the table row containing the secondary key association to update + * @param payer - The account that pays for the storage costs (use 0 to continue using current payer) + * @param secondary - Pointer to the **new** secondary key that will replace the existing one of the association + * @pre `iterator` points to an existing table row in the table + * @post the secondary key of the table row pointed to by `iterator` is replaced by `*secondary` + */ void db_idx_long_double_update(int32_t iterator, account_name payer, const long double* secondary); + +/** + * + * Remove a table row from a secondary quadruple-precision floating-point index table + * + * @brief Remove a table row from a secondary quadruple-precision floating-point index table + * @param iterator - Iterator to the table row to remove + * @pre `iterator` points to an existing table row in the table + * @post the table row pointed to by `iterator` is removed and the associated storage costs are refunded to the payer + */ void db_idx_long_double_remove(int32_t iterator); + +/** + * + * Find the table row following the referenced table row in a secondary quadruple-precision floating-point index table + * + * @brief Find the table row following the referenced table row in a secondary quadruple-precision floating-point index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the next table row + * @return iterator to the table row following the referenced table row (or the end iterator of the table if the referenced table row is the last one in the table) + * @pre `iterator` points to an existing table row in the table + * @post `*primary` will be replaced with the primary key of the table row following the referenced table row if it exists, otherwise `*primary` will be left untouched + */ int32_t db_idx_long_double_next(int32_t iterator, uint64_t* primary); + +/** + * + * Find the table row preceding the referenced table row in a secondary quadruple-precision floating-point index table + * + * @brief Find the table row preceding the referenced table row in a secondary quadruple-precision floating-point index table + * @param iterator - The iterator to the referenced table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the previous table row + * @return iterator to the table row preceding the referenced table row assuming one exists (it will return -1 if the referenced table row is the first one in the table) + * @pre `iterator` points to an existing table row in the table or it is the end iterator of the table + * @post `*primary` will be replaced with the primary key of the table row preceding the referenced table row if it exists, otherwise `*primary` will be left untouched + */ int32_t db_idx_long_double_previous(int32_t iterator, uint64_t* primary); + +/** + * + * Find a table row in a secondary quadruple-precision floating-point index table by primary key + * + * @brief Find a table row in a secondary quadruple-precision floating-point index table by primary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to a `long double` variable which will have its value set to the secondary key of the found table row + * @param primary - The primary key of the table row to look up + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @return iterator to the table row with a primary key equal to `id` or the end iterator of the table if the table row could not be found + */ int32_t db_idx_long_double_find_primary(account_name code, account_name scope, table_name table, long double* secondary, uint64_t primary); + +/** + * + * Find a table row in a secondary quadruple-precision floating-point index table by secondary key + * + * @brief Find a table row in a secondary quadruple-precision floating-point index table by secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key used to lookup the table row + * @param primary - Pointer to a `long double` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the first table row with a secondary key equal to `*secondary` or the end iterator of the table if the table row could not be found + */ int32_t db_idx_long_double_find_secondary(account_name code, account_name scope, table_name table, const long double* secondary, uint64_t* primary); + +/** + * + * Find the table row in a secondary quadruple-precision floating-point index table that matches the lowerbound condition for a given secondary key + * The table row that matches the lowerbound condition is the first table row in the table with the lowest secondary key that is >= the given key + * + * @brief Find the table row in a secondary quadruple-precision floating-point index table that matches the lowerbound condition for a given secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key first used to determine the lowerbound and which is then replaced with the secondary key of the found table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ int32_t db_idx_long_double_lowerbound(account_name code, account_name scope, table_name table, long double* secondary, uint64_t* primary); + +/** + * + * Find the table row in a secondary quadruple-precision floating-point index table that matches the upperbound condition for a given secondary key + * The table row that matches the upperbound condition is the first table row in the table with the lowest secondary key that is > the given key + * + * @brief Find the table row in a secondary quadruple-precision floating-point index table that matches the upperbound condition for a given secondary key + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @param secondary - Pointer to secondary key first used to determine the upperbound and which is then replaced with the secondary key of the found table row + * @param primary - Pointer to a `uint64_t` variable which will have its value set to the primary key of the found table row + * @post If and only if the table row is found, `*secondary` will be replaced with the secondary key of the found table row + * @post If and only if the table row is found, `*primary` will be replaced with the primary key of the found table row + * @return iterator to the found table row or the end iterator of the table if the table row could not be found + */ int32_t db_idx_long_double_upperbound(account_name code, account_name scope, table_name table, long double* secondary, uint64_t* primary); + +/** + * + * Get an end iterator representing just-past-the-end of the last table row of a secondary quadruple-precision floating-point index table + * + * @brief Get an end iterator representing just-past-the-end of the last table row of a secondary quadruple-precision floating-point index table + * @param code - The name of the owner of the table + * @param scope - The scope where the table resides + * @param table - The table name + * @return end iterator of the table + */ int32_t db_idx_long_double_end(account_name code, account_name scope, table_name table); +///@} databasec } diff --git a/libraries/eosiolib/dispatcher.hpp b/libraries/eosiolib/dispatcher.hpp index d1ed3fbfb4..eadc55bc3e 100644 --- a/libraries/eosiolib/dispatcher.hpp +++ b/libraries/eosiolib/dispatcher.hpp @@ -8,6 +8,7 @@ #include #define N(X) ::eosio::string_to_name(#X) namespace eosio { + template bool dispatch( uint64_t code, uint64_t act ) { if( code == FirstAction::get_account() && FirstAction::get_name() == act ) { @@ -25,7 +26,7 @@ namespace eosio { * static Contract::on( ActionType ) * ``` * - * For this to work the Actions must be dervied from the + * For this to work the Actions must be derived from eosio::contract * */ template @@ -37,6 +38,30 @@ namespace eosio { return eosio::dispatch( code, act ); } + /** + * @defgroup dispatcher Dispatcher API + * @brief Defines functions to dispatch action to proper action handler inside a contract + * @ingroup contractdev + */ + + /** + * @defgroup dispatchercpp Dispatcher C++ API + * @brief Defines C++ functions to dispatch action to proper action handler inside a contract + * @ingroup dispatcher + * @{ + */ + + /** + * Unpack the received action and execute the correponding action handler + * + * @brief Unpack the received action and execute the correponding action handler + * @tparam T - The contract class that has the correponding action handler, this contract should be derived from eosio::contract + * @tparam Q - The namespace of the action handler function + * @tparam Args - The arguments that the action handler accepts, i.e. members of the action + * @param obj - The contract object that has the correponding action handler + * @param func - The action handler + * @return true + */ template bool execute_action( T* obj, void (Q::*func)(Args...) ) { size_t size = action_data_size(); @@ -62,15 +87,36 @@ namespace eosio { boost::mp11::tuple_apply( f2, args ); return true; } + /// @} dispatcher +// Helper macro for EOSIO_API #define EOSIO_API_CALL( r, OP, elem ) \ case ::eosio::string_to_name( BOOST_PP_STRINGIZE(elem) ): \ eosio::execute_action( &thiscontract, &OP::elem ); \ break; +// Helper macro for EOSIO_ABI #define EOSIO_API( TYPE, MEMBERS ) \ BOOST_PP_SEQ_FOR_EACH( EOSIO_API_CALL, TYPE, MEMBERS ) +/** + * @addtogroup dispatcher + * @{ + */ + +/** + * Convenient macro to create contract apply handler + * To be able to use this macro, the contract needs to be derived from eosio::contract + * + * @brief Convenient macro to create contract apply handler + * @param TYPE - The class name of the contract + * @param MEMBERS - The sequence of available actions supported by this contract + * + * Example: + * @code + * EOSIO_ABI( eosio::bios, (setpriv)(setalimits)(setglimits)(setprods)(reqauth) ) + * @endcode + */ #define EOSIO_ABI( TYPE, MEMBERS ) \ extern "C" { \ void apply( uint64_t receiver, uint64_t code, uint64_t action ) { \ @@ -88,6 +134,7 @@ extern "C" { \ } \ } \ } \ + /// @} dispatcher /* diff --git a/libraries/eosiolib/eosiolib.cpp b/libraries/eosiolib/eosiolib.cpp index 59b91ad83f..75e3cd633c 100644 --- a/libraries/eosiolib/eosiolib.cpp +++ b/libraries/eosiolib/eosiolib.cpp @@ -58,13 +58,7 @@ namespace eosio { using ::memset; using ::memcpy; - /** - * @defgroup memorycppapi Memory C++ API - * @brief Defines common memory functions - * @ingroup memoryapi - * - * @{ - */ + class memory_manager // NOTE: Should never allocate another instance of memory_manager { @@ -520,7 +514,7 @@ namespace eosio { // allocate memory in 8 char blocks static const uint32_t _mem_block = 8; static const uint32_t _rem_mem_block_mask = _mem_block - 1; - static const uint32_t _initial_heap_size = 40;//32768; + static const uint32_t _initial_heap_size = 8192;//32768; // if sbrk is not called outside of this file, then this is the max times we can call it static const uint32_t _heaps_size = 16; char _initial_heap[_initial_heap_size]; @@ -537,6 +531,7 @@ namespace eosio { extern "C" { + void* malloc(size_t size) { return eosio::memory_heap.malloc(size); @@ -559,21 +554,4 @@ void free(void* ptr) return eosio::memory_heap.free(ptr); } -uint32_t now() { - return (uint32_t)(current_time() / 1000000); -} - -} - -/** - * Provide == for checksum256 in global namespace - */ -bool operator==(const checksum256& lhs, const checksum256& rhs) { - return memcmp(&lhs, &rhs, sizeof(lhs)) == 0; -} -bool operator==(const checksum160& lhs, const checksum160& rhs) { - return memcmp(&lhs, &rhs, sizeof(lhs)) == 0; -} -bool operator!=(const checksum160& lhs, const checksum160& rhs) { - return memcmp(&lhs, &rhs, sizeof(lhs)) != 0; } diff --git a/libraries/eosiolib/fixed_key.hpp b/libraries/eosiolib/fixed_key.hpp index a011f2f743..eb04a45b46 100644 --- a/libraries/eosiolib/fixed_key.hpp +++ b/libraries/eosiolib/fixed_key.hpp @@ -28,9 +28,18 @@ namespace eosio { bool operator<(const fixed_key &c1, const fixed_key &c2); /** - * @defgroup fixed_key fixed size key sorted lexicographically + * @defgroup fixed_key Fixed Size Key + * @brief Fixed size key sorted lexicographically for Multi Index Table + * @ingroup types + * @{ + */ + + /** + * Fixed size key sorted lexicographically for Multi Index Table + * + * @brief Fixed size key sorted lexicographically for Multi Index Table + * @tparam Size - Size of the fixed_key object * @ingroup types - * @{ */ template class fixed_key { @@ -74,8 +83,21 @@ namespace eosio { public: typedef uint128_t word_t; + + /** + * Get number of words contained in this fixed_key object. A word is defined to be 16 bytes in size + * + * @brief Get number of words contained in this fixed_key object + */ static constexpr size_t num_words() { return (Size + sizeof(word_t) - 1) / sizeof(word_t); } + + /** + * Get number of padded bytes contained in this fixed_key object. Padded bytes are the remaining bytes + * inside the fixed_key object after all the words are allocated + * + * @brief Get number of padded bytes contained in this fixed_key object + */ static constexpr size_t padded_bytes() { return num_words() * sizeof(word_t) - Size; } /** @@ -96,6 +118,12 @@ namespace eosio { std::copy(arr.begin(), arr.end(), _data.begin()); } + /** + * @brief Constructor to fixed_key object from std::array of num_words() words + * + * @details Constructor to fixed_key object from std::array of num_words() words + * @param arr - Source data + */ template::value && !std::is_same::value && @@ -109,6 +137,15 @@ namespace eosio { set_from_word_sequence(arr, *this); } + /** + * @brief Create a new fixed_key object from a sequence of words + * + * @details Create a new fixed_key object from a sequence of words + * @tparam FirstWord - The type of the first word in the sequence + * @tparam Rest - THe type of the remaining words in the sequence + * @param first_word - The first word in the sequence + * @param rest - The remaining words in the sequence + */ template static fixed_key @@ -128,13 +165,36 @@ namespace eosio { return key; } + /** + * Get the contained std::array + * @brief Get the contained std::array + */ const auto& get_array()const { return _data; } + /** + * Get the underlying data of the contained std::array + * @brief Get the underlying data of the contained std::array + */ auto data() { return _data.data(); } + + /** + * Get the underlying data of the contained std::array + * @brief Get the underlying data of the contained std::array + */ auto data()const { return _data.data(); } + /** + * Get the size of the contained std::array + * @brief Get the size of the contained std::array + */ auto size()const { return _data.size(); } + + /** + * Extract the contained data as an array of bytes + * @brief Extract the contained data as an array of bytes + * @return - the extracted data as array of bytes + */ std::array extract_as_byte_array()const { std::array arr; @@ -178,6 +238,8 @@ namespace eosio { * @brief Compares two fixed_key variables c1 and c2 * * @details Lexicographically compares two fixed_key variables c1 and c2 + * @param c1 - First fixed_key object to compare + * @param c2 - Second fixed_key object to compare * @return if c1 == c2, return true, otherwise false */ template @@ -189,6 +251,8 @@ namespace eosio { * @brief Compares two fixed_key variables c1 and c2 * * @details Lexicographically compares two fixed_key variables c1 and c2 + * @param c1 - First fixed_key object to compare + * @param c2 - Second fixed_key object to compare * @return if c1 != c2, return true, otherwise false */ template @@ -200,6 +264,8 @@ namespace eosio { * @brief Compares two fixed_key variables c1 and c2 * * @details Lexicographically compares two fixed_key variables c1 and c2 + * @param c1 - First fixed_key object to compare + * @param c2 - Second fixed_key object to compare * @return if c1 > c2, return true, otherwise false */ template @@ -211,6 +277,8 @@ namespace eosio { * @brief Compares two fixed_key variables c1 and c2 * * @details Lexicographically compares two fixed_key variables c1 and c2 + * @param c1 - First fixed_key object to compare + * @param c2 - Second fixed_key object to compare * @return if c1 < c2, return true, otherwise false */ template diff --git a/libraries/eosiolib/fixedpoint.hpp b/libraries/eosiolib/fixedpoint.hpp index fdea959421..9f2ced9fd2 100644 --- a/libraries/eosiolib/fixedpoint.hpp +++ b/libraries/eosiolib/fixedpoint.hpp @@ -7,7 +7,7 @@ namespace eosio /** * @defgroup fixedpoint Fixed Point * @ingroup mathcppapi - * @brief 32,64,128,256 bits version of Fixed Point variables + * @brief 32,64,128,256 bits version of fixed point variables * * Floating point operations are indeterministic, hence is prevented in smart contract. * The smart contract developers should use the appropriate Fixed_Point template class @@ -85,9 +85,10 @@ namespace eosio #endif /** + * The template param Q represents the Q Factor i.e number of decimals + * * @brief 128 bits representation of Fixed Point class. * - * The template param Q represents the Q Factor i.e number of decimals * Example: * @code * fixed_point128<6> a(123232.455667233) @@ -101,26 +102,63 @@ namespace eosio struct fixed_point128 { static_assert(Q < 128, "Maximum number of decimals supported in fixed_point128 is 128 decimals"); + + /** + * @brief Value of the fixed point represented as int128_t + * + * Value of the fixed point represented as int128_t + */ int128_t val; + /** - * Various constructors for fixed_point128 - * @brief Can create fixed_point128 instance from an int128_t, fixed_point128,64,32 instance - * + * Various constructors for fixed_point128. Can create fixed_point128 instance from an int128_t, fixed_point128,64,32 instance + * + * @brief Various constructors for fixed_point128 * * Example: * @code * fixed_point64<18> a(1234.455667); -ope * fixed_point128<3> b(a); + * fixed_point128<3> b(a); * fixed_point32<6> b(13324.32323); * fixed_point128<5> c(a); * @endcode */ + + /** + * Construct a new fixed point128 object from int128_t + * + * @brief Construct a new fixed point128 object + * @param v - int128_t representation of the fixed point value + */ fixed_point128(int128_t v=0) : val(v) {} + + /** + * Construct a new fixed point128 object from another fixed_point128 + * + * @brief Construct a new fixed point128 object from another fixed_point128 + * @param r - Another fixed_point128 as source + */ template fixed_point128(const fixed_point128 &r); + + /** + * Construct a new fixed point128 object from another fixed_point64 + * + * @brief Construct a new fixed point128 object from another fixed_point64 + * @param r -fixed_point64 as source + */ template fixed_point128(const fixed_point64 &r); + + /** + * Construct a new fixed point128 object from another fixed_point32 + * + * @brief Construct a new fixed point128 object from another fixed_point32 + * @param r -fixed_point32 as source + */ template fixed_point128(const fixed_point32 &r); + /** * Get the integer part of the 64 bit fixed number + * * @brief To get the integer part of the fixed number * @return Returns integer part of the fixed number * @@ -136,6 +174,7 @@ ope * fixed_point128<3> b(a); /** * Get the decimal part of the 64 bit fixed number + * * @brief To get the decimal part of the fixed number * @return Returns decimal part of the fixed number * @@ -150,6 +189,11 @@ ope * fixed_point128<3> b(a); return uint128_t(val << (32-Q)); } + /** + * Prints the fixed point value + * + * @brief Prints the fixed point value + */ void print() const { uint128_t ip((uint128_t)int_part()); uint128_t fp(frac_part()); @@ -159,12 +203,66 @@ ope * fixed_point128<3> b(a); } // Various assignment operators + /** + * Assignment operator. Assign fixed_point32 to fixed_point128 + * + * @brief Assignment operator + * @tparam qr - Precision of the source + * @param r - Source + * @return fixed_point128& - Reference to this object + */ template fixed_point128 &operator=(const fixed_point32 &r); + /** + * Assignment operator. Assign fixed_point32 to fixed_point64 + * + * @brief Assignment operator + * @tparam qr - Precision of the source + * @param r - Source + * @return fixed_point128& - Reference to this object + */ template fixed_point128 &operator=(const fixed_point64 &r); + /** + * Assignment operator. Assign fixed_point32 to fixed_point32 + * + * @brief Assignment operator + * @tparam qr - Precision of the source + * @param r - Source + * @return fixed_point128& - Reference to this object + */ template fixed_point128 &operator=(const fixed_point128 &r); + // Comparison functions + /** + * Equality operator + * + * @brief Equality operator + * @tparam qr - Precision of the source + * @param r - Source + * @return true - if equal + * @return false - otherwise + */ template bool operator==(const fixed_point128 &r) { return (val == r.val);} + + /** + * Greater than operator + * + * @brief Greater than operator + * @tparam qr - Precision of the source + * @param r - Source + * @return true - if equal + * @return false - otherwise + */ template bool operator>(const fixed_point128 &r) { return (val > r.val);} + + /** + * Less than operator + * + * @brief Less than operator + * @tparam qr - Precision of the source + * @param r - Source + * @return true - if equal + * @return false - otherwise + */ template bool operator<(const fixed_point128 &r) { return (val < r.val);} }; @@ -185,23 +283,38 @@ ope * fixed_point128<3> b(a); struct fixed_point64 { static_assert(Q < 128, "Maximum number of decimals supported in fixed_point64 is 128 decimals"); + + /** + * @brief Value of the fixed point represented as int64_t + * + * Value of the fixed point represented as int64_t + */ int64_t val; + + /** + * Construct a new fixed point64 object from int64_t + * + * @brief Construct a new fixed point64 object + * @param v - int64_t representation of the fixed point value + */ fixed_point64(int64_t v=0) : val(v) {} + /** - * Various constructors for fixed_point64 - * @brief Can create fixed_point64 instance from int64_t, fixed_point64,32 instances - * - * - * Example: - * @code - * fixed_point32<18> a(1234.455667); - * fixed_point64<3> b(a); - * fixed_point64<6> b(13324.32323); - * fixed_point64<5> c(a); - * @endcode - */ + * Construct a new fixed point64 object from another fixed_point64 + * + * @brief Construct a new fixed point64 object from another fixed_point64 + * @param r - Another fixed_point64 as source + */ template fixed_point64(const fixed_point64 &r); + + /** + * Construct a new fixed point64 object from another fixed_point32 + * + * @brief Construct a new fixed point64 object from another fixed_point32 + * @param r - fixed_point64 as source + */ template fixed_point64(const fixed_point32 &r); + /** * Get the integer part of the 64 bit fixed number * @brief To get the integer part of the fixed number @@ -233,6 +346,11 @@ ope * fixed_point128<3> b(a); return uint64_t(val << (32-Q)); } + /** + * Prints the fixed point value + * + * @brief Prints the fixed point value + */ void print() const { printi(int_part()); prints("."); @@ -240,19 +358,101 @@ ope * fixed_point128<3> b(a); } // Various assignment operators + /** + * Assignment operator. Assign fixed_point32 to fixed_point64 + * + * @brief Assignment operator + * @tparam qr - Precision of the source + * @param r - Source + * @return fixed_point64& - Reference to this object + */ template fixed_point64 &operator=(const fixed_point32 &r); + + /** + * Assignment operator. Assign fixed_point64 to fixed_point64 + * + * @brief Assignment operator + * @tparam qr - Precision of the source + * @param r - Source + * @return fixed_point64& - Reference to this object + */ template fixed_point64 &operator=(const fixed_point64 &r); // Arithmetic operations + /** + * Addition operator + * + * @brief Addition operator + * @tparam QR - Precision of the second addend + * @param r - Second addend + * @return - The result of addition + */ template fixed_point64< (Q>QR)?Q:QR > operator+(const fixed_point64 &r) const; + + /** + * Subtraction operator + * + * @brief Subtraction operator + * @tparam QR - Precision of the minuend + * @param r - Minuend + * @return - The result of subtraction + */ template fixed_point64< (Q>QR)?Q:QR > operator-(const fixed_point64 &r) const; + // product and division of two fixed_point64 instances will be fixed_point128 // The total number of decimals will be the max + /** + * Multiplication operator + * + * @brief Multiplication operator + * @tparam QR - Precision of the multiplier + * @param r - Multiplier + * @return - The result of multiplication + */ template fixed_point128 operator*(const fixed_point64 &r) const; + + /** + * Division operator + * + * @brief Division operator + * @tparam QR - Precision of the divisor + * @param r - Divisor + * @return - The result of division + */ template fixed_point128 operator/(const fixed_point64 &r) const; + // Comparison functions + /** + * Equality operator + * + * @brief Equality operator + * @tparam qr - Precision of the source + * @param r - Source + * @return true - if equal + * @return false - otherwise + */ template bool operator==(const fixed_point64 &r) { return (val == r.val);} + + /** + * Greater than operator + * + * @brief Greater than operator + * @tparam qr - Precision of the source + * @param r - Source + * @return true - if equal + * @return false - otherwise + */ template bool operator>(const fixed_point64 &r) { return (val > r.val);} + + /** + * Less than operator + * + * @brief Less than operator + * @tparam qr - Precision of the source + * @param r - Source + * @return true - if equal + * @return false - otherwise + */ template bool operator<(const fixed_point64 &r) { return (val < r.val);} }; @@ -277,12 +477,40 @@ ope * fixed_point128<3> b(a); struct fixed_point32 { static_assert(Q < 128, "Maximum number of decimals supported in fixed_point32 is 128 decimals"); - // translates given double variable to the int32 based on the scale factor + + /** + * @brief Value of the fixed point represented as int32_t + * + * Value of the fixed point represented as int32_t + */ int32_t val; + + /** + * Construct a new fixed point32 object from another fixed_point32 + * + * @brief Construct a new fixed point32 object from another fixed_point32 + * @param r - Another fixed_point32 as source + */ template fixed_point32(const fixed_point32 &r); + + /** + * Construct a new fixed point32 object from another fixed_point64. It will be truncated. + * + * @brief Construct a new fixed point32 object from another fixed_point64 + * @param r - Another fixed_point32 as source + */ template fixed_point32(const fixed_point64 &r); + + /** + * Construct a new fixed point32 object from int32_t + * + * @brief Construct a new fixed point32 object + * @param v - int32_t representation of the fixed point value + */ fixed_point32(int32_t param=0) : val(param) {} + + // translates given double variable to the int32 based on the scale factor // fixed_point32(double d=0) : val(d * (1< b(a); return uint32_t(val << (32-Q)); } + /** + * Prints the fixed point value + * + * @brief Prints the fixed point value + */ void print() const { printi(int_part()); prints("."); @@ -316,20 +549,105 @@ ope * fixed_point128<3> b(a); } // Various assignment operators + /** + * Assignment operator. Assign fixed_point32 to fixed_point32 + * + * @brief Assignment operator + * @tparam qr - Precision of the source + * @param r - Source + * @return fixed_point32& - Reference to this object + */ template fixed_point32 &operator=(const fixed_point32 &r); + + /** + * Assignment operator. Assign fixed_point64 to fixed_point32 + * + * @brief Assignment operator + * @tparam qr - Precision of the source + * @param r - Source + * @return fixed_point32& - Reference to this object + */ template fixed_point32 &operator=(const fixed_point64 &r); + + /** + * Addition operator + * + * @brief Addition operator + * @tparam QR - Precision of the second addend + * @param r - Second addend + * @return - The result of addition + */ template fixed_point32< (Q>QR)?Q:QR > operator+(const fixed_point32 &r) const; + + /** + * Subtraction operator + * + * @brief Subtraction operator + * @tparam QR - Precision of the minuend + * @param r - Minuend + * @return - The result of subtraction + */ template fixed_point32< (Q>QR)?Q:QR > operator-(const fixed_point32 &r) const; + // productd of to fixed_point32 instances will be fixed_point64 + /** + * Multiplication operator + * + * @brief Multiplication operator + * @tparam QR - Precision of the multiplier + * @param r - Multiplier + * @return - The result of multiplication + */ template fixed_point64 operator*(const fixed_point32 &r) const; + + /** + * Division operator + * + * @brief Division operator + * @tparam QR - Precision of the divisor + * @param r - Divisor + * @return - The result of division + */ template fixed_point64 operator/(const fixed_point32 &r) const; + // Comparison functions + /** + * Equality operator + * + * @brief Equality operator + * @tparam qr - Precision of the source + * @param r - Source + * @return true - if equal + * @return false - otherwise + */ template bool operator==(const fixed_point32 &r) { return (val == r.val);} + + /** + * Greater than operator + * + * @brief Greater than operator + * @tparam qr - Precision of the source + * @param r - Source + * @return true - if equal + * @return false - otherwise + */ template bool operator>(const fixed_point32 &r) { return (val > r.val);} + + /** + * Less than operator + * + * @brief Less than operator + * @tparam qr - Precision of the source + * @param r - Source + * @return true - if equal + * @return false - otherwise + */ template bool operator<(const fixed_point32 &r) { return (val < r.val);} }; + /// @} fixedpoint + // Helper functions template T assignHelper(T rhs_val, uint8_t q, uint8_t qr) @@ -338,6 +656,7 @@ ope * fixed_point128<3> b(a); return result; } + #if 0 // fixed_point256 methods template template @@ -599,5 +918,5 @@ ope * fixed_point128<3> b(a); return fixed_point128(result); } - /// @} fixedpoint + }; diff --git a/libraries/eosiolib/memory.hpp b/libraries/eosiolib/memory.hpp index c433761d06..4a4f56a1c4 100644 --- a/libraries/eosiolib/memory.hpp +++ b/libraries/eosiolib/memory.hpp @@ -9,14 +9,60 @@ void* sbrk(size_t num_bytes); + /** + * @defgroup memoryapi Memory API + * @brief Defines common memory functions + * @ingroup contractdev + */ + + /** + * @defgroup memorycppapi Memory C++ API + * @brief Defines common memory functions + * @ingroup memoryapi + * + * @{ + */ + extern "C" { +/** + * Allocate additional memory + * + * @brief Allocate additional memory + * @param size - Number of additional bytes to be allocated + * @return void* - Pointer to start of the new allocated memory + */ void* malloc(size_t size); +/** + * Allocate a block of memory for an array of **count** elements, each of them **size** bytes long, and initializes all bits with 0 + * + * @brief Allocate a block of memory for an array of **count** elements, each of them **size** bytes long, and initializes all bits with 0 + * @param count - Number of elements to allocate + * @param size - Size of each element + * @return void* - Pointer to start of the new allocated memory + */ void* calloc(size_t count, size_t size); +/** + * Reallocate the given area of memory, which is allocated by malloc(), calloc(), or realloc() previously + * + * @brief Reallocate the given area of memory + * @param ptr - Pointer to the memory area to be reallocated + * @param size - New size of the memory + * @return void* - Pointer to the new reallocated memory + */ void* realloc(void* ptr, size_t size); +/** + * + * Deallocates the given area of memory which is previously allocated by malloc(), calloc(), or realloc() + * @brief Deallocates the given area of memory + * + * @param ptr - Pointer to the memory to be deallocated + */ void free(void* ptr); } + +/// @}memorycppapi diff --git a/libraries/eosiolib/multi_index.hpp b/libraries/eosiolib/multi_index.hpp index 8ec221481d..d708255905 100644 --- a/libraries/eosiolib/multi_index.hpp +++ b/libraries/eosiolib/multi_index.hpp @@ -118,12 +118,106 @@ namespace _multi_index_detail { } +/** + * The indexed_by struct is used to instantiate the indices for the Multi-Index table. In EOSIO, up to 16 secondary indices can be specified. + * @brief The indexed_by struct is used to instantiate the indices for the Multi-Index table. In EOSIO, up to 16 secondary indices can be specified. + * + * @tparam IndexName - is the name of the index. The name must be provided as an EOSIO base32 encoded 64-bit integer and must conform to the EOSIO naming requirements of a maximum of 13 characters, the first twelve from the lowercase characters a-z, digits 0-5, and ".", and if there is a 13th character, it is restricted to lowercase characters a-p and ".". + * @tparam Extractor - is a function call operator that takes a const reference to the table object type and returns either a secondary key type or a reference to a secondary key type. It is recommended to use the `eosio::const_mem_fun` template, which is a type alias to the `boost::multi_index::const_mem_fun`. See the documentation for the Boost `const_mem_fun` key extractor for more details. + * + * Example: + * +* + * @code + * #include + * using namespace eosio; + * class mycontract: eosio::contract { + * struct record { + * uint64_t primary; + * uint128_t secondary; + * uint64_t primary_key() const { return primary; } + * uint64_t get_secondary() const { return secondary; } + * EOSLIB_SERIALIZE( record, (primary)(secondary) ) + * }; + * public: + * mycontract( account_name self ):contract(self){} + * void myaction() { + * auto code = _self; + * auto scope = _self; + * multi_index > > table( code, scope); + * } + * } + * EOSIO_ABI( mycontract, (myaction) ) + * @endcode + */ template struct indexed_by { enum constants { index_name = IndexName }; typedef Extractor secondary_extractor_type; }; +/** + * @defgroup multiindex Multi Index Table + * @brief Defines EOSIO Multi Index Table + * @ingroup databasecpp + * + * + * + * EOSIO Multi-Index API provides a C++ interface to the EOSIO database. It is patterned after Boost Multi Index Container. + * EOSIO Multi-Index table requires exactly a uint64_t primary key. For the table to be able to retrieve the primary key, + * the object stored inside the table is required to have a const member function called primary_key() that returns uint64_t. + * EOSIO Multi-Index table also supports up to 16 secondary indices. The type of the secondary indices could be any of: + * - uint64_t + * - uint128_t + * - uint256_t + * - double + * - long double + * + * @tparam TableName - name of the table + * @tparam T - type of the data stored inside the table + * @tparam Indices - secondary indices for the table, up to 16 indices is supported here + * + * Example: + * + * @code + * #include + * using namespace eosio; + * class mycontract: contract { + * struct record { + * uint64_t primary; + * uint64_t secondary_1; + * uint128_t secondary_2; + * uint256_t secondary_3; + * double secondary_4; + * long double secondary_5; + * uint64_t primary_key() const { return primary; } + * uint64_t get_secondary_1() const { return secondary_1; } + * uint128_t get_secondary_2() const { return secondary_2; } + * uint256_t get_secondary_3() const { return secondary_3; } + * double get_secondary_4() const { return secondary_4; } + * long double get_secondary_5() const { return secondary_5; } + * EOSLIB_SERIALIZE( record, (primary)(secondary_1)(secondary_2)(secondary_3)(secondary_4)(secondary_5) ) + * }; + * public: + * mycontract( account_name self ):contract(self){} + * void myaction() { + * auto code = _self; + * auto scope = _self; + * multi_index >, + * indexed_by< N(bysecondary2), const_mem_fun >, + * indexed_by< N(bysecondary3), const_mem_fun >, + * indexed_by< N(bysecondary4), const_mem_fun >, + * indexed_by< N(bysecondary5), const_mem_fun > + * > table( code, scope); + * } + * } + * EOSIO_ABI( mycontract, (myaction) ) + * @endcode + * @{ + */ + template class multi_index { @@ -319,6 +413,17 @@ class multi_index return lb; } + const_iterator require_find( secondary_key_type&& secondary, const char* error_msg = "unable to find secondary key" )const { + return require_find( secondary, error_msg ); + } + + const_iterator require_find( const secondary_key_type& secondary, const char* error_msg = "unable to find secondary key" )const { + auto lb = lower_bound( secondary ); + eosio_assert( lb != cend(), error_msg ); + eosio_assert( secondary == secondary_extractor_type()(*lb), error_msg ); + return lb; + } + const T& get( secondary_key_type&& secondary, const char* error_msg = "unable to find secondary key" )const { return get( secondary, error_msg ); } @@ -488,12 +593,128 @@ class multi_index } /// load_object_by_primary_iterator public: - + /** + * Constructs an instance of a Multi-Index table. + * @brief Constructs an instance of a Multi-Index table. + * + * @param code - Account that owns table + * @param scope - Scope identifier within the code hierarchy + * + * @pre code and scope member properties are initialized + * @post each secondary index table initialized + * @post Secondary indices are updated to refer to the newly added object. If the secondary index tables do not exist, they are created. + * @post The payer is charged for the storage usage of the new object and, if the table (and secondary index tables) must be created, for the overhead of the table creation. + * + * Notes + * The `eosio::multi_index` template has template parameters ``, where: + * - `TableName` is the name of the table, maximum 12 characters long, characters in the name from the set of lowercase letters, digits 1 to 5, and the "." (period) character; + * - `T` is the object type (i.e., row definition); + * - `Indices` is a list of up to 16 secondary indices. + * - Each must be a default constructable class or struct + * - Each must have a function call operator that takes a const reference to the table object type and returns either a secondary key type or a reference to a secondary key type + * - It is recommended to use the eosio::const_mem_fun template, which is a type alias to the boost::multi_index::const_mem_fun. See the documentation for the Boost const_mem_fun key extractor for more details. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ multi_index( uint64_t code, uint64_t scope ) :_code(code),_scope(scope),_next_primary_key(unset_next_primary_key) {} + /** + * Returns the `code` member property. + * @brief Returns the `code` member property. + * + * @return Account name of the Code that owns the Primary Table. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(N(dan), N(dan)); // code, scope + * eosio_assert(addresses.get_code() == N(dan), "Codes don't match."); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ uint64_t get_code()const { return _code; } + + /** + * Returns the `scope` member property. + * @brief Returns the `scope` member property. + * + * @return Scope id of the Scope within the Code of the Current Receiver under which the desired Primary Table instance can be found. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(N(dan), N(dan)); // code, scope + * eosio_assert(addresses.get_code() == N(dan), "Scopes don't match"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ uint64_t get_scope()const { return _scope; } struct const_iterator : public std::iterator { @@ -559,20 +780,482 @@ class multi_index typedef std::reverse_iterator const_reverse_iterator; + /** + * Returns an iterator pointing to the object_type with the lowest primary key value in the Multi-Index table. + * @brief Returns an iterator pointing to the object_type with the lowest primary key value in the Multi-Index table. + * + * @return An iterator pointing to the object_type with the lowest primary key value in the Multi-Index table. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(_self, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * auto itr = addresses.find(N(dan)); + * eosio_assert(itr == addresses.cbegin(), "Only address is not at front."); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_iterator cbegin()const { return lower_bound(std::numeric_limits::lowest()); } + + /** + * Returns an iterator pointing to the object_type with the lowest primary key value in the Multi-Index table. + * @brief Returns an iterator pointing to the object_type with the lowest primary key value in the Multi-Index table. + * + * @return An iterator pointing to the object_type with the lowest primary key value in the Multi-Index table. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(_self, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * auto itr = addresses.find(N(dan)); + * eosio_assert(itr == addresses.begin(), "Only address is not at front."); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_iterator begin()const { return cbegin(); } + /** + * Returns an iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * @brief Returns an iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * + * @return An iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(_self, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * auto itr = addresses.find(N(dan)); + * eosio_assert(itr != addresses.cend(), "Address for account doesn't exist"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_iterator cend()const { return const_iterator( this ); } + + /** + * Returns an iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * @brief Returns an iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * + * @return An iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(_self, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * auto itr = addresses.find(N(dan)); + * eosio_assert(itr != addresses.end(), "Address for account doesn't exist"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_iterator end()const { return cend(); } + /** + * Returns a reverse iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * @brief Returns a reverse iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * + * @return A reverse iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(brendan); + * address.first_name = "Brendan"; + * address.last_name = "Blumer"; + * address.street = "1 EOS Way"; + * address.city = "Hong Kong"; + * address.state = "HK"; + * }); + * auto itr = addresses.crbegin(); + * eosio_assert(itr->account_name == N(dan), "Incorrect Last Record "); + * itr++; + * eosio_assert(itr->account_name == N(brendan), "Incorrect Second Last Record"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_reverse_iterator crbegin()const { return std::make_reverse_iterator(cend()); } + + /** + * Returns a reverse iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * @brief Returns a reverse iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * + * @return A reverse iterator pointing to the `object_type` with the highest primary key value in the Multi-Index table. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(brendan); + * address.first_name = "Brendan"; + * address.last_name = "Blumer"; + * address.street = "1 EOS Way"; + * address.city = "Hong Kong"; + * address.state = "HK"; + * }); + * auto itr = addresses.rbegin(); + * eosio_assert(itr->account_name == N(dan), "Incorrect Last Record "); + * itr++; + * eosio_assert(itr->account_name == N(brendan), "Incorrect Second Last Record"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_reverse_iterator rbegin()const { return crbegin(); } + /** + * Returns an iterator pointing to the `object_type` with the lowest primary key value in the Multi-Index table. + * @brief Returns an iterator pointing to the `object_type` with the lowest primary key value in the Multi-Index table. + * + * @return An iterator pointing to the `object_type` with the lowest primary key value in the Multi-Index table. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(brendan); + * address.first_name = "Brendan"; + * address.last_name = "Blumer"; + * address.street = "1 EOS Way"; + * address.city = "Hong Kong"; + * address.state = "HK"; + * }); + * auto itr = addresses.crend(); + * itr--; + * eosio_assert(itr->account_name == N(brendan), "Incorrect First Record "); + * itr--; + * eosio_assert(itr->account_name == N(dan), "Incorrect Second Record"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_reverse_iterator crend()const { return std::make_reverse_iterator(cbegin()); } + + /** + * Returns an iterator pointing to the `object_type` with the lowest primary key value in the Multi-Index table. + * @brief Returns an iterator pointing to the `object_type` with the lowest primary key value in the Multi-Index table. + * + * @return An iterator pointing to the `object_type` with the lowest primary key value in the Multi-Index table. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(brendan); + * address.first_name = "Brendan"; + * address.last_name = "Blumer"; + * address.street = "1 EOS Way"; + * address.city = "Hong Kong"; + * address.state = "HK"; + * }); + * auto itr = addresses.rend(); + * itr--; + * eosio_assert(itr->account_name == N(brendan), "Incorrect First Record "); + * itr--; + * eosio_assert(itr->account_name == N(dan), "Incorrect Second Record"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_reverse_iterator rend()const { return crend(); } + /** + * Searches for the `object_type` with the lowest primary key that is greater than or equal to a given primary key. + * @brief Searches for the `object_type` with the lowest primary key that is greater than or equal to a given primary key. + * + * @param primary - Primary key that establishes the target value for the lower bound search. + * + * @return An iterator pointing to the `object_type` that has the lowest primary key that is greater than or equal to `primary`. If an object could not be found, it will return the `end` iterator. If the table does not exist** it will return `-1`. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint32_t zip = 0; + * uint64_t primary_key() const { return account_name; } + * uint64_t by_zip() const { return zip; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state)(zip) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address, indexed_by< N(zip), const_mem_fun > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * address.zip = 93446; + * }); + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(brendan); + * address.first_name = "Brendan"; + * address.last_name = "Blumer"; + * address.street = "1 EOS Way"; + * address.city = "Hong Kong"; + * address.state = "HK"; + * address.zip = 93445; + * }); + * uint32_t zipnumb = 93445; + * auto zip_index = addresses.get_index(); + * auto itr = zip_index.lower_bound(zipnumb); + * eosio_assert(itr->account_name == N(brendan), "Incorrect First Lower Bound Record "); + * itr++; + * eosio_assert(itr->account_name == N(dan), "Incorrect Second Lower Bound Record"); + * itr++; + * eosio_assert(itr == zip_index.end(), "Incorrect End of Iterator"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_iterator lower_bound( uint64_t primary )const { auto itr = db_lowerbound_i64( _code, _scope, TableName, primary ); if( itr < 0 ) return end(); @@ -580,6 +1263,69 @@ class multi_index return {this, &obj}; } + /** + * Searches for the `object_type` with the highest primary key that is less than or equal to a given primary key. + * @brief Searches for the `object_type` with the highest primary key that is less than or equal to a given primary key. + * + * @param primary - Primary key that establishes the target value for the upper bound search + * + * @return An iterator pointing to the `object_type` that has the highest primary key that is less than or equal to `primary`. If an object could not be found, it will return the `end` iterator. If the table does not exist** it will return `-1`. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint32_t zip = 0; + * uint64_t liked = 0; + * uint64_t primary_key() const { return account_name; } + * uint64_t by_zip() const { return zip; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state)(zip) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address, indexed_by< N(zip), const_mem_fun > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * address.zip = 93446; + * }); + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(brendan); + * address.first_name = "Brendan"; + * address.last_name = "Blumer"; + * address.street = "1 EOS Way"; + * address.city = "Hong Kong"; + * address.state = "HK"; + * address.zip = 93445; + * }); + * uint32_t zipnumb = 93445; + * auto zip_index = addresses.get_index(); + * auto itr = zip_index.upper_bound(zipnumb); + * eosio_assert(itr->account_name == N(dan), "Incorrect First Upper Bound Record "); + * itr++; + * eosio_assert(itr == zip_index.end(), "Incorrect End of Iterator"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_iterator upper_bound( uint64_t primary )const { auto itr = db_upperbound_i64( _code, _scope, TableName, primary ); if( itr < 0 ) return end(); @@ -587,10 +1333,51 @@ class multi_index return {this, &obj}; } - /** Ideally this method would only be used to determine the appropriate primary key to use within new objects added to a - * table in which the primary keys of the table are strictly intended from the beginning to be autoincrementing and - * thus will not ever be set to custom arbitrary values by the contract. - * Violating this agreement could result in the table appearing full when in reality there is plenty of space left. + /** + * Returns an available primary key. + * @brief Returns an available primary key. + * + * @return An available (unused) primary key value. + * + * Notes: + * Intended to be used in tables in which the primary keys of the table are strictly intended to be auto-incrementing, and thus will never be set to custom values by the contract. Violating this expectation could result in the table appearing to be full due to inability to allocate an available primary key. + * Ideally this method would only be used to determine the appropriate primary key to use within new objects added to a table in which the primary keys of the table are strictly intended from the beginning to be autoincrementing and thus will not ever be set to custom arbitrary values by the contract. Violating this agreement could result in the table appearing full when in reality there is plenty of space left. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t key; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return key; } + * EOSLIB_SERIALIZE( address, (key)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(payer, [&](auto& address) { + * address.key = addresses.available_primary_key(); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode */ uint64_t available_primary_key()const { if( _next_primary_key == unset_next_primary_key ) { @@ -611,6 +1398,57 @@ class multi_index return _next_primary_key; } + /** + * Returns an appropriately typed Secondary Index. + * @brief Returns an appropriately typed Secondary Index. + * + * @tparam IndexName - the ID of the desired secondary index + * + * @return An index of the appropriate type: Primitive 64-bit unsigned integer key (idx64), Primitive 128-bit unsigned integer key (idx128), 128-bit fixed-size lexicographical key (idx128), 256-bit fixed-size lexicographical key (idx256), Floating point key, Double precision floating point key, Long Double (quadruple) precision floating point key + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint32_t zip = 0; + * uint64_t primary_key() const { return account_name; } + * uint64_t by_zip() const { return zip; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state)(zip) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address, indexed_by< N(zip), const_mem_fun > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * address.zip = 93446; + * }); + * uint32_t zipnumb = 93446; + * auto zip_index = addresses.get_index(); + * auto itr = zip_index.find(zipnumb); + * eosio_assert(itr->account_name == N(dan), "Incorrect Record "); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ template auto get_index() { using namespace _multi_index_detail; @@ -624,6 +1462,68 @@ class multi_index return typename decltype(+hana::at_c<0>(res.value()))::type(this); } + /** + * Returns an appropriately typed Secondary Index. + * @brief Returns an appropriately typed Secondary Index. + * + * @tparam IndexName - the ID of the desired secondary index + * + * @return An index of the appropriate type: Primitive 64-bit unsigned integer key (idx64), Primitive 128-bit unsigned integer key (idx128), 128-bit fixed-size lexicographical key (idx128), 256-bit fixed-size lexicographical key (idx256), Floating point key, Double precision floating point key, Long Double (quadruple) precision floating point key + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint32_t zip = 0; + * uint64_t primary_key() const { return account_name; } + * uint64_t by_zip() const { return zip; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state)(zip) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address, indexed_by< N(zip), const_mem_fun > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * address.zip = 93446; + * }); + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(brendan); + * address.first_name = "Brendan"; + * address.last_name = "Blumer"; + * address.street = "1 EOS Way"; + * address.city = "Hong Kong"; + * address.state = "HK"; + * address.zip = 93445; + * }); + * uint32_t zipnumb = 93445; + * auto zip_index = addresses.get_index(); + * auto itr = zip_index.upper_bound(zipnumb); + * eosio_assert(itr->account_name == N(dan), "Incorrect First Upper Bound Record "); + * itr++; + * eosio_assert(itr == zip_index.end(), "Incorrect End of Iterator"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ template auto get_index()const { using namespace _multi_index_detail; @@ -637,12 +1537,122 @@ class multi_index return typename decltype(+hana::at_c<1>(res.value()))::type(this); } + /** + * Returns an iterator to the given object in a Multi-Index table. + * @brief Returns an iterator to the given object in a Multi-Index table. + * + * @param obj - A reference to the desired object + * + * @return An iterator to the given object + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint32_t zip = 0; + * uint64_t primary_key() const { return account_name; } + * uint64_t by_zip() const { return zip; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state)(zip) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address, indexed_by< N(zip), const_mem_fun > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * address.zip = 93446; + * }); + * addresses.emplace(payer, [&](auto& address) { + * address.account_name = N(brendan); + * address.first_name = "Brendan"; + * address.last_name = "Blumer"; + * address.street = "1 EOS Way"; + * address.city = "Hong Kong"; + * address.state = "HK"; + * address.zip = 93445; + * }); + * auto user = addresses.get(N(dan)); + * auto itr = address.find(N(dan)); + * eosio_assert(iterator_to(user) == itr, "Invalid iterator"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_iterator iterator_to( const T& obj )const { const auto& objitem = static_cast(obj); eosio_assert( objitem.__idx == this, "object passed to iterator_to is not in multi_index" ); return {this, &objitem}; } - + /** + * Adds a new object (i.e., row) to the table. + * @brief Adds a new object (i.e., row) to the table. + * + * @param payer - Account name of the payer for the Storage usage of the new object + * @param constructor - Lambda function that does an in-place initialization of the object to be created in the table + * + * @pre A multi index table has been instantiated + * @post A new object is created in the Multi-Index table, with a unique primary key (as specified in the object). The object is serialized and written to the table. If the table does not exist, it is created. + * @post Secondary indices are updated to refer to the newly added object. If the secondary index tables do not exist, they are created. + * @post The payer is charged for the storage usage of the new object and, if the table (and secondary index tables) must be created, for the overhead of the table creation. + * + * @return A primary key iterator to the newly created object + * + * Exception - The account is not authorized to write to the table. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(_self, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ template const_iterator emplace( uint64_t payer, Lambda&& constructor ) { using namespace _multi_index_detail; @@ -688,6 +1698,68 @@ class multi_index return {this, ptr}; } + /** + * Modifies an existing object in a table. + * @brief Modifies an existing object in a table. + * + * @param itr - an iterator pointing to the object to be updated + * @param payer - account name of the payer for the Storage usage of the updated row + * @param updater - lambda function that updates the target object + * + * @pre itr points to an existing element + * @pre payer is a valid account that is authorized to execute the action and be billed for storage usage. + * + * @post The modified object is serialized, then replaces the existing object in the table. + * @post Secondary indices are updated; the primary key of the updated object is not changed. + * @post The payer is charged for the storage usage of the updated object. + * @post If payer is the same as the existing payer, payer only pays for the usage difference between existing and updated object (and is refunded if this difference is negative). + * @post If payer is different from the existing payer, the existing payer is refunded for the storage usage of the existing object. + * + * Exceptions: + * If called with an invalid precondition, execution is aborted. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(_self, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * auto itr = addresses.find(N(dan)); + * eosio_assert(itr != addresses.end(), "Address for account not found"); + * addresses.modify( itr, account payer, [&]( auto& address ) { + * address.city = "San Luis Obispo"; + * address.state = "CA"; + * }); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ template void modify( const_iterator itr, uint64_t payer, Lambda&& updater ) { eosio_assert( itr != end(), "cannot pass end iterator to modify" ); @@ -695,6 +1767,69 @@ class multi_index modify( *itr, payer, std::forward(updater) ); } + /** + * Modifies an existing object in a table. + * @brief Modifies an existing object in a table. + * + * @param obj - a reference to the object to be updated + * @param payer - account name of the payer for the Storage usage of the updated row + * @param updater - lambda function that updates the target object + * + * @pre obj is an existing object in the table + * @pre payer is a valid account that is authorized to execute the action and be billed for storage usage. + * + * @post The modified object is serialized, then replaces the existing object in the table. + * @post Secondary indices are updated; the primary key of the updated object is not changed. + * @post The payer is charged for the storage usage of the updated object. + * @post If payer is the same as the existing payer, payer only pays for the usage difference between existing and updated object (and is refunded if this difference is negative). + * @post If payer is different from the existing payer, the existing payer is refunded for the storage usage of the existing object. + * + * Exceptions: + * If called with an invalid precondition, execution is aborted. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(_self, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * auto itr = addresses.find(N(dan)); + * eosio_assert(itr != addresses.end(), "Address for account not found"); + * addresses.modify( *itr, payer, [&]( auto& address ) { + * address.city = "San Luis Obispo"; + * address.state = "CA"; + * }); + * eosio_assert(itr->city == "San Luis Obispo", "Address not modified"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ template void modify( const T& obj, uint64_t payer, Lambda&& updater ) { using namespace _multi_index_detail; @@ -751,12 +1886,104 @@ class multi_index }); } + /** + * Retrieves an existing object from a table using its primary key. + * @brief Retrieves an existing object from a table using its primary key. + * + * @param primary - Primary key value of the object + * @return A constant reference to the object containing the specified primary key. + * + * Exception - No object matches the given key + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(_self, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * auto user = addresses.get(N(dan)); + * eosio_assert(user.first_name == "Daniel", "Couldn't get him."); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const T& get( uint64_t primary, const char* error_msg = "unable to find key" )const { auto result = find( primary ); eosio_assert( result != cend(), error_msg ); return *result; } + /** + * Search for an existing object in a table using its primary key. + * @brief Search for an existing object in a table using its primary key. + * + * @param primary - Primary key value of the object + * @return An iterator to the found object which has a primary key equal to `primary` OR the `end` iterator of the referenced table if an object with primary key `primary` is not found. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(_self, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * auto itr = addresses.find(N(dan)); + * eosio_assert(itr != addresses.end(), "Couldn't get him."); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_iterator find( uint64_t primary )const { auto itr2 = std::find_if(_items_vector.rbegin(), _items_vector.rend(), [&](const item_ptr& ptr) { return ptr._item->primary_key() == primary; @@ -771,6 +1998,87 @@ class multi_index return iterator_to(static_cast(i)); } + /** + * Search for an existing object in a table using its primary key. + * @brief Search for an existing object in a table using its primary key. + * + * @param primary - Primary key value of the object + * @param error_msg - error message if an object with primary key `primary` is not found. + * @return An iterator to the found object which has a primary key equal to `primary` OR throws an exception if an object with primary key `primary` is not found. + */ + + const_iterator require_find( uint64_t primary, const char* error_msg = "unable to find key" )const { + auto itr2 = std::find_if(_items_vector.rbegin(), _items_vector.rend(), [&](const item_ptr& ptr) { + return ptr._item->primary_key() == primary; + }); + if( itr2 != _items_vector.rend() ) + return iterator_to(*(itr2->_item)); + + auto itr = db_find_i64( _code, _scope, TableName, primary ); + eosio_assert( itr >= 0, error_msg ); + + const item& i = load_object_by_primary_iterator( itr ); + return iterator_to(static_cast(i)); + } + + /** + * Remove an existing object from a table using its primary key. + * @brief Remove an existing object from a table using its primary key. + * + * @param itr - An iterator pointing to the object to be removed + * + * @pre itr points to an existing element + * @post The object is removed from the table and all associated storage is reclaimed. + * @post Secondary indices associated with the table are updated. + * @post The existing payer for storage usage of the object is refunded for the table and secondary indices usage of the removed object, and if the table and indices are removed, for the associated overhead. + * + * @return For the signature with `const_iterator`, returns a pointer to the object following the removed object. + * + * Exceptions: + * The object to be removed is not in the table. + * The action is not authorized to modify the table. + * The given iterator is invalid. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(_self, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * auto itr = addresses.find(N(dan)); + * eosio_assert(itr != addresses.end(), "Address for account not found"); + * addresses.erase( itr ); + * eosio_assert(itr != addresses.end(), "Address not erased properly"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ const_iterator erase( const_iterator itr ) { eosio_assert( itr != end(), "cannot pass end iterator to erase" ); @@ -782,6 +2090,63 @@ class multi_index return itr; } + /** + * Remove an existing object from a table using its primary key. + * @brief Remove an existing object from a table using its primary key. + * + * @param obj - Object to be removed + * + * @pre obj is an existing object in the table + * @post The object is removed from the table and all associated storage is reclaimed. + * @post Secondary indices associated with the table are updated. + * @post The existing payer for storage usage of the object is refunded for the table and secondary indices usage of the removed object, and if the table and indices are removed, for the associated overhead. + * + * Exceptions: + * The object to be removed is not in the table. + * The action is not authorized to modify the table. + * The given iterator is invalid. + * + * Example: + * + * @code + * #include + * using namespace eosio; + * using namespace std; + * class addressbook: contract { + * struct address { + * uint64_t account_name; + * string first_name; + * string last_name; + * string street; + * string city; + * string state; + * uint64_t primary_key() const { return account_name; } + * EOSLIB_SERIALIZE( address, (account_name)(first_name)(last_name)(street)(city)(state) ) + * }; + * public: + * addressbook(account_name self):contract(self) {} + * typedef eosio::multi_index< N(address), address > address_index; + * void myaction() { + * address_index addresses(_self, _self); // code, scope + * // add to table, first argument is account to bill for storage + * addresses.emplace(_self, [&](auto& address) { + * address.account_name = N(dan); + * address.first_name = "Daniel"; + * address.last_name = "Larimer"; + * address.street = "1 EOS Way"; + * address.city = "Blacksburg"; + * address.state = "VA"; + * }); + * auto itr = addresses.find(N(dan)); + * eosio_assert(itr != addresses.end(), "Record is not found"); + * addresses.erase(*itr); + * itr = addresses.find(N(dan)); + * eosio_assert(itr == addresses.end(), "Record is not deleted"); + * } + * } + * EOSIO_ABI( addressbook, (myaction) ) + * @endcode + */ void erase( const T& obj ) { using namespace _multi_index_detail; @@ -814,5 +2179,5 @@ class multi_index } }; - + /// @} } /// eosio diff --git a/libraries/eosiolib/optional.hpp b/libraries/eosiolib/optional.hpp index 77ec21dc6f..fb3a404658 100644 --- a/libraries/eosiolib/optional.hpp +++ b/libraries/eosiolib/optional.hpp @@ -3,16 +3,43 @@ #include namespace eosio { - + /** + * @defgroup optionaltype Optional Type + * @brief Defines otional type which is similar to boost::optional + * @ingroup types + * @{ + */ + + /** + * Provides stack-based nullable value similar to boost::optional + * + * @brief Provides stack-based nullable value similar to boost::optional + */ template class optional { public: typedef T value_type; typedef typename std::aligned_storage::type storage_type; - + + /** + * Default constructor + * + * @brief Construct a new optional object + */ optional():_valid(false){} + + /** + * Destructor + * + * @brief Destroy the optional object + */ ~optional(){ reset(); } + /** + * Construct a new optional object from another optional object + * + * @brief Construct a new optional object + */ optional( optional& o ) :_valid(false) { @@ -20,6 +47,11 @@ namespace eosio { _valid = o._valid; } + /** + * Copy constructor + * + * @brief Construct a new optional object + */ optional( const optional& o ) :_valid(false) { @@ -27,6 +59,11 @@ namespace eosio { _valid = o._valid; } + /** + * Move constructor + * + * @brief Construct a new optional object + */ optional( optional&& o ) :_valid(false) { @@ -35,6 +72,11 @@ namespace eosio { o.reset(); } + /** + * Construct a new optional object from another type of optional object + * + * @brief Construct a new optional object from another type of optional object + */ template optional( const optional& o ) :_valid(false) @@ -43,6 +85,11 @@ namespace eosio { _valid = o._valid; } + /** + * Construct a new optional object from another type of optional object + * + * @brief Construct a new optional object from another type of optional object + */ template optional( optional& o ) :_valid(false) @@ -54,6 +101,11 @@ namespace eosio { _valid = o._valid; } + /** + * Construct a new optional object from another type of optional object + * + * @brief Construct a new optional object from another type of optional object + */ template optional( optional&& o ) :_valid(false) @@ -63,6 +115,11 @@ namespace eosio { o.reset(); } + /** + * Construct a new optional object from another object + * + * @brief Construct a new optional object from another object + */ template optional( U&& u ) :_valid(true) @@ -70,6 +127,11 @@ namespace eosio { new ((char*)ptr()) T( std::forward(u) ); } + /** + * Construct a new optional object from another object + * + * @brief Construct a new optional object from another object + */ template optional& operator=( U&& u ) { @@ -79,6 +141,13 @@ namespace eosio { return *this; } + /** + * Construct the contained value in place + * + * @brief Construct the contained value in place + * @tparam Args - Type of the contained value + * @param args - The value to be assigned as contained value + */ template void emplace(Args&& ... args) { if (_valid) { @@ -89,6 +158,14 @@ namespace eosio { _valid = true; } + /** + * Assignment Operator + * + * @brief Assignment Operator + * @tparam U - Type of the contained value of the optional object to be assigned from + * @param o - The other optional object to be assigned from + * @return optional& - The reference to this object + */ template optional& operator=( optional& o ) { if (this != &o) { @@ -104,6 +181,14 @@ namespace eosio { return *this; } + /** + * Assignment Operator + * + * @brief Assignment Operator + * @tparam U - Type of the contained value of the optional object to be assigned from + * @param o - The other optional object to be assigned from + * @return optional& - The reference to this object + */ template optional& operator=( const optional& o ) { if (this != &o) { @@ -119,6 +204,13 @@ namespace eosio { return *this; } + /** + * Assignment Operator + * + * @brief Assignment Operator + * @param o - The other optional object to be assigned from + * @return optional& - The reference to this object + */ optional& operator=( optional& o ) { if (this != &o) { if( _valid && o._valid ) { @@ -133,6 +225,13 @@ namespace eosio { return *this; } + /** + * Assignment Operator + * + * @brief Assignment Operator + * @param o - The other optional object to be assigned from + * @return optional& - The reference to this object + */ optional& operator=( const optional& o ) { if (this != &o) { if( _valid && o._valid ) { @@ -147,6 +246,14 @@ namespace eosio { return *this; } + /** + * Assignment Operator + * + * @brief Assignment Operator + * @tparam U - Type of the contained value of the optional object to be assigned from + * @param o - The other optional object to be assigned from + * @return optional& - The reference to this object + */ template optional& operator=( optional&& o ) { @@ -165,6 +272,13 @@ namespace eosio { return *this; } + /** + * Assignment Operator + * + * @brief Assignment Operator + * @param o - The other optional object to be assigned from + * @return optional& - The reference to this object + */ optional& operator=( optional&& o ) { if (this != &o) @@ -182,33 +296,91 @@ namespace eosio { return *this; } + /** + * Check if this optional has valid contained value + * + * @brief Check if this optional has valid contained value + * @return true - if this optional has valid contained value + * @return false - otherwise + */ bool valid()const { return _valid; } + + /** + * Logical Negation operator + * + * @brief Logical Negation Operator + * @return true - if this optional has invalid contained value + * @return false - otherwise + */ bool operator!()const { return !_valid; } - // this operation is not safe and can result in unintential - // casts and comparisons, use valid() or !! + /** + * Similar to valid(). However, this operation is not safe and can result in unintential + * casts and comparisons, use valid() or !! + * + * @brief Check if this optional has valid contained value + * @return true - if this optional has valid contained value + * @return false - otherwise + */ explicit operator bool()const { return _valid; } + /** + * Get contained value of this optional + * + * @brief Pointer Dereference operator + * @return T& - Contained value + */ T& operator*() { eosio_assert(_valid, "dereference of empty optional"); return ref(); } + + /** + * Get contained value of this optional + * + * @brief Pointer Dereference operator + * @return T& - Contained value + */ const T& operator*()const { eosio_assert(_valid, "dereference of empty optional"); return ref(); } + /** + * Get pointer to the contained value + * + * @brief Member Access Through Pointer Operator + * @return T& - The pointer to the contained value + */ T* operator->() { eosio_assert(_valid, "dereference of empty optional"); return ptr(); } + + /** + * Get pointer to the contained value + * + * @brief Member Access Through Pointer Operator + * @return T& - The pointer to the contained value + */ const T* operator->()const { eosio_assert(_valid, "dereference of empty optional"); return ptr(); } + /** + * Assignment Operator with nullptr + * + * @brief Assignment Operator with nullptr + * @return optional& - The reference to this object + */ optional& operator=(std::nullptr_t) { reset(); return *this; } + /** + * Call the destructor fot he contained value and mark this optional as valid + * + * @brief Reset the optional object + */ void reset() { if( _valid ) { @@ -217,17 +389,45 @@ namespace eosio { _valid = false; } + /** + * Check if a contained value is less than b contained value + * + * @brief Less than operator + * @param a - First object to compare + * @param b - Second object to compare + * @return true - if a contained value is less than b contained value + * @return false - otherwise + */ friend bool operator < ( const optional a, optional b ) { if( a.valid() && b.valid() ) return *a < *b; return a.valid() < b.valid(); } + + /** + * Check if a contained value is equal to b contained value + * + * @brief Equality operator + * @param a - First object to compare + * @param b - Second object to compare + * @return true - if contained value is equal to b contained value + * @return false - otherwise + */ friend bool operator == ( const optional a, optional b ) { if( a.valid() && b.valid() ) return *a == *b; return a.valid() == b.valid(); } + /** + * Serialize an optional object + * + * @brief Serialize an optional object + * @param ds - The stream to write + * @param op - The value to serialize + * @tparam Stream - Type of datastream + * @return eosio::datastream& - Reference to the datastream + */ template friend inline eosio::datastream& operator>> (eosio::datastream& ds, optional& op) { @@ -240,6 +440,15 @@ namespace eosio { return ds; } + /** + * Deserialize an optional object + * + * @brief Deserialize an optional object + * @param ds - The stream to read + * @param op - The destination for deserialized value + * @tparam Stream - Type of datastream + * @return eosio::datastream& - Reference to the datastream + */ template friend inline eosio::datastream& operator<< (eosio::datastream& ds, const optional& op) { @@ -261,21 +470,66 @@ namespace eosio { }; + /** + * Check equality between two optional object that shares same type of contained value + * + * @brief Equality Operator + * @tparam T - Type of contained value of the optional objects + * @param left - First object to be compared + * @param right - Second object to be compared + * @return true - if both optional objects are equal + * @return false + */ template bool operator == ( const optional& left, const optional& right ) { return (!left == !right) || (!!left && *left == *right); } + + /** + * Check equality between an optional object with another object + * + * @brief Equality Operator + * @tparam T - Type of contained value of the optional object + * @tparam U - Type of the other object to be compared + * @param left - First object to be compared + * @param u - Second object to be compared + * @return true - if the optional objects contained value is equal with the compared object + * @return false + */ template bool operator == ( const optional& left, const U& u ) { return !!left && *left == u; } + + /** + * Check inequality between two optional object that shares same type of contained value + * + * @brief Inquality Operator + * @tparam T - Type of contained value of the optional objects + * @param left - First object to be compared + * @param right - Second object to be compared + * @return true - if both optional objects are unequal + * @return false + */ template bool operator != ( const optional& left, const optional& right ) { return (!left != !right) || (!!left && *left != *right); } + + /** + * Check inequality between an optional object with another object + * + * @brief Inqquality Operator + * @tparam T - Type of contained value of the optional object + * @tparam U - Type of the other object to be compared + * @param left - First object to be compared + * @param u - Second object to be compared + * @return true - if the optional objects contained value is unequal with the compared object + * @return false + */ template bool operator != ( const optional& left, const U& u ) { return !left || *left != u; } - +///@} optional } // namespace eosio diff --git a/libraries/eosiolib/print.h b/libraries/eosiolib/print.h index de5b481016..63fd1da9d5 100644 --- a/libraries/eosiolib/print.h +++ b/libraries/eosiolib/print.h @@ -11,14 +11,14 @@ extern "C" { #endif /** * @defgroup consoleapi Console API - * @brief Enables applications to log/print text messages + * @brief Defines APIs to log/print text messages * @ingroup contractdev * */ /** * @defgroup consolecapi Console C API - * @brief C API to log/print text messages + * @brief Defnes %C API to log/print text messages * @ingroup consoleapi * @{ */ @@ -29,6 +29,7 @@ extern "C" { * @param cstr - a null terminated string * * Example: +* * @code * prints("Hello World!"); // Output: Hello World! * @endcode @@ -42,6 +43,7 @@ extern "C" { * @param len - len of string to be printed * * Example: +* * @code * prints_l("Hello World!", 5); // Output: Hello * @endcode @@ -54,6 +56,7 @@ extern "C" { * @param value of 64 bit signed integer to be printed * * Example: +* * @code * printi(-1e+18); // Output: -1000000000000000000 * @endcode @@ -66,6 +69,7 @@ extern "C" { * @param value of 64 bit unsigned integer to be printed * * Example: +* * @code * printui(1e+18); // Output: 1000000000000000000 * @endcode @@ -78,6 +82,7 @@ extern "C" { * @param value is a pointer to the 128 bit signed integer to be printed * * Example: +* * @code * int128_t large_int(-87654323456); * printi128(&large_int); // Output: -87654323456 @@ -91,6 +96,7 @@ extern "C" { * @param value is a pointer to the 128 bit unsigned integer to be printed * * Example: +* * @code * uint128_t large_int(87654323456); * printui128(&large_int); // Output: 87654323456 @@ -104,6 +110,7 @@ extern "C" { * @param value of float to be printed * * Example: +* * @code * float value = 5.0 / 10.0; * printsf(value); // Output: 0.5 @@ -117,6 +124,7 @@ extern "C" { * @param value of double to be printed * * Example: +* * @code * double value = 5.0 / 10.0; * printdf(value); // Output: 0.5 @@ -130,6 +138,7 @@ extern "C" { * @param value is a pointer to the long double to be printed * * Example: +* * @code * long double value = 5.0 / 10.0; * printqf(value); // Output: 0.5 diff --git a/libraries/eosiolib/print.hpp b/libraries/eosiolib/print.hpp index bf7e5b07c0..a90a277cf4 100644 --- a/libraries/eosiolib/print.hpp +++ b/libraries/eosiolib/print.hpp @@ -15,6 +15,7 @@ namespace eosio { /** * Prints string + * * @brief Prints string * @param ptr - a null terminated string */ @@ -36,6 +37,7 @@ namespace eosio { /** * Prints signed integer + * * @brief Prints signed integer as a 64 bit signed integer * @param num to be printed */ @@ -45,6 +47,7 @@ namespace eosio { /** * Prints 32 bit signed integer + * * @brief Prints 32 bit signed integer as a 64 bit signed integer * @param num to be printed */ @@ -54,6 +57,7 @@ namespace eosio { /** * Prints 64 bit signed integer + * * @brief Prints 64 bit signed integer as a 64 bit signed integer * @param num to be printed */ @@ -64,6 +68,7 @@ namespace eosio { /** * Prints unsigned integer + * * @brief Prints unsigned integer as a 64 bit unsigned integer * @param num to be printed */ @@ -73,6 +78,7 @@ namespace eosio { /** * Prints 32 bit unsigned integer + * * @brief Prints 32 bit unsigned integer as a 64 bit unsigned integer * @param num to be printed */ @@ -82,6 +88,7 @@ namespace eosio { /** * Prints 64 bit unsigned integer + * * @brief Prints 64 bit unsigned integer as a 64 bit unsigned integer * @param num to be printed */ @@ -91,6 +98,7 @@ namespace eosio { /** * Prints 128 bit signed integer + * * @brief Prints 128 bit signed integer * @param num to be printed */ @@ -100,6 +108,7 @@ namespace eosio { /** * Prints 128 bit unsigned integer + * * @brief Prints 128 bit unsigned integer * @param num to be printed */ @@ -110,6 +119,7 @@ namespace eosio { /** * Prints single-precision floating point number + * * @brief Prints single-precision floating point number (i.e. float) * @param num to be printed */ @@ -117,6 +127,7 @@ namespace eosio { /** * Prints double-precision floating point number + * * @brief Prints double-precision floating point number (i.e. double) * @param num to be printed */ @@ -124,6 +135,7 @@ namespace eosio { /** * Prints quadruple-precision floating point number + * * @brief Prints quadruple-precision floating point number (i.e. long double) * @param num to be printed */ @@ -132,6 +144,7 @@ namespace eosio { /** * Prints fixed_key as a hexidecimal string + * * @brief Prints fixed_key as a hexidecimal string * @param val to be printed */ @@ -142,6 +155,12 @@ namespace eosio { printhex(static_cast(arr.data()), arr.size()); } + /** + * Prints fixed_key as a hexidecimal string + * + * @brief Prints fixed_key as a hexidecimal string + * @param val to be printed + */ template inline void print( fixed_key& val ) { print(static_cast&>(val)); @@ -149,6 +168,7 @@ namespace eosio { /** * Prints a 64 bit names as base32 encoded string + * * @brief Prints a 64 bit names as base32 encoded string * @param name 64 bit name to be printed */ @@ -156,39 +176,43 @@ namespace eosio { printn(name.value); } + /** + * Prints bool + * + * @brief Prints bool + * @param val to be printed + */ inline void print( bool val ) { prints(val?"true":"false"); } + /** + * Prints class object + * + * @brief Prints class object + * @param t to be printed + * @pre T must implements print() function + */ template inline void print( T&& t ) { t.print(); } - + /** + * Prints null terminated string + * + * @brief Prints null terminated string + * @param s null terminated string to be printed + */ inline void print_f( const char* s ) { prints(s); } - template - inline void print_f( const char* s, Arg val, Args... rest ) { - while ( *s != '\0' ) { - if ( *s == '%' ) { - print( val ); - print_f( s+1, rest... ); - return; - } - prints_l( s, 1 ); - s++; - } - } - - - /** - * @defgroup consoleCppapi Console C++ API + /** + * @defgroup consolecppapi Console C++ API * @ingroup consoleapi - * @brief C++ wrapper for Console C API + * @brief Defines C++ wrapper to log/print text messages * * This API uses C++ variadic templates and type detection to * make it easy to print any native type. You can even overload @@ -208,13 +232,43 @@ namespace eosio { * @{ */ + + /** + * Prints formatted string. It behaves similar to C printf/ + * + * @brief Prints formatted string + * @tparam Arg - Type of the value used to replace the format specifier + * @tparam Args - Type of the value used to replace the format specifier + * @param s - Null terminated string with to be printed (it can contains format specifier) + * @param val - The value used to replace the format specifier + * @param rest - The values used to replace the format specifier + * + * Example: + * @code + * print_f("Number of apples: %", 10); + * @endcode + */ + template + inline void print_f( const char* s, Arg val, Args... rest ) { + while ( *s != '\0' ) { + if ( *s == '%' ) { + print( val ); + print_f( s+1, rest... ); + return; + } + prints_l( s, 1 ); + s++; + } + } + /** - * Print out value / list of values (except double) + * Print out value / list of values * @brief Print out value / list of values - * @param a Value to be printed - * @param args Other values to be printed + * @param a - The value to be printed + * @param args - The other values to be printed * * Example: +* * @code * const char *s = "Hello World!"; * uint64_t unsigned_64_bit_int = 1e+18; @@ -238,10 +292,12 @@ namespace eosio { /** * Overload c++ iostream * @brief Overload c++ iostream - * @param out Output strem - * @param v Value to be printed + * @param out - Output strem + * @param v - The value to be printed + * @return iostream& - Reference to the input output stream * * Example: +* * @code * const char *s = "Hello World!"; * uint64_t unsigned_64_bit_int = 1e+18; @@ -259,7 +315,7 @@ namespace eosio { static iostream cout; - /// @} consoleCppapi + /// @} consolecppapi } diff --git a/libraries/eosiolib/privileged.h b/libraries/eosiolib/privileged.h index f55676ba55..ce6f1403fe 100644 --- a/libraries/eosiolib/privileged.h +++ b/libraries/eosiolib/privileged.h @@ -13,15 +13,33 @@ extern "C" { /** * @defgroup privilegedcapi Privileged C API * @ingroup privilegedapi - * @brief Define C Privileged API + * @brief Defines %C Privileged API * * @{ */ + /** + * @brief Get the resource limits of an account + * Get the resource limits of an account + * @param account - name of the account whose resource limit to get + * @param ram_bytes - pointer to `int64_t` to hold retrieved ram limit in absolute bytes + * @param net_weight - pointer to `int64_t` to hold net limit + * @param cpu_weight - pointer to `int64_t` to hold cpu limit + */ + void get_resource_limits( account_name account, int64_t* ram_bytes, int64_t* net_weight, int64_t* cpu_weight ); + + /** + * @brief Set the resource limits of an account + * Set the resource limits of an account + * @param account - name of the account whose resource limit to be set + * @param ram_bytes - ram limit in absolute bytes + * @param net_weight - fractionally proportionate net limit of available resources based on (weight / total_weight_of_all_accounts) + * @param cpu_weight - fractionally proportionate cpu limit of available resources based on (weight / total_weight_of_all_accounts) + */ void set_resource_limits( account_name account, int64_t ram_bytes, int64_t net_weight, int64_t cpu_weight ); /** - * Propose the new active producer schedule + * Proposes a schedule change, once the block that contains the proposal becomes irreversible, the schedule is promoted to "pending" automatically. Once the block that promotes the schedule is irreversible, the schedule will become "active" * @param producer_data - packed data of produce_keys in the appropriate producer schedule order * @param producer_data_size - size of the data buffer * @@ -29,19 +47,56 @@ extern "C" { */ int64_t set_proposed_producers( char *producer_data, uint32_t producer_data_size ); + /** + * @brief Set new active producers + * Set new active producers. Producers will only be activated once the block which starts the next round is irrreversible + * @param producer_data - pointer to producer schedule packed as bytes + * @param producer_data_size - size of the packed producer schedule + * @pre `producer_data` is a valid pointer to a range of memory at least `producer_data_size` bytes long that contains serialized produced schedule data + */ + void set_active_producers( char *producer_data, uint32_t producer_data_size ); + /** + * @brief Check if an account is privileged + * Check if an account is privileged + * @param account - name of the account to be checked + * @return true if the account is privileged + * @return false if the account is not privileged + */ bool is_privileged( account_name account ); + /** + * @brief Set the privileged status of an account + * Set the privileged status of an account + * @param account - name of the account whose privileged account to be set + * @param is_priv - privileged status + */ void set_privileged( account_name account, bool is_priv ); + /** + * @brief Set the blockchain parameters + * Set the blockchain parameters + * @param data - pointer to blockchain parameters packed as bytes + * @param datalen - size of the packed blockchain parameters + * @pre `data` is a valid pointer to a range of memory at least `datalen` bytes long that contains packed blockchain params data + */ void set_blockchain_parameters_packed(char* data, uint32_t datalen); /** + * @brief Retrieve the blolckchain parameters * Retrieve the blolckchain parameters * @param data - output buffer of the blockchain parameters, only retrieved if sufficent size to hold packed data. * @param datalen - size of the data buffer, 0 to report required size. + * @return size of the blockchain parameters + * @pre `data` is a valid pointer to a range of memory at least `datalen` bytes long + * @post `data` is filled with packed blockchain parameters */ uint32_t get_blockchain_parameters_packed(char* data, uint32_t datalen); + /** + * @brief Activate new feature + * Activate new feature + * @param f - name (identifier) of the feature to be activated + */ void activate_feature( int64_t f ); ///@ } privilegedcapi diff --git a/libraries/eosiolib/privileged.hpp b/libraries/eosiolib/privileged.hpp index d89f10f08b..3091acf8b3 100644 --- a/libraries/eosiolib/privileged.hpp +++ b/libraries/eosiolib/privileged.hpp @@ -5,27 +5,96 @@ namespace eosio { + /** + * @defgroup privilegedcppapi Privileged C++ API + * @ingroup privilegedapi + * @brief Defines C++ Privileged API + * + * @{ + */ + + /** + * Tunable blockchain configuration that can be changed via consensus + * + * @brief Tunable blockchain configuration that can be changed via consensus + */ struct blockchain_parameters { + uint64_t max_block_net_usage; + uint32_t target_block_net_usage_pct; + uint32_t max_transaction_net_usage; + + /** + * The base amount of net usage billed for a transaction to cover incidentals + * @brief The base amount of net usage billed for a transaction to cover incidentals + */ uint32_t base_per_transaction_net_usage; + uint32_t net_usage_leeway; + uint32_t context_free_discount_net_usage_num; + uint32_t context_free_discount_net_usage_den; uint32_t max_block_cpu_usage; + uint32_t target_block_cpu_usage_pct; + uint32_t max_transaction_cpu_usage; + uint32_t min_transaction_cpu_usage; + + /** + * The numerator for the discount on cpu usage for CFA's + * + * @brief The numerator for the discount on cpu usage for CFA's + */ + uint64_t context_free_discount_cpu_usage_num; + + /** + * The denominator for the discount on cpu usage for CFA's + * + * @brief The denominator for the discount on cpu usage for CFA's + + */ + uint64_t context_free_discount_cpu_usage_den; + + /** + * Maximum lifetime of a transacton + * + * @brief Maximum lifetime of a transacton + */ uint32_t max_transaction_lifetime; + uint32_t deferred_trx_expiration_window; + uint32_t max_transaction_delay; + + /** + * Maximum size of inline action + * + * @brief Maximum size of inline action + */ uint32_t max_inline_action_size; + + /** + * Maximum depth of inline action + * + * @brief Maximum depth of inline action + */ uint16_t max_inline_action_depth; + + /** + * Maximum authority depth + * + * @brief Maximum authority depth + */ uint16_t max_authority_depth; + EOSLIB_SERIALIZE( blockchain_parameters, (max_block_net_usage)(target_block_net_usage_pct) (max_transaction_net_usage)(base_per_transaction_net_usage)(net_usage_leeway) @@ -39,13 +108,50 @@ namespace eosio { ) }; + /** + * @brief Set the blockchain parameters + * Set the blockchain parameters + * @param params - New blockchain parameters to set + */ void set_blockchain_parameters(const eosio::blockchain_parameters& params); + /** + * @brief Retrieve the blolckchain parameters + * Retrieve the blolckchain parameters + * @param params - It will be replaced with the retrieved blockchain params + */ void get_blockchain_parameters(eosio::blockchain_parameters& params); + ///@} priviledgedcppapi + + /** + * @defgroup producertype Producer Type + * @ingroup types + * @brief Defines producer type + * + * @{ + */ + + /** + * Maps producer with its signing key, used for producer schedule + * + * @brief Maps producer with its signing key + */ struct producer_key { - account_name producer_name; - public_key block_signing_key; + + /** + * Name of the producer + * + * @brief Name of the producer + */ + account_name producer_name; + + /** + * Block signing key used by this producer + * + * @brief Block signing key used by this producer + */ + public_key block_signing_key; friend bool operator < ( const producer_key& a, const producer_key& b ) { return a.producer_name < b.producer_name; @@ -53,5 +159,4 @@ namespace eosio { EOSLIB_SERIALIZE( producer_key, (producer_name)(block_signing_key) ) }; - } diff --git a/libraries/eosiolib/producer_schedule.hpp b/libraries/eosiolib/producer_schedule.hpp index d1b9dd7f5d..8fd2a26c97 100644 --- a/libraries/eosiolib/producer_schedule.hpp +++ b/libraries/eosiolib/producer_schedule.hpp @@ -4,11 +4,27 @@ #include namespace eosio { + /** * Defines both the order, account name, and signing keys of the active set of producers. + * + * @brief Defines both the order, account name, and signing keys of the active set of producers. */ struct producer_schedule { - uint32_t version; ///< sequentially incrementing version number + /** + * Version number of the schedule. It is sequentially incrementing version number + * + * @brief Version number of the schedule + */ + uint32_t version; + + /** + * List of producers for this schedule, including its signing key + * + * @brief List of producers for this schedule, including its signing key + */ std::vector producers; }; + + /// @} producertype } /// namespace eosio diff --git a/libraries/eosiolib/public_key.hpp b/libraries/eosiolib/public_key.hpp index 414d535bed..e7061ef74c 100644 --- a/libraries/eosiolib/public_key.hpp +++ b/libraries/eosiolib/public_key.hpp @@ -3,8 +3,31 @@ #include namespace eosio { + + /** + * @defgroup publickeytype Public Key Type + * @ingroup types + * @brief Specifies public key type + * + * @{ + */ + + /** + * EOSIO Public Key + * @brief EOSIO Public Key + */ struct public_key { + /** + * Type of the public key, could be either K1 or R1 + * @brief Type of the public key + */ unsigned_int type; + + /** + * Bytes of the public key + * + * @brief Bytes of the public key + */ std::array data; friend bool operator == ( const public_key& a, const public_key& b ) { @@ -15,4 +38,7 @@ namespace eosio { } EOSLIB_SERIALIZE( public_key, (type)(data) ) }; + } + +/// @} publickeytype diff --git a/libraries/eosiolib/reflect.hpp b/libraries/eosiolib/reflect.hpp index 9b83852f8e..bea480ffc6 100644 --- a/libraries/eosiolib/reflect.hpp +++ b/libraries/eosiolib/reflect.hpp @@ -66,9 +66,15 @@ void eosio::reflector::visit( Visitor&& v ) { \ /** - * @def EOSLIB_REFLECT(TYPE,MEMBERS) + * @addtogroup serializecpp + * @{ + */ + +/** + * Perform class reflection + * * @brief Specializes eosio::reflector for TYPE - * + * @param TYPE - the class template to be reflected * @param MEMBERS - a sequence of member names. (field1)(field2)(field3) * * @see EOSLIB_REFLECT_DERIVED @@ -76,13 +82,32 @@ void eosio::reflector::visit( Visitor&& v ) { \ #define EOSLIB_REFLECT( TYPE, MEMBERS ) \ EOSLIB_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) +/** + * Perform class template reflection + * + * @brief Perform class template reflection + * @param TEMPLATE_ARGS - a sequence of template args. (args1)(args2)(args3) + * @param TYPE - the class template to be reflected + * @param MEMBERS - a sequence of member names. (field1)(field2)(field3) + */ #define EOSLIB_REFLECT_TEMPLATE( TEMPLATE_ARGS, TYPE, MEMBERS ) \ EOSLIB_REFLECT_DERIVED_TEMPLATE( TEMPLATE_ARGS, TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) +/** + * Perform class reflection on empty class + * + * @brief Perform class reflection on empty class + * @param TYPE - the class to be reflected + */ #define EOSLIB_REFLECT_EMPTY( TYPE ) \ EOSLIB_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, BOOST_PP_SEQ_NIL ) - +/** + * Perform forward declaration of class reflection + * + * @brief Perform forward declaration of class reflection + * @param TYPE - the class to be reflected + */ #define EOSLIB_REFLECT_FWD( TYPE ) \ namespace eosio { \ template<> struct reflector {\ @@ -97,6 +122,7 @@ namespace eosio { \ template static void visit( type& t, Visitor&& v ); \ }; } +///@} #define EOSLIB_REFLECT_DERIVED_IMPL( TYPE, MEMBERS ) \ EOSLIB_REFLECT_IMPL_DERIVED_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) @@ -105,13 +131,18 @@ namespace eosio { \ EOSLIB_REFLECT_DERIVED_IMPL_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) +/** + * @addtogroup serializecpp + * @{ + */ /** - * @def EOSLIB_REFLECT_DERIVED(TYPE,INHERITS,MEMBERS) + * Perform class reflection where TYPE inherits other reflected classes * * @brief Specializes eosio::reflector for TYPE where * type inherits other reflected classes - * + * + * @param TYPE - the class to be reflected * @param INHERITS - a sequence of base class names (basea)(baseb)(basec) * @param MEMBERS - a sequence of member names. (field1)(field2)(field3) */ @@ -127,6 +158,17 @@ template<> struct reflector {\ }; \ EOSLIB_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \ }; } + +/** + * Perform class template reflection where TYPE inherits other reflected classes + * + * @brief Perform class template reflection where TYPE inherits other reflected classes + * + * @param TEMPLATE_ARGS - a sequence of template args. (args1)(args2)(args3) + * @param TYPE - the class to be reflected + * @param INHERITS - a sequence of base class names (basea)(baseb)(basec) + * @param MEMBERS - a sequence of member names. (field1)(field2)(field3) + */ #define EOSLIB_REFLECT_DERIVED_TEMPLATE( TEMPLATE_ARGS, TYPE, INHERITS, MEMBERS ) \ namespace eosio { \ template struct reflector {\ @@ -139,3 +181,6 @@ template struct reflector {\ }; \ EOSLIB_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \ }; } + + +///@} diff --git a/libraries/eosiolib/serialize.hpp b/libraries/eosiolib/serialize.hpp index 0cc9a04026..eff10d3cc6 100644 --- a/libraries/eosiolib/serialize.hpp +++ b/libraries/eosiolib/serialize.hpp @@ -8,12 +8,24 @@ OP t.elem /** - * @def EOSLIB_SERIALIZE(TYPE,MEMBERS) + * @defgroup serialize Serialize API + * @brief Defines functions to serialize and deserialize object + * @ingroup contractdev + */ + +/** + * @defgroup serializecpp Serialize C++ API + * @brief Defines C++ API to serialize and deserialize object + * @ingroup serialize + * @{ + */ + +/** + * Defines serialization and deserialization for a class * - * @brief Specializes eosio::reflector for TYPE where - * type inherits other reflected classes + * @brief Defines serialization and deserialization for a class * - * @param INHERITS - a sequence of base class names (basea)(baseb)(basec) + * @param TYPE - the class to have its serialization and deserialization defined * @param MEMBERS - a sequence of member names. (field1)(field2)(field3) */ #define EOSLIB_SERIALIZE( TYPE, MEMBERS ) \ @@ -26,7 +38,17 @@ return ds BOOST_PP_SEQ_FOR_EACH( EOSLIB_REFLECT_MEMBER_OP, >>, MEMBERS );\ } - +/** + * Defines serialization and deserialization for a class which inherits from other classes that + * have their serialization and deserialization defined + * + * @brief Defines serialization and deserialization for a class which inherits from other classes that + * have their serialization and deserialization defined + * + * @param TYPE - the class to have its serialization and deserialization defined + * @param BASE - a sequence of base class names (basea)(baseb)(basec) + * @param MEMBERS - a sequence of member names. (field1)(field2)(field3) + */ #define EOSLIB_SERIALIZE_DERIVED( TYPE, BASE, MEMBERS ) \ template \ friend DataStream& operator << ( DataStream& ds, const TYPE& t ){ \ @@ -38,3 +60,4 @@ ds >> static_cast(t); \ return ds BOOST_PP_SEQ_FOR_EACH( EOSLIB_REFLECT_MEMBER_OP, >>, MEMBERS );\ } +///@} serializecpp diff --git a/libraries/eosiolib/singleton.hpp b/libraries/eosiolib/singleton.hpp index b913d963a5..48e75126ed 100644 --- a/libraries/eosiolib/singleton.hpp +++ b/libraries/eosiolib/singleton.hpp @@ -4,19 +4,48 @@ namespace eosio { + /** + * @defgroup singleton Singleton Table + * @brief Defines EOSIO Singleton Table + * @ingroup databasecpp + * @{ + */ + /** * This wrapper uses a single table to store named objects various types. * - * @tparam SingletonName - the name of this singlton variable + * @tparam SingletonName - the name of this singleton variable * @tparam T - the type of the singleton */ template class singleton { + /** + * Primary key of the data inside singleton table + * + * @brief Primary key of the data singleton table + */ constexpr static uint64_t pk_value = SingletonName; + + /** + * Structure of data inside the singleton table + * + * @brief Structure of data inside the singleton table + */ struct row { + /** + * Value to be stored inside the singleton table + * + * @brief Value to be stored inside the singleton table + */ T value; + /** + * Get primary key of the data + * + * @brief Get primary key of the data + * @return uint64_t - Primary Key + */ uint64_t primary_key() const { return pk_value; } EOSLIB_SERIALIZE( row, (value) ) @@ -26,29 +55,72 @@ namespace eosio { public: + /** + * Construct a new singleton object given the table's owner and the scope + * + * @brief Construct a new singleton object + * @param code - The table's owner + * @param scope - The scope of the table + */ singleton( account_name code, scope_name scope ) : _t( code, scope ) {} + /** + * Check if the singleton table exists + * + * @brief Check if the singleton table exists + * @return true - if exists + * @return false - otherwise + */ bool exists() { return _t.find( pk_value ) != _t.end(); } + /** + * Get the value stored inside the singleton table. Will throw an exception if it doesn't exist + * + * @brief Get the value stored inside the singleton table + * @return T - The value stored + */ T get() { auto itr = _t.find( pk_value ); eosio_assert( itr != _t.end(), "singleton does not exist" ); return itr->value; } + /** + * Get the value stored inside the singleton table. If it doesn't exist, it will return the specified default value + * + * @brief Get the value stored inside the singleton table or return the specified default value if it doesn't exist + * @param def - The default value to be returned in case the data doesn't exist + * @return T - The value stored + */ T get_or_default( const T& def = T() ) { auto itr = _t.find( pk_value ); return itr != _t.end() ? itr->value : def; } + /** + * Get the value stored inside the singleton table. If it doesn't exist, it will create a new one with the specified default value + * + * @brief Get the value stored inside the singleton table or create a new one with the specified default value if it doesn't exist + * @param bill_to_account - The account to bill for the newly created data if the data doesn't exist + * @param def - The default value to be created in case the data doesn't exist + * @return T - The value stored + */ T get_or_create( account_name bill_to_account, const T& def = T() ) { auto itr = _t.find( pk_value ); return itr != _t.end() ? itr->value : _t.emplace(bill_to_account, [&](row& r) { r.value = def; })->value; } + /** + * Set new value to the singleton table + * + * @brief Set new value to the singleton table + * + * @param value - New value to be set + * @param bill_to_account - Account to pay for the new value + */ void set( const T& value, account_name bill_to_account ) { auto itr = _t.find( pk_value ); if( itr != _t.end() ) { @@ -58,6 +130,11 @@ namespace eosio { } } + /** + * Remove the only data inside singleton table + * + * @brief Remove the only data inside singleton table + */ void remove( ) { auto itr = _t.find( pk_value ); if( itr != _t.end() ) { @@ -69,4 +146,5 @@ namespace eosio { table _t; }; +/// @} singleton } /// namespace eosio diff --git a/libraries/eosiolib/symbol.hpp b/libraries/eosiolib/symbol.hpp index b679f9d4fe..8e63a0f18e 100644 --- a/libraries/eosiolib/symbol.hpp +++ b/libraries/eosiolib/symbol.hpp @@ -8,6 +8,25 @@ namespace eosio { + /** + * @defgroup symbolapi Symbol API + * @brief Defines API for managing symbols + * @ingroup contractdev + */ + + /** + * @defgroup symbolcppapi Symbol CPP API + * @brief Defines %CPP API for managing symbols + * @ingroup symbolapi + * @{ + */ + + /** + * Converts string to uint64_t representation of symbol + * + * @param precision - precision of symbol + * @param str - the string representation of the symbol + */ static constexpr uint64_t string_to_symbol( uint8_t precision, const char* str ) { uint32_t len = 0; while( str[len] ) ++len; @@ -25,10 +44,25 @@ namespace eosio { return result; } + /** + * Macro for converting string to char representation of symbol + * + * @param precision - precision of symbol + * @param str - the string representation of the symbol + */ #define S(P,X) ::eosio::string_to_symbol(P,#X) + /** + * uint64_t representation of a symbol name + */ typedef uint64_t symbol_name; + /** + * Checks if provided symbol name is valid. + * + * @param sym - symbol name of type symbol_name + * @return true - if symbol is valid + */ static constexpr bool is_valid_symbol( symbol_name sym ) { sym >>= 8; for( int i = 0; i < 7; ++i ) { @@ -46,29 +80,71 @@ namespace eosio { return true; } - static constexpr uint32_t symbol_name_length( symbol_name tmp ) { - tmp >>= 8; /// skip precision + /** + * Returns the character length of the provided symbol + * + * @param sym - symbol to retrieve length for (uint64_t) + * @return length - character length of the provided symbol + */ + static constexpr uint32_t symbol_name_length( symbol_name sym ) { + sym >>= 8; /// skip precision uint32_t length = 0; - while( tmp & 0xff && length <= 7) { + while( sym & 0xff && length <= 7) { ++length; - tmp >>= 8; + sym >>= 8; } return length; } + /** + * \struct Stores information about a symbol + * + * @brief Stores information about a symbol + */ struct symbol_type { + /** + * The symbol name + */ symbol_name value; symbol_type() { } + + /** + * What is the type of the symbol + */ symbol_type(symbol_name s): value(s) { } + + /** + * Is this symbol valid + */ bool is_valid()const { return is_valid_symbol( value ); } + + /** + * This symbol's precision + */ uint64_t precision()const { return value & 0xff; } + + /** + * Returns uint64_t representation of symbol name + */ uint64_t name()const { return value >> 8; } + + /** + * The length of this symbol + */ uint32_t name_length()const { return symbol_name_length( value ); } + /** + * + */ operator symbol_name()const { return value; } + /** + * %Print the symbol + * + * @brief %Print the symbol + */ void print(bool show_precision=true)const { if( show_precision ){ ::eosio::print(precision()); @@ -88,25 +164,64 @@ namespace eosio { EOSLIB_SERIALIZE( symbol_type, (value) ) }; + /** + * \struct Extended asset which stores the information of the owner of the symbol + * + */ struct extended_symbol : public symbol_type { - extended_symbol( symbol_name s = 0, account_name c = 0 ):symbol_type{s},contract(c){} - - account_name contract; - + /** + * The owner of the symbol + * + * @brief The owner of the symbol + */ + account_name contract; + + extended_symbol( symbol_name sym = 0, account_name acc = 0 ):symbol_type{sym},contract(acc){} + + /** + * %Print the extended symbol + * + * @brief %Print the extended symbol + */ void print()const { symbol_type::print(); prints("@"); printn( contract ); } + + /** + * Equivalency operator. Returns true if a == b (are the same) + * + * @brief Subtraction operator + * @param a - The extended asset to be subtracted + * @param b - The extended asset used to subtract + * @return boolean - true if both provided symbols are the same + */ friend bool operator == ( const extended_symbol& a, const extended_symbol& b ) { return std::tie( a.value, a.contract ) == std::tie( b.value, b.contract ); } + + /** + * Inverted equivalency operator. Returns true if a != b (are different) + * + * @brief Subtraction operator + * @param a - The extended asset to be subtracted + * @param b - The extended asset used to subtract + * @return boolean - true if both provided symbols are the same + */ friend bool operator != ( const extended_symbol& a, const extended_symbol& b ) { return std::tie( a.value, a.contract ) != std::tie( b.value, b.contract ); } + + friend bool operator < ( const extended_symbol& a, const extended_symbol& b ) { + return std::tie( a.value, a.contract ) < std::tie( b.value, b.contract ); + } + EOSLIB_SERIALIZE( extended_symbol, (value)(contract) ) }; + // }@ symbolapi + } /// namespace eosio diff --git a/libraries/eosiolib/system.h b/libraries/eosiolib/system.h index dbdd84b855..b7b39dfa5a 100644 --- a/libraries/eosiolib/system.h +++ b/libraries/eosiolib/system.h @@ -10,14 +10,14 @@ extern "C" { /** * @defgroup systemapi System API * @ingroup contractdev - * @brief Define API for interacting with system level intrinsics + * @brief Defines API for interacting with system level intrinsics * */ /** * @defgroup systemcapi System C API * @ingroup systemapi - * @brief Define API for interacting with system level intrinsics + * @brief Defines API for interacting with system level intrinsics * * @{ */ @@ -26,6 +26,14 @@ extern "C" { * Aborts processing of this action and unwinds all pending changes if the test condition is true * @brief Aborts processing of this action and unwinds all pending changes * @param test - 0 to abort, 1 to ignore + * + * Example: +* + * @code + * eosio_assert(1 == 2, "One is not equal to two."); + * eosio_assert(1 == 1, "One is not equal to one."); + * @endcode + * * @param msg - a null terminated string explaining the reason for failure */ void eosio_assert( uint32_t test, const char* msg ); @@ -44,13 +52,21 @@ extern "C" { * @brief Aborts processing of this action and unwinds all pending changes * @param test - 0 to abort, 1 to ignore * @param code - the error code - */ void eosio_assert_code( uint32_t test, uint64_t code ); - /** - * This method will abort execution of wasm without failing the contract. This - * is used to bypass all cleanup / destructors that would normally be called. + /** + * This method will abort execution of wasm without failing the contract. This is used to bypass all cleanup / destructors that would normally be called. + * @brief Aborts execution of wasm without failing the contract + * @param code - the exit code + * Example: +* + * @code + * eosio_exit(0); + * eosio_exit(1); + * eosio_exit(2); + * eosio_exit(3); + * @endcode */ [[noreturn]] void eosio_exit( int32_t code ); @@ -67,8 +83,10 @@ extern "C" { * @brief Get time (rounded down to the nearest second) of the current block (i.e. the block including this action) * @return time in seconds from 1970 of the current block */ - uint32_t now(); - + inline uint32_t now() { + return (uint32_t)( current_time() / 1000000 ); + } ///@ } systemcapi + } diff --git a/libraries/eosiolib/transaction.h b/libraries/eosiolib/transaction.h index bb29f159ad..99e1d3c2c4 100644 --- a/libraries/eosiolib/transaction.h +++ b/libraries/eosiolib/transaction.h @@ -7,21 +7,10 @@ extern "C" { /** - * @defgroup transactionapi transaction API + * @defgroup transactionapi Transaction API * @ingroup contractdev - * @brief Define API for sending transactions and inline messages + * @brief Defines API for sending transactions and inline actions * - * A EOS.IO transaction has the following abstract structure: - * - * ``` - * struct transaction { - * Name scope[]; ///< accounts whose data may be read or written - * Name readScope[]; ///< accounts whose data may be read - * message messages[]; ///< accounts that have approved this message - * }; - * ``` - * - * This API enables your contract to construct and send transactions * * Deferred transactions will not be processed until a future block. They * can therefore have no effect on the success of failure of their parent @@ -37,16 +26,11 @@ extern "C" { * which is processed immediately after the current message's processing * ends such that the success or failure of the parent transaction is * dependent on the success of the message. If an inline message fails in - * processing then the whole tree of transactions and messages rooted in the + * processing then the whole tree of transactions and actions rooted in the * block will me marked as failing and none of effects on the database will * persist. * - * Because of this and the parallel nature of transaction application, - * inline messages may not affect any `scope` which is not listed in - * their parent transaction's `scope`. They also may not read any `scope` - * not listed in either their parent transaction's `scope` or `readScope`. - * - * Inline messages and Deferred transactions must adhere to the permissions + * Inline actions and Deferred transactions must adhere to the permissions * available to the parent transaction or, in the future, delegated to the * contract account for future use. */ @@ -54,21 +38,48 @@ extern "C" { /** * @defgroup transactioncapi Transaction C API * @ingroup transactionapi - * @brief Define API for sending transactions + * @brief Defines API for sending transactions * * @{ */ - void send_deferred(const uint128_t& sender_id, account_name payer, const char *serialized_transaction, size_t size, uint32_t replace_existing = 0); - /** - * cancel deferred transaction - * @return 1 if transaction was canceled, 0 if transaction was not found - */ + /** + * Sends a deferred transaction. + * + * @brief Sends a deferred transaction. + * @param sender_id - ID of sender + * @param payer - Account paying for RAM + * @param serialized_transaction - Pointer of serialized transaction to be deferred + * @param size - Size to reserve + * @param replace_existing - f this is `0` then if the provided sender_id is already in use by an in-flight transaction from this contract, which will be a failing assert. If `1` then transaction will atomically cancel/replace the inflight transaction + */ + void send_deferred(const uint128_t& sender_id, account_name payer, const char *serialized_transaction, size_t size, uint32_t replace_existing = 0); + + /** + * Cancels a deferred transaction. + * + * @brief Cancels a deferred transaction. + * @param sender_id - The id of the sender + * + * @pre The deferred transaction ID exists. + * @pre The deferred transaction ID has not yet been published. + * @post Deferred transaction canceled. + * + * @return 1 if transaction was canceled, 0 if transaction was not found + * + * Example: +* + * @code + * id = 0xffffffffffffffff + * cancel_deferred( id ); + * @endcode + */ int cancel_deferred(const uint128_t& sender_id); /** - * access a copy of the currently executing transaction + * Access a copy of the currently executing transaction. * + * @brief Access a copy of the currently executing transaction. * @param buffer - a buffer to write the current transaction to * @param size - the size of the buffer, 0 to return required size * @return the size of the transaction written to the buffer, or number of bytes that can be copied if size==0 passed @@ -76,28 +87,54 @@ extern "C" { size_t read_transaction(char *buffer, size_t size); /** - * get the size of the currently executing transaction + * Gets the size of the currently executing transaction. + * + * @brief Gets the size of the currently executing transaction. + * @return size of the currently executing transaction */ size_t transaction_size(); /** - * get the block number used for TAPOS on the currently executing transaction + * Gets the block number used for TAPOS on the currently executing transaction. * + * @brief Gets the block number used for TAPOS on the currently executing transaction. + * @return block number used for TAPOS on the currently executing transaction + * Example: + * @code + * int tbn = tapos_block_num(); + * @endcode */ int tapos_block_num(); /** - * get the block prefix used for TAPOS on the currently executing transaction + * Gets the block prefix used for TAPOS on the currently executing transaction. + * + * @brief Gets the block prefix used for TAPOS on the currently executing transaction. + * @return block prefix used for TAPOS on the currently executing transaction + * Example: + * @code + * int tbp = tapos_block_prefix(); + * @endcode */ int tapos_block_prefix(); /** - * get the expiration of the currently executing transaction + * Gets the expiration of the currently executing transaction. + * + * @brief Gets the expiration of the currently executing transaction. + * @return expiration of the currently executing transaction + * Example: + * @code + * time tm = expiration(); + * eosio_print(tm); + * @endcode */ time expiration(); /** - * Retrieve the indicated action from the active transaction. + * Retrieves the indicated action from the active transaction. + * + * @brief Retrieves the indicated action from the active transaction. * @param type - 0 for context free action, 1 for action * @param index - the index of the requested action * @param buff - output packed buff of the action @@ -108,6 +145,8 @@ extern "C" { /** * Retrieve the signed_transaction.context_free_data[index]. + * + * @brief Retrieve the signed_transaction.context_free_data[index]. * @param index - the index of the context_free_data entry to retrieve * @param buff - output buff of the context_free_data entry * @param size - amount of context_free_data[index] to retrieve into buff, 0 to report required size diff --git a/libraries/eosiolib/transaction.hpp b/libraries/eosiolib/transaction.hpp index 362fd2fafb..1586b92b09 100644 --- a/libraries/eosiolib/transaction.hpp +++ b/libraries/eosiolib/transaction.hpp @@ -54,6 +54,12 @@ namespace eosio { EOSLIB_SERIALIZE_DERIVED( transaction, transaction_header, (context_free_actions)(actions)(transaction_extensions) ) }; + /** + * + * + * + * + */ struct onerror { uint128_t sender_id; bytes sent_trx; diff --git a/libraries/eosiolib/types.h b/libraries/eosiolib/types.h index 095e7fb33d..32448f9914 100644 --- a/libraries/eosiolib/types.h +++ b/libraries/eosiolib/types.h @@ -14,43 +14,101 @@ extern "C" { /** * @defgroup types Builtin Types * @ingroup contractdev - * @brief Specifies typedefs and aliases + * @brief Specifies builtin types, typedefs and aliases * * @{ */ +/** + * @brief Name of an account + * @details Name of an account + */ typedef uint64_t account_name; + +/** + * @brief Name of a permission + * @details Name of an account + */ typedef uint64_t permission_name; + +/** + * @brief Name of a table + * @details Name of atable + */ typedef uint64_t table_name; + +/** + * @brief Time + * @details Time + */ typedef uint32_t time; + +/** + * @brief Name of a scope + * @details Name of a scope + */ typedef uint64_t scope_name; + +/** + * @brief Name of an action + * @details Name of an action + */ typedef uint64_t action_name; +/** + * @brief Macro to align/overalign a type to ensure calls to intrinsics with pointers/references are properly aligned + * @details Macro to align/overalign a type to ensure calls to intrinsics with pointers/references are properly aligned + */ + typedef uint16_t weight_type; /* macro to align/overalign a type to ensure calls to intrinsics with pointers/references are properly aligned */ #define ALIGNED(X) __attribute__ ((aligned (16))) X +/** + * @brief EOSIO Public Key + * @details EOSIO Public Key. It is 34 bytes. + */ struct public_key { char data[34]; }; +/** + * @brief EOSIO Signature + * @details EOSIO Signature. It is 66 bytes. + */ struct signature { uint8_t data[66]; }; +/** + * @brief 256-bit hash + * @details 256-bit hash + */ struct ALIGNED(checksum256) { uint8_t hash[32]; }; +/** + * @brief 160-bit hash + * @details 160-bit hash + */ struct ALIGNED(checksum160) { uint8_t hash[20]; }; +/** + * @brief 512-bit hash + * @details 512-bit hash + */ struct ALIGNED(checksum512) { uint8_t hash[64]; }; +/** + * @brief Type of EOSIO Transaction Id + * @details Type of EOSIO Transaction Id. It is 256-bit hash + */ typedef struct checksum256 transaction_id_type; typedef struct checksum256 block_id_type; diff --git a/libraries/eosiolib/types.hpp b/libraries/eosiolib/types.hpp index f0466f22e6..e2776a3292 100644 --- a/libraries/eosiolib/types.hpp +++ b/libraries/eosiolib/types.hpp @@ -13,9 +13,11 @@ namespace eosio { typedef std::vector>> extensions_type; /** - * @brief Converts a base32 symbol into its binary representation, used by string_to_name() + * Converts a base32 symbol into its binary representation, used by string_to_name() * - * @details Converts a base32 symbol into its binary representation, used by string_to_name() + * @brief Converts a base32 symbol into its binary representation, used by string_to_name() + * @param c - Character to be converted + * @return constexpr char - Converted character * @ingroup types */ static constexpr char char_to_symbol( char c ) { @@ -28,11 +30,12 @@ namespace eosio { /** - * @brief Converts a base32 string to a uint64_t. - * - * @details Converts a base32 string to a uint64_t. This is a constexpr so that + * Converts a base32 string to a uint64_t. This is a constexpr so that * this method can be used in template arguments as well. * + * @brief Converts a base32 string to a uint64_t. + * @param str - String representation of the name + * @return constexpr uint64_t - 64-bit unsigned integer representation of the name * @ingroup types */ static constexpr uint64_t string_to_name( const char* str ) { @@ -61,7 +64,11 @@ namespace eosio { } /** - * @brief used to generate a compile time uint64_t from the base32 encoded string interpretation of X + * Used to generate a compile time uint64_t from the base32 encoded string interpretation of X + * + * @brief Used to generate a compile time uint64_t from the base32 encoded string interpretation of X + * @param X - String representation of the name + * @return constexpr uint64_t - 64-bit unsigned integer representation of the name * @ingroup types */ #define N(X) ::eosio::string_to_name(#X) @@ -98,15 +105,20 @@ namespace eosio { } /** - * @brief wraps a uint64_t to ensure it is only passed to methods that expect a Name - * @details wraps a uint64_t to ensure it is only passed to methods that expect a Name and - * that no mathematical operations occur. It also enables specialization of print - * so that it is printed as a base32 string. + * Wraps a uint64_t to ensure it is only passed to methods that expect a Name and + * that no mathematical operations occur. It also enables specialization of print + * so that it is printed as a base32 string. * + * @brief wraps a uint64_t to ensure it is only passed to methods that expect a Name * @ingroup types - * @{ */ struct name { + /** + * Conversion Operator to convert name to uint64_t + * + * @brief Conversion Operator + * @return uint64_t - Converted result + */ operator uint64_t()const { return value; } // keep in sync with name::operator string() in eosio source code definition for name @@ -126,7 +138,22 @@ namespace eosio { return str; } + /** + * Equality Operator for name + * + * @brief Equality Operator for name + * @param a - First data to be compared + * @param b - Second data to be compared + * @return true - if equal + * @return false - if unequal + */ friend bool operator==( const name& a, const name& b ) { return a.value == b.value; } + + /** + * Internal Representation of the account name + * + * @brief Internal Representation of the account name + */ account_name value = 0; private: @@ -136,13 +163,13 @@ namespace eosio { str = str.substr(0, last + 1); } }; - /// @} } // namespace eosio namespace std { /** - * @brief provide less for checksum256 + * Provide less for checksum256 + * @brief Provide less for checksum256 */ template<> struct less : binary_function { @@ -154,8 +181,40 @@ namespace std { } // namespace std /** - * Provide == for checksum256 in global namespace + * Equality Operator for checksum256 + * + * @brief Equality Operator for checksum256 + * @param lhs - First data to be compared + * @param rhs - Second data to be compared + * @return true - if equal + * @return false - if unequal + */ +inline bool operator==(const checksum256& lhs, const checksum256& rhs) { + return memcmp(&lhs, &rhs, sizeof(lhs)) == 0; +} + +/** + * Equality Operator for checksum160 + * + * @brief Equality Operator for checksum256 + * @param lhs - First data to be compared + * @param rhs - Second data to be compared + * @return true - if equal + * @return false - if unequal + */ +inline bool operator==(const checksum160& lhs, const checksum160& rhs) { + return memcmp(&lhs, &rhs, sizeof(lhs)) == 0; +} + +/** + * Equality Operator for checksum160 + * + * @brief Equality Operator for checksum256 + * @param lhs - First data to be compared + * @param rhs - Second data to be compared + * @return true - if unequal + * @return false - if equal */ -bool operator==(const checksum256& lhs, const checksum256& rhs); -bool operator==(const checksum160& lhs, const checksum160& rhs); -bool operator!=(const checksum160& lhs, const checksum160& rhs); +inline bool operator!=(const checksum160& lhs, const checksum160& rhs) { + return memcmp(&lhs, &rhs, sizeof(lhs)) != 0; +} diff --git a/libraries/eosiolib/varint.hpp b/libraries/eosiolib/varint.hpp index ac8fe3ce75..b8240839aa 100644 --- a/libraries/eosiolib/varint.hpp +++ b/libraries/eosiolib/varint.hpp @@ -6,42 +6,208 @@ /** - * @defgroup varint Variable Length Integer + * @defgroup varint Variable Length Integer Type + * @brief Defines variable length integer type which provides more efficient serialization * @ingroup types - * @{ + * @{/ */ +/** + * Variable Length Unsigned Integer. This provides more efficient serialization of 32-bit unsigned int. + * It serialuzes a 32-bit unsigned integer in as few bytes as possible + * `varuint32` is unsigned and uses [VLQ or Base-128 encoding](https://en.wikipedia.org/wiki/Variable-length_quantity) + * + * @brief Variable Length Unsigned Integer + */ struct unsigned_int { + /** + * Construct a new unsigned int object + * + * @brief Construct a new unsigned int object + * @param v - Source + */ unsigned_int( uint32_t v = 0 ):value(v){} + /** + * Construct a new unsigned int object from a type that is convertible to uint32_t + * + * @brief Construct a new unsigned int object + * @tparam T - Type of the source + * @param v - Source + * @pre T must be convertible to uint32_t + */ template unsigned_int( T v ):value(v){} //operator uint32_t()const { return value; } //operator uint64_t()const { return value; } + /** + * Convert unsigned_int as T + * @brief Conversion Operator + * @tparam T - Target type of conversion + * @return T - Converted target + */ template operator T()const { return static_cast(value); } + /** + * Assign 32-bit unsigned integer + * + * @brief Assignment operator + * @param v - Soruce + * @return unsigned_int& - Reference to this object + */ unsigned_int& operator=( uint32_t v ) { value = v; return *this; } - + + /** + * Contained value + * + * @brief Contained value + */ uint32_t value; + /** + * Check equality between a unsigned_int object and 32-bit unsigned integer + * + * @brief Equality Operator + * @param i - unsigned_int object to compare + * @param v - 32-bit unsigned integer to compare + * @return true - if equal + * @return false - otherwise + */ friend bool operator==( const unsigned_int& i, const uint32_t& v ) { return i.value == v; } + + /** + * Check equality between 32-bit unsigned integer and a unsigned_int object + * + * @brief Equality Operator + * @param i - 32-bit unsigned integer to compare + * @param v - unsigned_int object to compare + * @return true - if equal + * @return false - otherwise + */ friend bool operator==( const uint32_t& i, const unsigned_int& v ) { return i == v.value; } + + /** + * Check equality between two unsigned_int objects + * + * @brief Equality Operator + * @param i - First unsigned_int object to compare + * @param v - Second unsigned_int object to compare + * @return true - if equal + * @return false - otherwise + */ friend bool operator==( const unsigned_int& i, const unsigned_int& v ) { return i.value == v.value; } + /** + * Check inequality between a unsigned_int object and 32-bit unsigned integer + * + * @brief Inequality Operator + * @param i - unsigned_int object to compare + * @param v - 32-bit unsigned integer to compare + * @return true - if inequal + * @return false - otherwise + */ friend bool operator!=( const unsigned_int& i, const uint32_t& v ) { return i.value != v; } + + /** + * Check inequality between 32-bit unsigned integer and a unsigned_int object + * + * @brief Equality Operator + * @param i - 32-bit unsigned integer to compare + * @param v - unsigned_int object to compare + * @return true - if unequal + * @return false - otherwise + */ friend bool operator!=( const uint32_t& i, const unsigned_int& v ) { return i != v.value; } + + /** + * Check inequality between two unsigned_int objects + * + * @brief Inequality Operator + * @param i - First unsigned_int object to compare + * @param v - Second unsigned_int object to compare + * @return true - if inequal + * @return false - otherwise + */ friend bool operator!=( const unsigned_int& i, const unsigned_int& v ) { return i.value != v.value; } + /** + * Check if the given unsigned_int object is less than the given 32-bit unsigned integer + * + * @brief Less than Operator + * @param i - unsigned_int object to compare + * @param v - 32-bit unsigned integer to compare + * @return true - if i less than v + * @return false - otherwise + */ friend bool operator<( const unsigned_int& i, const uint32_t& v ) { return i.value < v; } + + /** + * Check if the given 32-bit unsigned integer is less than the given unsigned_int object + * + * @brief Less than Operator + * @param i - 32-bit unsigned integer to compare + * @param v - unsigned_int object to compare + * @return true - if i less than v + * @return false - otherwise + */ friend bool operator<( const uint32_t& i, const unsigned_int& v ) { return i < v.value; } + + /** + * Check if the first given unsigned_int is less than the second given unsigned_int object + * + * @brief Less than Operator + * @param i - First unsigned_int object to compare + * @param v - Second unsigned_int object to compare + * @return true - if i less than v + * @return false - otherwise + */ friend bool operator<( const unsigned_int& i, const unsigned_int& v ) { return i.value < v.value; } + /** + * Check if the given unsigned_int object is greater or equal to the given 32-bit unsigned integer + * + * @brief Greater or Equal to Operator + * @param i - unsigned_int object to compare + * @param v - 32-bit unsigned integer to compare + * @return true - if i is greater or equal to v + * @return false - otherwise + */ friend bool operator>=( const unsigned_int& i, const uint32_t& v ) { return i.value >= v; } + + /** + * Check if the given 32-bit unsigned integer is greater or equal to the given unsigned_int object + * + * @brief Greater or Equal to Operator + * @param i - 32-bit unsigned integer to compare + * @param v - unsigned_int object to compare + * @return true - if i is greater or equal to v + * @return false - otherwise + */ friend bool operator>=( const uint32_t& i, const unsigned_int& v ) { return i >= v.value; } + + /** + * Check if the first given unsigned_int is greater or equal to the second given unsigned_int object + * + * @brief Greater or Equal to Operator + * @param i - First unsigned_int object to compare + * @param v - Second unsigned_int object to compare + * @return true - if i is greater or equal to v + * @return false - otherwise + */ friend bool operator>=( const unsigned_int& i, const unsigned_int& v ) { return i.value >= v.value; } + + /** + * Serialize an unsigned_int object with as few bytes as possible + * + * @brief Serialize an unsigned_int object with as few bytes as possible + * @param ds - The stream to write + * @param v - The value to serialize + * @tparam DataStream - Type of datastream + * @return DataStream& - Reference to the datastream + */ template friend DataStream& operator << ( DataStream& ds, const unsigned_int& v ){ uint64_t val = v.value; @@ -54,6 +220,15 @@ struct unsigned_int { return ds; } + /** + * Deserialize an unsigned_int object + * + * @brief Deserialize an unsigned_int object + * @param ds - The stream to read + * @param vi - The destination for deserialized value + * @tparam DataStream - Type of datastream + * @return DataStream& - Reference to the datastream + */ template friend DataStream& operator >> ( DataStream& ds, unsigned_int& vi ){ uint64_t v = 0; char b = 0; uint8_t by = 0; @@ -68,38 +243,208 @@ struct unsigned_int { }; /** - * @brief serializes a 32 bit signed integer in as few bytes as possible + * Variable Length Signed Integer. This provides more efficient serialization of 32-bit signed int. + * It serializes a 32-bit signed integer in as few bytes as possible. + * `varint32' is signed and uses [Zig-Zag encoding](https://developers.google.com/protocol-buffers/docs/encoding#signed-integers) * - * Uses the google protobuf algorithm for seralizing signed numbers + * @brief Variable Length Signed Integer */ struct signed_int { + /** + * Construct a new signed int object + * + * @brief Construct a new signed int object + * @param v - Source + */ signed_int( int32_t v = 0 ):value(v){} + + /** + * Convert signed_int to primitive 32-bit signed integer + * @brief Conversion operator + * + * @return int32_t - The converted result + */ operator int32_t()const { return value; } + + + /** + * Assign an object that is convertible to int32_t + * + * @brief Assignment operator + * @tparam T - Type of the assignment object + * @param v - Source + * @return unsigned_int& - Reference to this object + */ template signed_int& operator=( const T& v ) { value = v; return *this; } + + /** + * Increment operator + * + * @brief Increment operator + * @return signed_int - New signed_int with value incremented from the current object's value + */ signed_int operator++(int) { return value++; } + + /** + * Increment operator + * + * @brief Increment operator + * @return signed_int - Reference to current object + */ signed_int& operator++(){ ++value; return *this; } + /** + * Contained value + * + * @brief Contained value + */ int32_t value; + /** + * Check equality between a signed_int object and 32-bit integer + * + * @brief Equality Operator + * @param i - signed_int object to compare + * @param v - 32-bit integer to compare + * @return true - if equal + * @return false - otherwise + */ friend bool operator==( const signed_int& i, const int32_t& v ) { return i.value == v; } + + /** + * Check equality between 32-bit integer and a signed_int object + * + * @brief Equality Operator + * @param i - 32-bit integer to compare + * @param v - signed_int object to compare + * @return true - if equal + * @return false - otherwise + */ friend bool operator==( const int32_t& i, const signed_int& v ) { return i == v.value; } + + /** + * Check equality between two signed_int objects + * + * @brief Equality Operator + * @param i - First signed_int object to compare + * @param v - Second signed_int object to compare + * @return true - if equal + * @return false - otherwise + */ friend bool operator==( const signed_int& i, const signed_int& v ) { return i.value == v.value; } + + /** + * Check inequality between a signed_int object and 32-bit integer + * + * @brief Inequality Operator + * @param i - signed_int object to compare + * @param v - 32-bit integer to compare + * @return true - if inequal + * @return false - otherwise + */ friend bool operator!=( const signed_int& i, const int32_t& v ) { return i.value != v; } + + /** + * Check inequality between 32-bit integer and a signed_int object + * + * @brief Equality Operator + * @param i - 32-bit integer to compare + * @param v - signed_int object to compare + * @return true - if unequal + * @return false - otherwise + */ friend bool operator!=( const int32_t& i, const signed_int& v ) { return i != v.value; } + + /** + * Check inequality between two signed_int objects + * + * @brief Inequality Operator + * @param i - First signed_int object to compare + * @param v - Second signed_int object to compare + * @return true - if inequal + * @return false - otherwise + */ friend bool operator!=( const signed_int& i, const signed_int& v ) { return i.value != v.value; } + /** + * Check if the given signed_int object is less than the given 32-bit integer + * + * @brief Less than Operator + * @param i - signed_int object to compare + * @param v - 32-bit integer to compare + * @return true - if i less than v + * @return false - otherwise + */ friend bool operator<( const signed_int& i, const int32_t& v ) { return i.value < v; } + + /** + * Check if the given 32-bit integer is less than the given signed_int object + * + * @brief Less than Operator + * @param i - 32-bit integer to compare + * @param v - signed_int object to compare + * @return true - if i less than v + * @return false - otherwise + */ friend bool operator<( const int32_t& i, const signed_int& v ) { return i < v.value; } + + /** + * Check if the first given signed_int is less than the second given signed_int object + * + * @brief Less than Operator + * @param i - First signed_int object to compare + * @param v - Second signed_int object to compare + * @return true - if i less than v + * @return false - otherwise + */ friend bool operator<( const signed_int& i, const signed_int& v ) { return i.value < v.value; } + + /** + * Check if the given signed_int object is greater or equal to the given 32-bit integer + * + * @brief Greater or Equal to Operator + * @param i - signed_int object to compare + * @param v - 32-bit integer to compare + * @return true - if i is greater or equal to v + * @return false - otherwise + */ friend bool operator>=( const signed_int& i, const int32_t& v ) { return i.value >= v; } + + /** + * Check if the given 32-bit integer is greater or equal to the given signed_int object + * + * @brief Greater or Equal to Operator + * @param i - 32-bit integer to compare + * @param v - signed_int object to compare + * @return true - if i is greater or equal to v + * @return false - otherwise + */ friend bool operator>=( const int32_t& i, const signed_int& v ) { return i >= v.value; } - friend bool operator>=( const signed_int& i, const signed_int& v ) { return i.value >= v.value; } + /** + * Check if the first given signed_int is greater or equal to the second given signed_int object + * + * @brief Greater or Equal to Operator + * @param i - First signed_int object to compare + * @param v - Second signed_int object to compare + * @return true - if i is greater or equal to v + * @return false - otherwise + */ + friend bool operator>=( const signed_int& i, const signed_int& v ) { return i.value >= v.value; } + /** + * Serialize an signed_int object with as few bytes as possible + * + * @brief Serialize an signed_int object with as few bytes as possible + * @param ds - The stream to write + * @param v - The value to serialize + * @tparam DataStream - Type of datastream + * @return DataStream& - Reference to the datastream + */ template friend DataStream& operator << ( DataStream& ds, const signed_int& v ){ uint32_t val = uint32_t((v.value<<1) ^ (v.value>>31)); @@ -111,6 +456,16 @@ struct signed_int { } while( val ); return ds; } + + /** + * Deserialize an signed_int object + * + * @brief Deserialize an signed_int object + * @param ds - The stream to read + * @param vi - The destination for deserialized value + * @tparam DataStream - Type of datastream + * @return DataStream& - Reference to the datastream + */ template friend DataStream& operator >> ( DataStream& ds, signed_int& vi ){ uint32_t v = 0; char b = 0; int by = 0; diff --git a/libraries/libc++/CMakeLists.txt b/libraries/libc++/CMakeLists.txt index fb2266cf28..b18e98208c 100644 --- a/libraries/libc++/CMakeLists.txt +++ b/libraries/libc++/CMakeLists.txt @@ -18,12 +18,12 @@ add_library(c++ target_include_directories(c++ PUBLIC $ - $) + $) target_link_libraries(c++ c) install(TARGETS c++ EXPORT EosioLib - LIBRARY DESTINATION ${SDK_INSTALL_PREFIX}/lib/ - ARCHIVE DESTINATION ${SDK_INSTALL_PREFIX}/lib/) + LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libcxx/include/ DESTINATION ${SDK_INSTALL_PREFIX}/include/libcxx) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libcxx/include/ DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/libcxx) diff --git a/libraries/libc/CMakeLists.txt b/libraries/libc/CMakeLists.txt index 10e6189fa3..1bdeb90233 100644 --- a/libraries/libc/CMakeLists.txt +++ b/libraries/libc/CMakeLists.txt @@ -48,12 +48,12 @@ add_dependencies(c EosioClang) target_include_directories(c PUBLIC "$" - $) + $) install(TARGETS c EXPORT EosioLib - LIBRARY DESTINATION ${SDK_INSTALL_PREFIX}/lib/ - ARCHIVE DESTINATION ${SDK_INSTALL_PREFIX}/lib/) + LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/musl/include/ DESTINATION ${SDK_INSTALL_PREFIX}/include/libc) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/musl/src/internal/ DESTINATION ${SDK_INSTALL_PREFIX}/include/libc) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/musl/arch/eos/ DESTINATION ${SDK_INSTALL_PREFIX}/include/libc) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/musl/include/ DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/libc) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/musl/src/internal/ DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/libc) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/musl/arch/eos/ DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/libc) diff --git a/modules/EosioWasmToolchain.cmake b/modules/EosioWasmToolchain.cmake deleted file mode 100644 index 3315c36598..0000000000 --- a/modules/EosioWasmToolchain.cmake +++ /dev/null @@ -1,32 +0,0 @@ -message(STATUS "Setting up Eosio Wasm Toolchain") -set(CMAKE_SYSTEM_NAME WebAssembly) - -if (WASM_ROOT STREQUAL "") - set(WASM_INSTALL_ROOT "${CMAKE_INSTALL_PREFIX}/eosio") -else(WASM_ROOT STREQUAL "") - set(WASM_INSTALL_ROOT "${WASM_ROOT}") -endif(WASM_ROOT STREQUAL "") - -set(CMAKE_C_COMPILER "${WASM_INSTALL_ROOT}/bin/eosio-cc") -set(CMAKE_CXX_COMPILER "${WASM_INSTALL_ROOT}/bin/eosio-cpp") - -set(CMAKE_C_FLAGS " -O3 ") -set(CMAKE_CXX_FLAGS " -O3 ") - -set(WASM_LINKER "${WASM_INSTALL_ROOT}/bin/eosio-ld") - -set(CMAKE_C_LINK_EXECUTABLE "${WASM_LINKER} -o ") -set(CMAKE_CXX_LINK_EXECUTABLE "${WASM_LINKER} -o ") - -set(CMAKE_AR "${WASM_INSTALL_ROOT}/bin/eosio-ar" CACHE PATH "ar" FORCE) -set(CMAKE_RANLIB "${WASM_INSTALL_ROOT}/bin/eosio-ranlib" CACHE PATH "ranlib" FORCE) - -set(EosioLib_DIR ${WASM_INSTALL_ROOT}/lib/cmake) - -# hack for CMake on Linux -set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) -set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) - -# hack for OSX -set(CMAKE_OSX_SYSROOT="${WASM_INSTALL_ROOT}/eosio.wasmsdk") -set(CMAKE_OSX_DEPLOYMENT_TARGET="") diff --git a/modules/EosioWasmToolchain.cmake.in b/modules/EosioWasmToolchain.cmake.in index d4a87d9850..85b6a6ee31 100644 --- a/modules/EosioWasmToolchain.cmake.in +++ b/modules/EosioWasmToolchain.cmake.in @@ -1,32 +1,28 @@ message(STATUS "Setting up Eosio Wasm Toolchain") set(CMAKE_SYSTEM_NAME WebAssembly) -if (WASM_ROOT STREQUAL "") - set(WASM_INSTALL_ROOT "${CMAKE_INSTALL_PREFIX}/eosio") -else(WASM_ROOT STREQUAL "") - set(WASM_INSTALL_ROOT "${WASM_ROOT}") -endif(WASM_ROOT STREQUAL "") +set(EOSIO_WASMSDK_VERSION "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@") -set(CMAKE_C_COMPILER "${WASM_INSTALL_ROOT}/bin/eosio-cc") -set(CMAKE_CXX_COMPILER "${WASM_INSTALL_ROOT}/bin/eosio-cpp") +set(CLANG_DIR @CMAKE_INSTALL_PREFIX@/) -set(CMAKE_C_FLAGS " -O3 -I@Boost_INCLUDE_DIRS@ ") -set(CMAKE_CXX_FLAGS " -O3 -I@Boost_INCLUDE_DIRS@ ") +set(CMAKE_C_COMPILER "${CLANG_DIR}/bin/eosio-cc") +set(CMAKE_CXX_COMPILER "${CLANG_DIR}/bin/eosio-cpp") -set(WASM_LINKER "${WASM_INSTALL_ROOT}/bin/eosio-ld") +set(CMAKE_C_FLAGS " -O3 -I@BOOST_ROOT@/include ") +set(CMAKE_CXX_FLAGS " -O3 -I@BOOST_ROOT@/include ") + +set(WASM_LINKER "${CLANG_DIR}/bin/eosio-ld") set(CMAKE_C_LINK_EXECUTABLE "${WASM_LINKER} -o ") set(CMAKE_CXX_LINK_EXECUTABLE "${WASM_LINKER} -o ") -set(CMAKE_AR "${WASM_INSTALL_ROOT}/bin/eosio-ar" CACHE PATH "ar" FORCE) -set(CMAKE_RANLIB "${WASM_INSTALL_ROOT}/bin/eosio-ranlib" CACHE PATH "ranlib" FORCE) - -set(EosioLib_DIR ${WASM_INSTALL_ROOT}/lib/cmake) +set(CMAKE_AR "${CLANG_DIR}/bin/eosio-ar" CACHE PATH "ar" FORCE) +set(CMAKE_RANLIB "${CLANG_DIR}/bin/eosio-ranlib" CACHE PATH "ranlib" FORCE) # hack for CMake on Linux set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) # hack for OSX -set(CMAKE_OSX_SYSROOT="${WASM_INSTALL_ROOT}/eosio.wasmsdk") +set(CMAKE_OSX_SYSROOT="${CLANG_DIR}") set(CMAKE_OSX_DEPLOYMENT_TARGET="") diff --git a/modules/EosioWasmToolchainBuild.cmake b/modules/EosioWasmToolchainBuild.cmake deleted file mode 100644 index 058a1e3e78..0000000000 --- a/modules/EosioWasmToolchainBuild.cmake +++ /dev/null @@ -1,28 +0,0 @@ -message(STATUS "Setting up Eosio Wasm Toolchain") -set(CMAKE_SYSTEM_NAME WebAssembly) - -set(WASM_INSTALL_ROOT "${CMAKE_INSTALL_PREFIX}") -set(CLANG_DIR ${CMAKE_BINARY_DIR}/EosioClang-prefix/src/EosioClang-build) - -set(CMAKE_C_COMPILER "${CLANG_DIR}/bin/eosio-cc") -set(CMAKE_CXX_COMPILER "${CLANG_DIR}/bin/eosio-cpp") - -set(CMAKE_C_FLAGS " -O3 -eosio-imports=${CMAKE_BINARY_DIR}/eosio.imports ") -set(CMAKE_CXX_FLAGS " -O3 ") - -set(WASM_LINKER "${CLANG_DIR}/bin/eosio-ld") - -set(CMAKE_C_LINK_EXECUTABLE "${WASM_LINKER} -o ") -set(CMAKE_CXX_LINK_EXECUTABLE "${WASM_LINKER} -o ") - -set(CMAKE_AR "${CLANG_DIR}/bin/llvm-ar" CACHE PATH "ar" FORCE) -set(CMAKE_RANLIB "${CLANG_DIR}/bin/llvm-ranlib" CACHE PATH "ranlib" FORCE) - -find_package(Boost 1.67 REQUIRED) - -set(STANDARD_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/libraries/libc++/libcxx/include" - "${CMAKE_CURRENT_SOURCE_DIR}/libraries/libc/musl/include" - "${CMAKE_CURRENT_SOURCE_DIR}/libraries/eosiolib" - "${CMAKE_CURRENT_SOURCE_DIR}/libraries/boost/include" - "${Boost_INCLUDE_DIRS}") -set(STANDARD_LIBS c++ c eosio) diff --git a/modules/EosioWasmToolchainBuild.cmake.in b/modules/EosioWasmToolchainBuild.cmake.in new file mode 100644 index 0000000000..b9b2a4a041 --- /dev/null +++ b/modules/EosioWasmToolchainBuild.cmake.in @@ -0,0 +1,28 @@ +message(STATUS "Setting up Eosio Wasm Toolchain") +set(CMAKE_SYSTEM_NAME WebAssembly) + +set(EOSIO_WASMSDK_VERSION "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@") + +set(CLANG_DIR @CMAKE_BINARY_DIR@/EosioClang-prefix/src/EosioClang-build) + +set(CMAKE_C_COMPILER "${CLANG_DIR}/bin/eosio-cc") +set(CMAKE_CXX_COMPILER "${CLANG_DIR}/bin/eosio-cpp") + +set(CMAKE_C_FLAGS " -O3 -I@CMAKE_BINARY_DIR@/libraries/ -I@CMAKE_SOURCE_DIR@/libraries/boost/include -I@CMAKE_SOURCE_DIR@/libraries/libc++/libcxx/include -I@CMAKE_SOURCE_DIR@/libraries/libc/musl/include -I@CMAKE_SOURCE_DIR@/libraries -I@BOOST_ROOT@/include") +set(CMAKE_CXX_FLAGS " -O3 -I@CMAKE_BINARY_DIR@/libraries/ -I@CMAKE_SOURCE_DIR@/libraries/boost/include -I@CMAKE_SOURCE_DIR@/libraries/libc++/libcxx/include -I@CMAKE_SOURCE_DIR@/libraries/libc/musl/include -I@CMAKE_SOURCE_DIR@/libraries -I@BOOST_ROOT@/include --std=c++14 ") + +set(WASM_LINKER "${CLANG_DIR}/bin/eosio-ld ") + +set(CMAKE_C_LINK_EXECUTABLE "${WASM_LINKER} -L@CMAKE_BINARY_DIR@/libraries/eosiolib -L@CMAKE_BINARY_DIR@/libraries/libc -L@CMAKE_BINARY_DIR@/libraries/libc++ -eosio-imports=@CMAKE_BINARY_DIR@/eosio.imports -eosio-pp-dir=@CMAKE_BINARY_DIR@/external/wabt -o -leosio -lc++ -lc ") +set(CMAKE_CXX_LINK_EXECUTABLE "${WASM_LINKER} -L@CMAKE_BINARY_DIR@/libraries/eosiolib -L@CMAKE_BINARY_DIR@/libraries/libc -L@CMAKE_BINARY_DIR@/libraries/libc++ -eosio-imports=@CMAKE_BINARY_DIR@/eosio.imports -eosio-pp-dir=@CMAKE_BINARY_DIR@/external/wabt -o -leosio -lc++ -lc ") + +set(CMAKE_AR "${CLANG_DIR}/bin/llvm-ar" CACHE PATH "ar" FORCE) +set(CMAKE_RANLIB "${CLANG_DIR}/bin/llvm-ranlib" CACHE PATH "ranlib" FORCE) + +# hack for CMake on Linux +set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) +set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) + +# hack for OSX +set(CMAKE_OSX_SYSROOT="${CLANG_DIR}/eosio.wasmsdk") +set(CMAKE_OSX_DEPLOYMENT_TARGET="") diff --git a/uninstall.sh b/uninstall.sh new file mode 100755 index 0000000000..e1c3d0c521 --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,30 @@ +#! /bin/bash + +binaries=(eosio-ranlib + eosio-ar + eosio-objdump + eosio-readelf + eosio-pp + eosio-cc + eosio-cpp + eosio-ld) + +if [ -d "/usr/local/eosio.wasmsdk" ]; then + printf "\tDo you wish to remove this install? (requires sudo)\n" + select yn in "Yes" "No"; do + case $yn in + [Yy]* ) + pushd /usr/local &> /dev/null + rm -rf eosio.wasmsdk + pushd bin &> /dev/null + for binary in ${binaries[@]}; do + rm ${binary} + done + popd &> /dev/null + break;; + [Nn]* ) + printf "\tAborting uninstall\n\n" + exit -1;; + esac + done +fi