first release of translation facility

* runtime - loading and translating
 * design-time - works with *.ts file (pip_tr utility)
 * compile-time - CMake macro for compile *.ts
This commit is contained in:
2024-11-05 13:49:00 +03:00
parent 73ed51e3d4
commit 57f8c1313e
52 changed files with 1571 additions and 480 deletions

View File

@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(PIP)
set(PIP_MAJOR 4)
set(PIP_MINOR 3)
set(PIP_REVISION 2)
set(PIP_MINOR 4)
set(PIP_REVISION 0)
set(PIP_SUFFIX )
set(PIP_COMPANY SHS)
set(PIP_DOMAIN org.SHS)
@@ -82,6 +82,7 @@ shstk_is_parent_exists(_pe)
if (_pe)
set(BUILDING_pip 1 PARENT_SCOPE)
set(pip_ROOT_SRC "${CMAKE_CURRENT_SOURCE_DIR}" PARENT_SCOPE)
set(pip_ROOT_SRC "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
@@ -188,10 +189,12 @@ if (NOT DEFINED PIP_CMG)
if (CMAKE_CROSSCOMPILING OR (DEFINED ANDROID_PLATFORM))
set(PIP_CMG "pip_cmg")
set(PIP_RC "pip_rc")
set(PIP_TR "pip_tr")
set(PIP_DEPLOY_TOOL "deploy_tool")
else()
set(PIP_CMG "${CMAKE_CURRENT_BINARY_DIR}/utils/code_model_generator/pip_cmg")
set(PIP_RC "${CMAKE_CURRENT_BINARY_DIR}/utils/resources_compiler/pip_rc")
set(PIP_TR "${CMAKE_CURRENT_BINARY_DIR}/utils/translator/pip_tr")
set(PIP_DEPLOY_TOOL "${CMAKE_CURRENT_BINARY_DIR}/utils/deploy_tool/deploy_tool")
endif()
endif()
@@ -502,55 +505,6 @@ endif()
string(REPLACE ";" "," PIP_EXPORTS_STR "${PIP_EXPORTS}")
target_compile_definitions(pip PRIVATE "PICODE_DEFINES=\"${PIP_EXPORTS_STR}\"")
# Install
# Check if system or local install will be used (to system install use "-DLIB=" argument of cmake)
if(NOT LOCAL)
if(WIN32)
if(MINGW)
if (NOT CROSSTOOLS)
install(FILES ${HDRS} DESTINATION ${MINGW_INCLUDE}/pip)
if(HDR_DIRS)
install(DIRECTORY ${HDR_DIRS} DESTINATION ${MINGW_INCLUDE}/pip)
endif()
install(TARGETS ${PIP_MODULES} ARCHIVE DESTINATION ${MINGW_LIB})
endif()
install(TARGETS ${PIP_MODULES} RUNTIME DESTINATION ${MINGW_BIN})
find_library(STDLIB "stdc++-6" PATHS ${MINGW_BIN} NO_DEFAULT_PATH)
find_library(STDLIB "stdc++-6")
#message("${STDLIB}")
if (STDLIB)
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/code_model_generator")
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/resources_compiler")
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/deploy_tool")
endif()
else()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pip_export.h DESTINATION include)
endif()
else()
if (NOT CROSSTOOLS)
install(FILES ${HDRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/pip)
if(HDR_DIRS)
install(DIRECTORY ${HDR_DIRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/pip)
endif()
endif()
install(TARGETS ${PIP_MODULES} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
else()
if(NOT PIP_FREERTOS)
if(WIN32)
install(TARGETS ${PIP_MODULES} RUNTIME DESTINATION bin)
install(TARGETS ${PIP_MODULES} ARCHIVE DESTINATION lib)
else()
install(TARGETS ${PIP_MODULES} DESTINATION lib)
endif()
install(FILES ${HDRS} DESTINATION include/pip)
if(HDR_DIRS)
install(DIRECTORY ${HDR_DIRS} DESTINATION include/pip)
endif()
endif()
endif()
file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in")
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
if(NOT PIP_FREERTOS)
@@ -575,10 +529,79 @@ if(NOT PIP_FREERTOS)
add_subdirectory("utils/cloud_dispatcher")
endif()
endif()
endif()
# Translations
set(PIP_LANG)
if (NOT CROSSTOOLS)
pip_translation(PIP_LANG lang/pip_ru.ts)
add_custom_target(pip_lang SOURCES "${PIP_LANG}")
endif()
# Install
# Check if system or local install will be used (to system install use "-DLIB=" argument of cmake)
if(NOT LOCAL)
if(WIN32)
if(MINGW)
if (NOT CROSSTOOLS)
install(FILES ${HDRS} DESTINATION ${MINGW_INCLUDE}/pip)
if(PIP_LANG)
install(FILES ${PIP_LANG} DESTINATION ${MINGW_INCLUDE}/../share/pip/lang)
endif()
if(HDR_DIRS)
install(DIRECTORY ${HDR_DIRS} DESTINATION ${MINGW_INCLUDE}/pip)
endif()
install(TARGETS ${PIP_MODULES} ARCHIVE DESTINATION ${MINGW_LIB})
endif()
install(TARGETS ${PIP_MODULES} RUNTIME DESTINATION ${MINGW_BIN})
find_library(STDLIB "stdc++-6" PATHS ${MINGW_BIN} NO_DEFAULT_PATH)
find_library(STDLIB "stdc++-6")
#message("${STDLIB}")
if (STDLIB)
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/code_model_generator")
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/resources_compiler")
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/deploy_tool")
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/translator")
endif()
else()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pip_export.h DESTINATION include)
endif()
else()
if (NOT CROSSTOOLS)
install(FILES ${HDRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/pip)
if(PIP_LANG)
install(FILES ${PIP_LANG} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pip/lang)
endif()
if(HDR_DIRS)
install(DIRECTORY ${HDR_DIRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/pip)
endif()
endif()
install(TARGETS ${PIP_MODULES} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
else()
if(NOT PIP_FREERTOS)
if(WIN32)
install(TARGETS ${PIP_MODULES} RUNTIME DESTINATION bin)
install(TARGETS ${PIP_MODULES} ARCHIVE DESTINATION lib)
else()
install(TARGETS ${PIP_MODULES} DESTINATION lib)
endif()
install(FILES ${HDRS} DESTINATION include/pip)
if(PIP_LANG)
install(FILES ${PIP_LANG} DESTINATION share/pip/lang)
endif()
if(HDR_DIRS)
install(DIRECTORY ${HDR_DIRS} DESTINATION include/pip)
endif()
endif()
endif()
file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in")
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
shstk_is_parent_exists(_pe)
if (_pe)
set(PIP_MODULES ${PIP_MODULES} PARENT_SCOPE)

View File

@@ -45,10 +45,12 @@ endif()
if (BUILDING_PIP AND (NOT CMAKE_CROSSCOMPILING))
set(PIP_CMG "$<TARGET_FILE_DIR:pip_cmg>/$<TARGET_FILE_NAME:pip_cmg>" CACHE STRING "")
set(PIP_RC "$<TARGET_FILE_DIR:pip_rc>/$<TARGET_FILE_NAME:pip_rc>" CACHE STRING "")
set(PIP_TR "$<TARGET_FILE_DIR:pip_tr>/$<TARGET_FILE_NAME:pip_tr>" CACHE STRING "")
set(PIP_DEPLOY_TOOL "$<TARGET_FILE_DIR:deploy_tool>/$<TARGET_FILE_NAME:deploy_tool>" CACHE STRING "")
else()
find_program(PIP_CMG pip_cmg${PIP_BINEXT} HINTS ${PIP_BINDIR} ${PIP_FIND_PROGRAM_ARG})
find_program(PIP_RC pip_rc${PIP_BINEXT} HINTS ${PIP_BINDIR} ${PIP_FIND_PROGRAM_ARG})
find_program(PIP_TR pip_tr${PIP_BINEXT} HINTS ${PIP_BINDIR} ${PIP_FIND_PROGRAM_ARG})
find_program(PIP_DEPLOY_TOOL deploy_tool${PIP_BINEXT} HINTS ${PIP_BINDIR} ${PIP_FIND_PROGRAM_ARG})
endif()
if (NOT PIP_LIBRARY)

View File

@@ -18,6 +18,14 @@
Generate C++ files for resource file
You should add ${<out_var>} to your target
pip_translation(<out_var> ts_file)
Generate *.btf (binary translation file) from *.ts file
You should add ${<out_var>} to your target and then install it to somewhere
for later loading in runtime by PITranslator
]]
@@ -119,3 +127,34 @@ macro(pip_resources RESULT INPUT)
VERBATIM)
endmacro()
macro(pip_translation RESULT INPUT)
#message(STATUS "src = ${CCM_SRC}")
#message(STATUS "result = ${RESULT}")
#message(STATUS "options = \"${CCM_OPTS}\"")
get_filename_component(BTF_FILENAME "${INPUT}" NAME_WE)
set(BTF_FILENAME "${BTF_FILENAME}.btf")
set(BTF_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BTF_FILENAME})
list(APPEND ${RESULT} "${BTF_OUTPUT}")
if(IS_ABSOLUTE "${INPUT}")
set(IN_FILES "${INPUT}")
else()
set(IN_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${INPUT}")
endif()
#message(STATUS "CCM = ${RESULT}")
if(NOT DEFINED PIP_DLL_DIR)
set(PIP_DLL_DIR ${CMAKE_CURRENT_BINARY_DIR})
endif()
#message("PIP_TR: ${PIP_TR}")
#message("BTF_OUTPUT: ${BTF_OUTPUT}")
#message("IN_FILES: ${IN_FILES}")
#message("PIP_DLL_DIR: ${PIP_DLL_DIR}")
add_custom_command(OUTPUT ${BTF_OUTPUT}
COMMAND ${PIP_TR}
ARGS -C -o "${BTF_OUTPUT}" "${IN_FILES}"
DEPENDS ${IN_FILES}
WORKING_DIRECTORY ${PIP_DLL_DIR}
COMMENT "Generating ${BTF_FILENAME}"
VERBATIM)
endmacro()

531
lang/pip_ru.ts Normal file
View File

@@ -0,0 +1,531 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ru">
<context>
<name>PICLI</name>
<message>
<location filename="../libs/main/application/picli.cpp" line="120"/>
<source>Arguments overflow, &quot;%1&quot; ignored</source>
<translation>Переизбыток аргументов, &quot;%1&quot; проигнорирован</translation>
</message>
</context>
<context>
<name>PIDiag</name>
<message>
<location filename="../libs/main/io_utils/pidiagnostics.cpp" line="155"/>
<source>/s</source>
<translation>/сек</translation>
</message>
</context>
<context>
<name>PIFile</name>
<message>
<location filename="../libs/main/io_devices/pifile.cpp" line="299"/>
<source>Downsize is not supported yet :-(</source>
<translation>Уменьшение размера не поддерживается</translation>
</message>
</context>
<context>
<name>PICloud</name>
<message>
<location filename="../libs/cloud/picloudtcp.cpp" line="139"/>
<source>Invalid PICloud::TCP version!</source>
<translation>Неверная версия PICloud::TCP!</translation>
</message>
<message>
<location filename="../libs/cloud/picloudserver.cpp" line="230"/>
<source>Error: buffer overflow, drop %1 bytes</source>
<translation>Ошибка: переполнение буфера, отброшено %1 байт</translation>
</message>
<message>
<location filename="../libs/cloud/picloudserver.cpp" line="251"/>
<source>Warning: reject client with duplicated ID</source>
<translation>Предупреждение: отклонен клиент с дублирующимся ID</translation>
</message>
</context>
<context>
<name>PICrypt</name>
<message>
<location filename="../libs/crypt/picrypt.cpp" line="205"/>
<source>internal error: bad hash size</source>
<translation>внутренняя ошибка: плохой размер хэша</translation>
</message>
<message>
<location filename="../libs/crypt/picrypt.cpp" line="39"/>
<source>Error while initialize sodium!</source>
<translation>Ошибка инициализации sodium!</translation>
</message>
<message>
<location filename="../libs/crypt/picrypt.cpp" line="209"/>
<source>invalid key size %1, should be %2, filled with zeros</source>
<translation>неверный размер ключа %1, должен быть %2, заполненный нулями</translation>
</message>
<message>
<location filename="../libs/crypt/picrypt.cpp" line="29"/>
<source>Warning: PICrypt is disabled, to enable install sodium library and rebuild pip</source>
<translation>Предупреждение: PICrypt неактивен, для активации установите библиотеку sodium и пересоберите PIP</translation>
</message>
</context>
<context>
<name>PIBinLog</name>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="436"/>
<source>Read record error</source>
<translation>Ошибка чтения записи</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="432"/>
<source>End of BinLog file</source>
<translation>Конец BinLog файла</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="776"/>
<source>Error, can&apos;t open &quot;%1&quot;</source>
<translation>Ошибка, невозможно открыть &quot;%1&quot;</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="262"/>
<source>Creating directory &quot;%1&quot;</source>
<translation>Создание директории &quot;%1&quot;</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="785"/>
<source>Error, can&apos;t create &quot;%1&quot;</source>
<translation>Ошибка, невозможно создать &quot;%1&quot;</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="140"/>
<source>Error: File is null &quot;%1&quot;</source>
<translation>Ошибка, Файл пуст &quot;%1&quot;</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="789"/>
<source>Start join binlogs to &quot;%1&quot;</source>
<translation>Начало слияния логов в &quot;%1&quot;</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="514"/>
<source>BinLogFile has too old verion</source>
<translation>BinLogFile очень старой версии</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="513"/>
<source>BinLogFile has invalid version</source>
<translation>BinLogFile неверной версии</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="515"/>
<source>BinLogFile has too new version</source>
<translation>BinLogFile очень новой версии</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="386"/>
<source>Can&apos;t find record with id = %1</source>
<translation>Невозможно найти запись с ID = %1</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="803"/>
<source>Error, can&apos;t write to file &quot;%1&quot;</source>
<translation>Ошибка, невозможно записать в &quot;%1&quot;</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="126"/>
<source>Error: Can&apos;t open file &quot;%1&quot;: %2</source>
<translation>Ошибка: Невозможно открыть файл &quot;%1&quot;: %2</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="149"/>
<source>Warning: Empty BinLog file &quot;%1&quot;</source>
<translation>Предупреждение: Пустой BinLog файл &quot;%1&quot;</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="825"/>
<source>Finish join binlogs, total time %1</source>
<translation>Завершение слияния логов, общее время %1</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="440"/>
<source>too small read buffer: %1, data size: %2</source>
<translation>слишком маленький буфер: %1, размер данных: %2</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="133"/>
<source>Error: Can&apos;t write binlog file header &quot;%1&quot;</source>
<translation>Ошибка: Невозможно записать заголовок в &quot;%1&quot;</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="319"/>
<source>Error: can`t write with id = 0! ID must be &gt; 0</source>
<translation>Ошибка: Невозможно записать с ID = 0! ID должен быть &gt; 0</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="495"/>
<source>BinLogFile signature is corrupted or invalid file</source>
<translation>Неверный заголовок BinLogFile, либо файл поврежден</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="295"/>
<source>Can&apos;t create new file, maybe path &quot;%1&quot; is invalid</source>
<translation>Невозможно создать новый файл, возможно путь &quot;%1&quot; неверен</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="286"/>
<source>Can&apos;t create new file, maybe LogDir &quot;%1&quot; is invalid</source>
<translation>Невозможно создать новый файл, возможно LogDir &quot;%1&quot; неверен</translation>
</message>
<message>
<location filename="../libs/main/io_devices/pibinarylog.cpp" line="104"/>
<source>Error: ReadWrite mode not supported, use WriteOnly or ReadOnly</source>
<translation>Ошибка: Режим ReadWrite не поддерживается, используйте WriteOnly или ReadOnly</translation>
</message>
</context>
<context>
<name>PIOpenCL</name>
<message>
<location filename="../libs/opencl/piopencl.cpp" line="509"/>
<source>Error: empty range</source>
<translation>Ошибка: пустой диапазон</translation>
</message>
<message>
<location filename="../libs/opencl/piopencl.cpp" line="586"/>
<source>setArgValue invalid index %1</source>
<translation>setArgValue неверный индекс %1</translation>
</message>
<message>
<location filename="../libs/opencl/piopencl.cpp" line="616"/>
<source>bindArgValue invalid index %1</source>
<translation>bindArgValue неверный индекс %1</translation>
</message>
<message>
<location filename="../libs/opencl/piopencl.cpp" line="592"/>
<source>setArgValue set scalar to &quot;%1 %2&quot;</source>
<translation>setArgValue устанавливается скаляр в &quot;%1 %2&quot;</translation>
</message>
<message>
<location filename="../libs/opencl/piopencl.cpp" line="93"/>
<source>Error: OpenCL platforms not found!</source>
<translation>Ошибка: Платформы OpenCL не найдены!</translation>
</message>
<message>
<location filename="../libs/opencl/piopencl.cpp" line="622"/>
<source>bindArgValue set buffer to &quot;%1 %2&quot;</source>
<translation>bindArgValue устанавливается буфер в &quot;%1 %2&quot;</translation>
</message>
</context>
<context>
<name>PISerial</name>
<message>
<location filename="../libs/main/io_devices/piserial.cpp" line="887"/>
<source>Read error: %1</source>
<translation>Ошибка чтения: %1</translation>
</message>
<message>
<location filename="../libs/main/io_devices/piserial.cpp" line="726"/>
<source>Unable to open &quot;%1&quot;: %2</source>
<translation>Невозможно открыть &quot;%1&quot;: %2</translation>
</message>
<message>
<location filename="../libs/main/io_devices/piserial.cpp" line="467"/>
<source>Warning: Custom speed %1</source>
<translation>Предупреждение: Нестандартная скорость %1</translation>
</message>
<message>
<location filename="../libs/main/io_devices/piserial.cpp" line="695"/>
<source>Unable to find device &quot;%1&quot;</source>
<translation>Невозможно найти устройство &quot;%1&quot;</translation>
</message>
<message>
<location filename="../libs/main/io_devices/piserial.cpp" line="826"/>
<source>Can`t set attributes for &quot;%1&quot;</source>
<translation>Невозможно установить атрибуты для &quot;%1&quot;</translation>
</message>
<message>
<location filename="../libs/main/io_devices/piserial.cpp" line="792"/>
<source>Unable to set comm state for &quot;%1&quot;</source>
<translation>Невозможно установить comm state для &quot;%1&quot;</translation>
</message>
<message>
<location filename="../libs/main/io_devices/piserial.cpp" line="470"/>
<source>Warning: Unknown speed %1, using 115200</source>
<translation>Предупреждение: Неизвестная скорость %1, используется 115200</translation>
</message>
</context>
<context>
<name>PIString</name>
<message>
<location filename="../libs/main/text/pistring.cpp" line="1774"/>
<source>B</source>
<translation>Б</translation>
</message>
<message>
<location filename="../libs/main/text/pistring.cpp" line="1794"/>
<source>EiB</source>
<translation>ЭиБ</translation>
</message>
<message>
<location filename="../libs/main/text/pistring.cpp" line="1791"/>
<source>GiB</source>
<translation>ГиБ</translation>
</message>
<message>
<location filename="../libs/main/text/pistring.cpp" line="1789"/>
<source>KiB</source>
<translation>КиБ</translation>
</message>
<message>
<location filename="../libs/main/text/pistring.cpp" line="1790"/>
<source>MiB</source>
<translation>МиБ</translation>
</message>
<message>
<location filename="../libs/main/text/pistring.cpp" line="1793"/>
<source>PiB</source>
<translation>ПиБ</translation>
</message>
<message>
<location filename="../libs/main/text/pistring.cpp" line="1792"/>
<source>TiB</source>
<translation>ТиБ</translation>
</message>
<message>
<location filename="../libs/main/text/pistring.cpp" line="1796"/>
<source>YiB</source>
<translation>ЙиБ</translation>
</message>
<message>
<location filename="../libs/main/text/pistring.cpp" line="1795"/>
<source>ZiB</source>
<translation>ЗиБ</translation>
</message>
</context>
<context>
<name>PIThread</name>
<message>
<location filename="../libs/main/thread/pithread.cpp" line="667"/>
<source>Warning, terminate!</source>
<translation>Предупреждение, прекращение потока!</translation>
</message>
<message>
<location filename="../libs/main/thread/pithread.cpp" line="785"/>
<source>Error: Can`t start new thread: %1</source>
<translation>Ошибка: Невозможно начать новый поток: %1</translation>
</message>
<message>
<location filename="../libs/main/thread/pithread.cpp" line="572"/>
<source>[PIThread &quot;%1&quot;] Warning, terminate on destructor!</source>
<translation>[PIThread &quot;%1&quot;] Предупреждение, прекращение в деструкторе!</translation>
</message>
</context>
<context>
<name>PIProcess</name>
<message>
<location filename="../libs/main/system/piprocess.cpp" line="200"/>
<source>&quot;CreateProcess&quot; error: %1</source>
<translation>Ошибка &quot;CreateProcess&quot;: %1</translation>
</message>
</context>
<context>
<name>PIVariant</name>
<message>
<location filename="../libs/main/types/pivariant.cpp" line="415"/>
<source>Can`t initialize PIVariant from unregistered type &quot;%1&quot;!</source>
<translation>Невозможно инициализировать PIVariant из незарегистрированного типа &quot;%1&quot;!</translation>
</message>
<message>
<location filename="../libs/main/types/pivariant.cpp" line="393"/>
<source>Can`t initialize PIVariant from unregistered typeID &quot;%1&quot;!</source>
<translation>Невозможно инициализировать PIVariant из незарегистрированного ID типа &quot;%1&quot;!</translation>
</message>
</context>
<context>
<name>PICompress</name>
<message>
<location filename="../libs/compress/picompress.cpp" line="63"/>
<source>Error: invalid input</source>
<translation>Ошибка: неверный вход</translation>
</message>
<message>
<location filename="../libs/compress/picompress.cpp" line="74"/>
<source>Error: invalid input or not enought memory</source>
<translation>Ошибка: неверный вход или недостаточно памяти</translation>
</message>
<message>
<location filename="../libs/compress/picompress.cpp" line="80"/>
<source>Warning: PICompress is disabled, to enable install zlib library and build pip_compress library</source>
<translation>Предупреждение: PICompress неактивен, для активации установите библиотеку zlib и пересоберите PIP</translation>
</message>
</context>
<context>
<name>PIEthernet</name>
<message>
<location filename="../libs/main/io_devices/piethernet.cpp" line="1233"/>
<source>Can`t get interfaces: %1</source>
<translation>Невозможно получить интерфейсы: %1</translation>
</message>
<message>
<location filename="../libs/main/io_devices/piethernet.cpp" line="903"/>
<source>Can`t accept new connection, %1</source>
<translation>Невозможно принять новое соединение, %1</translation>
</message>
<message>
<location filename="../libs/main/io_devices/piethernet.cpp" line="1096"/>
<source>Error allocating memory needed to call GetAdaptersInfo</source>
<translation>Ошибка выделения памяти для вызова GetAdaptersInfo</translation>
</message>
</context>
<context>
<name>PIIODevice</name>
<message>
<location filename="../libs/main/io_devices/piiodevice.cpp" line="226"/>
<source>Error: Device is running after destructor!</source>
<translation>Ошибка: Устройство в поточном выполнении после деструктора!</translation>
</message>
</context>
<context>
<name>PIIOString</name>
<message>
<location filename="../libs/main/io_devices/piiostring.cpp" line="54"/>
<source>Error: ReadWrite mode not supported, use WriteOnly or ReadOnly</source>
<translation>Ошибка: Режим ReadWrite не поддерживается, используйте WriteOnly или ReadOnly</translation>
</message>
</context>
<context>
<name>PIConnection</name>
<message>
<location filename="../libs/main/io_utils/piconnection.cpp" line="146"/>
<source>Error,</source>
<translation>Ошибка,</translation>
</message>
<message>
<location filename="../libs/main/io_utils/piconnection.cpp" line="922"/>
<source>Null Device!</source>
<translation>Нет Устройства!</translation>
</message>
<message>
<location filename="../libs/main/io_utils/piconnection.cpp" line="913"/>
<source>No such device &quot;%1&quot;!</source>
<translation>Нет устройства &quot;%1&quot;!</translation>
</message>
<message>
<location filename="../libs/main/io_utils/piconnection.cpp" line="903"/>
<source>No such full path &quot;%1&quot;!</source>
<translation>Нет полного пути &quot;%1&quot;!</translation>
</message>
<message>
<location filename="../libs/main/io_utils/piconnection.cpp" line="927"/>
<source>Device &quot;%1&quot; can`t write!</source>
<translation>Устройство &quot;%1&quot; не может писать!</translation>
</message>
<message>
<location filename="../libs/main/io_utils/piconnection.cpp" line="986"/>
<source>Error: can`t create device &quot;%1&quot;!</source>
<translation>Ошибка: Невозможно создать устройство &quot;%1&quot;!</translation>
</message>
<message>
<location filename="../libs/main/io_utils/piconnection.cpp" line="242"/>
<source>&quot;addFilter&quot; error: no such device &quot;%1&quot;!</source>
<translation>ошибка &quot;addFilter&quot;: нет устройства &quot;%1&quot;!</translation>
</message>
<message>
<location filename="../libs/main/io_utils/piconnection.cpp" line="743"/>
<source>&quot;addSender&quot; error: no such device &quot;%1&quot;!</source>
<translation>ошибка &quot;addSender&quot;: нет устройства &quot;%1&quot;!</translation>
</message>
<message>
<location filename="../libs/main/io_utils/piconnection.cpp" line="146"/>
<source>names assigned to both devices and filters!</source>
<translation>имена назначены одновременно устройствам и фильтрам!</translation>
</message>
<message>
<location filename="../libs/main/io_utils/piconnection.cpp" line="512"/>
<source>&quot;addFilter&quot; error: no such device or filter &quot;%1&quot;!</source>
<translation>ошибка &quot;addFilter&quot;: нет устройства или фильтра &quot;%1&quot;!</translation>
</message>
</context>
<context>
<name>PISystemTime</name>
<message>
<location filename="../libs/main/types/pisystemtime.cpp" line="335"/>
<source>fromSystemTime() Warning: null frequency</source>
<translation>fromSystemTime() Предупреждение: нулевая частота</translation>
</message>
<message>
<location filename="../libs/main/types/pisystemtime.cpp" line="325"/>
<source>toSystemTime() Warning: invalid hertz: %1</source>
<translation>toSystemTime() Предупреждение: неверная частота: %1</translation>
</message>
</context>
<context>
<name>PIEthUtilBase</name>
<message>
<location filename="../libs/io_utils/piethutilbase.cpp" line="91"/>
<source>PICrypt wasn`t built!</source>
<translation>PICrypt не был собран!</translation>
</message>
</context>
<context>
<name>PIBaseTransfer</name>
<message>
<location filename="../libs/main/io_utils/pibasetransfer.cpp" line="125"/>
<source>invalid CRC</source>
<translation>неверная CRC</translation>
</message>
<message>
<location filename="../libs/main/io_utils/pibasetransfer.cpp" line="219"/>
<source>restart receive</source>
<translation>перезапуск приема</translation>
</message>
<message>
<location filename="../libs/main/io_utils/pibasetransfer.cpp" line="176"/>
<source>invalid reply id</source>
<translation>неверный ID ответа</translation>
</message>
<message>
<location filename="../libs/main/io_utils/pibasetransfer.cpp" line="102"/>
<source>invalid packet signature</source>
<translation>неверная подпись пакета</translation>
</message>
</context>
<context>
<name>PIClientServer</name>
<message>
<location filename="../libs/client_server/piclientserver_server.cpp" line="39"/>
<source>ClientFactory returns nullptr!</source>
<translation>ClientFactory вернул nullptr!</translation>
</message>
<message>
<location filename="../libs/client_server/piclientserver_server.cpp" line="33"/>
<source>Server::newConnection overflow clients count</source>
<translation>Server::newConnection переполнение количества клиентов</translation>
</message>
</context>
<context>
<name>PIStateMachine</name>
<message>
<location filename="../libs/main/state_machine/pistatemachine_state.cpp" line="111"/>
<source>Error: &quot;%1&quot; no initial state!</source>
<translation>Ошибка: &quot;%1&quot; без стартового состояния!</translation>
</message>
</context>
<context>
<name>PIStreamPacker</name>
<message>
<location filename="../libs/io_utils/pistreampacker.cpp" line="218"/>
<source>Warning! Not recommended to use with non-reliable device</source>
<translation>Предупреждение! Не рекомендуется использовать с ненадежными устройствами</translation>
</message>
</context>
<context>
<name>PISystemMonitor</name>
<message>
<location filename="../libs/main/application/pisystemmonitor.cpp" line="111"/>
<source>Can`t find process with ID = %1!</source>
<translation>Невозможно найти процесс с ID = %1!</translation>
</message>
<message>
<location filename="../libs/main/application/pisystemmonitor.cpp" line="118"/>
<source>Can`t open process with ID = %1, %2!</source>
<translation>Невозможно открыть процесс с ID = %1, %2!</translation>
</message>
</context>
</TS>

1
lang/update.bat Normal file
View File

@@ -0,0 +1 @@
pip_tr --Parse -r -l ru -o pip_ru.ts ../libs

View File

@@ -20,7 +20,7 @@
#include "piclientserver_client.h"
#include "piethernet.h"
#include "piliterals_time.h"
#include "pitranslator.h"
PIClientServer::Server::Server() {
@@ -30,13 +30,13 @@ PIClientServer::Server::Server() {
CONNECTL(tcp_server, newConnection, [this](PIEthernet * c) {
PIMutexLocker guard(clients_mutex);
if (clients.size_s() >= max_clients) {
piCout << "Server::newConnection overflow clients count";
piCout << "Server::newConnection overflow clients count"_tr("PIClientServer");
delete c;
return;
}
auto sc = client_factory();
if (!sc) {
piCout << "ClientFactory returns nullptr!";
piCout << "ClientFactory returns nullptr!"_tr("PIClientServer");
return;
}
sc->createForServer(this, c);

View File

@@ -20,6 +20,7 @@
#include "picloudclient.h"
#include "picloudtcp.h"
#include "pitranslator.h"
PICloudClient::PICloudClient(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(path, mode), PICloudBase() {
@@ -174,7 +175,7 @@ void PICloudClient::_readed(PIByteArray & ba) {
if (is_connected) {
mutex_buff.lock();
if (buff.size_s() > threadedReadBufferSize()) {
piCoutObj << "Error: buffer overflow, drop" << ba.size() << "bytes";
piCoutObj << "Error: buffer overflow, drop %1 bytes"_tr("PICloud").arg(ba.size());
mutex_buff.unlock();
return;
}

View File

@@ -20,6 +20,7 @@
#include "picloudserver.h"
#include "piliterals_time.h"
#include "pitranslator.h"
PICloudServer::PICloudServer(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(path, mode), PICloudBase() {
@@ -226,7 +227,7 @@ void PICloudServer::Client::pushBuffer(const PIByteArray & ba) {
if (!is_connected) return;
mutex_buff.lock();
if (buff.size_s() > threadedReadBufferSize()) {
piCoutObj << "Error: buffer overflow, drop" << ba.size() << "bytes";
piCoutObj << "Error: buffer overflow, drop %1 bytes"_tr("PICloud").arg(ba.size());
mutex_buff.unlock();
return;
}
@@ -247,7 +248,7 @@ void PICloudServer::_readed(PIByteArray & ba) {
Client * oc = index_clients.value(id, nullptr);
clients_mutex.unlock();
if (oc) {
piCoutObj << "Warning: reject client with duplicated ID";
piCoutObj << "Warning: reject client with duplicated ID"_tr("PICloud");
tcp.sendDisconnected(id);
} else {
Client * c = new Client(this, id);

View File

@@ -23,6 +23,7 @@
#include "picrypt.h"
#include "piethernet.h"
#include "pistreampacker.h"
#include "pitranslator.h"
const char hash_cloud_key[] = "_picloud_";
@@ -95,7 +96,7 @@ int PICloud::TCP::sendData(const PIByteArray & data) {
PIByteArray ba;
ba << header;
ba.append(data);
// piCout << "[PICloud::TCP] sendData" << ba.toHex();
// piCout << "[PICloud::TCP] sendData" << ba.toHex();
mutex_send.lock();
streampacker->send(ba);
mutex_send.unlock();
@@ -135,7 +136,7 @@ PIPair<PICloud::TCP::Type, PICloud::TCP::Role> PICloud::TCP::parseHeader(PIByteA
ba >> hdr;
if (hdr.version != header.version) {
piCout << "[PICloud]"
<< "invalid PICloud::TCP version!";
<< "Invalid PICloud::TCP version!"_tr("PICloud");
return ret;
}
ret.first = (Type)hdr.type;

View File

@@ -18,6 +18,8 @@
*/
#include "picompress.h"
#include "pitranslator.h"
#ifdef PIP_COMPRESS
# ifdef ESP_PLATFORM
# include "esp32/rom/miniz.h"
@@ -39,7 +41,7 @@ PIByteArray piCompress(const PIByteArray & ba, int level) {
ret = compress2(zba.data(), &sz, ba.data(), ba.size(), level);
if (ret != Z_OK) {
piCout << "[PICompress]"
<< "Error: invalid input or not enought memory";
<< "Error: invalid input or not enought memory"_tr("PICompress");
return ba;
}
zba.resize(sz);
@@ -47,7 +49,7 @@ PIByteArray piCompress(const PIByteArray & ba, int level) {
return zba;
#else
piCout << "[PICompress]"
<< "Warning: PICompress is disabled, to enable install zlib library and build pip_compress library";
<< "Warning: PICompress is disabled, to enable install zlib library and build pip_compress library"_tr("PICompress");
#endif
return ba;
}
@@ -58,7 +60,7 @@ PIByteArray piDecompress(const PIByteArray & zba) {
ullong sz = 0;
if (zba.size() < sizeof(ullong)) {
piCout << "[PICompress]"
<< "Error: invalid input";
<< "Error: invalid input"_tr("PICompress");
return zba;
}
PIByteArray ba(zba.data(zba.size() - sizeof(ullong)), sizeof(ullong));
@@ -69,13 +71,13 @@ PIByteArray piDecompress(const PIByteArray & zba) {
ret = uncompress(ba.data(), &s, zba.data(), zba.size());
if (ret != Z_OK) {
piCout << "[PICompress]"
<< "Error: invalid input or not enought memory";
<< "Error: invalid input or not enought memory"_tr("PICompress");
return zba;
}
return ba;
#else
piCout << "[PICompress]"
<< "Warning: PICompress is disabled, to enable install zlib library and build pip_compress library";
<< "Warning: PICompress is disabled, to enable install zlib library and build pip_compress library"_tr("PICompress");
#endif
return zba;
}

View File

@@ -18,13 +18,15 @@
*/
#include "picrypt.h"
#include "pitranslator.h"
#ifdef PIP_CRYPT
# include <sodium.h>
#endif
#define PICRYPT_DISABLED_WARNING \
piCout << "[PICrypt]" \
<< "Warning: PICrypt is disabled, to enable install sodium library and rebuild pip";
<< "Warning: PICrypt is disabled, to enable install sodium library and rebuild pip"_tr("PICrypt");
const char hash_def_key[] = "_picrypt_\0\0\0\0\0\0\0";
const int hash_def_key_size = 9;
@@ -34,7 +36,7 @@ PICrypt::PICrypt() {
#ifdef PIP_CRYPT
if (!init())
piCout << "[PICrypt]"
<< "Error while initialize sodium!";
<< "Error while initialize sodium!"_tr("PICrypt");
nonce_.resize(crypto_secretbox_NONCEBYTES);
key_.resize(crypto_secretbox_KEYBYTES);
randombytes_buf(key_.data(), key_.size());
@@ -107,7 +109,7 @@ PIByteArray PICrypt::decrypt(const PIByteArray & crypt_data, bool * ok) {
memcpy(nonce_.data(), crypt_data.data(crypt_data.size() - nonce_.size()), nonce_.size());
if (crypto_secretbox_open_easy(ret.data(), crypt_data.data(), crypt_data.size() - nonce_.size(), nonce_.data(), key_.data()) != 0) {
if (ok) *ok = false;
// piCout << "[PICrypt]" << "bad key_";
// piCout << "[PICrypt]" << "bad key_";
return PIByteArray();
}
#endif
@@ -134,7 +136,7 @@ PIByteArray PICrypt::decrypt(const PIByteArray & crypt_data, PIByteArray key, bo
memcpy(n.data(), crypt_data.data(crypt_data.size() - n.size()), n.size());
if (crypto_secretbox_open_easy(ret.data(), crypt_data.data(), crypt_data.size() - n.size(), n.data(), key.data()) != 0) {
if (ok) *ok = false;
// piCout << "[PICrypt]" << "bad key_";
// piCout << "[PICrypt]" << "bad key_";
return PIByteArray();
} else if (ok)
*ok = true;
@@ -200,11 +202,11 @@ ullong PICrypt::shorthash(const PIString & s, PIByteArray key) {
#ifdef PIP_CRYPT
if (crypto_shorthash_BYTES != sizeof(hash))
piCout << "[PICrypt]"
<< "internal error: bad hash size";
<< "internal error: bad hash size"_tr("PICrypt");
if (!init()) return hash;
if (key.size() != crypto_shorthash_KEYBYTES) {
piCout << "[PICrypt]"
<< "invalid key size" << key.size() << ", shoud be" << crypto_shorthash_KEYBYTES << ", filled zeros";
<< "invalid key size %1, should be %2, filled with zeros"_tr("PICrypt").arg(key.size()).arg(crypto_shorthash_KEYBYTES);
key.resize(crypto_shorthash_KEYBYTES, 0);
}
PIByteArray in(s.data(), s.size());
@@ -389,7 +391,7 @@ PIByteArray PICrypt::decrypt(const PIByteArray & crypt_data, const PIByteArray &
if (crypto_box_open_easy(ret.data(), crypt_data.data(), crypt_data.size() - n.size(), n.data(), public_key.data(), secret_key.data()) !=
0) {
if (ok) *ok = false;
// piCout << "[PICrypt]" << "bad key_";
// piCout << "[PICrypt]" << "bad key_";
return PIByteArray();
} else if (ok)
*ok = true;

View File

@@ -24,6 +24,7 @@
#define PIFFT_P_H
#include "picout.h"
#include "pimathcomplex.h"
#include "pivector.h"
#if defined(PIP_FFTW) || defined(PIP_FFTWf) || defined(PIP_FFTWl) || defined(PIP_FFTWq)
# include "fftw3.h"
@@ -41,7 +42,7 @@ public:
explicit PIFFTW_Private() {
plan = 0;
// #ifndef PIP_FFTW
// piCout << "[PIFFTW]" << "Warning: PIFFTW is disabled, to enable install libfftw3-dev library and build pip with -DFFTW=1";
// piCout << "[PIFFTW]" << "Warning: PIFFTW is disabled, to enable install libfftw3-dev library and build pip with -DFFTW=1";
// #endif
p_makeThreadSafe();
}

View File

@@ -18,6 +18,8 @@
*/
#include "piethutilbase.h"
#include "pitranslator.h"
#ifdef PIP_CRYPT
# include "picrypt.h"
#endif
@@ -85,7 +87,8 @@ void PIEthUtilBase::createCryptKey(const PIString & k) {
_key = PICrypt::hash("sodium_bug");
_key = PICrypt::hash(k);
#else
piCout << "[PIEthUtilBase] PICrypt wasn`t built!";
piCout << "[PIEthUtilBase]"
<< "PICrypt wasn`t built!"_tr("PIEthUtilBase");
#endif
_crypt = true;
}

View File

@@ -25,6 +25,7 @@
#include "piiodevice.h"
#include "piliterals_bytes.h"
#include "pitranslator.h"
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif
@@ -214,7 +215,7 @@ void PIStreamPacker::received(const PIByteArray & data) {
void PIStreamPacker::assignDevice(PIIODevice * dev) {
if (!dev) return;
if (!dev->infoFlags()[PIIODevice::Reliable]) {
piCoutObj << "Warning! Not recommended to use with non-reliable" << dev;
piCoutObj << "Warning! Not recommended to use with non-reliable device"_tr("PIStreamPacker") << dev;
}
CONNECT2(void, const uchar *, ssize_t, dev, threadedReadEvent, this, received);
CONNECT1(void, PIByteArray, this, sendRequest, dev, write);

View File

@@ -20,6 +20,7 @@
#include "picli.h"
#include "pisysteminfo.h"
#include "pitranslator.h"
//! \class PICLI picli.h
@@ -116,7 +117,7 @@ void PICLI::parse() {
_args_opt << cra;
continue;
}
piCoutObj << "Arguments overflow, \"" << cra << "\" ignored";
piCoutObj << "Arguments overflow, \"%1\" ignored"_tr("PICLI").arg(cra);
}
if (last == 0 ? false : last->has_value) {
last->value = cra;

View File

@@ -108,14 +108,14 @@ bool PISystemMonitor::startOnProcess(int pID, PISystemTime interval) {
PRIVATE->file.open(PRIVATE->proc_dir + "stat", PIIODevice::ReadOnly);
PRIVATE->filem.open(PRIVATE->proc_dir + "statm", PIIODevice::ReadOnly);
if (!PRIVATE->file.isOpened()) {
piCoutObj << "Can`t find process with ID = " << pID_ << "!";
piCoutObj << "Can`t find process with ID = %1!"_tr("PISystemMonitor").arg(pID_);
return false;
}
# endif
# else
PRIVATE->hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID_);
if (PRIVATE->hProc == 0) {
piCoutObj << "Can`t open process with ID = "_tr << pID_ << "," << errorString();
piCoutObj << "Can`t open process with ID = %1, %2!"_tr("PISystemMonitor").arg(pID_).arg(errorString());
return false;
}
PRIVATE->tm.reset();
@@ -377,12 +377,12 @@ void PISystemMonitor::gatherThread(llong id) {
FILETIME times[4];
HANDLE thdl = OpenThread(THREAD_QUERY_INFORMATION, FALSE, DWORD(id));
if (!thdl) {
piCout << "[PISystemMonitor] gatherThread(" << id << "):: OpenThread() error:" << errorString();
piCoutObj << "GatherThread(" << id << "):: OpenThread() error:" << errorString();
return;
}
if (GetThreadTimes(thdl, &(times[0]), &(times[1]), &(times[2]), &(times[3])) == 0) {
CloseHandle(thdl);
piCout << "[PISystemMonitor] gatherThread(" << id << "):: GetThreadTimes() error:" << errorString();
piCoutObj << "GatherThread(" << id << "):: GetThreadTimes() error:" << errorString();
return;
}
CloseHandle(thdl);

View File

@@ -19,8 +19,11 @@
#include "pitranslator.h"
#include "pidir.h"
#include "pifile.h"
#include "piliterals_string.h"
#include "pitranslator_p.h"
#include "pivaluetree_conversions.h"
#include "tr/pip_all.h"
//! \class PITranslator pitranslator.h
@@ -33,28 +36,38 @@
//!
PRIVATE_DEFINITION_START(PITranslator)
PITranslatorPrivate::Translation content;
PRIVATE_DEFINITION_END(PITranslator)
PIString PITranslator::tr(const PIString & in, const PIString & context) {
auto s = instance();
auto c = s->contexts.value(context.hash());
if (!c) return in;
return c->strings.value(in.hash(), in);
return instance()->PRIVATEWB->content.translate(in, context);
}
void PITranslator::clear() {
instance()->clearInternal();
instance()->PRIVATEWB->content.clear();
}
void PITranslator::loadLang(const PIString & short_lang) {
auto s = instance();
void PITranslator::loadLang(const PIString & short_lang, PIString dir) {
if (dir.isEmpty()) dir = PIDir::current().absolute("lang");
clear();
auto files = PIDir(dir).entries();
for (const auto & f: files) {
if (!f.baseName().endsWith(short_lang)) continue;
loadFile(f.path);
}
piCout << "Loaded %1 string for lang \"%2\""_a.arg(instance()->PRIVATEWB->content.count()).arg(short_lang);
/*auto s = instance();
auto vt = PIValueTreeConversions::fromText(getBuiltinConfig());
auto lang = vt.child(short_lang.toLowerCase().trim());
for (const auto & cn: lang.children()) {
auto c = s->createContextInternal(cn.name());
auto c = s->PRIVATEWB->content.createContext(cn.name());
for (const auto & s: cn.children())
c->add(s.name(), s.value().toString());
}
}*/
}
@@ -62,11 +75,11 @@ void PITranslator::loadConfig(const PIString & content) {
auto s = instance();
auto lang = PIValueTreeConversions::fromText(content);
for (const auto & cn: lang.children()) {
auto c = s->createContextInternal(cn.name());
auto c = s->PRIVATEWB->content.createContext(cn.name());
for (const auto & s: cn.children())
c->add(s.name(), s.value().toString());
}
auto c = s->createContextInternal("");
auto c = s->PRIVATEWB->content.createContext("");
for (const auto & s: lang.children()) {
if (s.hasChildren()) continue;
c->add(s.name(), s.value().toString());
@@ -74,11 +87,26 @@ void PITranslator::loadConfig(const PIString & content) {
}
bool PITranslator::load(const PIByteArray & content) {
return instance()->PRIVATEWB->content.load(content);
}
bool PITranslator::loadFile(const PIString & path) {
PIFile f(path, PIIODevice::ReadOnly);
if (f.isClosed()) return false;
if (!PITranslatorPrivate::checkHeader(&f)) return false;
auto data = f.readAll();
data.remove(0, PITranslatorPrivate::headerSize());
return load(data);
}
PITranslator::PITranslator() {}
PITranslator::~PITranslator() {
clearInternal();
PRIVATE->content.clear();
}
@@ -86,21 +114,3 @@ PITranslator * PITranslator::instance() {
static PITranslator ret;
return &ret;
}
void PITranslator::clearInternal() {
piDeleteAll(contexts.values());
contexts.clear();
}
PITranslator::Context * PITranslator::createContextInternal(const PIString & context) {
auto & ret(contexts[context.hash()]);
if (!ret) ret = new Context();
return ret;
}
void PITranslator::Context::add(const PIString & in, const PIString & out) {
strings[in.hash()] = out;
}

View File

@@ -29,7 +29,8 @@
#include "pistring.h"
#define piTr PITranslator::tr
#define piTr PITranslator::tr
#define piTrNoOp PITranslator::trNoOp
//! \ingroup Application
//! \~\brief
@@ -39,34 +40,59 @@ class PIP_EXPORT PITranslator {
public:
static PIString tr(const PIString & in, const PIString & context = {});
static PIString tr(const char * in, const PIString & context = {}) { return tr(PIString::fromUTF8(in), context); }
static PIString trNoOp(const PIString & in, const PIString & context = {}) { return in; }
static PIString trNoOp(const char * in, const PIString & context = {}) { return trNoOp(PIString::fromUTF8(in), context); }
static void clear();
static void loadLang(const PIString & short_lang);
static void loadLang(const PIString & short_lang, PIString dir = {});
static void loadConfig(const PIString & content);
static bool load(const PIByteArray & content);
static bool loadFile(const PIString & path);
private:
PITranslator();
~PITranslator();
NO_COPY_CLASS(PITranslator)
struct Context {
void add(const PIString & in, const PIString & out);
PIMap<uint, PIString> strings;
};
PRIVATE_DECLARATION(PIP_EXPORT)
static PITranslator * instance();
void clearInternal();
Context * createContextInternal(const PIString & context);
PIMap<uint, Context *> contexts;
};
class PIStringContextTr {
public:
PIStringContextTr(PIString && s): _s(s) {}
operator PIString() const { return PITranslator::tr(_s); }
PIString operator()(const PIString & ctx = {}) const { return PITranslator::tr(_s, ctx); }
private:
PIString _s;
};
class PIStringContextTrNoOp {
public:
PIStringContextTrNoOp(PIString && s): _s(s) {}
operator PIString() const { return _s; }
PIString operator()(const PIString & ctx = {}) const { return _s; }
private:
PIString _s;
};
//! \~\brief
//! \~english PIString from UTF-8
//! \~russian PIString из UTF-8
inline PIString operator""_tr(const char * v, size_t sz) {
return PITranslator::tr(PIString::fromUTF8(v, sz));
//! \~english Translate string with \a PITranslator::tr()
//! \~russian Перевести строку с помощью \a PITranslator::tr()
inline PIStringContextTr operator""_tr(const char * v, size_t sz) {
return PIStringContextTr(PIString::fromUTF8(v, sz));
}
//! \~\brief
//! \~english Translate string with \a PITranslator::tr()
//! \~russian Перевести строку с помощью \a PITranslator::tr()
inline PIStringContextTrNoOp operator""_trNoOp(const char * v, size_t sz) {
return PIStringContextTrNoOp(PIString::fromUTF8(v, sz));
}
#endif

View File

@@ -0,0 +1,124 @@
/*
PIP - Platform Independent Primitives
Translation private
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pitranslator_p.h"
#include "pichunkstream.h"
#include "piiodevice.h"
constexpr int currentVersion = 1;
const PIByteArray fileHeader("PIPBTF", 6);
void PITranslatorPrivate::Context::add(const PIMap<uint, PIString> & sm) {
auto it = sm.makeIterator();
while (it.next())
strings[it.key()] = it.value();
}
void PITranslatorPrivate::Translation::clear() {
piDeleteAll(contexts.values());
contexts.clear();
lang.clear();
}
PITranslatorPrivate::Context * PITranslatorPrivate::Translation::createContext(const PIString & context) {
return createContext(context.hash());
}
PITranslatorPrivate::Context * PITranslatorPrivate::Translation::createContext(uint hash) {
auto & ret(contexts[hash]);
if (!ret) ret = new Context();
return ret;
}
PIString PITranslatorPrivate::Translation::translate(const PIString & in, const PIString & context) {
auto c = contexts.value(context.hash());
if (!c) return in;
return c->strings.value(in.hash(), in);
}
bool PITranslatorPrivate::Translation::load(const PIByteArray & data) {
if (data.size_s() <= 4) return false;
PIChunkStream cs(data);
Context * ctx = nullptr;
PIMap<uint, PIString> strings;
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: {
int version = cs.getData<int>();
if (version != currentVersion) {
piCout << "Invalid translation version!";
return false;
}
} break;
case 3: {
uint ctx_hash = cs.getData<uint>();
ctx = createContext(ctx_hash);
} break;
case 4: {
cs.get(strings);
if (ctx) ctx->add(strings);
} break;
}
}
return true;
}
int PITranslatorPrivate::Translation::count() const {
int ret = 0;
auto cit = contexts.makeIterator();
while (cit.next())
ret += cit.value()->strings.size_s();
return ret;
}
PIByteArray PITranslatorPrivate::Translation::save() {
PIChunkStream cs;
cs.add(1, currentVersion).add(2, lang);
auto cit = contexts.makeIterator();
while (cit.next()) {
cs.add(3, cit.key()).add(4, cit.value()->strings);
}
return cs.data();
}
int PITranslatorPrivate::headerSize() {
return fileHeader.size_s();
}
bool PITranslatorPrivate::checkHeader(PIIODevice * d) {
if (!d) return false;
return d->read(fileHeader.size_s()) == fileHeader;
}
void PITranslatorPrivate::writeHeader(PIIODevice * d) {
if (!d) return;
d->write(fileHeader);
}

View File

@@ -0,0 +1,53 @@
/*
PIP - Platform Independent Primitives
Translation private
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef pitranslator_p_H
#define pitranslator_p_H
#include "pistring.h"
class PIIODevice;
namespace PITranslatorPrivate {
struct PIP_EXPORT Context {
void add(const PIString & in, const PIString & out) { strings[in.hash()] = out; }
void add(const PIMap<uint, PIString> & sm);
PIMap<uint, PIString> strings;
};
struct PIP_EXPORT Translation {
void clear();
Context * createContext(const PIString & context);
Context * createContext(uint hash);
PIString translate(const PIString & in, const PIString & context);
bool load(const PIByteArray & data);
int count() const;
PIByteArray save();
PIString lang;
PIMap<uint, Context *> contexts;
};
PIP_EXPORT int headerSize();
PIP_EXPORT bool checkHeader(PIIODevice * d);
PIP_EXPORT void writeHeader(PIIODevice * d);
} // namespace PITranslatorPrivate
#endif

View File

@@ -1,16 +0,0 @@
#ifndef pitr_pip_all_H
#define pitr_pip_all_H
#include "pip_ru.h"
#include "pistring.h"
PIString getBuiltinConfig() {
// clang-format off
static const PIString ret =
PIString::fromUTF8(config_ru)
;
// clang-format on
return ret;
}
#endif

View File

@@ -1,25 +0,0 @@
constexpr char config_ru[] = "\
[ru.PIString] \n\
B = Б \n\
KiB = KиБ \n\
MiB = MиБ \n\
GiB = ГиБ \n\
TiB = ТиБ \n\
PiB = ПиБ \n\
EiB = ЭиБ \n\
ZiB = ЗиБ \n\
YiB = ЙиБ \n\
\n\
[ru.PIDiag] \n\
/s = /сек \n\
\n\
[ru.PITime] \n\
Hz = Гц \n\
KHz = КГц \n\
kHz = кГц \n\
MHz = МГц \n\
GHz = ГГц \n\
THz = ТГц \n\
PHz = ПГц \n\
\n\
";

View File

@@ -24,6 +24,7 @@
#include "piliterals_time.h"
#include "pipropertystorage.h"
#include "pitime.h"
#include "pitranslator.h"
#define PIBINARYLOG_VERSION_OLD 0x31
@@ -100,7 +101,7 @@ bool PIBinaryLog::openDevice() {
index.clear();
log_size = 0;
if (mode_ == ReadWrite) {
piCoutObj << "Error: ReadWrite mode not supported, use WriteOnly or ReadOnly";
piCoutObj << "Error: ReadWrite mode not supported, use WriteOnly or ReadOnly"_tr("PIBinLog");
return false;
}
if (path().isEmpty() && mode_ == WriteOnly) {
@@ -122,21 +123,21 @@ bool PIBinaryLog::openDevice() {
}
}
if (!file.open(path(), mode_)) {
piCoutObj << "Error: Can't open file" << path();
piCoutObj << "Error: Can't open file \"%1\": %2"_tr("PIBinLog").arg(path()).arg(errorString());
return false;
}
setName(path());
if (mode_ == WriteOnly) {
file.clear();
if (!writeFileHeader()) {
piCoutObj << "Error: Can't write binlog file header" << path();
piCoutObj << "Error: Can't write binlog file header \"%1\""_tr("PIBinLog").arg(path());
return false;
}
is_started = true;
}
if (mode_ == ReadOnly) {
if (file.isEmpty()) {
piCoutObj << "Error: File is null" << path();
piCoutObj << "Error: File is null \"%1\""_tr("PIBinLog").arg(path());
fileError();
return false;
}
@@ -145,7 +146,7 @@ bool PIBinaryLog::openDevice() {
return false;
}
if (isEmpty()) {
piCoutObj << "Warning: Empty BinLog file" << path();
piCoutObj << "Warning: Empty BinLog file \"%1\""_tr("PIBinLog").arg(path());
fileEnd();
}
play_time = 0;
@@ -175,7 +176,7 @@ bool PIBinaryLog::closeDevice() {
bool PIBinaryLog::threadedRead(const uchar * readed, ssize_t size) {
// piCout << "binlog threaded read";
// piCout << "binlog threaded read";
if (!canRead() || isEnd()) return PIIODevice::threadedRead(readed, size);
is_thread_ok = false;
logmutex.lock();
@@ -258,7 +259,7 @@ PIString PIBinaryLog::getLogfilePath(const PIString & log_dir, const PIString &
dir.setDir(dir.absolutePath());
if (!dir.isExists()) {
piCout << "[PIBinaryLog]"
<< "Creating directory" << dir.path();
<< "Creating directory \"%1\""_tr("PIBinLog").arg(dir.path());
dir.make(true);
}
const PIString npath = log_dir + PIDir::separator + prefix + PIDateTime::current().toString("yyyy_MM_dd__hh_mm_ss");
@@ -282,7 +283,7 @@ PIString PIBinaryLog::createNewFile() {
newFile(file.path());
return file.path();
}
piCoutObj << "Can't create new file, maybe LogDir" << ("\"" + logDir() + "\"") << "is invalid.";
piCoutObj << "Can't create new file, maybe LogDir \"%1\" is invalid"_tr("PIBinLog").arg(logDir());
return PIString();
}
@@ -291,7 +292,7 @@ void PIBinaryLog::createNewFile(const PIString & path) {
if (open(path, PIIODevice::WriteOnly)) {
newFile(file.path());
} else
piCoutObj << "Can't create new file, maybe path" << ("\"" + path + "\"") << "is invalid.";
piCoutObj << "Can't create new file, maybe path \"%1\" is invalid"_tr("PIBinLog").arg(path);
}
@@ -315,7 +316,7 @@ void PIBinaryLog::setPause(bool pause) {
int PIBinaryLog::writeBinLog(int id, const void * data, int size) {
if (size <= 0 || !canWrite()) return -1;
if (id == 0) {
piCoutObj << "Error: can`t write with id = 0! Id must be > 0";
piCoutObj << "Error: can`t write with id = 0! ID must be > 0"_tr("PIBinLog");
return -1;
}
if (is_pause) return 0;
@@ -359,7 +360,7 @@ PIByteArray PIBinaryLog::readBinLog(int id, PISystemTime * time, int * readed_id
Record br = readRecord();
logmutex.unlock();
if (br.id == -1) {
piCoutObj << "End of BinLog file";
piCoutObj << "End of BinLog file"_tr("PIBinLog");
fileEnd();
return PIByteArray();
}
@@ -373,7 +374,7 @@ PIByteArray PIBinaryLog::readBinLog(int id, PISystemTime * time, int * readed_id
br = readRecord();
logmutex.unlock();
if (br.id == -1) {
piCoutObj << "End of BinLog file";
piCoutObj << "End of BinLog file"_tr("PIBinLog");
fileEnd();
return PIByteArray();
}
@@ -382,7 +383,7 @@ PIByteArray PIBinaryLog::readBinLog(int id, PISystemTime * time, int * readed_id
if (readed_id) *readed_id = br.id;
return br.data;
}
piCoutObj << "Can't find record with id =" << id;
piCoutObj << "Can't find record with id = %1"_tr("PIBinLog").arg(id);
return PIByteArray();
}
@@ -428,15 +429,15 @@ ssize_t PIBinaryLog::readDevice(void * read_to, ssize_t max_size) {
}
if (br.id == -1) {
fileEnd();
piCoutObj << "End of BinLog file";
piCoutObj << "End of BinLog file"_tr("PIBinLog");
return 0;
}
if (br.id == 0) {
piCoutObj << "Read record error";
piCoutObj << "Read record error"_tr("PIBinLog");
return -1;
}
const ssize_t sz = piMini(max_size, br.data.size());
if (sz < br.data.size_s()) piCoutObj << "too small read buffer:" << max_size << ", data size:" << br.data.size();
if (sz < br.data.size_s()) piCoutObj << "too small read buffer: %1, data size: %2"_tr("PIBinLog").arg(max_size).arg(br.data.size());
memcpy(read_to, br.data.data(), sz);
return sz;
}
@@ -491,7 +492,7 @@ bool PIBinaryLog::checkFileHeader() {
for (uint i = 0; i < PIBINARYLOG_SIGNATURE_SIZE; i++)
if (read_sig[i] != binlog_sig[i]) correct = false;
if (!correct) {
piCoutObj << "BinLogFile signature is corrupted or invalid file";
piCoutObj << "BinLogFile signature is corrupted or invalid file"_tr("PIBinLog");
return false;
}
uchar read_version = 0;
@@ -509,9 +510,9 @@ bool PIBinaryLog::checkFileHeader() {
}
return true;
}
if (read_version == 0) piCoutObj << "BinLogFile has invalid version";
if (read_version < PIBINARYLOG_VERSION) piCoutObj << "BinLogFile has too old verion";
if (read_version > PIBINARYLOG_VERSION) piCoutObj << "BinLogFile has too newest version";
if (read_version == 0) piCoutObj << "BinLogFile has invalid version"_tr("PIBinLog");
if (read_version < PIBINARYLOG_VERSION) piCoutObj << "BinLogFile has too old verion"_tr("PIBinLog");
if (read_version > PIBINARYLOG_VERSION) piCoutObj << "BinLogFile has too new version"_tr("PIBinLog");
return false;
}
@@ -545,7 +546,7 @@ PIBinaryLog::Record PIBinaryLog::readRecord() {
if (br.id == 0) fileError();
moveIndex(index.index_pos.value(file.pos(), -1));
logmutex.unlock();
// piCoutObj << "readRecord done";
// piCoutObj << "readRecord done";
return br;
}
@@ -721,7 +722,7 @@ bool PIBinaryLog::cutBinLog(const PIBinaryLog::BinLogInfo & src, const PIString
PIBinaryLog slog;
if (!slog.open(src.path, PIIODevice::ReadOnly)) {
piCout << "[PIBinaryLog]"
<< "Error, can't open" << src.path;
<< "Error, can't open \"%1\""_tr("PIBinLog").arg(src.path);
return false;
}
const PIVector<int> ids = src.records.keys();
@@ -730,7 +731,7 @@ bool PIBinaryLog::cutBinLog(const PIBinaryLog::BinLogInfo & src, const PIString
dlog.createNewFile(dst);
if (!dlog.isOpened()) {
piCout << "[PIBinaryLog]"
<< "Error, can't create" << dst;
<< "Error, can't create \"%1\""_tr("PIBinLog").arg(dst);
return false;
}
bool first = true;
@@ -746,7 +747,7 @@ bool PIBinaryLog::cutBinLog(const PIBinaryLog::BinLogInfo & src, const PIString
if (ids.contains(br.id)) {
if (dlog.writeBinLog_raw(br.id, br.timestamp - st, br.data) <= 0) {
piCout << "[PIBinaryLog]"
<< "Error, can't write to file" << dst;
<< "Error, can't write to file \"%1\""_tr("PIBinLog").arg(dst);
return false;
}
}
@@ -772,7 +773,7 @@ bool PIBinaryLog::joinBinLogsSerial(const PIStringList & src,
for (const PIString & fn: src) {
if (!slog.open(fn, PIIODevice::ReadOnly)) {
piCout << "[PIBinaryLog]"
<< "Error, can't open" << fn;
<< "Error, can't open \"%1\""_tr("PIBinLog").arg(fn);
return false;
}
if (first) {
@@ -781,11 +782,11 @@ bool PIBinaryLog::joinBinLogsSerial(const PIStringList & src,
dlog.createNewFile(dst);
if (!dlog.isOpened()) {
piCout << "[PIBinaryLog]"
<< "Error, can't create" << dst;
<< "Error, can't create \"%1\""_tr("PIBinLog").arg(dst);
return false;
}
piCout << "[PIBinaryLog]"
<< "Start join binlogs to" << dst;
<< "Start join binlogs to \"%1\""_tr("PIBinLog").arg(dst);
} else {
dtime = lt;
}
@@ -799,7 +800,7 @@ bool PIBinaryLog::joinBinLogsSerial(const PIStringList & src,
lt = dtime + br.timestamp;
if (dlog.writeBinLog_raw(br.id, lt, br.data) <= 0) {
piCout << "[PIBinaryLog]"
<< "Error, can't write to file" << dst;
<< "Error, can't write to file \"%1\""_tr("PIBinLog").arg(dst);
return false;
}
if (tm.elapsed_s() > 0.1) {
@@ -821,7 +822,7 @@ bool PIBinaryLog::joinBinLogsSerial(const PIStringList & src,
// piCout << "[PIBinaryLog]" << "complete" << fn;
}
piCout << "[PIBinaryLog]"
<< "Finish join binlogs, total time" << PITime::fromSystemTime(lt).toString();
<< "Finish join binlogs, total time %1"_tr("PIBinLog").arg(PITime::fromSystemTime(lt).toString());
return true;
}
@@ -853,7 +854,7 @@ int PIBinaryLog::posForTime(const PISystemTime & time) {
void PIBinaryLog::seekTo(int rindex) {
// piCoutObj << "seekTo";
// piCoutObj << "seekTo";
logmutex.lock();
pausemutex.lock();
if (rindex < index.index.size_s() && rindex >= 0) {
@@ -866,7 +867,7 @@ void PIBinaryLog::seekTo(int rindex) {
startlogtime = PISystemTime::current() - lastrecord.timestamp;
}
}
// piCoutObj << "seekTo done";
// piCoutObj << "seekTo done";
pausemutex.unlock();
logmutex.unlock();
}
@@ -947,7 +948,7 @@ void PIBinaryLog::configureFromFullPathDevice(const PIString & full_path) {
break;
}
}
// piCoutObj << "configured";
// piCoutObj << "configured";
}
@@ -989,7 +990,7 @@ void PIBinaryLog::propertyChanged(const char * s) {
split_time = property("splitTime").toSystemTime();
split_size = property("splitFileSize").toLLong();
split_count = property("splitRecordCount").toInt();
// piCoutObj << "propertyChanged" << s << play_mode;
// piCoutObj << "propertyChanged" << s << play_mode;
}

View File

@@ -24,6 +24,7 @@
#include "piliterals.h"
#include "pipropertystorage.h"
#include "pisysteminfo.h"
#include "pitranslator.h"
// clang-format off
#ifdef QNX
# include <arpa/inet.h>
@@ -897,7 +898,9 @@ void PIEthernet::server_func(void * eth) {
piMSleep(10);
return;
}
if (ce->debug()) piCout << "[PIEthernet] Can`t accept new connection," << ethErrorString();
if (ce->debug())
piCout << "[PIEthernet]"
<< "Can`t accept new connection, %1"_tr("PIEthernet").arg(ethErrorString());
piMSleep(50);
return;
}
@@ -1081,14 +1084,16 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO);
PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_INFO));
if (!pAdapterInfo) {
piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersInfo";
piCout << "[PIEthernet]"
<< "Error allocating memory needed to call GetAdaptersInfo"_tr("PIEthernet");
return il;
}
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
HeapFree(GetProcessHeap(), 0, pAdapterInfo);
pAdapterInfo = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), 0, ulOutBufLen);
if (!pAdapterInfo) {
piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersInfo";
piCout << "[PIEthernet]"
<< "Error allocating memory needed to call GetAdaptersInfo"_tr("PIEthernet");
return il;
}
}
@@ -1134,7 +1139,8 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
ifc.ifc_len = 256;
ifc.ifc_buf = new char[ifc.ifc_len];
if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
piCout << "[PIEthernet] Can`t get interfaces:" << errorString();
piCout << "[PIEthernet]"
<< "Can`t get interfaces: %1"_tr("PIEthernet").arg(errorString());
delete[] ifc.ifc_buf;
return il;
}
@@ -1223,7 +1229,8 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
}
freeifaddrs(ret);
} else
piCout << "[PIEthernet] Can`t get interfaces:" << errorString();
piCout << "[PIEthernet]"
<< "Can`t get interfaces: %1"_tr("PIEthernet").arg(errorString());
if (s != -1) ::close(s);
# endif
# endif

View File

@@ -23,6 +23,7 @@
#include "piincludes_p.h"
#include "piiostream.h"
#include "pitime_win.h"
#include "pitranslator.h"
#ifdef WINDOWS
# undef S_IFDIR
# undef S_IFREG
@@ -295,7 +296,7 @@ void PIFile::resize(llong new_size, uchar fill_) {
clear();
return;
}
piCoutObj << "Downsize is not supported yet :-(";
piCoutObj << "Downsize is not supported yet :-("_tr("PIFile");
}

View File

@@ -56,12 +56,12 @@ bool PIIOByteArray::open(const PIByteArray & buffer) {
ssize_t PIIOByteArray::readDevice(void * read_to, ssize_t size) {
// piCout << "PIIOByteArray::read" << data_ << size << canRead();
// piCout << "PIIOByteArray::read" << data_ << size << canRead();
if (!canRead() || !data_) return -1;
int ret = piMini(size, data_->size_s() - pos);
if (ret <= 0) return -1;
memcpy(read_to, data_->data(pos), ret);
// piCout << "readed" << ret;
// piCout << "readed" << ret;
pos += size;
if (pos > data_->size_s()) pos = data_->size_s();
return ret;
@@ -69,12 +69,12 @@ ssize_t PIIOByteArray::readDevice(void * read_to, ssize_t size) {
ssize_t PIIOByteArray::writeDevice(const void * data, ssize_t size) {
// piCout << "PIIOByteArray::write" << data << size << canWrite();
// piCout << "PIIOByteArray::write" << data << size << canWrite();
if (!canWrite() || !data) return -1;
// piCout << "write" << data;
if (pos > data_->size_s()) pos = data_->size_s();
PIByteArray rs = PIByteArray(data, size);
// piCoutObj << rs;
// piCoutObj << rs;
data_->insert(pos, rs);
pos += rs.size_s();
return rs.size_s();

View File

@@ -25,6 +25,7 @@
#include "piliterals_time.h"
#include "pipropertystorage.h"
#include "pitime.h"
#include "pitranslator.h"
//! \class PIIODevice piiodevice.h
@@ -222,7 +223,7 @@ void PIIODevice::stopThreadedRead() {
if (!destroying) {
interrupt();
} else {
piCoutObj << "Error: Device is running after destructor!";
piCoutObj << "Error: Device is running after destructor!"_tr("PIIODevice");
}
#endif
}
@@ -535,7 +536,7 @@ void PIIODevice::splitFullPath(PIString fpwm, PIString * full_path, DeviceMode *
if (fpwm.find('(') > 0 && fpwm.find(')') > 0) {
PIString dms(fpwm.right(fpwm.length() - fpwm.findLast('(')).takeRange('(', ')').trim().toLowerCase().removeAll(' '));
PIStringList opts(dms.split(","));
piForeachC(PIString & o, opts) {
for (const auto & o: opts) {
// piCout << dms;
if (o == "r"_a || o == "ro"_a || o == "read"_a || o == "readonly"_a) dm |= ReadOnly;
if (o == "w"_a || o == "wo"_a || o == "write"_a || o == "writeonly"_a) dm |= WriteOnly;
@@ -666,7 +667,7 @@ PIMap<PIConstChars, PIIODevice::FabricInfo> & PIIODevice::fabrics() {
bool PIIODevice::threadedRead(const uchar * readed, ssize_t size) {
// piCout << "iodevice threaded read";
// piCout << "iodevice threaded read";
if (func_read) return func_read(readed, size, ret_data_);
return true;
}

View File

@@ -19,6 +19,8 @@
#include "piiostring.h"
#include "pitranslator.h"
//! \class PIIOString piiostring.h
//! \details
@@ -49,7 +51,7 @@ void PIIOString::clear() {
bool PIIOString::open(PIString * string, PIIODevice::DeviceMode mode) {
if (mode == PIIODevice::ReadWrite) {
piCoutObj << "Error: ReadWrite mode not supported, use WriteOnly or ReadOnly";
piCoutObj << "Error: ReadWrite mode not supported, use WriteOnly or ReadOnly"_tr("PIIOString");
str = nullptr;
return false;
}

View File

@@ -24,6 +24,7 @@
#include "piincludes_p.h"
#include "pipropertystorage.h"
#include "pitime.h"
#include "pitranslator.h"
#include "piwaitevent_p.h"
#include <errno.h>
@@ -463,10 +464,10 @@ int PISerial::convertSpeed(PISerial::Speed speed) {
default: break;
}
#ifdef WINDOWS
piCoutObj << "Warning: Custom speed" << (int)speed;
piCoutObj << "Warning: Custom speed %1"_tr("PISerial").arg((int)speed);
return (int)speed;
#else
piCoutObj << "Warning: Unknown speed" << (int)speed << ", using 115200";
piCoutObj << "Warning: Unknown speed %1, using 115200"_tr("PISerial").arg((int)speed);
return B115200;
#endif
}
@@ -691,7 +692,7 @@ bool PISerial::openDevice() {
}
}
if (p.isEmpty()) {
piCoutObj << "Unable to find device \"" << pl << "\"";
piCoutObj << "Unable to find device \"%1\""_tr("PISerial").arg(pl);
}
}
if (p.isEmpty()) return false;
@@ -708,7 +709,7 @@ bool PISerial::openDevice() {
PIString wp = "//./" + p;
PRIVATE->hCom = CreateFileA(wp.dataAscii(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
if (PRIVATE->hCom == INVALID_HANDLE_VALUE) {
piCoutObj << "Unable to open \"" << p << "\"" << errorString();
piCoutObj << "Unable to open \"%1\": %2"_tr("PISerial").arg(p).arg(errorString());
fd = -1;
return false;
}
@@ -722,7 +723,7 @@ bool PISerial::openDevice() {
}
fd = ::open(p.data(), O_NOCTTY | om);
if (fd == -1) {
piCoutObj << "Unable to open \"" << p << "\"";
piCoutObj << "Unable to open \"%1\": %2"_tr("PISerial").arg(p).arg(errorString());
return false;
}
tcgetattr(fd, &PRIVATE->desc);
@@ -747,7 +748,7 @@ bool PISerial::closeDevice() {
#ifdef WINDOWS
SetCommState(PRIVATE->hCom, &PRIVATE->sdesc);
SetCommMask(PRIVATE->hCom, PRIVATE->mask);
// piCoutObj << "close" <<
// piCoutObj << "close" <<
CloseHandle(PRIVATE->hCom);
PRIVATE->hCom = 0;
#else
@@ -788,7 +789,7 @@ void PISerial::applySettings() {
}
PRIVATE->desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT;
if (SetCommState(PRIVATE->hCom, &PRIVATE->desc) == -1) {
piCoutObj << "Unable to set comm state for \"" << path() << "\"";
piCoutObj << "Unable to set comm state for \"%1\""_tr("PISerial").arg(path());
return;
}
#else
@@ -822,7 +823,7 @@ void PISerial::applySettings() {
setTimeouts();
if (tcsetattr(fd, TCSANOW, &PRIVATE->desc) < 0) {
piCoutObj << "Can`t set attributes for \"" << path() << "\"";
piCoutObj << "Can`t set attributes for \"%1\""_tr("PISerial").arg(path());
return;
}
#endif
@@ -871,7 +872,7 @@ ssize_t PISerial::readDevice(void * read_to, ssize_t max_size) {
// piCoutObj << "read ..." << PRIVATE->hCom << max_size;
DWORD mask = 0;
if (GetCommMask(PRIVATE->hCom, &mask) == FALSE) {
piCoutObj << "read error" << errorString();
piCoutObj << "Read error: %1"_tr("PISerial").arg(errorString());
stop();
close();
return 0;
@@ -883,7 +884,7 @@ ssize_t PISerial::readDevice(void * read_to, ssize_t max_size) {
DWORD err = GetLastError();
// piCoutObj << "read" << err;
if (err == ERROR_BAD_COMMAND || err == ERROR_ACCESS_DENIED) {
piCoutObj << "read error" << errorString();
piCoutObj << "Read error: %1"_tr("PISerial").arg(errorString());
stop();
close();
return 0;

View File

@@ -21,9 +21,12 @@
#include "piliterals_time.h"
#include "pitime.h"
#include "pitranslator.h"
const uint PIBaseTransfer::signature = 0x54424950;
PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) {
header.sig = signature;
crc_enabled = true;
@@ -96,7 +99,7 @@ void PIBaseTransfer::received(PIByteArray data) {
data >> h;
PacketType pt = (PacketType)h.type;
if (!h.check_sig()) {
piCoutObj << "invalid packet signature";
piCoutObj << "invalid packet signature"_tr("PIBaseTransfer");
diag.received(data.size(), false);
return;
} else
@@ -119,7 +122,7 @@ void PIBaseTransfer::received(PIByteArray data) {
ccrc = 0;
if (rcrc != ccrc) {
header.id = h.id;
piCoutObj << "invalid CRC";
piCoutObj << "invalid CRC"_tr("PIBaseTransfer");
sendReply(pt_ReplyInvalid);
} else {
mutex_session.lock();
@@ -170,9 +173,9 @@ void PIBaseTransfer::received(PIByteArray data) {
if (send_up > 20 && send_up > packets_count * 2) packets_count += piMaxi(packets_count / 10, 1);
// piCoutObj << packets_count;
} else
piCoutObj << "invalid reply id";
piCoutObj << "invalid reply id"_tr("PIBaseTransfer");
mutex_session.unlock();
// piCoutObj << "Done Packet" << h.id;
// piCoutObj << "Done Packet" << h.id;
}
if (is_receiving && h.id == 0) {
if (pt == pt_ReplySuccess) {
@@ -213,7 +216,7 @@ void PIBaseTransfer::received(PIByteArray data) {
}
if (is_receiving) {
if (header.session_id != h.session_id) {
piCoutObj << "restart receive";
piCoutObj << "restart receive"_tr("PIBaseTransfer");
mutex_header.unlock();
finish_receive(false, true);
} else {
@@ -344,7 +347,7 @@ bool PIBaseTransfer::send_process() {
mutex_send.unlock();
if (break_) return finish_send(false);
}
// piCoutObj << "send done, checking";
// piCoutObj << "send done, checking";
PITimeMeasurer rtm;
int prev_chk = 0;
mutex_send.lock();
@@ -516,7 +519,7 @@ bool PIBaseTransfer::getStartRequest() {
diag.sended(ba.size_s());
sendRequest(ba);
if (break_) return false;
// piCoutObj << replies[0];
// piCoutObj << replies[0];
mutex_session.lock();
if (replies[0] == pt_ReplySuccess) {
state_string = "send permited!";
@@ -532,7 +535,7 @@ bool PIBaseTransfer::getStartRequest() {
void PIBaseTransfer::processData(int id, PIByteArray & data) {
// piCoutObj << "received packet" << id << ", size" << data.size();
// piCoutObj << "received packet" << id << ", size" << data.size();
if (id < 1 || id > replies.size_s()) return;
if (!session[id - 1].isEmpty()) {
header.id = id;
@@ -595,7 +598,7 @@ PIByteArray PIBaseTransfer::build_packet(int id) {
hdr << header;
mutex_header.unlock();
ret.insert(0, hdr);
// piCoutObj << "Send Packet" << header.id << ret.size();
// piCoutObj << "Send Packet" << header.id << ret.size();
return ret;
}

View File

@@ -23,6 +23,7 @@
#include "piiostream.h"
#include "piliterals_time.h"
#include "pitime.h"
#include "pitranslator.h"
/** \class PIConnection
* \brief Complex Input/Output point
@@ -142,7 +143,7 @@ bool PIConnection::configure(PIConfig & conf, const PIString & name_) {
// piCout << name_list << flt_list << chk_set;
chk_set.remove("");
if (!chk_set.isEmpty()) {
piCoutObj << "Error," << chk_set.toVector() << "names assigned to both devices and filters!";
piCoutObj << "Error,"_tr("PIConnection") << chk_set.toVector() << "names assigned to both devices and filters!"_tr("PIConnection");
return false;
}
PIMap<PIString, PIString> dev_aliases;
@@ -238,7 +239,7 @@ bool PIConnection::configure(PIConfig & conf, const PIString & name_) {
}
setDebug(pdebug);
for (const PIString & f: filter_fails) {
piCoutObj << "\"addFilter\" error: no such device \"" << f << "\"!";
piCoutObj << "\"addFilter\" error: no such device \"%1\"!"_tr("PIConnection").arg(f);
}
for (const PIConfig::Entry * e: cb) {
PIString f(e->getValue("from").value()), t(e->getValue("to").value());
@@ -469,7 +470,7 @@ PIPacketExtractor * PIConnection::addFilter(const PIString & name_, const PIStri
if (extractors.value(full_path, nullptr)) pe = extractors.value(full_path, nullptr)->extractor;
if (pe) dev = pe;
if (!dev) {
piCoutObj << "\"addFilter\" error: no such device or filter \"" << full_path << "\"!";
piCoutObj << "\"addFilter\" error: no such device or filter \"%1\"!"_tr("PIConnection").arg(full_path);
return nullptr;
}
if (!e) {
@@ -508,7 +509,7 @@ PIPacketExtractor * PIConnection::addFilter(PIPacketExtractor * filter, const PI
if (pe) {
dev = pe;
} else {
piCoutObj << "\"addFilter\" error: no such device or filter \"" << full_path << "\"!";
piCoutObj << "\"addFilter\" error: no such device or filter \"%1\"!"_tr("PIConnection").arg(full_path);
return nullptr;
}
if (!e) {
@@ -739,7 +740,7 @@ void PIConnection::addSender(const PIString & name_, const PIString & full_path_
}
PIIODevice * dev = devByString(full_path_name);
if (!dev) {
piCoutObj << "\"addSender\" error: no such device \"" << full_path_name << "\"!";
piCoutObj << "\"addSender\" error: no such device \"%1\"!"_tr("PIConnection").arg(full_path_name);
return;
}
if (!s->isRunning() && start_) {
@@ -899,7 +900,7 @@ int PIConnection::writeByFullPath(const PIString & full_path, const PIByteArray
PIIODevice * dev = __device_pool__->device(fp);
// piCout << "SEND" << full_path << fp;
if (!dev) {
piCoutObj << "No such full path \"" << full_path << "\"!";
piCoutObj << "No such full path \"%1\"!"_tr("PIConnection").arg(full_path);
return -1;
}
return write(dev, data);
@@ -909,7 +910,7 @@ int PIConnection::writeByFullPath(const PIString & full_path, const PIByteArray
int PIConnection::writeByName(const PIString & name_, const PIByteArray & data) {
PIIODevice * dev = deviceByName(name_);
if (!dev) {
piCoutObj << "No such device \"" << name_ << "\"!";
piCoutObj << "No such device \"%1\"!"_tr("PIConnection").arg(name_);
return -1;
}
return write(dev, data);
@@ -918,12 +919,12 @@ int PIConnection::writeByName(const PIString & name_, const PIByteArray & data)
int PIConnection::write(PIIODevice * dev, const PIByteArray & data) {
if (!dev) {
piCoutObj << "Null Device!";
piCoutObj << "Null Device!"_tr("PIConnection");
return -1;
}
if (!dev->isOpened()) return -1;
if (!dev->canWrite()) {
piCoutObj << "Device \"" << dev->constructFullPath() << "\" can`t write!";
piCoutObj << "Device \"%1\" can`t write!"_tr("PIConnection").arg(dev->constructFullPath());
return -1;
}
int ret = dev->write(data);
@@ -982,7 +983,7 @@ PIIODevice * PIConnection::DevicePool::addDevice(PIConnection * parent, const PI
// piCout << "new device" << fp;
dd->dev = PIIODevice::createFromFullPath(fp);
if (!dd->dev) {
piCoutObj << "Error: can`t create device \"" << fp << "\"!"; //:" << errorString();
piCoutObj << "Error: can`t create device \"%1\"!"_tr("PIConnection").arg(fp);
return nullptr;
}
dd->dev->setProperty("__fullPath__", fp);
@@ -1258,7 +1259,7 @@ void PIConnection::unboundExtractor(PIPacketExtractor * pe) {
void PIConnection::packetExtractorReceived(const uchar * data, int size) {
PIString from(emitter() ? emitter()->name() : PIString());
PIIODevice * cd = (PIIODevice *)emitter();
// piCout << "packetExtractorReceived" << from << cd;
// piCout << "packetExtractorReceived" << from << cd;
if (cd) {
PIVector<PIPacketExtractor *> be(bounded_extractors.value(cd));
// piCout << be << (void*)data << size;

View File

@@ -152,16 +152,16 @@ void PIDiagnostics::sended(int size) {
void PIDiagnostics::tick(int) {
auto speed_sec = "/s"_tr("PIDiag");
mutex_state.lock();
auto speed_sec = PITranslator::tr("/s", "PIDiag");
// piCoutObj << "lock";
int tcnt_recv = 0;
int tcnt_send = 0;
Entry send = calcHistory(history_send, tcnt_send);
Entry recv = calcHistory(history_rec, tcnt_recv);
float itr = disconn_.toSeconds() * (float(tcnt_recv) / history_rec.size());
float its = disconn_.toSeconds() * (float(tcnt_send) / history_send.size());
float hz = 1. / interval().toSeconds();
int tcnt_recv = 0;
int tcnt_send = 0;
Entry send = calcHistory(history_send, tcnt_send);
Entry recv = calcHistory(history_rec, tcnt_recv);
float itr = disconn_.toSeconds() * (float(tcnt_recv) / history_rec.size());
float its = disconn_.toSeconds() * (float(tcnt_send) / history_send.size());
float hz = 1. / interval().toSeconds();
if (tcnt_recv == 0) {
cur_state.integral_freq = cur_state.immediate_freq = 0;
cur_state.received_packets_per_sec = cur_state.received_bytes_per_sec = 0;
@@ -197,7 +197,7 @@ void PIDiagnostics::tick(int) {
diag = PIDiagnostics::Good;
}
if ((tcnt_send + tcnt_recv) != 0) {
// piCoutObj << tcnt_recv << tcnt_send;
// piCoutObj << tcnt_recv << tcnt_send;
history_rec.dequeue();
history_send.dequeue();
Entry e;
@@ -225,7 +225,7 @@ PIDiagnostics::Entry PIDiagnostics::calcHistory(PIQueue<Entry> & hist, int & cnt
if (!hist[i].empty) cnt++;
}
e.empty = false;
// piCoutObj << hist.size() << cnt;
// piCoutObj << hist.size() << cnt;
return e;
}

View File

@@ -19,7 +19,6 @@
#include "piresourcesstorage.h"
#include "pichunkstream.h"
#include "piset.h"
@@ -42,11 +41,11 @@ void PIResourcesStorage::Section::add(const PIResourcesStorage::Section & s) {
void PIResourcesStorage::Section::purge() {
PIVector<PIByteArray *> bav = entries.values();
PISet<PIByteArray *> bas;
piForeach(PIByteArray * i, bav) {
for (auto i: bav) {
if (i) bas << i;
}
bav = bas.toVector();
piForeach(PIByteArray * i, bav)
for (auto i: bav)
delete i;
entries.clear();
}
@@ -76,14 +75,14 @@ void PIResourcesStorage::registerSection(const uchar * rc_data, const uchar * rc
PIVector<PIResourcesStorage::__RCEntry> el;
dba >> el;
PIMap<PIString, PIVector<PIResourcesStorage::__RCEntry>> ebs;
piForeachC(PIResourcesStorage::__RCEntry & e, el) {
for (const auto & e: el) {
ebs[e.section] << e;
}
auto it = ebs.makeIterator();
while (it.next()) {
PIResourcesStorage::Section s;
const PIVector<PIResourcesStorage::__RCEntry> & itv(it.value());
piForeachC(PIResourcesStorage::__RCEntry & e, itv) {
for (const auto & e: itv) {
// piCout << "add" << e.name << e.alias << PIString::readableSize(e.size);
PIByteArray * eba = new PIByteArray(&(rc_data[e.offset]), e.size);
s.entries[e.name] = eba;
@@ -123,7 +122,7 @@ PIByteArray PIResourcesStorage::get(const PIString & entry_name) const {
void PIResourcesStorage::clear() {
// piCout << "PIResourcesStorage clear";
PIVector<Section *> sv = sections.values();
piForeach(Section * i, sv) {
for (auto i: sv) {
if (i) i->purge();
}
sections.clear();

View File

@@ -20,7 +20,7 @@
#include "pistatemachine_state.h"
#include "pistatemachine_transition.h"
#include "pitranslator.h"
PIStateBase::~PIStateBase() {
piDeleteAll(transitions);
@@ -108,7 +108,7 @@ bool PIStateBase::start(bool force) {
setActive(true);
return initial_state->start();
} else {
piCout << "error:" << getName() << "no initial state!";
piCout << "Error: \"%1\" no initial state!"_tr("PIStateMachine").arg(getName());
return false;
}
} else {

View File

@@ -19,6 +19,7 @@
#include "piliterals_time.h"
#include "pitime.h"
#include "pitranslator.h"
#ifndef MICRO_PIP
# include "piincludes_p.h"
@@ -196,7 +197,7 @@ void PIProcess::startProc(bool detached) {
CloseHandle(PRIVATE->pi.hThread);
CloseHandle(PRIVATE->pi.hProcess);
} else
piCoutObj << "\"CreateProcess\" error, " << errorString();
piCoutObj << "\"CreateProcess\" error: %1"_tr("PIProcess").arg(errorString());
# else
// cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;

View File

@@ -297,7 +297,7 @@ llong PIString::toNumberBase(const PIString & value, int base, bool * ok) {
void PIString::appendFromChars(const char * c, int s, const char * codepage) {
// piCout << "appendFromChars";
// piCout << "appendFromChars";
if (s == 0) return;
int old_sz = size_s();
if (s == -1) s = strlen(c);
@@ -523,6 +523,31 @@ void PIString::trimsubstr(int & st, int & fn) const {
}
PIString PIString::minArgPlaceholder() {
if (size() < 2) return {};
int min = -1;
PIString ret, tmp;
for (int i = 0; i < size_s(); ++i) {
if (at(i) == '%') {
int j = 0;
for (j = i + 1; j < size_s(); ++j) {
if (!at(j).isDigit()) break;
}
bool ok = false;
tmp = mid(i + 1, j - i - 1);
int cur = tmp.toInt(10, &ok);
if (!ok) continue;
if (min < 0 || min > cur) {
min = cur;
ret = tmp;
}
}
}
if (ret.isEmpty()) return {};
return "%" + ret;
}
uint PIString::hash() const {
return piHashData((const uchar *)d.data(), d.size() * sizeof(PIChar));
}
@@ -1744,10 +1769,9 @@ ldouble PIString::toLDouble() const {
//! piCout << s; // 47.6 GiB
//! \endcode
PIString & PIString::setReadableSize(llong bytes) {
static const PIString tr_c = "PIString"_a;
clear();
if (bytes < 1024) {
*this += (PIString::fromNumber(bytes) + " "_a + PITranslator::tr("B", tr_c));
*this += (PIString::fromNumber(bytes) + " "_a + "B"_tr("PIString"));
return *this;
}
double fres = bytes;
@@ -1762,14 +1786,21 @@ PIString & PIString::setReadableSize(llong bytes) {
}
return false;
};
if (checkRange(PITranslator::tr("KiB", tr_c))) return *this;
if (checkRange(PITranslator::tr("MiB", tr_c))) return *this;
if (checkRange(PITranslator::tr("GiB", tr_c))) return *this;
if (checkRange(PITranslator::tr("TiB", tr_c))) return *this;
if (checkRange(PITranslator::tr("PiB", tr_c))) return *this;
if (checkRange(PITranslator::tr("EiB", tr_c))) return *this;
if (checkRange(PITranslator::tr("ZiB", tr_c))) return *this;
checkRange(PITranslator::tr("YiB", tr_c), true);
if (checkRange("KiB"_tr("PIString"))) return *this;
if (checkRange("MiB"_tr("PIString"))) return *this;
if (checkRange("GiB"_tr("PIString"))) return *this;
if (checkRange("TiB"_tr("PIString"))) return *this;
if (checkRange("PiB"_tr("PIString"))) return *this;
if (checkRange("EiB"_tr("PIString"))) return *this;
if (checkRange("ZiB"_tr("PIString"))) return *this;
checkRange("YiB"_tr("PIString"), true);
return *this;
}
PIString & PIString::arg(const PIString & v) {
auto ph = minArgPlaceholder();
if (!ph.isEmpty()) replaceAll(ph, v);
return *this;
}

View File

@@ -1682,6 +1682,61 @@ public:
//! \~\sa PIString::readableSize()
PIString & setReadableSize(llong bytes);
//! \~english Replace all occurances like "%1", "%2", ... with lowest value to "v" and returns this string.
//! \~russian Заменяет все вхождения типа "%1", "%2", ... с наименьшим значением на "v" и возвращает эту строку.
//! \~\details
//! \~\code
//! piCout << PIString("color %1 is not %2, but %1").arg("red").arg("green"); // color red is not green, but red
//! \endcode
PIString & arg(const PIString & v);
//! \~english Replace all occurances like "%1", "%2", ... with lowest value to "v" and returns this string.
//! \~russian Заменяет все вхождения типа "%1", "%2", ... с наименьшим значением на "v" и возвращает эту строку.
PIString & arg(short v, int base = 10) { return arg(PIString::fromNumber(v, base)); }
//! \~english Replace all occurances like "%1", "%2", ... with lowest value to "v" and returns this string.
//! \~russian Заменяет все вхождения типа "%1", "%2", ... с наименьшим значением на "v" и возвращает эту строку.
PIString & arg(ushort v, int base = 10) { return arg(PIString::fromNumber(v, base)); }
//! \~english Replace all occurances like "%1", "%2", ... with lowest value to "v" and returns this string.
//! \~russian Заменяет все вхождения типа "%1", "%2", ... с наименьшим значением на "v" и возвращает эту строку.
//! \~\details
//! \~\code
//! piCout << PIString("ten = %1").arg(10); // ten = 10
//! piCout << PIString("'%1' is max hex letter (%2 in dec)").arg(0xF, 16).arg(0xF); // 'F' is max hex letter (15 in dec)
//! \endcode
PIString & arg(int v, int base = 10) { return arg(PIString::fromNumber(v, base)); }
//! \~english Replace all occurances like "%1", "%2", ... with lowest value to "v" and returns this string.
//! \~russian Заменяет все вхождения типа "%1", "%2", ... с наименьшим значением на "v" и возвращает эту строку.
PIString & arg(uint v, int base = 10) { return arg(PIString::fromNumber(v, base)); }
//! \~english Replace all occurances like "%1", "%2", ... with lowest value to "v" and returns this string.
//! \~russian Заменяет все вхождения типа "%1", "%2", ... с наименьшим значением на "v" и возвращает эту строку.
PIString & arg(llong v, int base = 10) { return arg(PIString::fromNumber(v, base)); }
//! \~english Replace all occurances like "%1", "%2", ... with lowest value to "v" and returns this string.
//! \~russian Заменяет все вхождения типа "%1", "%2", ... с наименьшим значением на "v" и возвращает эту строку.
PIString & arg(ullong v, int base = 10) { return arg(PIString::fromNumber(v, base)); }
//! \~english Replace all occurances like "%1", "%2", ... with lowest value to "v" and returns this string.
//! \~russian Заменяет все вхождения типа "%1", "%2", ... с наименьшим значением на "v" и возвращает эту строку.
PIString & arg(float v, char format = 'f', int precision = 8) { return arg(PIString::fromNumber(v, format, precision)); }
//! \~english Replace all occurances like "%1", "%2", ... with lowest value to "v" and returns this string.
//! \~russian Заменяет все вхождения типа "%1", "%2", ... с наименьшим значением на "v" и возвращает эту строку.
//! \~\details
//! \~\code
//! piCout << PIString("light speed = %1 %2").arg(M_LIGHT_SPEED, 'g', 4).arg("m/s"); // light speed = 2.998e+08 m/s
//! \endcode
PIString & arg(double v, char format = 'f', int precision = 8) { return arg(PIString::fromNumber(v, format, precision)); }
//! \~english Replace all occurances like "%1", "%2", ... with lowest value to "v" and returns this string.
//! \~russian Заменяет все вхождения типа "%1", "%2", ... с наименьшим значением на "v" и возвращает эту строку.
PIString & arg(ldouble v, char format = 'f', int precision = 8) { return arg(PIString::fromNumber(v, format, precision)); }
//! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details
@@ -1867,6 +1922,7 @@ private:
void buildData(const char * cp = __syslocname__) const;
void deleteData() const;
void trimsubstr(int & st, int & fn) const;
PIString minArgPlaceholder();
PIDeque<PIChar> d;
mutable bool changed_ = true;

View File

@@ -22,6 +22,7 @@
#include "piincludes_p.h"
#include "piintrospection_threads.h"
#include "pitime.h"
#include "pitranslator.h"
#ifndef MICRO_PIP
# include "pisystemtests.h"
#endif
@@ -568,7 +569,7 @@ PIThread::PIThread(bool startNow, PISystemTime loop_delay): PIObject() {
PIThread::~PIThread() {
PIINTROSPECTION_THREAD_DELETE(this);
if (!running_ || PRIVATE->thread == 0) return;
piCout << "[PIThread \"" << name() << "\"] Warning, terminate on destructor!";
piCout << "[PIThread \"%1\"] Warning, terminate on destructor!"_tr("PIThread").arg(name());
#ifdef FREERTOS
// void * ret(0);
// PICout(PICoutManipulators::DefaultControls) << "~PIThread" << PRIVATE->thread;
@@ -663,7 +664,7 @@ void PIThread::stop() {
void PIThread::terminate() {
piCoutObj << "Warning, terminate!";
piCoutObj << "Warning, terminate!"_tr("PIThread");
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "terminate ..." << running_;
#ifdef FREERTOS
PICout(PICoutManipulators::DefaultControls) << "FreeRTOS can't terminate pthreads! waiting for stop";
@@ -781,7 +782,7 @@ bool PIThread::_startThread(void * func) {
running_ = false;
PRIVATE->thread = 0;
piCoutObj << "Error: Can`t start new thread:" << errorString();
piCoutObj << "Error: Can`t start new thread: %1"_tr("PIThread").arg(errorString());
return false;
}

View File

@@ -23,6 +23,7 @@
#include "piiostream.h"
#include "piliterals_time.h"
#include "pitime.h"
#include "pitranslator.h"
#include <ctime>
#ifdef QNX
@@ -320,7 +321,8 @@ PISystemTime PITimeMeasurer::elapsed() const {
PISystemTime PISystemTime::Frequency::toSystemTime() const {
if (value_hz <= 0.) {
piCout << "[PISystemTime::Frequency] toSystemTime() warning: invalid hertz" << value_hz;
piCout << "[PISystemTime::Frequency]"
<< "toSystemTime() Warning: invalid hertz: %1"_tr("PISystemTime").arg(value_hz);
return PISystemTime();
}
return PISystemTime::fromSeconds(1. / value_hz);
@@ -329,7 +331,8 @@ PISystemTime PISystemTime::Frequency::toSystemTime() const {
PISystemTime::Frequency PISystemTime::Frequency::fromSystemTime(const PISystemTime & st) {
if (st == PISystemTime()) {
piCout << "[PISystemTime::Frequency] fromSystemTime() warning: null frequency";
piCout << "[PISystemTime::Frequency]"
<< "fromSystemTime() Warning: null frequency"_tr("PISystemTime");
return Frequency();
}
return Frequency(1. / st.toSeconds());

View File

@@ -19,6 +19,8 @@
#include "pivariant.h"
#include "pitranslator.h"
//! \class PIVariant pivariant.h
//! \details
@@ -388,7 +390,7 @@ PIVariant PIVariant::fromValue(const PIByteArray & c, uint type_id) {
} else
#endif
{
piCout << "Can`t initialize PIVariant from unregistered typeID \"" << type_id << "\"!";
piCout << "Can`t initialize PIVariant from unregistered typeID \"%1\"!"_tr("PIVariant").arg(type_id);
return ret;
}
}
@@ -410,7 +412,7 @@ PIVariant PIVariant::fromValue(const PIByteArray & c, const PIString & type) {
} else
#endif
{
piCout << "Can`t initialize PIVariant from unregistered type \"" << type << "\"!";
piCout << "Can`t initialize PIVariant from unregistered type \"%1\"!"_tr("PIVariant").arg(type);
return ret;
}
}

View File

@@ -1,6 +1,7 @@
#include "piopencl.h"
#include "piresources.h"
#include "pitranslator.h"
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS
#define CL_TARGET_OPENCL_VERSION 120
@@ -88,7 +89,8 @@ void PIOpenCL::Initializer::init() {
cl_uint plat_num = 0;
ret = clGetPlatformIDs(max_size, cl_platforms, &plat_num);
if (ret != 0) {
piCout << "[PIOpenCL] Error: OpenCL platforms not found!";
piCout << "[PIOpenCL]"
<< "Error: OpenCL platforms not found!"_tr("PIOpenCL");
return;
}
for (uint i = 0; i < plat_num; i++) {
@@ -504,7 +506,7 @@ bool PIOpenCL::Program::initKernels(PIVector<void *> kerns) {
bool PIOpenCL::Kernel::execute() {
if (dims.isEmpty()) {
piCout << "[PIOpenCL::Kernel]"
<< "Error: empty range";
<< "Error: empty range"_tr("PIOpenCL");
return false;
}
cl_int ret = clEnqueueNDRangeKernel(context_->PRIVATEWB->queue, PRIVATE->kernel, dims.size(), 0, dims.data(), 0, 0, 0, 0);
@@ -581,13 +583,13 @@ void setArgV(cl_kernel k, int index, T v) {
bool PIOpenCL::Kernel::setArgValueS(int index, const PIVariant & value) {
if (index < 0 || index >= args_.size_s()) {
piCout << "[PIOpenCL::Kernel]"
<< "setArgValue invalid index" << index;
<< "setArgValue invalid index %1"_tr("PIOpenCL").arg(index);
return false;
}
KernelArg & ka(args_[index]);
if (ka.dims > 0) {
piCout << "[PIOpenCL::Kernel]"
<< "setArgValue set scalar to \"" << ka.type_name << ka.arg_name << "\"";
<< "setArgValue set scalar to \"%1 %2\""_tr("PIOpenCL").arg(ka.type_name).arg(ka.arg_name);
return false;
}
switch (ka.arg_type) {
@@ -611,13 +613,13 @@ bool PIOpenCL::Kernel::bindArgValue(int index, Buffer * buffer) {
if (!buffer) return false;
if (index < 0 || index >= args_.size_s()) {
piCout << "[PIOpenCL::Kernel]"
<< "bindArgValue invalid index" << index;
<< "bindArgValue invalid index %1"_tr("PIOpenCL").arg(index);
return false;
}
KernelArg & ka(args_[index]);
if (ka.dims <= 0) {
piCout << "[PIOpenCL::Kernel]"
<< "bindArgValue set buffer to \"" << ka.type_name << ka.arg_name << "\"";
<< "bindArgValue set buffer to \"%1 %2\""_tr("PIOpenCL").arg(ka.type_name).arg(ka.arg_name);
return false;
}
clSetKernelArg(PRIVATE->kernel, index, sizeof(buffer->PRIVATEWB->buffer), &(buffer->PRIVATEWB->buffer));

View File

@@ -8,25 +8,45 @@
#include "pilog.h"
#include "pimathbase.h"
#include "pip.h"
#include "pitranslator_p.h"
#include "pivaluetree_conversions.h"
using namespace PICoutManipulators;
template<typename Type>
void foo() {
static_assert(std::is_arithmetic<Type>::value || is_complex<Type>::value, "Type must be arithmetic");
}
int main(int argc, char * argv[]) {
// piCout << PIString::readableSize(50_KiB);
// piCout << PIString::readableSize(1_GB);
PITranslator::loadLang("ru");
PITranslator::loadConfig("[]\ntest \\\nstring=привет\n"_u8);
PISerial f("COM123");
f.open();
/*auto test = [](PIString s, PIString v) {
piCout << " in:" << s;
piCout << "arg:" << minArgPlaceholder(s);
piCout << "out:" << arg(s, v);
piCout << "";
};
test(" %", "asd");
test("%", "asd");
test("1", "asd");
test(" %11", "asd");
test("%1%2 %0f%0g", "asd");
test("%01 ", "asd");*/
/*piCout << PIString::readableSize(50_KiB);
piCout << PIString::readableSize(1_GB);
PITranslator::loadLang("ru");
piCout << PIString::readableSize(50_KiB);
piCout << PIString::readableSize(1_GB);
piCout << "test\nstring"_tr;
PITranslator::clear();
piCout << PIString::readableSize(50_KiB);
piCout << PIString::readableSize(1_GB);
piCout << "test\nstring"_tr;
piCout << "hello!"_tr;
PITranslator::loadConfig("[]\nhello!=привет!\n[Co]\nhello!=привет CO!\n"_u8);
piCout << "hello!"_tr("Co") << "hello!"_tr;*/
// piCout << "hello!"_trNoOp;
// PICodeParser parser;
// parser.parseFile("cmg_test.h");
/*for (auto m: parser.macros) {

View File

@@ -20,8 +20,7 @@
#include "picli.h"
#include "picodeparser.h"
#include "piiostream.h"
#include <iostream>
#include "pitranslator.h"
using namespace PICoutManipulators;
@@ -107,10 +106,6 @@ void help() {
piCout << help_string;
}
void printError(const PIString & msg) {
std::cerr << msg.data() << std::endl;
}
PIString toCName(const PIString & s) {
PIString ret(s.trimmed());
@@ -307,7 +302,7 @@ bool writeClassStreamMembersOut(PIIOTextStream & ts, const PICodeParser::Entity
++cnt;
if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
if (used_id[cnt]) {
printError("Error with \"" + e->name + "\" stream operator: ID " + PIString::fromNumber(cnt) + " already used");
piCerr << "Error with \"%1\" stream operator: ID %2 already used"_tr("pip_cmg").arg(e->name).arg(cnt);
return false;
}
if (m.dims.isEmpty()) {
@@ -361,7 +356,7 @@ bool writeClassStreamMembersIn(PIIOTextStream & ts, const PICodeParser::Entity *
++cnt;
if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
if (used_id[cnt]) {
printError("Error with \"" + e->name + "\" stream operator: ID " + PIString::fromNumber(cnt) + " already used");
piCerr << "Error with \"%1\" stream operator: ID %2 already used"_tr("pip_cmg").arg(e->name).arg(cnt);
return false;
}
used_id << cnt;
@@ -496,7 +491,7 @@ bool writeModel(PICodeParser & parser, PICLI & cli, const PIString out, bool met
PIFile f(out + ".cpp");
f.clear();
if (!f.open(PIIODevice::WriteOnly)) {
piCout << "Error: can`t open out file" << f.path();
piCerr << "Error: can`t open output file \"%1\""_tr("pip_cmg").arg(f.path());
return false;
}
PIIOTextStream ts(&f);
@@ -585,7 +580,7 @@ bool writeModel(PICodeParser & parser, PICLI & cli, const PIString out, bool met
f.setPath(out + ".h");
f.clear();
if (!f.open(PIIODevice::WriteOnly)) {
piCout << "Error: can`t open out file" << f.path();
piCerr << "Error: can`t open output file \"%1\""_tr("pip_cmg").arg(f.path());
return false;
}
ts << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n");

View File

@@ -640,7 +640,7 @@ int main(int argc, char * argv[]) {
if (!objdump.isEmpty()) ++etcnt;
if (!otool.isEmpty()) ++etcnt;
if (etcnt > 1) {
piCout << "Can use only one of \"readelf\", \"objdump\" and \"otool\"!";
piCerr << "Can use only one of \"readelf\", \"objdump\" and \"otool\"!";
return 1;
}
if (etcnt > 0) is_ldd = false;

View File

@@ -20,17 +20,19 @@
#include "pifile.h"
#include "piiostream.h"
#include "pitranslator.h"
void TSFile::Context::confirm(const PIString & msg, const PIString & file, int line) {
if (msg.isEmpty()) return;
bool TSFile::Context::confirm(const PIString & msg, const PIString & file, int line) {
if (msg.isEmpty()) return false;
bool is_new = !messages.contains(msg);
auto & m(messages[msg]);
m.source = msg;
m.filename = file;
m.line = line >= 0 ? PIString::fromNumber(line) : PIString();
m.obsolete = false;
if (is_new) m.type = "unfinished";
m.type.setFlag(Message::Missing, false);
if (is_new) m.type.setFlag(Message::Unfinished);
return is_new;
}
@@ -65,14 +67,21 @@ PIString TSFile::unmask(const PIString & in) {
TSFile::Content TSFile::read(const PIString & path) {
enum Phase {
pHeader,
pContext,
pContextName,
pMessage,
pMessageBody,
};
Content ret;
PIFile f(path, PIIODevice::ReadOnly);
if (!f.isOpened()) return ret;
PIIOTextStream ts(&f);
Context * cc = nullptr;
Message msg;
int phase = 0;
bool multi_source = false, multi_translation = false;
int phase = pHeader;
bool multi_source = false, multi_translation = false, multi_comment = false;
while (!ts.isEnd()) {
auto line = ts.readLine().trim();
if (multi_source) {
@@ -91,28 +100,45 @@ TSFile::Content TSFile::read(const PIString & path) {
msg.translation += "\n" + unmask(line);
continue;
}
if (multi_comment) {
if (line.endsWith("</translatorcomment>")) {
line.cutRight(20);
multi_comment = false;
}
msg.comment += "\n" + unmask(line);
continue;
}
switch (phase) {
case 0:
if (line == "<context>") phase = 1;
case pHeader:
if (line.startsWith("<TS")) {
int ind = line.find("language");
line.remove(0, ind + 8);
line.takeSymbol();
ret.lang = line.takeRange('"', '"');
// piCout << "lang" << ret.lang;
phase = pContext;
}
break;
case 1:
case pContext:
if (line == "<context>") phase = pContextName;
break;
case pContextName:
if (line.startsWith("<name>")) {
line.cutLeft(6).cutRight(7);
// if (line == context) phase = 2;
cc = &(ret[line]);
phase = 2;
cc = &(ret.contexts[line]);
phase = pMessage;
}
break;
case 2:
case pMessage:
if (line == "<message>") {
msg = {};
phase = 3;
phase = pMessageBody;
}
break;
case 3:
case pMessageBody:
if (line == "</message>") {
if (cc) cc->messages[msg.source] = msg;
phase = 2;
phase = pMessage;
} else if (line.startsWith("<source>")) {
line.cutLeft(8);
if (line.endsWith("</source>"))
@@ -136,29 +162,41 @@ TSFile::Content TSFile::read(const PIString & path) {
PIString t = trs.takeCWord();
trs.cutLeft(1);
PIString v = trs.takeRange('\"', '\"');
if (t == "type") msg.type = v;
if (t == "type") {
if (v == "unfinished")
msg.type.setFlag(Message::Unfinished);
else if (v == "vanished")
msg.type.setFlag(Message::Missing);
}
}
if (line.endsWith("</translation>"))
line.cutRight(14);
else
multi_translation = true;
msg.translation = unmask(line);
} else if (line.startsWith("<translatorcomment>")) {
line.cutLeft(19);
if (line.endsWith("</translatorcomment>"))
line.cutRight(20);
else
multi_comment = true;
msg.comment = unmask(line);
}
break;
}
if (line == "</context>") {
cc = nullptr;
phase = 0;
phase = pContext;
}
}
return ret;
}
bool TSFile::write(const PIString & path, const TSFile::Content & content, const PIString & lang, bool no_obsolete) {
bool TSFile::write(const PIString & path, const TSFile::Content & content, bool no_obsolete) {
PIFile outf(path, PIIODevice::ReadWrite);
if (!outf.isOpened()) {
piCerr << "Can`t open" << outf.path() << "!";
piCerr << "Can`t open file \"%1\"!"_tr("TSFile").arg(outf.path());
return false;
}
outf.clear();
@@ -172,23 +210,29 @@ bool TSFile::write(const PIString & path, const TSFile::Content & content, const
ts << "/>\n";
}
ts << " <source>" << mask(m.source) << "</source>\n";
if (m.comment.isNotEmpty()) {
ts << " <translatorcomment>" << mask(m.comment) << "</translatorcomment>\n";
}
ts << " <translation";
if (m.type.isNotEmpty()) ts << " type=\"" << m.type << "\"";
if (m.type[Message::Missing])
ts << " type=\"vanished\"";
else if (m.type[Message::Unfinished])
ts << " type=\"unfinished\"";
ts << ">" << mask(m.translation) << "</translation>\n";
ts << " </message>\n";
};
ts << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
ts << "<!DOCTYPE TS>\n";
ts << "<TS version=\"2.1\" language=\"" << lang << "\">\n";
auto cit = content.makeIterator();
ts << "<TS version=\"2.1\" language=\"" << content.lang << "\">\n";
auto cit = content.contexts.makeIterator();
while (cit.next()) {
if (cit.value().messages.isEmpty()) continue;
ts << "<context>\n";
ts << " <name>" << cit.key() << "</name>\n";
auto mit = cit.value().messages.makeIterator();
while (mit.next()) {
if (mit.value().obsolete && no_obsolete) continue;
if (mit.value().type[Message::Missing] && no_obsolete) continue;
writeMessage(mit.value());
}
ts << "</context>\n";
@@ -197,3 +241,14 @@ bool TSFile::write(const PIString & path, const TSFile::Content & content, const
return true;
}
void TSFile::Content::markAllMissing() {
auto cit = contexts.makeIterator();
while (cit.next()) {
auto mit = cit.value().messages.makeIterator();
while (mit.next()) {
mit.value().type.setFlag(Message::Missing);
}
}
}

View File

@@ -21,25 +21,33 @@
namespace TSFile {
struct Message {
enum Type {
Unfinished = 0x1,
Missing = 0x2,
};
PIString source;
PIString translation;
PIString type;
PIString comment;
PIString filename;
PIString line;
bool obsolete = true;
PIFlags<Type> type;
};
struct Context {
PIMap<PIString, Message> messages;
void confirm(const PIString & msg, const PIString & file, int line = -1);
bool confirm(const PIString & msg, const PIString & file, int line = -1);
};
using Content = PIMap<PIString, Context>;
struct Content {
void markAllMissing();
PIString lang;
PIMap<PIString, Context> contexts;
};
PIString mask(const PIString & in);
PIString unmask(const PIString & in);
Content read(const PIString & path);
bool write(const PIString & path, const Content & content, const PIString & lang, bool no_obsolete);
bool write(const PIString & path, const Content & content, bool no_obsolete);
} // namespace TSFile

View File

@@ -21,6 +21,7 @@
#include "parser.h"
#include "picli.h"
#include "piiostream.h"
#include "pitranslator.h"
using namespace PICoutManipulators;
@@ -56,7 +57,7 @@ int main(int argc, char * argv[]) {
PIVector<ParserSection> files = parse(cli.argumentValue("input"));
if (files.isEmpty()) {
piCout << "Error: resources description file is empty";
piCerr << "Error: resources description file is empty"_tr("pip_rc");
return 0;
}
if (cli.hasArgument("list")) {
@@ -76,7 +77,7 @@ int main(int argc, char * argv[]) {
if (outf.open(out_file, PIIODevice::ReadWrite)) {
outf.clear();
} else {
piCout << "Error: can`t open out file" << out_file;
piCerr << "Error: can`t open output file \"%1\""_tr("pip_rc").arg(out_file);
return 1;
}
PIIOTextStream ts(&outf);
@@ -86,7 +87,7 @@ int main(int argc, char * argv[]) {
ts << "// \"" << _a << "\"\n";
ts << "\n";
if (!generate(init_name, outf, files)) {
piCout << "Error: generate fail";
piCerr << "Error: generate fail"_tr("pip_rc");
return 1;
}
}

View File

@@ -7,10 +7,17 @@ set_deploy_property(pip_tr
COMPANY "${PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(pip_tr _RC)
add_executable(pip_tr "main.cpp" ${_RC})
set(TS_LIST)
if (NOT CROSSTOOLS)
file(GLOB TS_LIST "${pip_ROOT_SRC}/lang/*.ts")
endif()
add_executable(pip_tr "main.cpp" "parser.h" "parser.cpp" ${_RC} ${TS_LIST})
target_link_libraries(pip_tr pip_qt_support pip)
if (DEFINED LIB)
install(TARGETS pip_tr DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
else()
install(TARGETS pip_tr DESTINATION bin)
endif()
if (NOT CROSSTOOLS)
add_custom_command(TARGET pip_tr POST_BUILD COMMAND "${CMAKE_COMMAND}" --build "${PIP_DLL_DIR}" --target pip_lang)
endif()

View File

@@ -17,14 +17,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "parser.h"
#include "picli.h"
#include "pidir.h"
#include "pifile.h"
#include "piiostream.h"
#include "pijson.h"
#include "pivaluetree.h"
#include "pivaluetree_conversions.h"
#include "ts_file.h"
#include "piliterals_string.h"
#include "pitranslator.h"
#include "pitranslator_p.h"
using namespace PICoutManipulators;
@@ -42,12 +41,17 @@ void header() {
piCout << Bold << "PIP Translator";
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
piCout << Green << Bold << "Usage:" << Default
<< "\"pip_tr [-hHqn] -l <lang> -o <output_file> <file1/dir1> [<file2/dir2>] [<file3/dir3>] [...]\"" << NewLine;
<< "\"pip_tr -P [-hHqnr] -l <lang> -o <output_file> <file1/dir1> [<file2/dir2>] [<file3/dir3>] [...]\"" << NewLine
<< "\"pip_tr -C [-hHq] -o <output_file> <ts_file>\"" << NewLine;
}
void usage() {
header();
piCout << Green << Bold << "Details:";
piCout << Bold << "Mode";
piCout << "-P --Parse " << Green << "- parse sources and create/update *.ts file";
piCout << "-C --Compile " << Green << "- compile *.ts file";
piCout << "";
piCout << Bold << "Debug control";
piCout << "-h " << Green << "- display this message and exit";
piCout << "-H " << Green << "- display details help";
@@ -56,10 +60,12 @@ void usage() {
piCout << Bold << "Output control";
piCout << "-l <lang> " << Green << "- translation language (e.g. en_US, ru_RU)";
piCout << "-n, --no-obsolete " << Green << "- drop unused translations in output file";
piCout << "-o <output_file> " << Green << "- output file for translation (QtLinguist *.ts file)";
piCout << "-o <output_file> " << Green
<< "- output file for translation (QtLinguist *.ts file for parse mode or binary file for compile mode)";
piCout << "";
piCout << Bold << "Input control";
piCout << "<file/dir> " << Green << "- add file or dir translation";
piCout << "-r, --recursive " << Green << "- scan directories recursively";
piCout << "<file/dir> " << Green << "- add source file/dir for parse mode or *.ts file for compile mode";
}
void help() {
@@ -67,105 +73,10 @@ void help() {
piCout << help_string;
}
PIString fromCode(const PIString & in) {
return in.replacedAll("\\n", '\n').replaceAll("\\r", '\r').replaceAll("\\t", '\t');
}
void gatherStrings(TSFile::Content & content, const PIString & file, const PIString & file_loc) {
PIString source, context;
int pos = -1, ppos = 0, line = -1;
int len = 0;
auto isCLetter = [](const PIChar c) { return c.isAlpha() || c.isDigit() || c == '_'; };
static const PIStringList keyword({"PITranslator::tr", "piTr"});
for (const auto & kw: keyword) {
for (;;) {
source.clear();
context.clear();
pos = file.find(kw, pos + 1);
if (pos < 0) break;
if (pos > 0) {
auto pc = file[pos - 1];
if (isCLetter(pc) || pc == ':') {
pos += kw.size_s();
continue;
}
}
pos += kw.size_s();
if (pos < file.size_s() - 1) {
auto pc = file[pos];
if (isCLetter(pc) || pc == ':') {
pos += kw.size_s();
continue;
}
}
// piCout << "PITranslator" << pos;
pos = file.find('(', pos);
if (pos < 0) break;
// piCout << "(" << pos;
pos += 1;
pos = file.findRange('"', '"', '\\', pos, &len);
if (pos < 0) break;
// piCout << "\"" << pos;
source = file.mid(pos, len);
pos += len + 1;
line = file.lineNumber(pos);
ppos = pos;
while (pos < file.size_s()) {
if (!file[pos].isSpace() && file[pos] != '\n' && file[pos] != '\r') break;
++pos;
}
if (pos < file.size_s()) {
// piCout << "check comma" << file[pos];
if (file[pos] == ',') {
pos += 1;
pos = file.findRange('"', '"', '\\', pos, &len);
// piCout << "check range" << file.mid(pos, len);
if (pos >= 0) {
context = file.mid(pos, len);
pos += len + 1;
ppos = pos;
}
}
}
content[context].confirm(fromCode(source), file_loc, line);
pos = ppos;
piCout << "Context = \"" << context << "\", message = \"" << source << "\"";
}
}
auto & ec(content[""]);
pos = -1;
for (;;) {
source.clear();
pos = file.find('"', pos + 1);
if (pos < 0) break;
pos = file.findRange('"', '"', '\\', pos, &len);
if (pos < 0) break;
// piCout << "\"" << pos;
source = file.mid(pos, len);
pos += len + 1;
if (file.mid(pos, 3) == "_tr") {
pos += 3;
if (pos < file.size_s() - 1) {
auto pc = file[pos];
if (isCLetter(pc) || pc == ':') {
continue;
}
}
ec.confirm(fromCode(source), file_loc, file.lineNumber(pos));
piCout << "_tr = \"" << source << "\"";
}
}
}
enum Mode {
mParse = 1,
mCompile = 2,
};
int main(int argc, char * argv[]) {
PICLI cli(argc, argv);
@@ -177,48 +88,99 @@ int main(int argc, char * argv[]) {
cli.addArgument("Help");
cli.addArgument("quiet");
cli.addArgument("no-obsolete");
cli.addArgument("recursive");
cli.addArgument("Parse");
cli.addArgument("Compile");
if (cli.hasArgument("Help")) {
help();
return 0;
}
if (cli.hasArgument("help") || cli.argumentValue("output").isEmpty() || cli.argumentValue("language").isEmpty() ||
cli.optionalArguments().isEmpty()) {
int mode = 0;
if (cli.hasArgument("Parse")) mode |= mParse;
if (cli.hasArgument("Compile")) mode |= mCompile;
if (cli.hasArgument("help") || cli.argumentValue("output").isEmpty() || cli.optionalArguments().isEmpty() ||
(mode != mParse && mode != mCompile)) {
usage();
return 0;
}
if (mode == mParse && cli.argumentValue("language").isEmpty()) {
usage();
return 0;
}
piDebug = !cli.hasArgument("quiet");
PIString out_path = cli.argumentValue("output");
PIStringList files;
const static PIStringList ext({"h", "hpp", "cpp", "cxx"});
for (const PIString & a: cli.optionalArguments()) {
if (PIDir::isExists(a)) {
auto dl = PIDir(a).allEntries();
for (const auto & i: dl) {
if (!i.isFile()) continue;
if (ext.contains(i.extension().toLowerCase().trim())) files << i.path;
if (mode == mParse) {
piCout << Cyan << Bold << "Reading ts file ...";
auto content = TSFile::read(out_path);
if (content.lang.isEmpty()) content.lang = cli.argumentValue("language");
content.markAllMissing();
piCout << Cyan << Bold << "Reading done";
bool recursive = cli.hasArgument("recursive");
PIStringList files;
const static PIStringList ext({"h", "hpp", "cpp", "cxx"});
for (const PIString & a: cli.optionalArguments()) {
if (PIDir::isExists(a)) {
auto dl = recursive ? PIDir(a).allEntries() : PIDir(a).entries();
for (const auto & i: dl) {
if (!i.isFile()) continue;
if (ext.contains(i.extension().toLowerCase().trim())) files << i.path;
}
} else {
if (PIFile::isExists(a)) files << a;
}
} else {
if (PIFile::isExists(a)) files << a;
}
piCout << Cyan << Bold << "Read" << files.size_s() << "files ...";
PITimeMeasurer tm;
PIDir out_dir(PIFile::FileInfo(out_path).dir());
int count_all = 0, count_new = 0;
for (const auto & p: files) {
PIString file_loc = out_dir.relative(p);
PIFile f(p, PIIODevice::ReadOnly);
gatherStrings(content, PIString::fromUTF8(f.readAll()), file_loc, count_all, count_new);
}
auto elapsed = tm.elapsed();
piCout << Cyan << Bold
<< "Reading done, found %1 strings (%2 new) in %3 ms"_a.arg(count_all).arg(count_new).arg((int)elapsed.toMilliseconds());
piCout << Cyan << Bold << "Writing ts file ...";
if (!TSFile::write(out_path, content, cli.hasArgument("no-obsolete"))) return 1;
piCout << Cyan << Bold << "Writing done";
} else if (mode == mCompile) {
piCout << Cyan << Bold << "Reading ts file ...";
auto content = TSFile::read(cli.optionalArguments().front());
if (content.lang.isEmpty()) content.lang = cli.argumentValue("language");
piCout << Cyan << Bold << "Reading done";
int wcount = 0;
PITranslatorPrivate::Translation t;
t.lang = content.lang;
auto cit = content.contexts.makeIterator();
while (cit.next()) {
auto * c = t.createContext(cit.key());
auto mit = cit.value().messages.makeIterator();
while (mit.next()) {
const auto & m(mit.value());
if (m.type[TSFile::Message::Unfinished] || m.type[TSFile::Message::Missing]) continue;
c->add(m.source, m.translation);
++wcount;
// piCout << "tr" << m.source << "->" << m.translation;
}
}
PIFile outf(out_path, PIIODevice::WriteOnly);
if (!outf.isOpened()) {
piCerr << "Can`t open file \"%1\"!"_tr("TSFile").arg(outf.path());
return 1;
}
outf.clear();
piCout << Cyan << Bold << "Writing bin file ...";
PITranslatorPrivate::writeHeader(&outf);
outf.write(t.save());
piCout << Cyan << Bold << "Writing done (%1 strings)"_a.arg(wcount);
}
piCout << Cyan << Bold << "Reading ts file ...";
auto content = TSFile::read(out_path);
piCout << Cyan << Bold << "Reading done";
piCout << Cyan << Bold << "Read" << files.size_s() << "files ...";
PIDir out_dir(PIFile::FileInfo(out_path).dir());
for (const auto & p: files) {
PIString file_loc = out_dir.relative(p);
PIFile f(p, PIIODevice::ReadOnly);
gatherStrings(content, PIString::fromUTF8(f.readAll()), file_loc);
}
piCout << Cyan << Bold << "Reading done";
piCout << Cyan << Bold << "Writing ts file ...";
if (!TSFile::write(out_path, content, cli.argumentValue("language"), cli.hasArgument("no-obsolete"))) return 1;
piCout << Cyan << Bold << "Writing done";
return 0;
}

139
utils/translator/parser.cpp Normal file
View File

@@ -0,0 +1,139 @@
#include "parser.h"
#include "piliterals_string.h"
#include "pistringlist.h"
PIString fromCode(const PIString & in) {
return in.replacedAll("\\n", '\n')
.replaceAll("\\r", '\r')
.replaceAll("\\t", '\t')
.replaceAll("\\\"", '"')
.replaceAll("\\'", '\'')
.replaceAll("\\\\", '\\');
}
void gatherStrings(TSFile::Content & content, const PIString & file, const PIString & file_loc, int & count_all, int & count_new) {
static const PIStringList methods({"PITranslator::tr", "PITranslator::trNoOp", "piTr", "piTrNoOp"});
static const PIStringList literals({"_tr", "_trNoOp"});
PIString source, context;
int pos = -1, ppos = 0, line = -1;
int len = 0;
auto isCLetter = [](const PIChar c) { return c.isAlpha() || c.isDigit() || c == '_'; };
auto add = [&content, file_loc, &count_all, &count_new](const PIString & source, const PIString & context, int line) {
if (source.isEmpty()) return;
++count_all;
if (content.contexts[context].confirm(fromCode(source), file_loc, line)) ++count_new;
// piCout << "Context = \"" << context << "\", message = \"" << source << "\" (" << file_loc << ":" << line << ")";
};
// piCout << "file" << file_loc;
for (const auto & kw: methods) {
// piCout << "method" << kw;
for (;;) {
source.clear();
context.clear();
pos = file.find(kw, pos + 1);
if (pos < 0) break;
if (pos > 0) {
auto pc = file[pos - 1];
if (isCLetter(pc) || pc == ':') {
pos += kw.size_s();
continue;
}
}
pos += kw.size_s();
if (pos < file.size_s() - 1) {
auto pc = file[pos];
if (isCLetter(pc) || pc == ':') {
pos += kw.size_s();
continue;
}
}
// piCout << "PITranslator" << pos;
pos = file.find('(', pos);
if (pos < 0) break;
// piCout << "(" << pos;
pos += 1;
pos = file.findRange('"', '"', '\\', pos, &len);
if (pos < 0) break;
// piCout << "\"" << pos;
source = file.mid(pos, len);
pos += len + 1;
line = file.lineNumber(pos);
ppos = pos;
while (pos < file.size_s()) {
if (!file[pos].isSpace() && file[pos] != '\n' && file[pos] != '\r') break;
++pos;
}
if (pos < file.size_s()) {
// piCout << "check comma" << file[pos];
if (file[pos] == ',') {
pos += 1;
pos = file.findRange('"', '"', '\\', pos, &len);
// piCout << "check range" << file.mid(pos, len);
if (pos >= 0) {
context = file.mid(pos, len);
pos += len + 1;
ppos = pos;
}
}
}
pos = ppos;
add(source, context, line);
}
}
for (const auto & kw: literals) {
// piCout << "literal" << kw;
pos = -1;
for (;;) {
source.clear();
context.clear();
pos = file.find('"', pos + 1);
if (pos < 0) break;
pos = file.findRange('"', '"', '\\', pos, &len);
if (pos < 0) break;
// piCout << "\"" << pos;
source = file.mid(pos, len);
pos += len + 1;
if (file.mid(pos, kw.size_s()) == kw) {
// piCout << "line" << file.lineNumber(pos);
pos += kw.size_s();
if (pos < file.size_s() - 1) {
auto pc = file[pos];
if (isCLetter(pc) || pc == ':') {
continue;
}
}
ppos = pos;
while (pos < file.size_s()) {
if (!file[pos].isSpace() && file[pos] != '\n' && file[pos] != '\r') break;
++pos;
}
if (pos < file.size_s()) {
// piCout << "check comma" << file[pos];
if (file[pos] == '(') {
pos += 1;
pos = file.findRange('"', '"', '\\', pos, &len);
// piCout << "check range" << file.mid(pos, len);
if (pos >= 0) {
context = file.mid(pos, len);
pos += len + 1;
ppos = pos;
}
}
}
pos = ppos;
if (source.isEmpty()) continue;
line = file.lineNumber(pos);
add(source, context, line);
}
}
}
}

View File

@@ -0,0 +1,9 @@
#ifndef PITR_PARSER_H
#define PITR_PARSER_H
#include "ts_file.h"
PIString fromCode(const PIString & in);
void gatherStrings(TSFile::Content & content, const PIString & file, const PIString & file_loc, int & count_all, int & count_new);
#endif

View File

@@ -124,10 +124,12 @@ int main(int argc, char * argv[]) {
piCout << Cyan << Bold << "Reading ts file ...";
auto content = TSFile::read(out_path);
if (content.lang.isEmpty()) content.lang = cli.argumentValue("language");
content.markAllMissing();
piCout << Cyan << Bold << "Reading done";
piCout << Cyan << Bold << "Read" << files.size_s() << "files ...";
auto & context(content[contextName]);
auto & context(content.contexts[contextName]);
PIDir out_dir(PIFile::FileInfo(out_path).dir());
for (const auto & p: files) {
PIString ext = PIFile::FileInfo(p).extension().toLowerCase().trim();
@@ -142,7 +144,7 @@ int main(int argc, char * argv[]) {
piCout << Cyan << Bold << "Reading done";
piCout << Cyan << Bold << "Writing ts file ...";
if (!TSFile::write(out_path, content, cli.argumentValue("language"), cli.hasArgument("no-obsolete"))) return 1;
if (!TSFile::write(out_path, content, cli.hasArgument("no-obsolete"))) return 1;
piCout << Cyan << Bold << "Writing done";
return 0;