diff --git a/CMakeLists.txt b/CMakeLists.txt index 3eb5d1c5..6e248eaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/cmake/FindPIP.cmake b/cmake/FindPIP.cmake index 002c92c7..1730ae9f 100644 --- a/cmake/FindPIP.cmake +++ b/cmake/FindPIP.cmake @@ -45,10 +45,12 @@ endif() if (BUILDING_PIP AND (NOT CMAKE_CROSSCOMPILING)) set(PIP_CMG "$/$" CACHE STRING "") set(PIP_RC "$/$" CACHE STRING "") + set(PIP_TR "$/$" CACHE STRING "") set(PIP_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) diff --git a/cmake/PIPMacros.cmake b/cmake/PIPMacros.cmake index 81a1972d..5e1aa81b 100644 --- a/cmake/PIPMacros.cmake +++ b/cmake/PIPMacros.cmake @@ -18,6 +18,14 @@ Generate C++ files for resource file You should add ${} to your target + + + pip_translation( ts_file) + + Generate *.btf (binary translation file) from *.ts file + You should add ${} 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() + diff --git a/lang/pip_ru.ts b/lang/pip_ru.ts new file mode 100644 index 00000000..ab6ce5ce --- /dev/null +++ b/lang/pip_ru.ts @@ -0,0 +1,531 @@ + + + + + PICLI + + + Arguments overflow, "%1" ignored + Переизбыток аргументов, "%1" проигнорирован + + + + PIDiag + + + /s + /сек + + + + PIFile + + + Downsize is not supported yet :-( + Уменьшение размера не поддерживается + + + + PICloud + + + Invalid PICloud::TCP version! + Неверная версия PICloud::TCP! + + + + Error: buffer overflow, drop %1 bytes + Ошибка: переполнение буфера, отброшено %1 байт + + + + Warning: reject client with duplicated ID + Предупреждение: отклонен клиент с дублирующимся ID + + + + PICrypt + + + internal error: bad hash size + внутренняя ошибка: плохой размер хэша + + + + Error while initialize sodium! + Ошибка инициализации sodium! + + + + invalid key size %1, should be %2, filled with zeros + неверный размер ключа %1, должен быть %2, заполненный нулями + + + + Warning: PICrypt is disabled, to enable install sodium library and rebuild pip + Предупреждение: PICrypt неактивен, для активации установите библиотеку sodium и пересоберите PIP + + + + PIBinLog + + + Read record error + Ошибка чтения записи + + + + End of BinLog file + Конец BinLog файла + + + + Error, can't open "%1" + Ошибка, невозможно открыть "%1" + + + + Creating directory "%1" + Создание директории "%1" + + + + Error, can't create "%1" + Ошибка, невозможно создать "%1" + + + + Error: File is null "%1" + Ошибка, Файл пуст "%1" + + + + Start join binlogs to "%1" + Начало слияния логов в "%1" + + + + BinLogFile has too old verion + BinLogFile очень старой версии + + + + BinLogFile has invalid version + BinLogFile неверной версии + + + + BinLogFile has too new version + BinLogFile очень новой версии + + + + Can't find record with id = %1 + Невозможно найти запись с ID = %1 + + + + Error, can't write to file "%1" + Ошибка, невозможно записать в "%1" + + + + Error: Can't open file "%1": %2 + Ошибка: Невозможно открыть файл "%1": %2 + + + + Warning: Empty BinLog file "%1" + Предупреждение: Пустой BinLog файл "%1" + + + + Finish join binlogs, total time %1 + Завершение слияния логов, общее время %1 + + + + too small read buffer: %1, data size: %2 + слишком маленький буфер: %1, размер данных: %2 + + + + Error: Can't write binlog file header "%1" + Ошибка: Невозможно записать заголовок в "%1" + + + + Error: can`t write with id = 0! ID must be > 0 + Ошибка: Невозможно записать с ID = 0! ID должен быть > 0 + + + + BinLogFile signature is corrupted or invalid file + Неверный заголовок BinLogFile, либо файл поврежден + + + + Can't create new file, maybe path "%1" is invalid + Невозможно создать новый файл, возможно путь "%1" неверен + + + + Can't create new file, maybe LogDir "%1" is invalid + Невозможно создать новый файл, возможно LogDir "%1" неверен + + + + Error: ReadWrite mode not supported, use WriteOnly or ReadOnly + Ошибка: Режим ReadWrite не поддерживается, используйте WriteOnly или ReadOnly + + + + PIOpenCL + + + Error: empty range + Ошибка: пустой диапазон + + + + setArgValue invalid index %1 + setArgValue неверный индекс %1 + + + + bindArgValue invalid index %1 + bindArgValue неверный индекс %1 + + + + setArgValue set scalar to "%1 %2" + setArgValue устанавливается скаляр в "%1 %2" + + + + Error: OpenCL platforms not found! + Ошибка: Платформы OpenCL не найдены! + + + + bindArgValue set buffer to "%1 %2" + bindArgValue устанавливается буфер в "%1 %2" + + + + PISerial + + + Read error: %1 + Ошибка чтения: %1 + + + + Unable to open "%1": %2 + Невозможно открыть "%1": %2 + + + + Warning: Custom speed %1 + Предупреждение: Нестандартная скорость %1 + + + + Unable to find device "%1" + Невозможно найти устройство "%1" + + + + Can`t set attributes for "%1" + Невозможно установить атрибуты для "%1" + + + + Unable to set comm state for "%1" + Невозможно установить comm state для "%1" + + + + Warning: Unknown speed %1, using 115200 + Предупреждение: Неизвестная скорость %1, используется 115200 + + + + PIString + + + B + Б + + + + EiB + ЭиБ + + + + GiB + ГиБ + + + + KiB + КиБ + + + + MiB + МиБ + + + + PiB + ПиБ + + + + TiB + ТиБ + + + + YiB + ЙиБ + + + + ZiB + ЗиБ + + + + PIThread + + + Warning, terminate! + Предупреждение, прекращение потока! + + + + Error: Can`t start new thread: %1 + Ошибка: Невозможно начать новый поток: %1 + + + + [PIThread "%1"] Warning, terminate on destructor! + [PIThread "%1"] Предупреждение, прекращение в деструкторе! + + + + PIProcess + + + "CreateProcess" error: %1 + Ошибка "CreateProcess": %1 + + + + PIVariant + + + Can`t initialize PIVariant from unregistered type "%1"! + Невозможно инициализировать PIVariant из незарегистрированного типа "%1"! + + + + Can`t initialize PIVariant from unregistered typeID "%1"! + Невозможно инициализировать PIVariant из незарегистрированного ID типа "%1"! + + + + PICompress + + + Error: invalid input + Ошибка: неверный вход + + + + Error: invalid input or not enought memory + Ошибка: неверный вход или недостаточно памяти + + + + Warning: PICompress is disabled, to enable install zlib library and build pip_compress library + Предупреждение: PICompress неактивен, для активации установите библиотеку zlib и пересоберите PIP + + + + PIEthernet + + + Can`t get interfaces: %1 + Невозможно получить интерфейсы: %1 + + + + Can`t accept new connection, %1 + Невозможно принять новое соединение, %1 + + + + Error allocating memory needed to call GetAdaptersInfo + Ошибка выделения памяти для вызова GetAdaptersInfo + + + + PIIODevice + + + Error: Device is running after destructor! + Ошибка: Устройство в поточном выполнении после деструктора! + + + + PIIOString + + + Error: ReadWrite mode not supported, use WriteOnly or ReadOnly + Ошибка: Режим ReadWrite не поддерживается, используйте WriteOnly или ReadOnly + + + + PIConnection + + + Error, + Ошибка, + + + + Null Device! + Нет Устройства! + + + + No such device "%1"! + Нет устройства "%1"! + + + + No such full path "%1"! + Нет полного пути "%1"! + + + + Device "%1" can`t write! + Устройство "%1" не может писать! + + + + Error: can`t create device "%1"! + Ошибка: Невозможно создать устройство "%1"! + + + + "addFilter" error: no such device "%1"! + ошибка "addFilter": нет устройства "%1"! + + + + "addSender" error: no such device "%1"! + ошибка "addSender": нет устройства "%1"! + + + + names assigned to both devices and filters! + имена назначены одновременно устройствам и фильтрам! + + + + "addFilter" error: no such device or filter "%1"! + ошибка "addFilter": нет устройства или фильтра "%1"! + + + + PISystemTime + + + fromSystemTime() Warning: null frequency + fromSystemTime() Предупреждение: нулевая частота + + + + toSystemTime() Warning: invalid hertz: %1 + toSystemTime() Предупреждение: неверная частота: %1 + + + + PIEthUtilBase + + + PICrypt wasn`t built! + PICrypt не был собран! + + + + PIBaseTransfer + + + invalid CRC + неверная CRC + + + + restart receive + перезапуск приема + + + + invalid reply id + неверный ID ответа + + + + invalid packet signature + неверная подпись пакета + + + + PIClientServer + + + ClientFactory returns nullptr! + ClientFactory вернул nullptr! + + + + Server::newConnection overflow clients count + Server::newConnection переполнение количества клиентов + + + + PIStateMachine + + + Error: "%1" no initial state! + Ошибка: "%1" без стартового состояния! + + + + PIStreamPacker + + + Warning! Not recommended to use with non-reliable device + Предупреждение! Не рекомендуется использовать с ненадежными устройствами + + + + PISystemMonitor + + + Can`t find process with ID = %1! + Невозможно найти процесс с ID = %1! + + + + Can`t open process with ID = %1, %2! + Невозможно открыть процесс с ID = %1, %2! + + + diff --git a/lang/update.bat b/lang/update.bat new file mode 100644 index 00000000..2acb1aec --- /dev/null +++ b/lang/update.bat @@ -0,0 +1 @@ +pip_tr --Parse -r -l ru -o pip_ru.ts ../libs \ No newline at end of file diff --git a/libs/client_server/piclientserver_server.cpp b/libs/client_server/piclientserver_server.cpp index 4a6ec693..d31087bb 100644 --- a/libs/client_server/piclientserver_server.cpp +++ b/libs/client_server/piclientserver_server.cpp @@ -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); diff --git a/libs/cloud/picloudclient.cpp b/libs/cloud/picloudclient.cpp index 30ccab2c..dbed44ca 100644 --- a/libs/cloud/picloudclient.cpp +++ b/libs/cloud/picloudclient.cpp @@ -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; } diff --git a/libs/cloud/picloudserver.cpp b/libs/cloud/picloudserver.cpp index 14f519bf..709f94ef 100644 --- a/libs/cloud/picloudserver.cpp +++ b/libs/cloud/picloudserver.cpp @@ -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); diff --git a/libs/cloud/picloudtcp.cpp b/libs/cloud/picloudtcp.cpp index 861a8069..e64d177c 100644 --- a/libs/cloud/picloudtcp.cpp +++ b/libs/cloud/picloudtcp.cpp @@ -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::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; diff --git a/libs/compress/picompress.cpp b/libs/compress/picompress.cpp index b82f6208..90e915e9 100644 --- a/libs/compress/picompress.cpp +++ b/libs/compress/picompress.cpp @@ -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; } diff --git a/libs/crypt/picrypt.cpp b/libs/crypt/picrypt.cpp index 38e55853..0220c155 100644 --- a/libs/crypt/picrypt.cpp +++ b/libs/crypt/picrypt.cpp @@ -18,13 +18,15 @@ */ #include "picrypt.h" + +#include "pitranslator.h" #ifdef PIP_CRYPT # include #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; diff --git a/libs/fftw/pifft_p.h b/libs/fftw/pifft_p.h index 45795601..39aa3a75 100644 --- a/libs/fftw/pifft_p.h +++ b/libs/fftw/pifft_p.h @@ -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(); } diff --git a/libs/io_utils/piethutilbase.cpp b/libs/io_utils/piethutilbase.cpp index 5121239d..dfa24d02 100644 --- a/libs/io_utils/piethutilbase.cpp +++ b/libs/io_utils/piethutilbase.cpp @@ -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; } diff --git a/libs/io_utils/pistreampacker.cpp b/libs/io_utils/pistreampacker.cpp index 7ec34a18..a062a149 100644 --- a/libs/io_utils/pistreampacker.cpp +++ b/libs/io_utils/pistreampacker.cpp @@ -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); diff --git a/libs/main/application/picli.cpp b/libs/main/application/picli.cpp index 57553cb9..3f16ec78 100644 --- a/libs/main/application/picli.cpp +++ b/libs/main/application/picli.cpp @@ -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; diff --git a/libs/main/application/pisystemmonitor.cpp b/libs/main/application/pisystemmonitor.cpp index 98a5e428..2f51237e 100644 --- a/libs/main/application/pisystemmonitor.cpp +++ b/libs/main/application/pisystemmonitor.cpp @@ -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); diff --git a/libs/main/application/pitranslator.cpp b/libs/main/application/pitranslator.cpp index 674fd4d6..b2d1c009 100644 --- a/libs/main/application/pitranslator.cpp +++ b/libs/main/application/pitranslator.cpp @@ -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; -} diff --git a/libs/main/application/pitranslator.h b/libs/main/application/pitranslator.h index 6ccdf47a..c4435a80 100644 --- a/libs/main/application/pitranslator.h +++ b/libs/main/application/pitranslator.h @@ -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 strings; - }; + PRIVATE_DECLARATION(PIP_EXPORT) static PITranslator * instance(); - - void clearInternal(); - Context * createContextInternal(const PIString & context); - - PIMap 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 diff --git a/libs/main/application/pitranslator_p.cpp b/libs/main/application/pitranslator_p.cpp new file mode 100644 index 00000000..8d28a5d3 --- /dev/null +++ b/libs/main/application/pitranslator_p.cpp @@ -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 . +*/ + +#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 & 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 strings; + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: { + int version = cs.getData(); + if (version != currentVersion) { + piCout << "Invalid translation version!"; + return false; + } + } break; + case 3: { + uint ctx_hash = cs.getData(); + 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); +} diff --git a/libs/main/application/pitranslator_p.h b/libs/main/application/pitranslator_p.h new file mode 100644 index 00000000..8479b0ae --- /dev/null +++ b/libs/main/application/pitranslator_p.h @@ -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 . +*/ + +#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 & sm); + PIMap 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 contexts; +}; + +PIP_EXPORT int headerSize(); +PIP_EXPORT bool checkHeader(PIIODevice * d); +PIP_EXPORT void writeHeader(PIIODevice * d); + +} // namespace PITranslatorPrivate + +#endif diff --git a/libs/main/application/tr/pip_all.h b/libs/main/application/tr/pip_all.h deleted file mode 100644 index 476ffadb..00000000 --- a/libs/main/application/tr/pip_all.h +++ /dev/null @@ -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 diff --git a/libs/main/application/tr/pip_ru.h b/libs/main/application/tr/pip_ru.h deleted file mode 100644 index acc1ae56..00000000 --- a/libs/main/application/tr/pip_ru.h +++ /dev/null @@ -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\ -"; diff --git a/libs/main/io_devices/pibinarylog.cpp b/libs/main/io_devices/pibinarylog.cpp index 55c2433f..eea1fd7a 100644 --- a/libs/main/io_devices/pibinarylog.cpp +++ b/libs/main/io_devices/pibinarylog.cpp @@ -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 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; } diff --git a/libs/main/io_devices/piethernet.cpp b/libs/main/io_devices/piethernet.cpp index 9f9ac03e..cc50a176 100644 --- a/libs/main/io_devices/piethernet.cpp +++ b/libs/main/io_devices/piethernet.cpp @@ -24,6 +24,7 @@ #include "piliterals.h" #include "pipropertystorage.h" #include "pisysteminfo.h" +#include "pitranslator.h" // clang-format off #ifdef QNX # include @@ -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 diff --git a/libs/main/io_devices/pifile.cpp b/libs/main/io_devices/pifile.cpp index 0b4f0763..c6a09038 100644 --- a/libs/main/io_devices/pifile.cpp +++ b/libs/main/io_devices/pifile.cpp @@ -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"); } diff --git a/libs/main/io_devices/piiobytearray.cpp b/libs/main/io_devices/piiobytearray.cpp index 2859d619..3b6e8374 100644 --- a/libs/main/io_devices/piiobytearray.cpp +++ b/libs/main/io_devices/piiobytearray.cpp @@ -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(); diff --git a/libs/main/io_devices/piiodevice.cpp b/libs/main/io_devices/piiodevice.cpp index fa92731a..42cd04ca 100644 --- a/libs/main/io_devices/piiodevice.cpp +++ b/libs/main/io_devices/piiodevice.cpp @@ -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 & 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; } diff --git a/libs/main/io_devices/piiostring.cpp b/libs/main/io_devices/piiostring.cpp index 52226865..e2b2c5ac 100644 --- a/libs/main/io_devices/piiostring.cpp +++ b/libs/main/io_devices/piiostring.cpp @@ -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; } diff --git a/libs/main/io_devices/piserial.cpp b/libs/main/io_devices/piserial.cpp index 28a172f8..31af1b4e 100644 --- a/libs/main/io_devices/piserial.cpp +++ b/libs/main/io_devices/piserial.cpp @@ -24,6 +24,7 @@ #include "piincludes_p.h" #include "pipropertystorage.h" #include "pitime.h" +#include "pitranslator.h" #include "piwaitevent_p.h" #include @@ -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; diff --git a/libs/main/io_utils/pibasetransfer.cpp b/libs/main/io_utils/pibasetransfer.cpp index 3575a284..1829cd45 100644 --- a/libs/main/io_utils/pibasetransfer.cpp +++ b/libs/main/io_utils/pibasetransfer.cpp @@ -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; } diff --git a/libs/main/io_utils/piconnection.cpp b/libs/main/io_utils/piconnection.cpp index 5a4b7763..ee7d0a5b 100644 --- a/libs/main/io_utils/piconnection.cpp +++ b/libs/main/io_utils/piconnection.cpp @@ -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 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 be(bounded_extractors.value(cd)); // piCout << be << (void*)data << size; diff --git a/libs/main/io_utils/pidiagnostics.cpp b/libs/main/io_utils/pidiagnostics.cpp index dba39105..d6dd7f25 100644 --- a/libs/main/io_utils/pidiagnostics.cpp +++ b/libs/main/io_utils/pidiagnostics.cpp @@ -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 & hist, int & cnt if (!hist[i].empty) cnt++; } e.empty = false; - // piCoutObj << hist.size() << cnt; + // piCoutObj << hist.size() << cnt; return e; } diff --git a/libs/main/resources/piresourcesstorage.cpp b/libs/main/resources/piresourcesstorage.cpp index fce26322..8623c6f4 100644 --- a/libs/main/resources/piresourcesstorage.cpp +++ b/libs/main/resources/piresourcesstorage.cpp @@ -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 bav = entries.values(); PISet 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 el; dba >> el; PIMap> 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 & 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
sv = sections.values(); - piForeach(Section * i, sv) { + for (auto i: sv) { if (i) i->purge(); } sections.clear(); diff --git a/libs/main/state_machine/pistatemachine_state.cpp b/libs/main/state_machine/pistatemachine_state.cpp index f23b257b..6a5162d8 100644 --- a/libs/main/state_machine/pistatemachine_state.cpp +++ b/libs/main/state_machine/pistatemachine_state.cpp @@ -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 { diff --git a/libs/main/system/piprocess.cpp b/libs/main/system/piprocess.cpp index b63a0278..3463ab69 100644 --- a/libs/main/system/piprocess.cpp +++ b/libs/main/system/piprocess.cpp @@ -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; diff --git a/libs/main/text/pistring.cpp b/libs/main/text/pistring.cpp index bae3ae82..515d36f0 100644 --- a/libs/main/text/pistring.cpp +++ b/libs/main/text/pistring.cpp @@ -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; } diff --git a/libs/main/text/pistring.h b/libs/main/text/pistring.h index 02bec59f..27ffa208 100644 --- a/libs/main/text/pistring.h +++ b/libs/main/text/pistring.h @@ -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 d; mutable bool changed_ = true; diff --git a/libs/main/thread/pithread.cpp b/libs/main/thread/pithread.cpp index afdef1f3..aa00aa21 100644 --- a/libs/main/thread/pithread.cpp +++ b/libs/main/thread/pithread.cpp @@ -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; } diff --git a/libs/main/types/pisystemtime.cpp b/libs/main/types/pisystemtime.cpp index eaa7f8fc..4cbb1e27 100644 --- a/libs/main/types/pisystemtime.cpp +++ b/libs/main/types/pisystemtime.cpp @@ -23,6 +23,7 @@ #include "piiostream.h" #include "piliterals_time.h" #include "pitime.h" +#include "pitranslator.h" #include #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()); diff --git a/libs/main/types/pivariant.cpp b/libs/main/types/pivariant.cpp index 0130c82f..56e8f506 100644 --- a/libs/main/types/pivariant.cpp +++ b/libs/main/types/pivariant.cpp @@ -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; } } diff --git a/libs/opencl/piopencl.cpp b/libs/opencl/piopencl.cpp index 017852e4..b34c99cf 100644 --- a/libs/opencl/piopencl.cpp +++ b/libs/opencl/piopencl.cpp @@ -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 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)); diff --git a/main.cpp b/main.cpp index 49821cc7..764a1f9d 100644 --- a/main.cpp +++ b/main.cpp @@ -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 -void foo() { - static_assert(std::is_arithmetic::value || is_complex::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) { diff --git a/utils/code_model_generator/main.cpp b/utils/code_model_generator/main.cpp index 5b569b62..fd9eb2ab 100755 --- a/utils/code_model_generator/main.cpp +++ b/utils/code_model_generator/main.cpp @@ -20,8 +20,7 @@ #include "picli.h" #include "picodeparser.h" #include "piiostream.h" - -#include +#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"); diff --git a/utils/deploy_tool/main.cpp b/utils/deploy_tool/main.cpp index 563f6d0a..6c43ab8b 100644 --- a/utils/deploy_tool/main.cpp +++ b/utils/deploy_tool/main.cpp @@ -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; diff --git a/utils/qt_support/ts_file.cpp b/utils/qt_support/ts_file.cpp index 281bf26e..6ec9af28 100644 --- a/utils/qt_support/ts_file.cpp +++ b/utils/qt_support/ts_file.cpp @@ -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("")) { + line.cutRight(20); + multi_comment = false; + } + msg.comment += "\n" + unmask(line); + continue; + } switch (phase) { - case 0: - if (line == "") phase = 1; + case pHeader: + if (line.startsWith("") phase = pContextName; + break; + case pContextName: if (line.startsWith("")) { 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 == "") { msg = {}; - phase = 3; + phase = pMessageBody; } break; - case 3: + case pMessageBody: if (line == "") { if (cc) cc->messages[msg.source] = msg; - phase = 2; + phase = pMessage; } else if (line.startsWith("")) { line.cutLeft(8); if (line.endsWith("")) @@ -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("")) line.cutRight(14); else multi_translation = true; msg.translation = unmask(line); + } else if (line.startsWith("")) { + line.cutLeft(19); + if (line.endsWith("")) + line.cutRight(20); + else + multi_comment = true; + msg.comment = unmask(line); } break; } if (line == "") { 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 << " " << mask(m.source) << "\n"; + if (m.comment.isNotEmpty()) { + ts << " " << mask(m.comment) << "\n"; + } ts << " " << mask(m.translation) << "\n"; ts << " \n"; }; ts << "\n"; ts << "\n"; - ts << "\n"; - auto cit = content.makeIterator(); + ts << "\n"; + auto cit = content.contexts.makeIterator(); while (cit.next()) { if (cit.value().messages.isEmpty()) continue; ts << "\n"; ts << " " << cit.key() << "\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 << "\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); + } + } +} diff --git a/utils/qt_support/ts_file.h b/utils/qt_support/ts_file.h index 8ea6c126..01b939d3 100644 --- a/utils/qt_support/ts_file.h +++ b/utils/qt_support/ts_file.h @@ -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; }; struct Context { PIMap 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; +struct Content { + void markAllMissing(); + PIString lang; + PIMap 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 diff --git a/utils/resources_compiler/main.cpp b/utils/resources_compiler/main.cpp index 8cf65b42..f0ed7675 100644 --- a/utils/resources_compiler/main.cpp +++ b/utils/resources_compiler/main.cpp @@ -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 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; } } diff --git a/utils/translator/CMakeLists.txt b/utils/translator/CMakeLists.txt index d3ae9f7d..8559e1a8 100644 --- a/utils/translator/CMakeLists.txt +++ b/utils/translator/CMakeLists.txt @@ -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() diff --git a/utils/translator/main.cpp b/utils/translator/main.cpp index 050dce55..f8b548db 100644 --- a/utils/translator/main.cpp +++ b/utils/translator/main.cpp @@ -17,14 +17,13 @@ along with this program. If not, see . */ +#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 -o [] [] [...]\"" << NewLine; + << "\"pip_tr -P [-hHqnr] -l -o [] [] [...]\"" << NewLine + << "\"pip_tr -C [-hHq] -o \"" << 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 " << Green << "- translation language (e.g. en_US, ru_RU)"; piCout << "-n, --no-obsolete " << Green << "- drop unused translations in output file"; - piCout << "-o " << Green << "- output file for translation (QtLinguist *.ts file)"; + piCout << "-o " << Green + << "- output file for translation (QtLinguist *.ts file for parse mode or binary file for compile mode)"; piCout << ""; piCout << Bold << "Input control"; - piCout << " " << Green << "- add file or dir translation"; + piCout << "-r, --recursive " << Green << "- scan directories recursively"; + piCout << " " << 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; } diff --git a/utils/translator/parser.cpp b/utils/translator/parser.cpp new file mode 100644 index 00000000..073c28af --- /dev/null +++ b/utils/translator/parser.cpp @@ -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); + } + } + } +} diff --git a/utils/translator/parser.h b/utils/translator/parser.h new file mode 100644 index 00000000..5e900d34 --- /dev/null +++ b/utils/translator/parser.h @@ -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 diff --git a/utils/value_tree_translator/main.cpp b/utils/value_tree_translator/main.cpp index 0a3a0cde..e9c48d98 100644 --- a/utils/value_tree_translator/main.cpp +++ b/utils/value_tree_translator/main.cpp @@ -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;