~aleteoryx/muditaos

b67398196692d6badbf186cc762631402d7bbb3c — Alek Rudnik 4 years ago a775de9 + 25fc56f
Merge branch 'master' into stable
230 files changed, 1545 insertions(+), 5953 deletions(-)

M .gitmodules
M CMakeLists.txt
M Jenkinsfile
M Target_RT1051.cmake
M board/linux/libiosyscalls/src/syscalls_posix.cpp
M board/linux/libiosyscalls/test/CMakeLists.txt
A cmake/modules/AddBootBin.cmake
A cmake/modules/AddHexTarget.cmake
A cmake/modules/AddPackage.cmake
M cmake/modules/Colours.cmake
M cmake/modules/DiskImage.cmake
A cmake/modules/FetchBootloader.cmake
M cmake/modules/GenVersionHpp.cmake
A cmake/modules/GitHubWorkerMessages.cmake
M cmake/modules/PureCoverage.cmake
M cmake/modules/SerialPort.cmake
M cmake/modules/Utils.cmake
M cmake/modules/Version.cmake
M configure.sh
M debug_crash_dump.sh
M doc/Doxyfile.in
M doc/boot_and_update.md
R {generate_purephone_image => generate_image}.sh
M host-tools/CMakeLists.txt
M host-tools/genlittlefs/CMakeLists.txt
M host-tools/genlittlefs/lfs_ioaccess.c
M host-tools/genlittlefs/mklfs.c
M host-tools/pure-flash/pure-flash.c
M image/assets/lang/English.json
M module-apps/Application.cpp
M module-apps/Application.hpp
M module-apps/CMakeLists.txt
A module-apps/StatusBarManager.cpp
R module-apps/{TopBarManager => StatusBarManager}.hpp
D module-apps/TopBarManager.cpp
M module-apps/application-alarm-clock/windows/AlarmClockMainWindow.cpp
M module-apps/application-calculator/data/CalculatorInputProcessorText.cpp
M module-apps/application-calendar/windows/AllEventsWindow.cpp
M module-apps/application-calendar/windows/DayEventsWindow.cpp
M module-apps/application-calendar/windows/EventReminderWindow.cpp
M module-apps/application-calendar/windows/EventReminderWindow.hpp
M module-apps/application-call/ApplicationCall.cpp
M module-apps/application-call/windows/CallWindow.cpp
M module-apps/application-call/windows/CallWindow.hpp
M module-apps/application-call/windows/EmergencyCallWindow.cpp
M module-apps/application-call/windows/EmergencyCallWindow.hpp
M module-apps/application-call/windows/EnterNumberWindow.cpp
M module-apps/application-call/windows/EnterNumberWindow.hpp
M module-apps/application-call/windows/NumberWindow.cpp
M module-apps/application-calllog/windows/CallLogDetailsWindow.cpp
M module-apps/application-desktop/ApplicationDesktop.cpp
M module-apps/application-desktop/models/ActiveNotificationsModel.cpp
M module-apps/application-desktop/windows/ChargingBatteryWindow.cpp
M module-apps/application-desktop/windows/DeadBatteryWindow.cpp
M module-apps/application-desktop/windows/DesktopMainWindow.cpp
M module-apps/application-desktop/windows/DesktopMainWindow.hpp
M module-apps/application-desktop/windows/LogoWindow.cpp
M module-apps/application-desktop/windows/PostUpdateWindow.cpp
M module-apps/application-desktop/windows/PostUpdateWindow.hpp
M module-apps/application-desktop/windows/Update.cpp
M module-apps/application-desktop/windows/UpdateProgress.cpp
M module-apps/application-desktop/windows/UpdateProgress.hpp
M module-apps/application-meditation/windows/MeditationTimerWindow.cpp
M module-apps/application-meditation/windows/MeditationTimerWindow.hpp
M module-apps/application-notes/windows/NoteEditWindow.cpp
M module-apps/application-notes/windows/NoteMainWindow.cpp
M module-apps/application-notes/windows/NotePreviewWindow.cpp
M module-apps/application-onboarding/ApplicationOnBoarding.cpp
M module-apps/application-onboarding/model/EULARepository.cpp
M module-apps/application-onboarding/windows/SkipDialogWindow.cpp
M module-apps/application-onboarding/windows/SkipDialogWindow.hpp
M module-apps/application-settings-new/models/SARInfoRepository.cpp
M module-apps/locks/handlers/LockPolicyHandler.cpp
M module-apps/locks/windows/LockInputWindow.cpp
M module-apps/locks/windows/LockInputWindow.hpp
M module-apps/notifications/NotificationData.cpp
M module-apps/popups/HomeModesWindow.cpp
M module-apps/popups/PowerOffWindow.cpp
M module-apps/popups/PowerOffWindow.hpp
M module-apps/popups/TetheringNotificationPopup.cpp
M module-apps/popups/TetheringNotificationPopup.hpp
M module-apps/popups/TetheringOffPopup.cpp
M module-apps/popups/TetheringOffPopup.hpp
M module-apps/popups/VolumeWindow.cpp
M module-apps/popups/lock-popups/PhoneLockChangeInfoWindow.cpp
M module-apps/popups/lock-popups/PhoneLockChangeInfoWindow.hpp
M module-apps/popups/lock-popups/PhoneLockInputWindow.cpp
M module-apps/popups/lock-popups/PhoneLockInputWindow.hpp
M module-apps/popups/lock-popups/PhoneLockedInfoWindow.cpp
M module-apps/popups/lock-popups/PhoneLockedInfoWindow.hpp
M module-apps/popups/lock-popups/PhoneLockedWindow.cpp
M module-apps/popups/lock-popups/PhoneLockedWindow.hpp
M module-apps/popups/lock-popups/SimInfoWindow.cpp
M module-apps/popups/lock-popups/SimInfoWindow.hpp
M module-apps/popups/lock-popups/SimLockInputWindow.cpp
M module-apps/popups/lock-popups/SimLockInputWindow.hpp
M module-apps/popups/lock-popups/SimNotReadyWindow.cpp
M module-apps/popups/lock-popups/SimNotReadyWindow.hpp
M module-apps/windows/AppWindow.cpp
M module-apps/windows/AppWindow.hpp
M module-apps/windows/OptionWindow.cpp
M module-apps/windows/OptionWindow.hpp
M module-cellular/CMakeLists.txt
M module-cellular/modem/mux/CellularMux.cpp
M module-db/CMakeLists.txt
M module-db/Database/Database.cpp
M module-db/Interface/NotificationsRecord.cpp
M module-db/tests/CMakeLists.txt
M module-db/tests/test-initializer/CMakeLists.txt
M module-gui/CMakeLists.txt
M module-gui/README.md
A module-gui/WINDOW.md
A module-gui/doc/window_structure.png
M module-gui/gui/dom/Item2JsonSerializingVisitor.cpp
M module-gui/gui/dom/Item2JsonSerializingVisitor.hpp
M module-gui/gui/dom/ItemDataNames.hpp
M module-gui/gui/input/InputEvent.cpp
M module-gui/gui/input/InputEvent.hpp
M module-gui/gui/input/Profile.cpp
M module-gui/gui/widgets/CMakeLists.txt
R module-gui/gui/widgets/{TopBar => StatusBar}.cpp
R module-gui/gui/widgets/{TopBar => StatusBar}.hpp
M module-gui/gui/widgets/Window.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/BatteryBar.cpp
R module-gui/gui/widgets/{TopBar => status-bar}/BatteryBar.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/BatteryBase.cpp
R module-gui/gui/widgets/{TopBar => status-bar}/BatteryBase.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/BatteryText.cpp
R module-gui/gui/widgets/{TopBar => status-bar}/BatteryText.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/Lock.cpp
R module-gui/gui/widgets/{TopBar => status-bar}/Lock.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/NetworkAccessTechnology.cpp
R module-gui/gui/widgets/{TopBar => status-bar}/NetworkAccessTechnology.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/PhoneMode.cpp
R module-gui/gui/widgets/{TopBar => status-bar}/PhoneMode.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/SIM.cpp
R module-gui/gui/widgets/{TopBar => status-bar}/SIM.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/SignalStrengthBar.cpp
R module-gui/gui/widgets/{TopBar => status-bar}/SignalStrengthBar.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/SignalStrengthBase.cpp
R module-gui/gui/widgets/{TopBar => status-bar}/SignalStrengthBase.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/SignalStrengthText.cpp
R module-gui/gui/widgets/{TopBar => status-bar}/SignalStrengthText.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/StatusBarWidgetBase.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/Style.hpp
R module-gui/gui/widgets/{TopBar => status-bar}/Time.cpp
R module-gui/gui/widgets/{TopBar => status-bar}/Time.hpp
M module-gui/gui/widgets/visitor/GuiVisitor.hpp
M module-gui/test/test-catch-text/CMakeLists.txt
M module-gui/test/test-catch/CMakeLists.txt
M module-gui/test/test-google/test-gui-visitor-call.cpp
M module-services/CMakeLists.txt
M module-services/service-cellular/CMakeLists.txt
M module-services/service-cellular/ServiceCellular.cpp
M module-services/service-cellular/include/service-cellular/State.hpp
M module-services/service-cellular/include/service-cellular/api/notification/notification.hpp
M module-services/service-cellular/service-cellular/CellularMessage.hpp
M module-services/service-cellular/service-cellular/ServiceCellular.hpp
M module-services/service-cellular/src/ServiceCellularPriv.cpp
M module-services/service-cellular/src/SimCard.cpp
M module-services/service-cellular/src/SimCard.hpp
M module-services/service-cellular/src/State.cpp
M module-services/service-db/test/CMakeLists.txt
M module-services/service-db/test/test-settings/CMakeLists.txt
M module-services/service-db/test/test-settings/Database.cpp
M module-services/service-desktop/CMakeLists.txt
M module-services/service-desktop/endpoints/backup/BackupRestore.cpp
M module-services/service-desktop/tests/CMakeLists.txt
M module-services/service-eink/CMakeLists.txt
M module-services/service-eink/EinkDisplay.cpp
M module-services/service-eink/ServiceEink.cpp
M module-services/service-eink/board/linux/renderer/CMakeLists.txt
M module-services/service-eink/board/linux/renderer/src/RWindow.hpp
M module-services/service-evtmgr/CMakeLists.txt
M module-services/service-evtmgr/EventManager.cpp
M module-services/service-evtmgr/WorkerEvent.cpp
M module-services/service-evtmgr/doc/battery_status_notification.svg
M module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp
A module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.cpp
M module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp
M module-services/service-evtmgr/service-evtmgr/EVMessages.hpp
M module-services/service-gui/ServiceGUI.cpp
M module-sys/CMakeLists.txt
M module-sys/Service/Message.hpp
M module-utils/CMakeLists.txt
D module-utils/CrashDebug
M module-utils/board/cross/log_rt1051.cpp
M module-utils/bootconfig/CMakeLists.txt
M module-utils/bootconfig/src/bootconfig.cpp
D module-utils/gsl/gsl
D module-utils/gsl/gsl_algorithm
D module-utils/gsl/gsl_assert
D module-utils/gsl/gsl_byte
D module-utils/gsl/gsl_util
D module-utils/gsl/multi_span
D module-utils/gsl/pointers
D module-utils/gsl/span
D module-utils/gsl/string_span
M module-utils/log/Logger.cpp
D module-utils/re2
M module-utils/test/CMakeLists.txt
M module-utils/third-party/libphonenumber.cmake
D module-utils/third-party/re2.cmake
M module-vfs/CMakeLists.txt
M module-vfs/drivers/include/purefs/fs/drivers/directory_handle_littlefs.hpp
M module-vfs/drivers/include/purefs/fs/drivers/file_handle_littlefs.hpp
M module-vfs/drivers/include/purefs/fs/drivers/mount_point_littlefs.hpp
M module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp
M module-vfs/drivers/src/thirdparty/littlefs/lfs_glue.cpp
D module-vfs/thirdparty/lfsfs/CMakeLists.txt
D module-vfs/thirdparty/lfsfs/littlefs
R {source/main => products/BellHybrid/BellHybridMain}.cpp
A products/BellHybrid/CMakeLists.txt
R {module-vfs/thirdparty/lfsfs/include/littlefs/lfs => products/BellHybrid/config}.h
A products/CMakeLists.txt
A products/PurePhone/CMakeLists.txt
A products/PurePhone/PurePhoneMain.cpp
R {source => products/PurePhone}/config.h
A source/CMakeLists.txt
M source/MessageType.hpp
M test/pytest/test_auto_lock.py
M third-party/CMakeLists.txt
A third-party/CrashDebug/CMakeLists.txt
A third-party/CrashDebug/src
A third-party/gsl
A third-party/littlefs/CMakeLists.txt
A third-party/littlefs/src
A third-party/re2/CMakeLists.txt
A third-party/re2/src
A tools/generate_update_image.sh
M .gitmodules => .gitmodules +13 -11
@@ 11,11 11,6 @@
[submodule "module-utils/crc32"]
	path = third-party/crc32/src
	url = ../crc32
[submodule "module-utils/re2"]
	path = module-utils/re2
	url = ../re2.git
	branch = rt1051
	shallow = true
[submodule "module-utils/protobuf"]
	path = third-party/protobuf/src
	url = ../protobuf.git


@@ 61,10 56,7 @@
[submodule "host-tools/littlefs-fuse/lfsfuse"]
	path = host-tools/littlefs-fuse/lfsfuse
	url = https://github.com/littlefs-project/littlefs-fuse.git
[submodule "module-vfs/thirdparty/lfsfs/littlefs"]
	path = module-vfs/thirdparty/lfsfs/littlefs
	url = https://github.com/littlefs-project/littlefs.git
[submodule "module-utils/sml"]
[submodule "third-party/sml"]
	path = third-party/sml/src
	url = https://github.com/boost-ext/sml
[submodule "tools/misc"]


@@ 74,8 66,8 @@
	path = test/harness
	url = ../QAMuditaHarness.git
	shallow = true
[submodule "module-utils/CrashDebug"]
	path = module-utils/CrashDebug
[submodule "third-party/CrashDebug"]
	path = third-party/CrashDebug/src
	url = https://github.com/adamgreen/CrashDebug.git
[submodule "third-party/minimp3/minimp3"]
	path = third-party/minimp3/minimp3


@@ 84,3 76,13 @@
[submodule "third-party/parallel-hashmap/src"]
	path = third-party/parallel-hashmap/src
	url = https://github.com/greg7mdp/parallel-hashmap.git
[submodule "third-party/littlefs/src"]
	path = third-party/littlefs/src
	url = https://github.com/littlefs-project/littlefs.git
[submodule "third-party/gsl"]
	path = third-party/gsl
	url = https://github.com/microsoft/GSL.git
[submodule "third-party/re2/src"]
	path = third-party/re2/src
	url = ../re2.git
	branch = rt1051

M CMakeLists.txt => CMakeLists.txt +46 -360
@@ 3,7 3,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
project(PurePhone)
project(PureOS)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")



@@ 16,9 16,11 @@ include(SerialPort)
include(CopyGdbInit)
include(Utils)
include(ModuleUtils)
include(FetchBootloader)
include(DiskImage)
include(AddPackage)

message("PROJECT_TARGET: ${PROJECT_TARGET}")
message("TARGET_SOURCES: ${TARGET_SOURCES}")
message("TARGET_COMPILE_DEFINITIONS: ${TARGET_COMPILE_OPTIONS}")
message("TARGET_LIBRARIES: ${TARGET_LIBRARIES}")
message("TARGET_LINKER_FLAGS: ${TARGET_LINKER_FLAGS}")


@@ 26,18 28,17 @@ message("TARGET_LINKER_FLAGS: ${TARGET_LINKER_FLAGS}")
string(REPLACE "TARGET_" "" PROJECT_TARGET_NAME ${PROJECT_TARGET})
string(TOLOWER "${PROJECT_TARGET_NAME}" PROJECT_TARGET_NAME)
message("Project target name: ${PROJECT_TARGET_NAME}")

add_executable(${PROJECT_NAME} "" )

if (NOT ${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
	set(ENABLE_TESTS ON)
    set(ENABLE_TESTS ON)
endif()



if (${ENABLE_TESTS})
	enable_testing()
	add_custom_target(check ${CMAKE_CTEST_COMMAND} -V)
	add_subdirectory(test)
	include(PureCoverage)
    enable_testing()
    add_custom_target(check ${CMAKE_CTEST_COMMAND} -V)
    add_subdirectory(test)
    include(PureCoverage)
endif ()

# setting build flags


@@ 62,44 63,35 @@ endif()

set(TOOLCHAIN_PATH "" CACHE STRING "Path to toolchain directory")

target_link_directories(${PROJECT_NAME} PUBLIC ${PROJECT_LIB_DIRECTORY})

message("Setting PROJECT_LIB_DIRECTORY to ${PROJECT_LIB_DIRECTORY}")
message("Setting CMAKE_BINARY_DIR to ${CMAKE_BINARY_DIR}")
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_CONFIG_DEFINITIONS}
                ${TARGET_COMPILE_DEFINITIONS}
                ${PROJECT_TARGET}
                )

define_serial(${PROJECT_NAME})

add_compile_definitions(FSL_RTOS_FREE_RTOS
                USB_STACK_FREERTOS
                DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
                FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1
                __STARTUP_INITIALIZE_NONCACHEDATA
                SDK_OS_FREE_RTOS
                XIP_EXTERNAL_FLASH=0
                CPU_MIMXRT1051DVL6B_cm7
                CPU_MIMXRT1051DVL6B
                SDK_DEBUGCONSOLE=0
                __MCUXPRESSO
                __USE_CMSIS
                __NEWLIB__
                SKIP_SYSCLK_INIT
                _GNU_SOURCE)
    USB_STACK_FREERTOS
    DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
    FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1
    __STARTUP_INITIALIZE_NONCACHEDATA
    SDK_OS_FREE_RTOS
    XIP_EXTERNAL_FLASH=0
    CPU_MIMXRT1051DVL6B_cm7
    CPU_MIMXRT1051DVL6B
    SDK_DEBUGCONSOLE=0
    __MCUXPRESSO
    __USE_CMSIS
    __NEWLIB__
    SKIP_SYSCLK_INIT
    _GNU_SOURCE)

add_compile_options( ${TARGET_COMPILE_OPTIONS}
                     $<$<COMPILE_LANGUAGE:C>:-std=gnu11>
                     -fsingle-precision-constant
                     -ffunction-sections
                     -fdata-sections
                     -MMD
                     -MP
                     -fno-builtin
                     -fno-diagnostics-color
                     # warning flags
                     -Wall -Wextra -Werror -Wno-unused-parameter -Wno-deprecated-declarations)
    $<$<COMPILE_LANGUAGE:C>:-std=gnu11>
    -fsingle-precision-constant
    -ffunction-sections
    -fdata-sections
    -MMD
    -MP
    -fno-builtin
    -fno-diagnostics-color
    # warning flags
    -Wall -Wextra -Werror -Wno-unused-parameter -Wno-deprecated-declarations)

include_directories(${CMAKE_SOURCE_DIR})

option (GENERATE_STACK_USAGE "Generate stack usage report" OFF)
if (GENERATE_STACK_USAGE)


@@ 114,214 106,34 @@ if (NOT ENABLE_SECURE_BOOT)
    add_compile_definitions(
        XIP_BOOT_HEADER_ENABLE=1
        XIP_BOOT_HEADER_DCD_ENABLE=0
    )
endif ()

target_compile_features(${PROJECT_NAME} PUBLIC
        ${TARGET_COMPILE_FEATURES})


target_compile_options(${PROJECT_NAME} PUBLIC $<$<COMPILE_LANGUAGE:C>:-Wno-discarded-qualifiers>)
add_compile_options("-Wno-error=deprecated-declarations")
target_compile_options(${PROJECT_NAME} PUBLIC "-Wno-error=deprecated-declarations")

target_sources(${CMAKE_PROJECT_NAME} PUBLIC ${TARGET_SOURCES})
target_sources(${CMAKE_PROJECT_NAME}
        PRIVATE

        source/main.cpp
        PUBLIC
        source/MessageType.hpp

        )
endif ()

set(PROJECT_INCLUDES

        ${CMAKE_CURRENT_SOURCE_DIR}/source
        ${CMAKE_CURRENT_SOURCE_DIR}/config


        CACHE INTERNAL "")

include_directories(${CMAKE_CURRENT_SOURCE_DIR})

target_include_directories(${PROJECT_NAME} PUBLIC ${TARGET_DIR_INCLUDES})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_INCLUDES})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_BINARY_DIR})

add_subdirectory(third-party)

if (${PROJECT_TARGET} STREQUAL "TARGET_Linux")
     add_subdirectory(board/linux/libiosyscalls)
    add_subdirectory(board/linux/libiosyscalls)
endif()
message("${PROJECT_NAME}: add_subdirectory module-sys")
add_subdirectory(module-sys)

message("${PROJECT_NAME}: add_subdirectory module-utils")
add_subdirectory(source)
add_subdirectory(module-sys)
add_subdirectory(module-utils)

message("${PROJECT_NAME}: add_subdirectory module-os")
add_subdirectory(module-os)

message("${PROJECT_NAME}: add_subdirectory module-bsp")
add_subdirectory(module-bsp)

message("${PROJECT_NAME}: add_subdirectory module-vfs")
add_subdirectory(module-vfs)

message("${PROJECT_NAME}: add_subdirectory module-gui")
add_subdirectory(module-gui)

message("${PROJECT_NAME}: add_subdirectory module-db")
add_subdirectory(module-db)

message("${PROJECT_NAME}: add_subdirectory module-cellular")
add_subdirectory(module-cellular)

message("${PROJECT_NAME}: add_subdirectory module-audio")
add_subdirectory(module-audio)

message("${PROJECT_NAME}: add_subdirectory module-services")
add_subdirectory(module-services)

message("${PROJECT_NAME}: add_subdirectory module-apps")
add_subdirectory(module-apps)

message("${PROJECT_NAME}: add_subdirectory module-bluetooth")
add_subdirectory(module-bluetooth)

message("${PROJECT_NAME}: add_subdirectory module-lwip")
add_subdirectory(module-lwip)

add_subdirectory(image)

set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES SUFFIX ".elf")

set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES LINK_FLAGS "-Xlinker -Map=${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.map ")

# M.P: Please don't change the order of modules in the first group ("module-bsp" - "module-utils")
# They have to be arranged in specific order because of circular dependencies that need to be correctly resolved
# In case of doubt please contact me: mateusz.piesta@mudita.com
target_link_libraries(${PROJECT_NAME}
        date::date
        module-apps
        service-desktop
        service-bluetooth
        service-lwip
        ${LWIP_LIBRARIES}
        )

if (${PROJECT_TARGET} STREQUAL "TARGET_Linux")
    target_link_libraries(${PROJECT_NAME} iosyscalls)
endif()

include(tools/clang-tidy.cmake)

set_source_files_properties(source/main.cpp PROPERTIES COMPILE_DEFINITIONS "${ENABLED_APPS_DEFINES}")

target_link_options(${PROJECT_NAME} PUBLIC ${TARGET_LINK_OPTIONS})

add_subdirectory(host-tools)


if (${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
    set(HEX_FILE ${CMAKE_PROJECT_NAME}.hex)
    set(BIN_FILE ${CMAKE_BINARY_DIR}/sys/current/boot.bin)

    if (ENABLE_SECURE_BOOT)
        set (SREC_FILE ${CMAKE_PROJECT_NAME}.srec)
        # .srec file required by elftosb
        add_custom_command(
            COMMENT "Generate ${CMAKE_PROJECT_NAME}.srec"
            OUTPUT ${CMAKE_BINARY_DIR}/${SREC_FILE}
            DEPENDS ${CMAKE_PROJECT_NAME}
            COMMAND ${CMAKE_OBJCOPY} -Osrec $<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${SREC_FILE}
            )

        add_custom_command(
            COMMENT "Generate signed boot.bin (Secure Boot)"
            OUTPUT ${BIN_FILE}
            DEPENDS ${CMAKE_BINARY_DIR}/${SREC_FILE}
            COMMAND ${CMAKE_SOURCE_DIR}/config/elftosb_wrapper.sh "${ELFTOSB_PATH}" "${CST_PATH}" -f imx -V
            -c ${CMAKE_BINARY_DIR}/imx_authenticated_hab.bd
            -o ${BIN_FILE}
            ${CMAKE_BINARY_DIR}/${SREC_FILE}
            VERBATIM
            )
    else ()
        add_custom_command(
            COMMENT "Generate boot.bin"
            OUTPUT ${BIN_FILE}
            DEPENDS ${CMAKE_PROJECT_NAME}
            COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${BIN_FILE}
            )
    endif()

    add_custom_command(
        COMMENT "Generate ${CMAKE_PROJECT_NAME}.hex"
        OUTPUT ${CMAKE_BINARY_DIR}/${HEX_FILE}
        DEPENDS ${CMAKE_PROJECT_NAME}
        COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${HEX_FILE}
        )

    add_custom_target(
        ${HEX_FILE}-target ALL
        DEPENDS ${CMAKE_BINARY_DIR}/${HEX_FILE}
        )

    # download the bootloader
    set(ECOBOOT_FILE ecoboot.bin)
    set(ECOBOOT_DOWNLOAD_LOG ${CMAKE_BINARY_DIR}/download_info.txt)

    if(DEFINED ENV{ASSETS_LOGIN} AND DEFINED ENV{ASSETS_TOKEN})
        message("ecooboot download with tokens")
        add_custom_command(OUTPUT ${ECOBOOT_FILE}
            COMMAND ${CMAKE_SOURCE_DIR}/tools/download_asset.py
            -l $ENV{ASSETS_LOGIN}
            -t $ENV{ASSETS_TOKEN}
            -w ${CMAKE_BINARY_DIR} ecoboot download
            > ${ECOBOOT_DOWNLOAD_LOG}
            COMMENT "Downloading ${ECOBOOT_FILE}"
            BYPRODUCTS ${ECOBOOT_DOWNLOAD_LOG}
            )
    else()
        message("ecoboot download with git")
        add_custom_command(OUTPUT ${ECOBOOT_FILE}
            COMMAND ${CMAKE_SOURCE_DIR}/tools/download_asset.py
            -w ${CMAKE_BINARY_DIR} ecoboot download
            > ${ECOBOOT_DOWNLOAD_LOG}
            COMMENT "Downloading ${ECOBOOT_FILE}"
            BYPRODUCTS ${ECOBOOT_DOWNLOAD_LOG}
            )
    endif()

    add_custom_target(${ECOBOOT_FILE}-target DEPENDS ${ECOBOOT_FILE})

    # generate version.json file (runs CMake script at build time)
    set(VERSION_JSON_FILE version.json)
    add_custom_command(OUTPUT ${VERSION_JSON_FILE}
        COMMAND ${CMAKE_COMMAND}
        -DSRC_DIR=${CMAKE_SOURCE_DIR}
        -DECOBOOT_DOWNLOAD_LOG=${ECOBOOT_DOWNLOAD_LOG}
        -B ${CMAKE_BINARY_DIR}
        -P ${CMAKE_SOURCE_DIR}/cmake/modules/GenUpdateVersionJson.cmake
        DEPENDS ${ECOBOOT_FILE}-target ${ECOBOOT_DOWNLOAD_LOG}
        )

    add_custom_target(${VERSION_JSON_FILE}-target DEPENDS ${VERSION_JSON_FILE})

    multicomp_install(PROGRAMS ${CMAKE_BINARY_DIR}/${ECOBOOT_FILE} DESTINATION "./" 
        COMPONENTS Standalone Update)
    multicomp_install(FILES ${CMAKE_BINARY_DIR}/${VERSION_JSON_FILE} DESTINATION "./" 
        COMPONENTS Standalone Update)
endif()

if (${CMAKE_BUILD_TYPE} STREQUAL "Release")
    add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
        COMMAND ${CMAKE_STRIP} --strip-debug --strip-unneeded $<TARGET_FILE:${CMAKE_PROJECT_NAME}>
        )
endif()
include(tools/clang-tidy.cmake)

install(
    FILES ${PROJECT_SOURCE_DIR}/changelog.md


@@ 329,31 141,11 @@ install(
    COMPONENT Standalone
    )

if (${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
    add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} --only-keep-debug
                $<TARGET_FILE:${CMAKE_PROJECT_NAME}>
                $<TARGET_FILE:${CMAKE_PROJECT_NAME}>.debug
        COMMAND ${CMAKE_STRIP} --strip-debug --strip-unneeded $<TARGET_FILE:${CMAKE_PROJECT_NAME}>
        COMMAND ${CMAKE_OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE:${CMAKE_PROJECT_NAME}>.debug
                $<TARGET_FILE:${CMAKE_PROJECT_NAME}>
        )
endif()

include(DiskImage)

message_serial_status()

option (BUILD_DOC_WITH_ALL "Build documentation" OFF)
include (GenDoxygenDoc)

message("SRC DIR: ${CMAKE_SOURCE_DIR}")

include(Version)
configure_file(
    ${SRC_DIR}/source/version.hpp.template
    ${CMAKE_BINARY_DIR}/source/version.hpp
    )

add_custom_target(
    version ALL
    COMMAND ${CMAKE_COMMAND}


@@ 363,114 155,8 @@ add_custom_target(
    COMMENT
        "Generating version info"
    )
add_dependencies(${PROJECT_NAME} version)

if (${PROJECT_TARGET} STREQUAL "TARGET_Linux")
    set(CPACK_SYSTEM_NAME "Linux")
    set(CPACK_COMPONENTS_ALL Standalone)
else()
    set(CPACK_SYSTEM_NAME "RT1051")
    set(CPACK_COMPONENTS_ALL Standalone Update)
endif()
set(CPACK_PACKAGE_VENDOR "Mudita")
set(CPACK_PACKAGE_NAME "PurePhone")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://mudita.com/products/pure/")
set(CPACK_TOPLEVEL_TAG ${CPACK_SYSTEM_NAME})
# the CPACK_PACKAGE_FILE_NAME variable will be reset after include(CPack) hence a copy
set(PACKAGE_COMMON_NAME ${CPACK_PACKAGE_NAME}-${CMAKE_PROJECT_VERSION}-${CPACK_TOPLEVEL_TAG})
set(CPACK_PACKAGE_FILE_NAME ${PACKAGE_COMMON_NAME})
# setting this will CPack prevent from additing the default 'package' target
set(CPACK_OUTPUT_CONFIG_FILE ${CMAKE_BINARY_DIR}/PackageConfig.cmake)
set(CPACK_GENERATOR "External")
set(CPACK_COMPONENTS_GROUPING IGNORE)
set(CPACK_EXTERNAL_ENABLE_STAGING TRUE)
set(PACKAGE_STAGING_DIRECTORY ${CMAKE_BINARY_DIR}/_CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME})
message(PACKAGE_STAGING_DIRECTORY ${CMAKE_BINARY_DIR}/_CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME})
message("CPACK_TOPLEVEL_TAG:'${CPACK_TOPLEVEL_TAG}'")
message("CPACK_GENERATOR:'${CPACK_GENERATOR}'")
message("CPACK_PACKAGE_FILE_NAME:'${CPACK_PACKAGE_FILE_NAME}'")

include(CPack)

if (${PROJECT_TARGET} STREQUAL "TARGET_Linux")
    multicomp_install(
        TARGETS ${CMAKE_PROJECT_NAME}
        DESTINATION "./"
        COMPONENTS Standalone Update
        )
    add_custom_target(package-standalone-staged
        COMMAND ${CMAKE_CPACK_COMMAND}
        -C $<CONFIGURATION>
        --config ${CPACK_OUTPUT_CONFIG_FILE}
        DEPENDS ${CMAKE_PROJECT_NAME} service_renderer
    )
    set(PACKAGE_STANDALONE_FILE_NAME ${PACKAGE_COMMON_NAME}-Standalone.tar.gz)
    set(PACKAGE_STANDALONE_MIME "application/x-compressed-tar")

    add_custom_target(package-standalone
        COMMAND tar
        -czf ${CMAKE_BINARY_DIR}/${PACKAGE_STANDALONE_FILE_NAME}
        -C ${PACKAGE_STAGING_DIRECTORY}/Standalone "."
        DEPENDS package-standalone-staged
        )
    add_custom_target(
        eeprom_image ALL
        DEPENDS genlittlefs
        DEPENDS assets
        COMMAND ${CMAKE_BINARY_DIR}/genlittlefs -b 128 -s 32768 --overwrite --image ${CMAKE_BINARY_DIR}/eeprom.img ${CMAKE_BINARY_DIR}/sys/personalization.json
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        COMMENT "Generate eeprom image"
    )
endif()

if (${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
    set(PACKAGE_STANDALONE_MIME "application/x-xz")
    set(PACKAGE_STANDALONE_FILE_NAME ${PACKAGE_COMMON_NAME}-image.tar.xz)
    add_custom_target(package-standalone
        COMMAND tar -ScJf ${PACKAGE_STANDALONE_FILE_NAME} ${DISK_IMAGE_NAME}
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        DEPENDS ${BIN_FILE} ${ECOBOOT_FILE}-target ${VERSION_JSON_FILE}-target disk_image
        )

    set(PACKAGE_UPDATE_FILE_NAME ${PACKAGE_COMMON_NAME}-Update.tar)
    set(PACKAGE_UPDATE_MIME "application/x-tar")
    set(UPDATE_STAGING_DIRECTORY ${PACKAGE_STAGING_DIRECTORY}/Update)
    add_custom_target(package-update-staged
        COMMAND ${CMAKE_CPACK_COMMAND}
        -C $<CONFIGURATION>
        --config ${CPACK_OUTPUT_CONFIG_FILE}
        DEPENDS  ${BIN_FILE} ${ECOBOOT_FILE}-target ${VERSION_JSON_FILE}-target
        )
    add_custom_target(package-update-checksums
        COMMAND rhash
        -u checksums.txt
        -r .
        WORKING_DIRECTORY ${UPDATE_STAGING_DIRECTORY}
        DEPENDS package-update-staged
        )

    
    add_custom_target(package-update
        COMMAND tar
        -cf ${CMAKE_BINARY_DIR}/${PACKAGE_UPDATE_FILE_NAME}
        -C ${PACKAGE_STAGING_DIRECTORY}/Update "."
        DEPENDS  ${ECOBOOT_FILE}-target ${VERSION_JSON_FILE}-target PurePhone package-update-staged package-update-checksums 
        )
endif()




if (NOT "$ENV{GITHUB_WORKSPACE}" STREQUAL "")
    message("set-output name=package-standalone::${PACKAGE_STANDALONE_FILE_NAME}")
    message("::set-output name=package-standalone::${PACKAGE_STANDALONE_FILE_NAME}")
    message("set-output name=standalone-mime_type::${PACKAGE_STANDALONE_MIME}")
    message("::set-output name=standalone-mime_type::${PACKAGE_STANDALONE_MIME}")

    message("set-output name=package-update::${PACKAGE_UPDATE_FILE_NAME}")
    message("::set-output name=package-update::${PACKAGE_UPDATE_FILE_NAME}")
    message("set-output name=update-mime_type::${PACKAGE_UPDATE_MIME}")
    message("::set-output name=update-mime_type::${PACKAGE_UPDATE_MIME}")

endif()
fetch_ecoboot()
add_subdirectory(products)

include(GitHubWorkerMessages)

M Jenkinsfile => Jenkinsfile +1 -1
@@ 124,7 124,7 @@ echo "./configure.sh linux Debug -G Ninja"
./configure.sh linux Debug -G Ninja

pushd build-linux-Debug
ninja -j ${JOBS}
ninja -j ${JOBS} Pure Bell
popd'''
                echo "Build Unit Tests"
                sh '''#!/bin/bash -e

M Target_RT1051.cmake => Target_RT1051.cmake +0 -3
@@ 78,7 78,6 @@ set(TARGET_SOURCES
        ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/xip/evkbimxrt1050_flexspi_nor_config.c
        ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/xip/evkbimxrt1050_sdram_ini_dcd.c
        ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/xip/fsl_flexspi_nor_boot.c
        ${CMAKE_SOURCE_DIR}/module-utils/CrashDebug/CrashCatcher/Core/src/CrashCatcher.c
        ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/crashdump/CrashCatcher_armv7m.S
        ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/crashdump/crashcatcher_impl.cpp
        ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/crashdump/crashdumpwriter_vfs.cpp


@@ 93,8 92,6 @@ set(TARGET_DIR_INCLUDES

set(BOARD_DIR_INCLUDES
        ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/newlib/include
        ${CMAKE_SOURCE_DIR}/module-utils/CrashDebug/CrashCatcher/include
        ${CMAKE_SOURCE_DIR}/module-utils/CrashDebug/CrashCatcher/Core/src
        ${CMAKE_SOURCE_DIR}/module-vfs/include/internal
)


M board/linux/libiosyscalls/src/syscalls_posix.cpp => board/linux/libiosyscalls/src/syscalls_posix.cpp +4 -4
@@ 48,7 48,7 @@ namespace
        __REAL_DECL(fsync);
        __REAL_DECL(fdatasync);

#if __GLIBC__ > 2 || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 32))
#if __GLIBC__ > 2 || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 33))
        __REAL_DECL(stat);
        __REAL_DECL(lstat);
        __REAL_DECL(fstat);


@@ 101,7 101,7 @@ namespace
        __REAL_DLSYM(fsync);
        __REAL_DLSYM(fdatasync);

#if __GLIBC__ > 2 || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 32))
#if __GLIBC__ > 2 || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 33))
        __REAL_DLSYM(stat);
        __REAL_DLSYM(lstat);
        __REAL_DLSYM(fstat);


@@ 137,7 137,7 @@ namespace
#if __GLIBC__ > 2 || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 28))
              && real::fcntl64
#endif
#if __GLIBC__ > 2 || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 32))
#if __GLIBC__ > 2 || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 33))
              && real::stat && real::lstat && real::fstat && real::stat64 && real::lstat64 && real::fstat64
#else
              && real::__xstat && real::__lxstat && real::__fxstat && real::__xstat64 && real::__lxstat64 &&


@@ 507,7 507,7 @@ extern "C"
    }
    __asm__(".symver _iosys_symlink,symlink@GLIBC_2.2.5");

#if __GLIBC__ > 2 || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 32))
#if __GLIBC__ > 2 || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 33))
    int _iosys_stat(const char *file, struct stat *pstat)
    {
        if (vfs::redirect_to_image(file)) {

M board/linux/libiosyscalls/test/CMakeLists.txt => board/linux/libiosyscalls/test/CMakeLists.txt +1 -1
@@ 9,5 9,5 @@ add_catch2_executable(
    LIBS
        module-vfs iosyscalls
    DEPS
        disk_image
        PurePhone-disk-img
)

A cmake/modules/AddBootBin.cmake => cmake/modules/AddBootBin.cmake +39 -0
@@ 0,0 1,39 @@
function(add_boot_bin SOURCE_TARGET)
    set(BIN_FILE ${CMAKE_BINARY_DIR}/sys/current/${SOURCE_TARGET}-boot.bin)

    if (ENABLE_SECURE_BOOT)
        set (SREC_FILE ${CMAKE_PROJECT_NAME}.srec)
        # .srec file required by elftosb
        add_custom_command(
            COMMENT "Generate ${CMAKE_PROJECT_NAME}.srec"
            OUTPUT ${CMAKE_BINARY_DIR}/${SREC_FILE}
            DEPENDS ${SOURCE_TARGET}
            COMMAND ${CMAKE_OBJCOPY} -Osrec $<TARGET_FILE:${SOURCE_TARGET}> ${SREC_FILE}
            WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
            )

        add_custom_command(
            COMMENT "Generate signed boot.bin (Secure Boot)"
            OUTPUT ${BIN_FILE}
            DEPENDS ${CMAKE_BINARY_DIR}/${SREC_FILE}
            COMMAND ${CMAKE_SOURCE_DIR}/config/elftosb_wrapper.sh "${ELFTOSB_PATH}" "${CST_PATH}" -f imx -V
            -c ${CMAKE_BINARY_DIR}/imx_authenticated_hab.bd
            -o ${BIN_FILE}
            ${CMAKE_BINARY_DIR}/${SREC_FILE}
            VERBATIM
            WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
            )
    else ()
        add_custom_command(
            COMMENT "Generate ${SOURCE_TARGET}-boot.bin"
            OUTPUT ${BIN_FILE}
            DEPENDS ${SOURCE_TARGET}
            COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${SOURCE_TARGET}> ${BIN_FILE}
            WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
            )
    endif()
    message("Adding '${SOURCE_TARGET}-boot.bin' target")
    add_custom_target(${SOURCE_TARGET}-boot.bin
        DEPENDS ${BIN_FILE})
    set_target_properties(${SOURCE_TARGET}-boot.bin PROPERTIES BIN_FILE ${BIN_FILE})
endfunction()

A cmake/modules/AddHexTarget.cmake => cmake/modules/AddHexTarget.cmake +13 -0
@@ 0,0 1,13 @@
function(add_hex_target SOURCE_TARGET)
    set(HEX_FILE ${SOURCE_TARGET}.hex)
    add_custom_command(
        COMMENT "Generate ${HEX_FILE}"
        OUTPUT ${CMAKE_BINARY_DIR}/${HEX_FILE}
        DEPENDS ${SOURCE_TARGET}
        COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${SOURCE_TARGET}>
        )
    add_custom_target(
        ${HEX_FILE}-target ALL
        DEPENDS ${CMAKE_BINARY_DIR}/${HEX_FILE}
        )
endfunction()

A cmake/modules/AddPackage.cmake => cmake/modules/AddPackage.cmake +73 -0
@@ 0,0 1,73 @@


macro(set_cpack_vars)
    if (${PROJECT_TARGET} STREQUAL "TARGET_Linux")
        set(CPACK_SYSTEM_NAME "Linux")
        set(CPACK_COMPONENTS_ALL Standalone)
    elseif(${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
        set(CPACK_SYSTEM_NAME "RT1051")
        set(CPACK_COMPONENTS_ALL Standalone Update)
    else()
        message(FATAL_ERROR "Unsupported project target: '${PROJECT_TARGET}'")
    endif()

    set(CPACK_PACKAGE_VENDOR "Mudita")
    set(CPACK_PACKAGE_HOMEPAGE_URL "https://mudita.com/products/pure/")

    set(CPACK_TOPLEVEL_TAG ${CPACK_SYSTEM_NAME})
    set(CPACK_OUTPUT_CONFIG_FILE ${CMAKE_BINARY_DIR}/PackageConfig.cmake)
    set(CPACK_GENERATOR "External")
    set(CPACK_COMPONENTS_GROUPING IGNORE)
    set(CPACK_EXTERNAL_ENABLE_STAGING TRUE)
    set(PACKAGE_COMMON_NAME ${CPACK_PACKAGE_NAME}-${CMAKE_PROJECT_VERSION}-${CPACK_TOPLEVEL_TAG})
    set(CPACK_PACKAGE_FILE_NAME ${PACKAGE_COMMON_NAME})
    set(PACKAGE_STAGING_DIRECTORY ${CMAKE_BINARY_DIR}/_CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME})

endmacro()

function(add_standalone_image SOURCE_TARGET)
    if (NOT ${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
        return()
    endif()
    set(BIN_FILE ${SOURCE_TARGET}-boot.bin)
    set(CPACK_PACKAGE_NAME ${SOURCE_TARGET})
    set_cpack_vars()

    set(PACKAGE_STANDALONE_MIME "application/x-xz")
    set(PACKAGE_STANDALONE_FILE_NAME ${PACKAGE_COMMON_NAME}-image.tar.xz)

    add_custom_target(${PACKAGE_COMMON_NAME}-package-standalone
        COMMAND tar -ScJf ${PACKAGE_STANDALONE_FILE_NAME} ${SOURCE_TARGET}.img
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        DEPENDS ${BIN_FILE} ${ECOBOOT_FILE}-target ${VERSION_JSON_FILE}-target ${SOURCE_TARGET}.img
        )

    message("Adding stand alone target '${SOURCE_TARGET}-StandaloneImage'")
    add_custom_target(${SOURCE_TARGET}-StandaloneImage
        DEPENDS ${PACKAGE_COMMON_NAME}-package-standalone)
endfunction()


function(add_update_package SOURCE_TARGET)
    if (NOT ${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
        return()
    endif()
    set(CPACK_PACKAGE_NAME ${SOURCE_TARGET})
    set_cpack_vars()
    set(UPDATE_PKG "${SOURCE_TARGET}-${CMAKE_PROJECT_VERSION}-${CPACK_SYSTEM_NAME}-Update.tar")
    add_custom_command(
        OUTPUT ${UPDATE_PKG}
        DEPENDS ${SOURCE_TARGET}
        DEPENDS ${SOURCE_TARGET}-boot.bin
        DEPENDS ecoboot.bin-target
        DEPENDS version.json-target
        DEPENDS assets
        COMMAND ${CMAKE_SOURCE_DIR}/tools/generate_update_image.sh ${SOURCE_TARGET} ${CMAKE_PROJECT_VERSION} ${CPACK_SYSTEM_NAME}
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        COMMENT "Generating update image"
        )
    message("Adding '${SOURCE_TARGET}-UpdatePackage' target")
    add_custom_target(${SOURCE_TARGET}-UpdatePackage
        DEPENDS ${UPDATE_PKG}
        )
endfunction()

M cmake/modules/Colours.cmake => cmake/modules/Colours.cmake +20 -20
@@ 2,27 2,27 @@ option(COLOR_OUTPUT "Use colored output" ON)
set(CMAKE_COLOR_MAKEFILE ${COLOR_OUTPUT})

if (COLOR_OUTPUT)
	string(ASCII 27 Esc)
	set(ColourReset "${Esc}[m")
	set(ColourBold  "${Esc}[1m")
	set(Red         "${Esc}[31m")
	set(Green       "${Esc}[32m")
	set(Yellow      "${Esc}[33m")
	set(Blue        "${Esc}[34m")
	set(Magenta     "${Esc}[35m")
	set(Cyan        "${Esc}[36m")
	set(White       "${Esc}[37m")
	set(BoldRed     "${Esc}[1;31m")
	set(BoldGreen   "${Esc}[1;32m")
	set(BoldYellow  "${Esc}[1;33m")
	set(BoldBlue    "${Esc}[1;34m")
	set(BoldMagenta "${Esc}[1;35m")
	set(BoldCyan    "${Esc}[1;36m")
	set(BoldWhite   "${Esc}[1;37m")
    string(ASCII 27 Esc)
    set(ColourReset "${Esc}[m")
    set(ColourBold  "${Esc}[1m")
    set(Red         "${Esc}[31m")
    set(Green       "${Esc}[32m")
    set(Yellow      "${Esc}[33m")
    set(Blue        "${Esc}[34m")
    set(Magenta     "${Esc}[35m")
    set(Cyan        "${Esc}[36m")
    set(White       "${Esc}[37m")
    set(BoldRed     "${Esc}[1;31m")
    set(BoldGreen   "${Esc}[1;32m")
    set(BoldYellow  "${Esc}[1;33m")
    set(BoldBlue    "${Esc}[1;34m")
    set(BoldMagenta "${Esc}[1;35m")
    set(BoldCyan    "${Esc}[1;36m")
    set(BoldWhite   "${Esc}[1;37m")

	set(ORANGE      "${Esc}[38;2;255;100;0m")
    set(Orange      "${Esc}[38;2;255;100;0m")

	add_compile_options (-fdiagnostics-color=always)
    add_compile_options (-fdiagnostics-color=always)
else (COLOR_OUTPUT)
	add_compile_options (-fdiagnostics-color=never)
    add_compile_options (-fdiagnostics-color=never)
endif (COLOR_OUTPUT)

M cmake/modules/DiskImage.cmake => cmake/modules/DiskImage.cmake +30 -17
@@ 1,19 1,32 @@
set(DISK_IMAGE_NAME ${CMAKE_PROJECT_NAME}.img)
set(DISK_IMAGE ${CMAKE_BINARY_DIR}/${DISK_IMAGE_NAME})
function(add_image SOURCE_TARGET)
    set(DISK_IMAGE_NAME ${SOURCE_TARGET}.img)
    set(DISK_IMAGE ${CMAKE_BINARY_DIR}/${DISK_IMAGE_NAME})
    set(BIN_FILE_TARGET ${SOURCE_TARGET}-boot.bin)
    get_target_property(BIN_FILE ${BIN_FILE_TARGET} BIN_FILE)

if (${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
    SET(TARGET_DEP ${BIN_FILE} pureflash)
else()
    SET(TARGET_DEP ${CMAKE_PROJECT_NAME})
endif()
    if (${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
        SET(TARGET_DEP ${BIN_FILE} pureflash)
    else()
        SET(TARGET_DEP ${SOURCE_TARGET})
    endif()

add_custom_target(
    disk_image ALL
    DEPENDS genlittlefs
    DEPENDS assets
    DEPENDS ${TARGET_DEP}
    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/generate_purephone_image.sh
    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/generate_purephone_image.sh ${DISK_IMAGE} ${CMAKE_BINARY_DIR}
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
    COMMENT "Generate ${DISK_IMAGE}"
    )
    add_custom_command(
        OUTPUT ${DISK_IMAGE_NAME}
        DEPENDS genlittlefs
        DEPENDS assets
        DEPENDS ${BIN_FILE_TARGET}
        DEPENDS ${TARGET_DEP}
        DEPENDS ${CMAKE_SOURCE_DIR}/generate_image.sh
        COMMAND ${CMAKE_SOURCE_DIR}/generate_image.sh
        ${DISK_IMAGE}
        ${CMAKE_BINARY_DIR}
        "$<$<STREQUAL:${PROJECT_TARGET},TARGET_RT1051>:${BIN_FILE}>"
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        COMMENT "Generate ${DISK_IMAGE_NAME}"
        )

    message("Adding disk image target: ${DISK_IMAGE_NAME}")
    add_custom_target(${SOURCE_TARGET}-disk-img
        DEPENDS ${DISK_IMAGE_NAME})

endfunction()

A cmake/modules/FetchBootloader.cmake => cmake/modules/FetchBootloader.cmake +35 -0
@@ 0,0 1,35 @@
# download the bootloader
set(ECOBOOT_FILE ecoboot.bin)
set(VERSION_JSON_FILE version.json)

function(fetch_ecoboot)
    set(ECOBOOT_DOWNLOAD_LOG ${CMAKE_BINARY_DIR}/download_info.txt)
        add_custom_command(OUTPUT ${ECOBOOT_FILE}
            COMMAND ${CMAKE_SOURCE_DIR}/tools/download_asset.py
            "$<$<BOOL:$ENV{ASSETS_LOGIN}>:-l$ENV{ASSETS_LOGIN}>"
            "$<$<BOOL:$ENV{ASSETS_TOKEN}>:-t$ENV{ASSETS_TOKEN}>"
            -w ${CMAKE_BINARY_DIR} ecoboot download
            > ${ECOBOOT_DOWNLOAD_LOG}
            COMMENT "Downloading ${ECOBOOT_FILE}"
            BYPRODUCTS ${ECOBOOT_DOWNLOAD_LOG}
            )

    add_custom_target(${ECOBOOT_FILE}-target DEPENDS ${ECOBOOT_FILE})

    # generate version.json file (runs CMake script at build time)
    add_custom_command(OUTPUT ${VERSION_JSON_FILE}
        COMMAND ${CMAKE_COMMAND}
        -DSRC_DIR=${CMAKE_SOURCE_DIR}
        -DECOBOOT_DOWNLOAD_LOG=${ECOBOOT_DOWNLOAD_LOG}
        -B ${CMAKE_BINARY_DIR}
        -P ${CMAKE_SOURCE_DIR}/cmake/modules/GenUpdateVersionJson.cmake
        DEPENDS ${ECOBOOT_FILE}-target ${ECOBOOT_DOWNLOAD_LOG}
        )

    add_custom_target(${VERSION_JSON_FILE}-target DEPENDS ${VERSION_JSON_FILE})

    multicomp_install(PROGRAMS ${CMAKE_BINARY_DIR}/${ECOBOOT_FILE} DESTINATION "./"
        COMPONENTS Standalone Update)
    multicomp_install(FILES ${CMAKE_BINARY_DIR}/${VERSION_JSON_FILE} DESTINATION "./"
        COMPONENTS Standalone Update)
endfunction()

M cmake/modules/GenVersionHpp.cmake => cmake/modules/GenVersionHpp.cmake +0 -1
@@ 3,7 3,6 @@

list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/cmake/modules")
include(Version)

configure_file(
    ${SRC_DIR}/source/version.hpp.template
    ${CMAKE_BINARY_DIR}/source/version.hpp

A cmake/modules/GitHubWorkerMessages.cmake => cmake/modules/GitHubWorkerMessages.cmake +14 -0
@@ 0,0 1,14 @@
function(github_worker_message)
    if (NOT DEFINED ENV{GITHUB_WORKSPACE})
        return()
    endif()
        message("set-output name=package-standalone::${PACKAGE_STANDALONE_FILE_NAME}")
        message("::set-output name=package-standalone::${PACKAGE_STANDALONE_FILE_NAME}")
        message("set-output name=standalone-mime_type::${PACKAGE_STANDALONE_MIME}")
        message("::set-output name=standalone-mime_type::${PACKAGE_STANDALONE_MIME}")

        message("set-output name=package-update::${PACKAGE_UPDATE_FILE_NAME}")
        message("::set-output name=package-update::${PACKAGE_UPDATE_FILE_NAME}")
        message("set-output name=update-mime_type::${PACKAGE_UPDATE_MIME}")
        message("::set-output name=update-mime_type::${PACKAGE_UPDATE_MIME}")
endfunction()

M cmake/modules/PureCoverage.cmake => cmake/modules/PureCoverage.cmake +0 -1
@@ 31,7 31,6 @@ if(COVERAGE_ENABLE)
        module-utils/gsl/.*
        module-utils/json/.*
        module-utils/libphonenumber/.*
        module-utils/re2/.*
        module-utils/segger/.*
        source/main.cpp
        test/.*

M cmake/modules/SerialPort.cmake => cmake/modules/SerialPort.cmake +3 -3
@@ 36,9 36,9 @@ macro(message_serial_status)
        if (SERIAL_PORT_DEF)
            message("Using serial port: ${SERIAL_PORT_DEF}")
        else()
            message ("${ORANGE}Serial Port not defined, modem support disabled! ${ColourReset}")
            message ("${ORANGE}add -DSERIAL_PORT=<path to serail> where modem is connected ${ColourReset}")
            message ("${ORANGE}ex.: \n ./configure.sh linux Debug -DSERIAL_PORT=/dev/ttyUSB0 ${ColourReset}")
            message ("${Orange}Serial Port not defined, modem support disabled! ${ColourReset}")
            message ("${Orange}add -DSERIAL_PORT=<path to serail> where modem is connected ${ColourReset}")
            message ("${Orange}ex.: \n ./configure.sh linux Debug -DSERIAL_PORT=/dev/ttyUSB0 ${ColourReset}")
        endif()
    endif()
endmacro()

M cmake/modules/Utils.cmake => cmake/modules/Utils.cmake +28 -0
@@ 12,3 12,31 @@ function(multicomp_install)
    endforeach()
endfunction()

macro(print_var VARIABLE)
    if(${VARIABLE})
        message(STATUS "${Green}${VARIABLE}: '${Orange}${${VARIABLE}}${ColourReset}'")
    else()
        message(STATUS "${Orange}No such variable: '${Red}${VARIABLE}${ColourReset}'")
    endif()
endmacro()

function(strip_executable TARGET)
    if (${CMAKE_BUILD_TYPE} STREQUAL "Release")
        add_custom_command(TARGET ${TARGET} POST_BUILD
            COMMAND ${CMAKE_STRIP} --strip-debug --strip-unneeded $<TARGET_FILE:${TARGET}>
            COMMENT "Striping  ${TARGET}"
            )
    endif()

    if (${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
        add_custom_command(TARGET ${TARGET} POST_BUILD
            COMMAND ${CMAKE_OBJCOPY} --only-keep-debug
                    $<TARGET_FILE:${TARGET}>
                    $<TARGET_FILE:${TARGET}>.debug
            COMMAND ${CMAKE_STRIP} --strip-debug --strip-unneeded $<TARGET_FILE:${TARGET}>
            COMMAND ${CMAKE_OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE:${TARGET}>.debug
                    $<TARGET_FILE:${TARGET}>
            COMMENT "Striping  ${TARGET}"
            )
    endif()
endfunction()

M cmake/modules/Version.cmake => cmake/modules/Version.cmake +0 -1
@@ 90,4 90,3 @@ set(CMAKE_PROJECT_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(CMAKE_PROJECT_VERSION_MINOR "${CMAKE_MATCH_2}")
set(CMAKE_PROJECT_VERSION_PATCH "${CMAKE_MATCH_3}")
set(CMAKE_PROJECT_VERSION "${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}")


M configure.sh => configure.sh +3 -3
@@ 1,5 1,5 @@
#!/bin/bash
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

if [[ $BASH_VERSINFO -lt 4 ]]; then


@@ 87,9 87,9 @@ if check_target && check_build_type ; then
        if $CMAKE_CMD; then
            Ninja=$(echo $@ | grep "Ninja")
            if [[ -z ${Ninja} ]]; then
                echo -e "\e[32mcd ${BUILD_DIR} && make -j $(nproc)\e[0m"
                echo -e "\e[32mcd ${BUILD_DIR} && make -j $(nproc) <Pure|Bell>\e[0m"
            else
                echo -e "\e[32mcd ${BUILD_DIR} && ninja\e[0m"
                echo -e "\e[32mcd ${BUILD_DIR} && ninja <Pure|Bell>\e[0m"
            fi
        else
            echo -e "configuration error!"

M debug_crash_dump.sh => debug_crash_dump.sh +1 -1
@@ 76,7 76,7 @@ function parse_args()

function exec_gdb()
{
    local CRASH_DEBUG="$BUILD_DIR/host-tools/crashdebug/CrashDebug"
    local CRASH_DEBUG="$BUILD_DIR/third-party/CrashDebug/bin/CrashDebug"

    exec "$GDB" "$PURE_ELF"                                                             \
        -ex "set target-charset ASCII"                                                  \

M doc/Doxyfile.in => doc/Doxyfile.in +0 -1
@@ 889,7 889,6 @@ EXCLUDE                = @PROJECT_SOURCE_DIR@/module-bluetooth/lib \
                         @PROJECT_SOURCE_DIR@/module-utils/tinyfsm \
                         @PROJECT_SOURCE_DIR@/module-utils/segger \
                         @PROJECT_SOURCE_DIR@/module-utils/sbini \
                         @PROJECT_SOURCE_DIR@/module-utils/re2 \
                         @PROJECT_SOURCE_DIR@/module-utils/libphonenumber \
                         @PROJECT_SOURCE_DIR@/module-utils/test \
                         @PROJECT_SOURCE_DIR@/module-db/tests \

M doc/boot_and_update.md => doc/boot_and_update.md +1 -1
@@ 65,7 65,7 @@ The type variable in `boot.json` is for MuditaOS - this will indicate a subdirec
6. Move into the project root directory and run the image generation script

```bash
    ./generate_purephone_image.sh pure.img build-rt1051-Debug
    ./generate_image.sh pure.img build-rt1051-Debug
```
   
   Example output:

R generate_purephone_image.sh => generate_image.sh +8 -6
@@ 4,13 4,14 @@

usage() {
cat << ==usage
Usage: $(basename $0) [image_path] [build_dir]
	image_path Destination image path name for. ex PurePhone.img
	build_dir  PurePhone build dir for ex. build-rt1051-RelWithDebInfo
Usage: $(basename $0) image_path build_dir [boot.bin_file]
    image_path    - Destination image path name e.g. PurePhone.img
    build_dir     - PurePhone build dir e.g. build-rt1051-RelWithDebInfo
    boot.bin_file - optional for linux image - name of the boot.bin file (for different targets)
==usage
}

if [ $# -ne 2 ]; then
if [[ ( $# -ne 2 ) && ( $# -ne 3 ) ]]; then
	echo "Error! Invalid argument count"
	usage
	exit -1


@@ 18,6 19,7 @@ fi

IMAGE_NAME=$(realpath $1)
BUILDDIR=$(realpath $2)
BIN_FILE=$3

if [ ! -d "$BUILDDIR" ]; then
	echo "Error! \${build_dir} (${BUILDDIR}) is not a directory"


@@ 106,8 108,8 @@ for i in $CURRENT_DATA; do
	fi
done

if [ -f "current/boot.bin" ]; then
	mcopy -s -i "$PART1" "current/boot.bin" ::/current/
if [[ -n "${BIN_FILE}" && -f "${BIN_FILE}" ]]; then
    mcopy -v -s -i "$PART1" ${BIN_FILE} ::/current/boot.bin
else
	echo "Warning! Missing boot.bin"
	echo "(it's fine for a Linux build)"

M host-tools/CMakeLists.txt => host-tools/CMakeLists.txt +0 -7
@@ 1,13 1,6 @@
if (CMAKE_CROSSCOMPILING)
    # Littlefs fuse is needed in rt1051 and Linux for manipulate images
    # genlittlefs is needed only on the Linux image for generate emulator target image
    set(CRASH_DEBUG_DIR "${CMAKE_SOURCE_DIR}/module-utils/CrashDebug")
    add_custom_target(
        crashdebug ALL
        COMMAND make -C ${CRASH_DEBUG_DIR} CrashDebug
        COMMAND ${CMAKE_COMMAND} -E make_directory crashdebug
        COMMAND ${CMAKE_COMMAND} -E copy ${CRASH_DEBUG_DIR}/bins/lin64/CrashDebug crashdebug
    )
    add_custom_target(
        lfsfuse ALL
        COMMAND ${CMAKE_COMMAND}

M host-tools/genlittlefs/CMakeLists.txt => host-tools/genlittlefs/CMakeLists.txt +2 -2
@@ 7,8 7,8 @@ find_package(BLKID REQUIRED)

# only add LittleFS subdirectory during a standalone config of genlittlefs
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../module-vfs/thirdparty/lfsfs
        ${CMAKE_CURRENT_BINARY_DIR}/lfsfs EXCLUDE_FROM_ALL
    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../third-party/littlefs
        ${CMAKE_CURRENT_BINARY_DIR}/littlefs EXCLUDE_FROM_ALL
    )
endif()


M host-tools/genlittlefs/lfs_ioaccess.c => host-tools/genlittlefs/lfs_ioaccess.c +2 -2
@@ 1,7 1,7 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <littlefs/lfs.h>
#include <lfs.h>
#include "lfs_ioaccess.h"
#include "parse_partitions.h"


M host-tools/genlittlefs/mklfs.c => host-tools/genlittlefs/mklfs.c +1 -1
@@ 1,7 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <littlefs/lfs.h>
#include <lfs.h>
#include "lfs_ioaccess.h"
#include "parse_partitions.h"
#include "parse_args.h"

M host-tools/pure-flash/pure-flash.c => host-tools/pure-flash/pure-flash.c +22 -8
@@ 7,6 7,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdbool.h>

#include <sys/types.h>
#include <sys/stat.h>


@@ 19,7 20,8 @@

static void syntax(char **argv)
{
    fprintf(stderr, "%s [filename] [blkdev]\n", argv[0]);
    fprintf(stderr, "%s [--force] filename blkdev\n", argv[0]);
    fprintf(stderr, "\t--force Skip device sanity checks (optional)\n");
}

static struct fiemap *read_fiemap(int fd)


@@ 223,7 225,7 @@ static int verify_image(const char *image_file, const char *block_device)
    return (result ? EXIT_FAILURE : EXIT_SUCCESS);
}

static int write_image(const char *image_file, const char *block_device)
static int write_image(const char *image_file, const char *block_device, bool force)
{
    struct stat sbuf;
    if (stat(image_file, &sbuf)) {


@@ 242,12 244,12 @@ static int write_image(const char *image_file, const char *block_device)
        fprintf(stderr, "Error: %s is not a block device\n", block_device);
        return EXIT_FAILURE;
    }
    if (gnu_dev_minor(sbuf.st_rdev)) {
    if (gnu_dev_minor(sbuf.st_rdev) && !force) {
        fprintf(stderr, "Error: %s is partition device not a disc\n", block_device);
        fprintf(stderr, "Please specify disk device instead of a partition\n");
        return EXIT_FAILURE;
    }
    {
    if (!force) {
        char mntpath[FILENAME_MAX];
        const int err = device_is_mounted(block_device, mntpath, sizeof mntpath);
        if (err > 0) {


@@ 307,14 309,26 @@ static int write_image(const char *image_file, const char *block_device)

int main(int argc, char **argv)
{
    if (argc < 3) {
    const char *img_file, *blk_dev;
    bool force;
    if (argc == 4 && !strcmp(argv[1], "--force")) {
        force    = true;
        img_file = argv[2];
        blk_dev  = argv[3];
    }
    else if (argc == 3) {
        force    = false;
        img_file = argv[1];
        blk_dev  = argv[2];
    }
    else {
        syntax(argv);
        return EXIT_FAILURE;
    }
    if (write_image(argv[1], argv[2])) {
    if (write_image(img_file, blk_dev, force)) {
        return EXIT_FAILURE;
    }
    int result = verify_image(argv[1], argv[2]);
    fprintf(stderr, "Write image %s to %s %s\n", argv[1], argv[2], result ? "FAILED" : "SUCCESS");
    int result = verify_image(img_file, blk_dev);
    fprintf(stderr, "Write image %s to %s %s\n", img_file, blk_dev, result ? "FAILED" : "SUCCESS");
    return result;
}

M image/assets/lang/English.json => image/assets/lang/English.json +2 -2
@@ 84,8 84,8 @@
  "home_modes_notdisturb": "DO NOT DISTURB",
  "home_modes_offline": "OFFLINE",
  "home_modes_message_only": "Message only",
  "topbar_battery_charging": "Charg",
  "topbar_battery_plugged": "Plug",
  "statusbar_battery_charging": "Charg",
  "statusbar_battery_plugged": "Plug",
  "app_alarm_clock_title_main": "Alarm clock",
  "app_alarm_clock_repeat_never": "Never",
  "app_alarm_clock_repeat_everyday": "Everyday",

M module-apps/Application.cpp => module-apps/Application.cpp +13 -13
@@ 7,8 7,8 @@
#include "Item.hpp"                           // for Item
#include "MessageType.hpp"                    // for MessageType
#include "module-sys/Timers/TimerFactory.hpp" // for Timer
#include "TopBar.hpp"
#include "TopBar/Time.hpp"
#include "StatusBar.hpp"
#include "status-bar/Time.hpp"
#include "Translator.hpp"                // for KeyInputSim...
#include "common_data/EventStore.hpp"    // for Battery
#include "common_data/RawKey.hpp"        // for RawKey, key...


@@ 17,6 17,7 @@
#include "log/log.hpp"                   // for LOG_INFO
#include "messages/AppMessage.hpp"       // for AppSwitchMe...
#include "service-appmgr/Controller.hpp" // for Controller
#include <service-cellular-api>
#include <service-cellular/CellularMessage.hpp>
#include <service-evtmgr/BatteryMessages.hpp>
#include <service-evtmgr/Constants.hpp>


@@ 105,15 106,15 @@ namespace app
        : Service(std::move(name), std::move(parent), stackDepth, priority),
          default_window(gui::name::window::main_window), windowsStack(this),
          keyTranslator{std::make_unique<gui::KeyInputSimpleTranslation>()}, startInBackground{startInBackground},
          callbackStorage{std::make_unique<CallbackStorage>()}, topBarManager{std::make_unique<TopBarManager>()},
          callbackStorage{std::make_unique<CallbackStorage>()}, statusBarManager{std::make_unique<StatusBarManager>()},
          settings(std::make_unique<settings::Settings>()), phoneMode{mode}, phoneLockSubject(this),
          lockPolicyHandler(this), simLockSubject(this)
    {
        topBarManager->enableIndicators({gui::top_bar::Indicator::Time});
        using TimeMode = gui::top_bar::TimeConfiguration::TimeMode;
        auto modifier  = std::make_shared<gui::top_bar::TimeConfiguration>(
        statusBarManager->enableIndicators({gui::status_bar::Indicator::Time});
        using TimeMode = gui::status_bar::TimeConfiguration::TimeMode;
        auto modifier  = std::make_shared<gui::status_bar::TimeConfiguration>(
            utils::dateAndTimeSettings.isTimeFormat12() ? TimeMode::Time12h : TimeMode::Time24h);
        topBarManager->set(gui::top_bar::Indicator::Time, std::move(modifier));
        statusBarManager->set(gui::status_bar::Indicator::Time, std::move(modifier));

        bus.channels.push_back(sys::BusChannel::ServiceCellularNotifications);



@@ 129,6 130,8 @@ namespace app
                [&](sys::Message *msg) -> sys::MessagePointer { return handleGetDOM(msg); });
        connect(typeid(AppUpdateWindowMessage),
                [&](sys::Message *msg) -> sys::MessagePointer { return handleUpdateWindow(msg); });
        connect(typeid(cellular::msg::notification::SimStateUpdate),
                [&](sys::Message *msg) -> sys::MessagePointer { return handleSimStateUpdateMessage(msg); });

        addActionReceiver(app::manager::actions::PhoneModeChanged, [this](auto &&params) {
            if (params != nullptr) {


@@ 333,9 336,6 @@ namespace app
        else if (msgl->messageType == MessageType::AppFocusLost) {
            return handleAppFocusLost(msgl);
        }
        else if (dynamic_cast<sevm::SIMMessage *>(msgl) != nullptr) {
            return handleSIMMessage(msgl);
        }
        return sys::msgNotHandled();
    }



@@ 613,7 613,7 @@ namespace app
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleSIMMessage(sys::Message *msgl)
    sys::MessagePointer Application::handleSimStateUpdateMessage(sys::Message *msgl)
    {
        if (getCurrentWindow()->updateSim()) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);


@@ 940,9 940,9 @@ namespace app
        item->attachTimer(timer);
    }

    const gui::top_bar::Configuration &Application::getTopBarConfiguration() const noexcept
    const gui::status_bar::Configuration &Application::getStatusBarConfiguration() const noexcept
    {
        return topBarManager->getConfiguration();
        return statusBarManager->getConfiguration();
    }

    void Application::addActionReceiver(manager::actions::ActionId actionId, OnActionReceived &&callback)

M module-apps/Application.hpp => module-apps/Application.hpp +4 -4
@@ 27,7 27,7 @@
#include <string>   // for string
#include <utility>  // for move, pair
#include <vector>   // for vector
#include <TopBarManager.hpp>
#include <StatusBarManager.hpp>
#include <popups/Popups.hpp>
#include <locks/handlers/PhoneLockSubject.hpp>
#include <locks/handlers/SimLockSubject.hpp>


@@ 177,7 177,7 @@ namespace app
        sys::MessagePointer handleAppRefresh(sys::Message *msgl);
        sys::MessagePointer handleGetDOM(sys::Message *msgl);
        sys::MessagePointer handleAppFocusLost(sys::Message *msgl);
        sys::MessagePointer handleSIMMessage(sys::Message *msgl);
        sys::MessagePointer handleSimStateUpdateMessage(sys::Message *msgl);

        virtual bool isPopupPermitted(gui::popup::ID popupId) const;



@@ 395,7 395,7 @@ namespace app
        void addActionReceiver(manager::actions::ActionId actionId, OnActionReceived &&callback);
        virtual void handleNotificationsChanged(std::unique_ptr<gui::SwitchData> notificationsParams);

        std::unique_ptr<TopBarManager> topBarManager;
        std::unique_ptr<StatusBarManager> statusBarManager;

        /// application's settings
        std::unique_ptr<settings::Settings> settings;


@@ 413,7 413,7 @@ namespace app

        [[nodiscard]] auto getLockPolicyHandler() noexcept -> locks::LockPolicyHandlerInterface &;

        const gui::top_bar::Configuration &getTopBarConfiguration() const noexcept;
        const gui::status_bar::Configuration &getStatusBarConfiguration() const noexcept;
    };

    /// Parameter pack used by application launch action.

M module-apps/CMakeLists.txt => module-apps/CMakeLists.txt +2 -1
@@ 21,7 21,7 @@ set( SOURCES
    "GuiTimer.cpp"
    "DOMResponder.cpp"
    "WindowsFactory.cpp"
    "TopBarManager.cpp"
    "StatusBarManager.cpp"
    "AsyncTask.cpp"
    "CallbackStorage.cpp"
    "windows/AppWindow.cpp"


@@ 125,6 125,7 @@ target_link_libraries(${PROJECT_NAME}
        service-cellular
        service-db
        service-evtmgr
        Microsoft.GSL::GSL
    PUBLIC
        module-audio
        module-bsp

A module-apps/StatusBarManager.cpp => module-apps/StatusBarManager.cpp +23 -0
@@ 0,0 1,23 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "StatusBarManager.hpp"
#include "StatusBar.hpp"

namespace app
{
    void StatusBarManager::enableIndicators(const gui::status_bar::Indicators &indicators)
    {
        statusBarConfiguration.enable(indicators);
    }

    auto StatusBarManager::getConfiguration() const noexcept -> const gui::status_bar::Configuration &
    {
        return statusBarConfiguration;
    }

    void StatusBarManager::set(gui::status_bar::Indicator indicator, std::shared_ptr<StatusBarVisitor> config)
    {
        statusBarConfiguration.setIndicatorModifier(indicator, std::move(config));
    }
} // namespace app

R module-apps/TopBarManager.hpp => module-apps/StatusBarManager.hpp +6 -6
@@ 3,18 3,18 @@

#pragma once

#include <TopBar.hpp>
#include <StatusBar.hpp>

namespace app
{
    class TopBarManager
    class StatusBarManager
    {
      public:
        void enableIndicators(const gui::top_bar::Indicators &indicators);
        [[nodiscard]] auto getConfiguration() const noexcept -> const gui::top_bar::Configuration &;
        void set(gui::top_bar::Indicator indicator, std::shared_ptr<StatusBarVisitor> config);
        void enableIndicators(const gui::status_bar::Indicators &indicators);
        [[nodiscard]] auto getConfiguration() const noexcept -> const gui::status_bar::Configuration &;
        void set(gui::status_bar::Indicator indicator, std::shared_ptr<StatusBarVisitor> config);

      private:
        gui::top_bar::Configuration topBarConfiguration;
        gui::status_bar::Configuration statusBarConfiguration;
    };
} // namespace app

D module-apps/TopBarManager.cpp => module-apps/TopBarManager.cpp +0 -23
@@ 1,23 0,0 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "TopBarManager.hpp"
#include "TopBar.hpp"

namespace app
{
    void TopBarManager::enableIndicators(const gui::top_bar::Indicators &indicators)
    {
        topBarConfiguration.enable(indicators);
    }

    auto TopBarManager::getConfiguration() const noexcept -> const gui::top_bar::Configuration &
    {
        return topBarConfiguration;
    }

    void TopBarManager::set(gui::top_bar::Indicator indicator, std::shared_ptr<StatusBarVisitor> config)
    {
        topBarConfiguration.setIndicatorModifier(indicator, std::move(config));
    }
} // namespace app

M module-apps/application-alarm-clock/windows/AlarmClockMainWindow.cpp => module-apps/application-alarm-clock/windows/AlarmClockMainWindow.cpp +0 -2
@@ 7,8 7,6 @@
#include "windows/DialogMetadata.hpp"
#include "messages/DialogMetadataMessage.hpp"
#include <InputEvent.hpp>
#include <gui/widgets/BottomBar.hpp>
#include <gui/widgets/TopBar.hpp>
#include <service-appmgr/Controller.hpp>
#include <module-services/service-db/service-db/DBNotificationMessage.hpp>


M module-apps/application-calculator/data/CalculatorInputProcessorText.cpp => module-apps/application-calculator/data/CalculatorInputProcessorText.cpp +1 -1
@@ 7,7 7,7 @@
#include <gui/input/InputEvent.hpp>
#include <gui/widgets/Text.hpp>
#include <i18n/i18n.hpp>
#include <module-utils/gsl/gsl_assert>
#include <gsl/assert>

calc::InputProcessorText::InputProcessorText(gsl::strict_not_null<gui::Text *> inputField) : inputField{inputField}
{}

M module-apps/application-calendar/windows/AllEventsWindow.cpp => module-apps/application-calendar/windows/AllEventsWindow.cpp +0 -2
@@ 5,8 5,6 @@
#include "InputEvent.hpp"
#include "application-calendar/ApplicationCalendar.hpp"
#include "application-calendar/data/CalendarData.hpp"
#include <gui/widgets/BottomBar.hpp>
#include <gui/widgets/TopBar.hpp>
#include <gui/widgets/Window.hpp>
#include <service-appmgr/Controller.hpp>


M module-apps/application-calendar/windows/DayEventsWindow.cpp => module-apps/application-calendar/windows/DayEventsWindow.cpp +0 -2
@@ 8,8 8,6 @@
#include <gui/widgets/Label.hpp>
#include <gui/widgets/Item.hpp>
#include <gui/widgets/Image.hpp>
#include <gui/widgets/BottomBar.hpp>
#include <gui/widgets/TopBar.hpp>

#include <time/time_conversion.hpp>
#include <module-db/queries/calendar/QueryEventsGetFiltered.hpp>

M module-apps/application-calendar/windows/EventReminderWindow.cpp => module-apps/application-calendar/windows/EventReminderWindow.cpp +3 -3
@@ 41,9 41,9 @@ namespace gui
        buildInterface();
    }

    top_bar::Configuration EventReminderWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration EventReminderWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        using namespace top_bar;
        using namespace status_bar;
        appConfiguration.enable({Indicator::Signal, Indicator::Time, Indicator::Battery, Indicator::SimCard});
        return appConfiguration;
    }


@@ 58,7 58,7 @@ namespace gui

        const uint32_t w = this->getWidth() - style::window::default_left_margin - style::window::default_right_margin;
        const uint32_t h = this->getHeight() - bottomBar->getHeight();
        body             = new gui::VBox(this, style::window::default_left_margin, topBar->getHeight(), w, h);
        body             = new gui::VBox(this, style::window::default_left_margin, statusBar->getHeight(), w, h);
        body->setBorderColor(gui::ColorNoColor);

        topImage = new gui::Image(body,

M module-apps/application-calendar/windows/EventReminderWindow.hpp => module-apps/application-calendar/windows/EventReminderWindow.hpp +1 -1
@@ 44,7 44,7 @@ namespace gui
        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
        auto handleSwitchData(SwitchData *data) -> bool override;
    };


M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +4 -5
@@ 36,8 36,9 @@ namespace app
                                     StartInBackground startInBackground)
        : Application(name, parent, mode, startInBackground, app::call_stack_size)
    {
        using namespace gui::top_bar;
        topBarManager->enableIndicators({Indicator::Signal, Indicator::Time, Indicator::Battery, Indicator::SimCard});
        using namespace gui::status_bar;
        statusBarManager->enableIndicators(
            {Indicator::Signal, Indicator::Time, Indicator::Battery, Indicator::SimCard});
        addActionReceiver(manager::actions::Call, [this](auto &&data) {
            switchWindow(window::name_call, std::forward<decltype(data)>(data));
            return actionHandled();


@@ 227,9 228,7 @@ namespace app
        windowsFactory.attach(app::window::name_dialogConfirm, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DialogConfirm>(app, name);
        });
        attachPopups({gui::popup::ID::Volume,
                      gui::popup::ID::Tethering,
                      gui::popup::ID::PhoneModes});
        attachPopups({gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes});
    }

    bool ApplicationCall::showNotification(std::function<bool()> action,

M module-apps/application-call/windows/CallWindow.cpp => module-apps/application-call/windows/CallWindow.cpp +2 -2
@@ 154,9 154,9 @@ namespace gui
        erase();
    }

    top_bar::Configuration CallWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration CallWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.enable(top_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.enable(status_bar::Indicator::NetworkAccessTechnology);
        return appConfiguration;
    }


M module-apps/application-call/windows/CallWindow.hpp => module-apps/application-call/windows/CallWindow.hpp +3 -3
@@ 27,8 27,8 @@ namespace gui
        gui::KeyInputMappedTranslation translator;
        sys::TimerHandle callTimer;
        sys::TimerHandle delayedExitTimer;
        std::chrono::seconds callDuration                   = std::chrono::seconds().zero();
        static constexpr inline auto callDelayedStopTime    = std::chrono::milliseconds{3000};
        std::chrono::seconds callDuration                = std::chrono::seconds().zero();
        static constexpr inline auto callDelayedStopTime = std::chrono::milliseconds{3000};

        [[nodiscard]] auto getDelayedStopTime() const
        {


@@ 70,7 70,7 @@ namespace gui
        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;

        bool handleDigit(const uint32_t digit);
        void connectTimerOnExit();

M module-apps/application-call/windows/EmergencyCallWindow.cpp => module-apps/application-call/windows/EmergencyCallWindow.cpp +2 -2
@@ 27,9 27,9 @@ namespace gui
        numberDescriptionLabel->setText(utils::translate("app_call_emergency_text"));
    }

    top_bar::Configuration EmergencyCallWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration EmergencyCallWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.enable(top_bar::Indicator::PhoneMode);
        appConfiguration.enable(status_bar::Indicator::PhoneMode);
        return appConfiguration;
    }


M module-apps/application-call/windows/EmergencyCallWindow.hpp => module-apps/application-call/windows/EmergencyCallWindow.hpp +1 -1
@@ 17,7 17,7 @@ namespace gui
        bool onInput(const InputEvent &inputEvent) override;

        void buildInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
    };

} /* namespace gui */

M module-apps/application-call/windows/EnterNumberWindow.cpp => module-apps/application-call/windows/EnterNumberWindow.cpp +2 -2
@@ 42,9 42,9 @@ namespace gui
        setFocusItem(newContactIcon);
    }

    top_bar::Configuration EnterNumberWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration EnterNumberWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.enable(top_bar::Indicator::PhoneMode);
        appConfiguration.enable(status_bar::Indicator::PhoneMode);
        return appConfiguration;
    }


M module-apps/application-call/windows/EnterNumberWindow.hpp => module-apps/application-call/windows/EnterNumberWindow.hpp +1 -1
@@ 22,7 22,7 @@ namespace gui

        void buildInterface() override;

        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;

        auto addNewContact() -> bool;
    };

M module-apps/application-call/windows/NumberWindow.cpp => module-apps/application-call/windows/NumberWindow.cpp +0 -2
@@ 8,10 8,8 @@
#include "application-call/data/CallSwitchData.hpp"

#include <ContactRecord.hpp>
#include <gui/widgets/BottomBar.hpp>
#include <gui/widgets/Image.hpp>
#include <gui/widgets/Label.hpp>
#include <gui/widgets/TopBar.hpp>
#include <gui/widgets/Window.hpp>
#include <i18n/i18n.hpp>
#include <InputMode.hpp>

M module-apps/application-calllog/windows/CallLogDetailsWindow.cpp => module-apps/application-calllog/windows/CallLogDetailsWindow.cpp +1 -0
@@ 15,6 15,7 @@
#include <widgets/TextWithIconsWidget.hpp>
#include <widgets/ActiveIconFactory.hpp>

#include <gsl/assert>
#include <i18n/i18n.hpp>
#include <time/time_conversion.hpp>
#include <Style.hpp>

M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +6 -5
@@ 34,7 34,7 @@
#include <module-services/service-desktop/service-desktop/Constants.hpp>
#include <module-apps/messages/AppMessage.hpp>
#include <SystemManager/messages/SystemManagerMessage.hpp>
#include <module-gui/gui/widgets/TopBar/SIM.hpp>
#include <module-gui/gui/widgets/status-bar/SIM.hpp>
#include <service-db/DBNotificationMessage.hpp>

#include <cassert>


@@ 47,10 47,11 @@ namespace app
        : Application(std::move(name), std::move(parent), mode, startInBackground), AsyncCallbackReceiver(this),
          dbNotificationHandler(this)
    {
        using namespace gui::top_bar;
        topBarManager->enableIndicators({Indicator::Signal, Indicator::Time, Indicator::Battery, Indicator::SimCard});
        topBarManager->set(Indicator::SimCard,
                           std::make_shared<SIMConfiguration>(SIMConfiguration::DisplayMode::OnlyInactiveState));
        using namespace gui::status_bar;
        statusBarManager->enableIndicators(
            {Indicator::Signal, Indicator::Time, Indicator::Battery, Indicator::SimCard});
        statusBarManager->set(Indicator::SimCard,
                              std::make_shared<SIMConfiguration>(SIMConfiguration::DisplayMode::OnlyInactiveState));
        bus.channels.push_back(sys::BusChannel::ServiceDBNotifications);

        addActionReceiver(app::manager::actions::ShowMMIResponse, [this](auto &&data) {

M module-apps/application-desktop/models/ActiveNotificationsModel.cpp => module-apps/application-desktop/models/ActiveNotificationsModel.cpp +2 -0
@@ 11,6 11,8 @@
#include <application-messages/Constants.hpp>
#include <service-appmgr/messages/SwitchRequest.hpp>

#include <gsl/assert>

using namespace gui;

namespace

M module-apps/application-desktop/windows/ChargingBatteryWindow.cpp => module-apps/application-desktop/windows/ChargingBatteryWindow.cpp +1 -3
@@ 4,8 4,6 @@
#include "ChargingBatteryWindow.hpp"
#include "InputEvent.hpp"
#include "gui/widgets/Image.hpp"
#include "gui/widgets/BottomBar.hpp"
#include "gui/widgets/TopBar.hpp"
#include "log/log.hpp"
#include <application-desktop/windows/Names.hpp>
#include <service-appmgr/model/ApplicationManager.hpp>


@@ 35,7 33,7 @@ namespace gui
    {
        AppWindow::buildInterface();
        bottomBar->setVisible(false);
        topBar->setVisible(false);
        statusBar->setVisible(false);
        new gui::Image(this, imgPositionX, imgPositionY, 0, 0, "charging_battery_W_G");
    }


M module-apps/application-desktop/windows/DeadBatteryWindow.cpp => module-apps/application-desktop/windows/DeadBatteryWindow.cpp +1 -3
@@ 4,8 4,6 @@
#include "DeadBatteryWindow.hpp"
#include "InputEvent.hpp"
#include "gui/widgets/Image.hpp"
#include "gui/widgets/BottomBar.hpp"
#include "gui/widgets/TopBar.hpp"
#include "log/log.hpp"
#include <application-desktop/windows/Names.hpp>
#include <service-appmgr/model/ApplicationManager.hpp>


@@ 35,7 33,7 @@ namespace gui
    {
        AppWindow::buildInterface();
        bottomBar->setVisible(false);
        topBar->setVisible(false);
        statusBar->setVisible(false);
        new gui::Image(this, imgPositionX, imgPositionY, 0, 0, "dead_battery_W_G");
    }


M module-apps/application-desktop/windows/DesktopMainWindow.cpp => module-apps/application-desktop/windows/DesktopMainWindow.cpp +16 -7
@@ 84,10 84,10 @@ namespace gui
        dayText = nullptr;
    }

    top_bar::Configuration DesktopMainWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration DesktopMainWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.disable(top_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.enable(top_bar::Indicator::PhoneMode);
        appConfiguration.disable(status_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.enable(status_bar::Indicator::PhoneMode);
        return appConfiguration;
    }



@@ 134,8 134,7 @@ namespace gui
    {
        // long press of '0' key is translated to '+'
        if (inputEvent.is(KeyCode::KEY_0)) {
            return app::manager::Controller::sendAction(
                application, app::manager::actions::Dial, std::make_unique<app::EnterNumberData>("+"));
            return resolveDialAction(std::string{"+"});
        }
        if (inputEvent.is(KeyCode::KEY_RF)) {
            application->switchWindow(popup::window::power_off_window);


@@ 157,8 156,7 @@ namespace gui
        // if numeric key was pressed record that key and send it to call application
        if (code != 0) {
            const auto &number = std::string(1, static_cast<char>(code));
            return app::manager::Controller::sendAction(
                application, app::manager::actions::Dial, std::make_unique<app::EnterNumberData>(number));
            return resolveDialAction(number);
        }
        else if (const auto notificationsNotFocused = (focusItem == nullptr);
                 notificationsNotFocused && !notificationsModel->isEmpty()) {


@@ 268,4 266,15 @@ namespace gui
        return true;
    }

    bool DesktopMainWindow::resolveDialAction(const std::string &number)
    {
        if (notificationsModel->isTetheringOn()) {
            return false;
        }
        else {
            return app::manager::Controller::sendAction(
                application, app::manager::actions::Dial, std::make_unique<app::EnterNumberData>(number));
        }
    }

} /* namespace gui */

M module-apps/application-desktop/windows/DesktopMainWindow.hpp => module-apps/application-desktop/windows/DesktopMainWindow.hpp +2 -1
@@ 45,11 45,12 @@ namespace gui
        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;

        bool updateTime() override;

      private:
        bool resolveDialAction(const std::string &number);
        bool showInformationPopup(std::function<bool()> action, const std::string &notification);
        void invalidate() noexcept;
        std::string osUpdateVer;

M module-apps/application-desktop/windows/LogoWindow.cpp => module-apps/application-desktop/windows/LogoWindow.cpp +1 -3
@@ 3,8 3,6 @@

#include "LogoWindow.hpp"
#include "gui/widgets/Image.hpp"
#include "gui/widgets/BottomBar.hpp"
#include "gui/widgets/TopBar.hpp"
#include "log/log.hpp"
#include <application-desktop/windows/Names.hpp>



@@ 25,7 23,7 @@ namespace gui
    {
        AppWindow::buildInterface();
        bottomBar->setVisible(false);
        topBar->setVisible(false);
        statusBar->setVisible(false);
        new gui::Image(this, 0, 0, 0, 0, "logo");
    }


M module-apps/application-desktop/windows/PostUpdateWindow.cpp => module-apps/application-desktop/windows/PostUpdateWindow.cpp +6 -6
@@ 54,13 54,13 @@ void PostUpdateWindow::rebuild()
    buildInterface();
}

top_bar::Configuration PostUpdateWindow::configureTopBar(top_bar::Configuration appConfiguration)
status_bar::Configuration PostUpdateWindow::configureStatusBar(status_bar::Configuration appConfiguration)
{
    appConfiguration.enable(top_bar::Indicator::Time);
    appConfiguration.disable(top_bar::Indicator::Lock);
    appConfiguration.disable(top_bar::Indicator::Battery);
    appConfiguration.disable(top_bar::Indicator::Signal);
    appConfiguration.disable(top_bar::Indicator::SimCard);
    appConfiguration.enable(status_bar::Indicator::Time);
    appConfiguration.disable(status_bar::Indicator::Lock);
    appConfiguration.disable(status_bar::Indicator::Battery);
    appConfiguration.disable(status_bar::Indicator::Signal);
    appConfiguration.disable(status_bar::Indicator::SimCard);
    return appConfiguration;
}


M module-apps/application-desktop/windows/PostUpdateWindow.hpp => module-apps/application-desktop/windows/PostUpdateWindow.hpp +1 -1
@@ 24,6 24,6 @@ namespace gui
        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
    };
} /* namespace gui */

M module-apps/application-desktop/windows/Update.cpp => module-apps/application-desktop/windows/Update.cpp +0 -2
@@ 2,8 2,6 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "log/log.hpp"
#include "gui/widgets/BottomBar.hpp"
#include "gui/widgets/TopBar.hpp"
#include "application-desktop/data/DesktopData.hpp"
#include <source/version.hpp>


M module-apps/application-desktop/windows/UpdateProgress.cpp => module-apps/application-desktop/windows/UpdateProgress.cpp +6 -8
@@ 2,8 2,6 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <log/log.hpp>
#include <gui/widgets/BottomBar.hpp>
#include <gui/widgets/TopBar.hpp>
#include <source/version.hpp>
#include <boot/bootconfig.hpp>



@@ 70,13 68,13 @@ namespace gui
        buildInterface();
    }

    top_bar::Configuration UpdateProgressWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration UpdateProgressWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.enable(top_bar::Indicator::Time);
        appConfiguration.disable(top_bar::Indicator::Lock);
        appConfiguration.disable(top_bar::Indicator::Battery);
        appConfiguration.disable(top_bar::Indicator::Signal);
        appConfiguration.disable(top_bar::Indicator::SimCard);
        appConfiguration.enable(status_bar::Indicator::Time);
        appConfiguration.disable(status_bar::Indicator::Lock);
        appConfiguration.disable(status_bar::Indicator::Battery);
        appConfiguration.disable(status_bar::Indicator::Signal);
        appConfiguration.disable(status_bar::Indicator::SimCard);
        return appConfiguration;
    }


M module-apps/application-desktop/windows/UpdateProgress.hpp => module-apps/application-desktop/windows/UpdateProgress.hpp +3 -3
@@ 20,8 20,8 @@ namespace gui
        unsigned int progressPercent = 0;
        std::string textInfo;

        gui::Label *percentLabel    = nullptr;
        HBarGraph *updateProgress   = nullptr;
        gui::Label *percentLabel  = nullptr;
        HBarGraph *updateProgress = nullptr;

        fs::path updateFile;



@@ 38,7 38,7 @@ namespace gui
        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
    };

} /* namespace gui */

M module-apps/application-meditation/windows/MeditationTimerWindow.cpp => module-apps/application-meditation/windows/MeditationTimerWindow.cpp +4 -4
@@ 122,14 122,14 @@ auto MeditationTimerWindow::onInput(const InputEvent &inputEvent) -> bool
    return AppWindow::onInput(inputEvent);
}

void MeditationTimerWindow::setWidgetVisible(bool tBar, bool bBar, bool counter)
void MeditationTimerWindow::setWidgetVisible(bool sBar, bool bBar, bool counter)
{
    applyToTopBar([tBar](top_bar::Configuration configuration) {
        configuration.setIndicator(top_bar::Indicator::Time, tBar);
    applyToStatusBar([sBar](status_bar::Configuration configuration) {
        configuration.setIndicator(status_bar::Indicator::Time, sBar);
        return configuration;
    });

    title->setVisible(tBar);
    title->setVisible(sBar);
    bottomBar->setActive(BottomBar::Side::CENTER, bBar);
    bottomBar->setActive(BottomBar::Side::LEFT, bBar);
    timer->setVisible(counter);

M module-apps/application-meditation/windows/MeditationTimerWindow.hpp => module-apps/application-meditation/windows/MeditationTimerWindow.hpp +1 -1
@@ 22,7 22,7 @@ namespace gui
        std::chrono::seconds meditationIntervalPeriod{0};
        sys::TimerHandle endScreenTimeout;

        void setWidgetVisible(bool topBar, bool bottomBar, bool counter);
        void setWidgetVisible(bool sBar, bool bottomBar, bool counter);
        void setVisibleRunning();
        void setVisiblePaused();
        void setVisiblePreparation();

M module-apps/application-notes/windows/NoteEditWindow.cpp => module-apps/application-notes/windows/NoteEditWindow.cpp +0 -3
@@ 15,9 15,6 @@

#include <i18n/i18n.hpp>

#include <module-gui/gui/widgets/BottomBar.hpp>
#include <module-gui/gui/widgets/TopBar.hpp>

#include <ctime>

namespace app::notes

M module-apps/application-notes/windows/NoteMainWindow.cpp => module-apps/application-notes/windows/NoteMainWindow.cpp +0 -4
@@ 10,10 10,6 @@

#include <i18n/i18n.hpp>

#include <gui/widgets/Label.hpp>
#include <gui/widgets/BottomBar.hpp>
#include <gui/widgets/TopBar.hpp>

#include <Style.hpp>
#include <module-apps/application-notes/style/NotesListStyle.hpp>
#include <module-apps/application-notes/style/NotesMainWindowStyle.hpp>

M module-apps/application-notes/windows/NotePreviewWindow.cpp => module-apps/application-notes/windows/NotePreviewWindow.cpp +0 -3
@@ 14,9 14,6 @@

#include <Style.hpp>

#include <module-gui/gui/widgets/BottomBar.hpp>
#include <module-gui/gui/widgets/TopBar.hpp>

namespace app::notes
{
    NotePreviewWindow::NotePreviewWindow(app::Application *app,

M module-apps/application-onboarding/ApplicationOnBoarding.cpp => module-apps/application-onboarding/ApplicationOnBoarding.cpp +3 -2
@@ 39,8 39,9 @@ namespace app
                                                 StartInBackground startInBackground)
        : Application(std::move(name), std::move(parent), mode, startInBackground, OnBoardingStackSize)
    {
        using namespace gui::top_bar;
        topBarManager->enableIndicators({Indicator::Signal, Indicator::Time, Indicator::Battery, Indicator::SimCard});
        using namespace gui::status_bar;
        statusBarManager->enableIndicators(
            {Indicator::Signal, Indicator::Time, Indicator::Battery, Indicator::SimCard});

        bus.channels.push_back(sys::BusChannel::ServiceDBNotifications);
        bus.channels.push_back(sys::BusChannel::PhoneLockChanges);

M module-apps/application-onboarding/model/EULARepository.cpp => module-apps/application-onboarding/model/EULARepository.cpp +1 -1
@@ 1,7 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <module-utils/gsl/gsl_util>
#include <gsl/util>
#include "module-utils/i18n/i18n.hpp"

#include "EULARepository.hpp"

M module-apps/application-onboarding/windows/SkipDialogWindow.cpp => module-apps/application-onboarding/windows/SkipDialogWindow.cpp +6 -6
@@ 9,15 9,15 @@ namespace app::onBoarding
    SkipDialogWindow::SkipDialogWindow(app::Application *app)
        : gui::DialogYesNo(app, gui::window::name::onBoarding_skip)
    {
        topBar->configure(configureTopBar(application->getTopBarConfiguration()));
        statusBar->configure(configureStatusBar(application->getStatusBarConfiguration()));
    }

    gui::top_bar::Configuration SkipDialogWindow::configureTopBar(gui::top_bar::Configuration appConfiguration)
    gui::status_bar::Configuration SkipDialogWindow::configureStatusBar(gui::status_bar::Configuration appConfiguration)
    {
        appConfiguration.setIndicator(gui::top_bar::Indicator::Time, true);
        appConfiguration.setIndicator(gui::top_bar::Indicator::Battery, false);
        appConfiguration.setIndicator(gui::top_bar::Indicator::SimCard, false);
        appConfiguration.setIndicator(gui::top_bar::Indicator::Signal, false);
        appConfiguration.setIndicator(gui::status_bar::Indicator::Time, true);
        appConfiguration.setIndicator(gui::status_bar::Indicator::Battery, false);
        appConfiguration.setIndicator(gui::status_bar::Indicator::SimCard, false);
        appConfiguration.setIndicator(gui::status_bar::Indicator::Signal, false);
        return appConfiguration;
    }
} // namespace app::onBoarding

M module-apps/application-onboarding/windows/SkipDialogWindow.hpp => module-apps/application-onboarding/windows/SkipDialogWindow.hpp +1 -1
@@ 12,6 12,6 @@ namespace app::onBoarding
      public:
        explicit SkipDialogWindow(app::Application *app);

        gui::top_bar::Configuration configureTopBar(gui::top_bar::Configuration appConfiguration) override;
        gui::status_bar::Configuration configureStatusBar(gui::status_bar::Configuration appConfiguration) override;
    };
} // namespace app::onBoarding

M module-apps/application-settings-new/models/SARInfoRepository.cpp => module-apps/application-settings-new/models/SARInfoRepository.cpp +1 -1
@@ 3,7 3,7 @@

#include "SARInfoRepository.hpp"

#include <gsl_util>
#include <gsl/util>
#include <i18n/i18n.hpp>

#include <fstream>

M module-apps/locks/handlers/LockPolicyHandler.cpp => module-apps/locks/handlers/LockPolicyHandler.cpp +1 -1
@@ 4,7 4,7 @@
#include "LockPolicyHandler.hpp"
#include <log/log.hpp>
#include <Application.hpp>
#include <gsl_assert>
#include <gsl/assert>

using namespace locks;


M module-apps/locks/windows/LockInputWindow.cpp => module-apps/locks/windows/LockInputWindow.cpp +8 -8
@@ 102,14 102,14 @@ namespace gui
        }
    }

    top_bar::Configuration LockInputWindow::configureTopBar(top_bar::Configuration appConfiguration)
    {
        appConfiguration.disable(top_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.enable(top_bar::Indicator::Time);
        appConfiguration.enable(top_bar::Indicator::PhoneMode);
        appConfiguration.enable(top_bar::Indicator::Battery);
        appConfiguration.enable(top_bar::Indicator::Signal);
        appConfiguration.enable(top_bar::Indicator::SimCard);
    status_bar::Configuration LockInputWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.disable(status_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.enable(status_bar::Indicator::Time);
        appConfiguration.enable(status_bar::Indicator::PhoneMode);
        appConfiguration.enable(status_bar::Indicator::Battery);
        appConfiguration.enable(status_bar::Indicator::Signal);
        appConfiguration.enable(status_bar::Indicator::SimCard);
        return appConfiguration;
    }


M module-apps/locks/windows/LockInputWindow.hpp => module-apps/locks/windows/LockInputWindow.hpp +1 -1
@@ 46,7 46,7 @@ namespace gui
        void setBottomBarWidgetsActive(bool left, bool center, bool right);

        [[nodiscard]] auto getToken(Token token) const -> std::string;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;

        std::unique_ptr<locks::Lock> lock = nullptr;
        gui::HBox *pinLabelsBox           = nullptr;

M module-apps/notifications/NotificationData.cpp => module-apps/notifications/NotificationData.cpp +1 -1
@@ 2,7 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "NotificationData.hpp"
#include <gsl_assert>
#include <gsl/assert>
uint32_t notifications::Notification::priorityPool = 0;

using namespace notifications;

M module-apps/popups/HomeModesWindow.cpp => module-apps/popups/HomeModesWindow.cpp +2 -2
@@ 21,7 21,7 @@ namespace gui
        AppWindow::buildInterface();

        bottomBar->setVisible(false);
        topBar->setVisible(false);
        statusBar->setVisible(false);

        modesBox = new ModesBox(this, 0, style::window::modes::top_offset);
    }


@@ 34,7 34,7 @@ namespace gui
        WindowWithTimer::onBeforeShow(mode, data);
        const auto popupData = dynamic_cast<ModesPopupData *>(data);
        if (popupData != nullptr) {
            const auto currentMode = popupData->getPhoneMode();
            const auto currentMode       = popupData->getPhoneMode();
            const auto currentFlightMode = popupData->getFlightMode();
            modesBox->update(currentMode, currentFlightMode);
        }

M module-apps/popups/PowerOffWindow.cpp => module-apps/popups/PowerOffWindow.cpp +7 -7
@@ 11,16 11,16 @@ namespace gui
    PowerOffWindow::PowerOffWindow(app::Application *app, std::unique_ptr<PowerOffPresenter> &&presenter)
        : DialogYesNo(app, popup::window::power_off_window), presenter(std::move(presenter))
    {
        topBar->configure(configureTopBar(application->getTopBarConfiguration()));
        statusBar->configure(configureStatusBar(application->getStatusBarConfiguration()));
    }

    top_bar::Configuration PowerOffWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration PowerOffWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.enable(top_bar::Indicator::Time);
        appConfiguration.disable(top_bar::Indicator::Lock);
        appConfiguration.disable(top_bar::Indicator::Battery);
        appConfiguration.disable(top_bar::Indicator::Signal);
        appConfiguration.disable(top_bar::Indicator::SimCard);
        appConfiguration.enable(status_bar::Indicator::Time);
        appConfiguration.disable(status_bar::Indicator::Lock);
        appConfiguration.disable(status_bar::Indicator::Battery);
        appConfiguration.disable(status_bar::Indicator::Signal);
        appConfiguration.disable(status_bar::Indicator::SimCard);
        return appConfiguration;
    }


M module-apps/popups/PowerOffWindow.hpp => module-apps/popups/PowerOffWindow.hpp +1 -1
@@ 15,7 15,7 @@ namespace gui
      public:
        PowerOffWindow(app::Application *app, std::unique_ptr<PowerOffPresenter> &&presenter);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
    };

} /* namespace gui */

M module-apps/popups/TetheringNotificationPopup.cpp => module-apps/popups/TetheringNotificationPopup.cpp +7 -7
@@ 9,16 9,16 @@ namespace gui
    TetheringNotificationPopup::TetheringNotificationPopup(app::Application *app, const std::string &name)
        : gui::DialogConfirm(app, name)
    {
        topBar->configure(configureTopBar(application->getTopBarConfiguration()));
        statusBar->configure(configureStatusBar(application->getStatusBarConfiguration()));
    }

    gui::top_bar::Configuration TetheringNotificationPopup::configureTopBar(
        gui::top_bar::Configuration appConfiguration)
    gui::status_bar::Configuration TetheringNotificationPopup::configureStatusBar(
        gui::status_bar::Configuration appConfiguration)
    {
        appConfiguration.setIndicator(gui::top_bar::Indicator::Time, false);
        appConfiguration.setIndicator(gui::top_bar::Indicator::Battery, true);
        appConfiguration.setIndicator(gui::top_bar::Indicator::SimCard, false);
        appConfiguration.setIndicator(gui::top_bar::Indicator::Signal, true);
        appConfiguration.setIndicator(gui::status_bar::Indicator::Time, false);
        appConfiguration.setIndicator(gui::status_bar::Indicator::Battery, true);
        appConfiguration.setIndicator(gui::status_bar::Indicator::SimCard, false);
        appConfiguration.setIndicator(gui::status_bar::Indicator::Signal, true);
        return appConfiguration;
    }
} // namespace gui

M module-apps/popups/TetheringNotificationPopup.hpp => module-apps/popups/TetheringNotificationPopup.hpp +1 -1
@@ 12,6 12,6 @@ namespace gui
      public:
        TetheringNotificationPopup(app::Application *app, const std::string &name);

        gui::top_bar::Configuration configureTopBar(gui::top_bar::Configuration appConfiguration) override;
        gui::status_bar::Configuration configureStatusBar(gui::status_bar::Configuration appConfiguration) override;
    };
} // namespace gui

M module-apps/popups/TetheringOffPopup.cpp => module-apps/popups/TetheringOffPopup.cpp +7 -7
@@ 13,16 13,16 @@ namespace gui
{
    TetheringOffPopup::TetheringOffPopup(app::Application *app, const std::string &name) : DialogYesNo{app, name}
    {
        topBar->configure(configureTopBar(application->getTopBarConfiguration()));
        statusBar->configure(configureStatusBar(application->getStatusBarConfiguration()));
    }

    top_bar::Configuration TetheringOffPopup::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration TetheringOffPopup::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.enable(top_bar::Indicator::Time);
        appConfiguration.disable(top_bar::Indicator::Lock);
        appConfiguration.disable(top_bar::Indicator::Battery);
        appConfiguration.disable(top_bar::Indicator::Signal);
        appConfiguration.disable(top_bar::Indicator::SimCard);
        appConfiguration.enable(status_bar::Indicator::Time);
        appConfiguration.disable(status_bar::Indicator::Lock);
        appConfiguration.disable(status_bar::Indicator::Battery);
        appConfiguration.disable(status_bar::Indicator::Signal);
        appConfiguration.disable(status_bar::Indicator::SimCard);
        return appConfiguration;
    }


M module-apps/popups/TetheringOffPopup.hpp => module-apps/popups/TetheringOffPopup.hpp +1 -1
@@ 11,7 11,7 @@ namespace gui
    {
      public:
        TetheringOffPopup(app::Application *app, const std::string &name);
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
    };


M module-apps/popups/VolumeWindow.cpp => module-apps/popups/VolumeWindow.cpp +1 -1
@@ 42,7 42,7 @@ namespace gui
        WindowWithTimer::buildInterface();

        bottomBar->setVisible(false);
        topBar->setVisible(false);
        statusBar->setVisible(false);

        addVolumeText();
        addVolumeBar();

M module-apps/popups/lock-popups/PhoneLockChangeInfoWindow.cpp => module-apps/popups/lock-popups/PhoneLockChangeInfoWindow.cpp +7 -7
@@ 14,14 14,14 @@ PhoneLockChangeInfoWindow::PhoneLockChangeInfoWindow(app::Application *app, cons
    buildInterface();
}

top_bar::Configuration PhoneLockChangeInfoWindow::configureTopBar(top_bar::Configuration appConfiguration)
status_bar::Configuration PhoneLockChangeInfoWindow::configureStatusBar(status_bar::Configuration appConfiguration)
{
    appConfiguration.enable(top_bar::Indicator::NetworkAccessTechnology);
    appConfiguration.enable(top_bar::Indicator::Time);
    appConfiguration.enable(top_bar::Indicator::PhoneMode);
    appConfiguration.enable(top_bar::Indicator::Battery);
    appConfiguration.enable(top_bar::Indicator::Signal);
    appConfiguration.enable(top_bar::Indicator::SimCard);
    appConfiguration.enable(status_bar::Indicator::NetworkAccessTechnology);
    appConfiguration.enable(status_bar::Indicator::Time);
    appConfiguration.enable(status_bar::Indicator::PhoneMode);
    appConfiguration.enable(status_bar::Indicator::Battery);
    appConfiguration.enable(status_bar::Indicator::Signal);
    appConfiguration.enable(status_bar::Indicator::SimCard);
    return appConfiguration;
}


M module-apps/popups/lock-popups/PhoneLockChangeInfoWindow.hpp => module-apps/popups/lock-popups/PhoneLockChangeInfoWindow.hpp +1 -1
@@ 18,6 18,6 @@ namespace gui

        void buildInterface() override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
    };
} /* namespace gui */

M module-apps/popups/lock-popups/PhoneLockInputWindow.cpp => module-apps/popups/lock-popups/PhoneLockInputWindow.cpp +5 -5
@@ 32,15 32,15 @@ namespace gui
        erase();
    }

    top_bar::Configuration PhoneLockInputWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration PhoneLockInputWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        if (phoneLockInputTypeAction == locks::PhoneLockInputTypeAction::Unlock) {
            appConfiguration.enable(top_bar::Indicator::Lock);
            appConfiguration.disable(top_bar::Indicator::Time);
            appConfiguration.enable(status_bar::Indicator::Lock);
            appConfiguration.disable(status_bar::Indicator::Time);
        }
        else {
            appConfiguration.enable(top_bar::Indicator::Time);
            appConfiguration.disable(top_bar::Indicator::Lock);
            appConfiguration.enable(status_bar::Indicator::Time);
            appConfiguration.disable(status_bar::Indicator::Lock);
        }
        return appConfiguration;
    }

M module-apps/popups/lock-popups/PhoneLockInputWindow.hpp => module-apps/popups/lock-popups/PhoneLockInputWindow.hpp +1 -1
@@ 22,7 22,7 @@ namespace gui
        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
    };

} /* namespace gui */

M module-apps/popups/lock-popups/PhoneLockedInfoWindow.cpp => module-apps/popups/lock-popups/PhoneLockedInfoWindow.cpp +8 -8
@@ 34,15 34,15 @@ bool PhoneLockedInfoWindow::onInput(const InputEvent &inputEvent)
    return AppWindow::onInput(inputEvent);
}

top_bar::Configuration PhoneLockedInfoWindow::configureTopBar(top_bar::Configuration appConfiguration)
status_bar::Configuration PhoneLockedInfoWindow::configureStatusBar(status_bar::Configuration appConfiguration)
{
    appConfiguration.disable(top_bar::Indicator::NetworkAccessTechnology);
    appConfiguration.disable(top_bar::Indicator::Time);
    appConfiguration.enable(top_bar::Indicator::PhoneMode);
    appConfiguration.enable(top_bar::Indicator::Lock);
    appConfiguration.enable(top_bar::Indicator::Battery);
    appConfiguration.enable(top_bar::Indicator::Signal);
    appConfiguration.enable(top_bar::Indicator::SimCard);
    appConfiguration.disable(status_bar::Indicator::NetworkAccessTechnology);
    appConfiguration.disable(status_bar::Indicator::Time);
    appConfiguration.enable(status_bar::Indicator::PhoneMode);
    appConfiguration.enable(status_bar::Indicator::Lock);
    appConfiguration.enable(status_bar::Indicator::Battery);
    appConfiguration.enable(status_bar::Indicator::Signal);
    appConfiguration.enable(status_bar::Indicator::SimCard);
    return appConfiguration;
}


M module-apps/popups/lock-popups/PhoneLockedInfoWindow.hpp => module-apps/popups/lock-popups/PhoneLockedInfoWindow.hpp +1 -1
@@ 19,6 19,6 @@ namespace gui
        bool onInput(const InputEvent &inputEvent) override;

        void buildInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
    };
} /* namespace gui */

M module-apps/popups/lock-popups/PhoneLockedWindow.cpp => module-apps/popups/lock-popups/PhoneLockedWindow.cpp +8 -8
@@ 65,15 65,15 @@ namespace gui
                                         listview::ScrollBarType::None);
    }

    top_bar::Configuration PhoneLockedWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration PhoneLockedWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.disable(top_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.disable(top_bar::Indicator::Time);
        appConfiguration.enable(top_bar::Indicator::PhoneMode);
        appConfiguration.enable(top_bar::Indicator::Lock);
        appConfiguration.enable(top_bar::Indicator::Battery);
        appConfiguration.enable(top_bar::Indicator::Signal);
        appConfiguration.enable(top_bar::Indicator::SimCard);
        appConfiguration.disable(status_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.disable(status_bar::Indicator::Time);
        appConfiguration.enable(status_bar::Indicator::PhoneMode);
        appConfiguration.enable(status_bar::Indicator::Lock);
        appConfiguration.enable(status_bar::Indicator::Battery);
        appConfiguration.enable(status_bar::Indicator::Signal);
        appConfiguration.enable(status_bar::Indicator::SimCard);
        return appConfiguration;
    }


M module-apps/popups/lock-popups/PhoneLockedWindow.hpp => module-apps/popups/lock-popups/PhoneLockedWindow.hpp +1 -1
@@ 46,7 46,7 @@ namespace gui
        bool onInput(const InputEvent &inputEvent) override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        void buildInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;

        bool updateTime() override;
    };

M module-apps/popups/lock-popups/SimInfoWindow.cpp => module-apps/popups/lock-popups/SimInfoWindow.cpp +7 -7
@@ 13,14 13,14 @@ SimInfoWindow::SimInfoWindow(app::Application *app, const std::string &name) : W
    buildInterface();
}

top_bar::Configuration SimInfoWindow::configureTopBar(top_bar::Configuration appConfiguration)
status_bar::Configuration SimInfoWindow::configureStatusBar(status_bar::Configuration appConfiguration)
{
    appConfiguration.enable(top_bar::Indicator::NetworkAccessTechnology);
    appConfiguration.enable(top_bar::Indicator::Time);
    appConfiguration.enable(top_bar::Indicator::PhoneMode);
    appConfiguration.enable(top_bar::Indicator::Battery);
    appConfiguration.enable(top_bar::Indicator::Signal);
    appConfiguration.enable(top_bar::Indicator::SimCard);
    appConfiguration.enable(status_bar::Indicator::NetworkAccessTechnology);
    appConfiguration.enable(status_bar::Indicator::Time);
    appConfiguration.enable(status_bar::Indicator::PhoneMode);
    appConfiguration.enable(status_bar::Indicator::Battery);
    appConfiguration.enable(status_bar::Indicator::Signal);
    appConfiguration.enable(status_bar::Indicator::SimCard);
    return appConfiguration;
}


M module-apps/popups/lock-popups/SimInfoWindow.hpp => module-apps/popups/lock-popups/SimInfoWindow.hpp +1 -1
@@ 18,6 18,6 @@ namespace gui

        void buildInterface() override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
    };
} /* namespace gui */

M module-apps/popups/lock-popups/SimLockInputWindow.cpp => module-apps/popups/lock-popups/SimLockInputWindow.cpp +7 -7
@@ 43,14 43,14 @@ namespace gui
        }
    }

    top_bar::Configuration SimLockInputWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration SimLockInputWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.disable(top_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.enable(top_bar::Indicator::Time);
        appConfiguration.enable(top_bar::Indicator::PhoneMode);
        appConfiguration.enable(top_bar::Indicator::Battery);
        appConfiguration.enable(top_bar::Indicator::Signal);
        appConfiguration.enable(top_bar::Indicator::SimCard);
        appConfiguration.disable(status_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.enable(status_bar::Indicator::Time);
        appConfiguration.enable(status_bar::Indicator::PhoneMode);
        appConfiguration.enable(status_bar::Indicator::Battery);
        appConfiguration.enable(status_bar::Indicator::Signal);
        appConfiguration.enable(status_bar::Indicator::SimCard);
        return appConfiguration;
    }


M module-apps/popups/lock-popups/SimLockInputWindow.hpp => module-apps/popups/lock-popups/SimLockInputWindow.hpp +1 -1
@@ 26,7 26,7 @@ namespace gui
        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
    };

} /* namespace gui */

M module-apps/popups/lock-popups/SimNotReadyWindow.cpp => module-apps/popups/lock-popups/SimNotReadyWindow.cpp +8 -8
@@ 15,15 15,15 @@ SimNotReadyWindow::SimNotReadyWindow(app::Application *app, const std::string &n
    buildInterface();
}

top_bar::Configuration SimNotReadyWindow::configureTopBar(top_bar::Configuration appConfiguration)
status_bar::Configuration SimNotReadyWindow::configureStatusBar(status_bar::Configuration appConfiguration)
{
    appConfiguration.disable(top_bar::Indicator::NetworkAccessTechnology);
    appConfiguration.disable(top_bar::Indicator::Lock);
    appConfiguration.enable(top_bar::Indicator::PhoneMode);
    appConfiguration.enable(top_bar::Indicator::Time);
    appConfiguration.enable(top_bar::Indicator::Battery);
    appConfiguration.enable(top_bar::Indicator::Signal);
    appConfiguration.enable(top_bar::Indicator::SimCard);
    appConfiguration.disable(status_bar::Indicator::NetworkAccessTechnology);
    appConfiguration.disable(status_bar::Indicator::Lock);
    appConfiguration.enable(status_bar::Indicator::PhoneMode);
    appConfiguration.enable(status_bar::Indicator::Time);
    appConfiguration.enable(status_bar::Indicator::Battery);
    appConfiguration.enable(status_bar::Indicator::Signal);
    appConfiguration.enable(status_bar::Indicator::SimCard);
    return appConfiguration;
}


M module-apps/popups/lock-popups/SimNotReadyWindow.hpp => module-apps/popups/lock-popups/SimNotReadyWindow.hpp +1 -1
@@ 17,6 17,6 @@ namespace gui
        SimNotReadyWindow(app::Application *app, const std::string &name);

        void buildInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
    };
} /* namespace gui */

M module-apps/windows/AppWindow.cpp => module-apps/windows/AppWindow.cpp +28 -28
@@ 4,8 4,8 @@
#include "AppWindow.hpp"
#include "Application.hpp"
#include "InputEvent.hpp"
#include "TopBar.hpp"
#include "TopBar/Time.hpp"
#include "StatusBar.hpp"
#include "status-bar/Time.hpp"
#include <Style.hpp>
#include <i18n/i18n.hpp>
#include <service-appmgr/Controller.hpp>


@@ 25,11 25,11 @@ namespace gui
    void AppWindow::destroyInterface()
    {
        erase(bottomBar);
        erase(topBar);
        erase(statusBar);
        erase(title);
        title     = nullptr;
        bottomBar = nullptr;
        topBar    = nullptr;
        statusBar = nullptr;
    }

    void AppWindow::rebuild()


@@ 51,67 51,67 @@ namespace gui
        title->setEllipsis(Ellipsis::Right);
        title->visible = false;

        auto config          = configureTopBar(application->getTopBarConfiguration());
        auto config          = configureStatusBar(application->getStatusBarConfiguration());
        namespace status_bar = style::header::status_bar;
        topBar               = new gui::top_bar::TopBar(
        statusBar            = new gui::status_bar::StatusBar(
            this, (style::window_width - status_bar::width) / 2, 0, status_bar::width, status_bar::height);
        topBar->configure(std::move(config));
        statusBar->configure(std::move(config));
    }

    top_bar::Configuration AppWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration AppWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        return appConfiguration;
    }

    void AppWindow::applyToTopBar(TopBarConfigurationChangeFunction configChange)
    void AppWindow::applyToStatusBar(StatusBarConfigurationChangeFunction configChange)
    {
        if (configChange) {
            auto newConfiguration = configChange(topBar->getConfiguration());
            topBar->configure(std::move(newConfiguration));
            auto newConfiguration = configChange(statusBar->getConfiguration());
            statusBar->configure(std::move(newConfiguration));
        }
    }

    bool AppWindow::updateSim()
    {
        if (topBar == nullptr) {
        if (statusBar == nullptr) {
            return false;
        }
        return topBar->updateSim();
        return statusBar->updateSim();
    }

    bool AppWindow::updateBatteryStatus()
    {
        if (topBar == nullptr) {
        if (statusBar == nullptr) {
            return false;
        }
        return topBar->updateBattery();
        return statusBar->updateBattery();
    }
    // updates battery level in the window
    bool AppWindow::updateSignalStrength()
    {
        if (topBar == nullptr) {
        if (statusBar == nullptr) {
            return false;
        }
        return topBar->updateSignalStrength();
        return statusBar->updateSignalStrength();
    }

    bool AppWindow::updateNetworkAccessTechnology()
    {
        if (topBar == nullptr) {
        if (statusBar == nullptr) {
            return false;
        }
        return topBar->updateNetworkAccessTechnology();
        return statusBar->updateNetworkAccessTechnology();
    }

    void AppWindow::updatePhoneMode(sys::phone_modes::PhoneMode mode)
    {
        auto fn = [&](gui::top_bar::Configuration cfg) -> gui::top_bar::Configuration {
            gui::top_bar::Configuration ret(cfg);
        auto fn = [&](gui::status_bar::Configuration cfg) -> gui::status_bar::Configuration {
            gui::status_bar::Configuration ret(cfg);
            ret.setPhoneMode(mode);
            return ret;
        };

        applyToTopBar(std::move(fn));
        applyToStatusBar(std::move(fn));
    }

    bool AppWindow::preventsAutoLocking() const noexcept


@@ 121,17 121,17 @@ namespace gui

    bool AppWindow::updateTime()
    {
        applyToTopBar([](top_bar::Configuration configuration) {
            using TimeMode = gui::top_bar::TimeConfiguration::TimeMode;
            auto modifier  = std::make_shared<gui::top_bar::TimeConfiguration>(
        applyToStatusBar([](status_bar::Configuration configuration) {
            using TimeMode = gui::status_bar::TimeConfiguration::TimeMode;
            auto modifier  = std::make_shared<gui::status_bar::TimeConfiguration>(
                utils::dateAndTimeSettings.isTimeFormat12() ? TimeMode::Time12h : TimeMode::Time24h);
            configuration.setIndicatorModifier(gui::top_bar::Indicator::Time, std::move(modifier));
            configuration.setIndicatorModifier(gui::status_bar::Indicator::Time, std::move(modifier));
            return configuration;
        });
        if (topBar == nullptr) {
        if (statusBar == nullptr) {
            return false;
        }
        return topBar->updateTime();
        return statusBar->updateTime();
    }

    void AppWindow::setTitle(const UTF8 &text)

M module-apps/windows/AppWindow.hpp => module-apps/windows/AppWindow.hpp +12 -11
@@ 3,7 3,7 @@

#pragma once

#include <gui/widgets/TopBar.hpp>
#include <gui/widgets/StatusBar.hpp>
#include <gui/widgets/BottomBar.hpp>
#include <gui/widgets/Window.hpp>
#include <Service/Service.hpp>


@@ 40,16 40,17 @@ namespace gui
        /**
         * Information bar for signal, battery and lock icon on the top of the screen.
         */
        gui::top_bar::TopBar *topBar = nullptr;
        gui::status_bar::StatusBar *statusBar = nullptr;
        /**
         * Pointer to the application object that owns the window.
         */
        app::Application *application = nullptr;

        /**
         * A function that applies configuration changes to the current top bar configuration.
         * A function that applies configuration changes to the current status bar configuration.
         */
        using TopBarConfigurationChangeFunction = std::function<top_bar::Configuration(top_bar::Configuration)>;
        using StatusBarConfigurationChangeFunction =
            std::function<status_bar::Configuration(status_bar::Configuration)>;

        /**
         * A flag that is set if current window state requires the phone to stay unlocked


@@ 83,17 84,17 @@ namespace gui
        void accept(GuiVisitor &visitor) override;

        /**
         * Configure the top bar using window-specific configuration.
         * @param appConfiguration      Application-wide top bar configuration that it to be modified.
         * @return window-specific configuration of the top bar.
         * Configure the status bar using window-specific configuration.
         * @param appConfiguration      Application-wide status bar configuration that it to be modified.
         * @return window-specific configuration of the status bar.
         */
        virtual top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration);
        virtual status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration);

        /**
         * Applies configuration change on the current top bar configuration.
         * @param configChange  The function that contains the top bar configuration changes.
         * Applies configuration change on the current status bar configuration.
         * @param configChange  The function that contains the status bar configuration changes.
         */
        void applyToTopBar(TopBarConfigurationChangeFunction configChange);
        void applyToStatusBar(StatusBarConfigurationChangeFunction configChange);

        /// Setting bottom bar temporary text
        /// @param text - bottomBar text

M module-apps/windows/OptionWindow.cpp => module-apps/windows/OptionWindow.cpp +7 -7
@@ 98,14 98,14 @@ namespace gui
        setFocusItem(optionsList);
    }

    top_bar::Configuration OptionWindow::configureTopBar(top_bar::Configuration appConfiguration)
    status_bar::Configuration OptionWindow::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.enable(top_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.enable(top_bar::Indicator::Time);
        appConfiguration.enable(top_bar::Indicator::PhoneMode);
        appConfiguration.enable(top_bar::Indicator::Battery);
        appConfiguration.enable(top_bar::Indicator::Signal);
        appConfiguration.enable(top_bar::Indicator::SimCard);
        appConfiguration.enable(status_bar::Indicator::NetworkAccessTechnology);
        appConfiguration.enable(status_bar::Indicator::Time);
        appConfiguration.enable(status_bar::Indicator::PhoneMode);
        appConfiguration.enable(status_bar::Indicator::Battery);
        appConfiguration.enable(status_bar::Indicator::Signal);
        appConfiguration.enable(status_bar::Indicator::SimCard);
        return appConfiguration;
    }


M module-apps/windows/OptionWindow.hpp => module-apps/windows/OptionWindow.hpp +1 -1
@@ 40,6 40,6 @@ namespace gui
        void onClose() override;
        void rebuild() override;
        void buildInterface() override;
        top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;
    };
}; // namespace gui

M module-cellular/CMakeLists.txt => module-cellular/CMakeLists.txt +3 -0
@@ 77,6 77,7 @@ target_include_directories(${PROJECT_NAME}
)

target_link_libraries(${PROJECT_NAME}
    PUBLIC
    service-cellular
    service-eink
    service-fota


@@ 87,6 88,8 @@ target_link_libraries(${PROJECT_NAME}
    module-db
    module-bsp
    date::date
    PRIVATE
    Microsoft.GSL::GSL
)

if (${ENABLE_TESTS})

M module-cellular/modem/mux/CellularMux.cpp => module-cellular/modem/mux/CellularMux.cpp +1 -1
@@ 17,7 17,7 @@
#include <SystemManager/messages/DeviceRegistrationMessage.hpp>
#include <time/time_conversion.hpp>

#include <gsl/gsl_util>
#include <gsl/util>

#include <memory>
#include <sstream>

M module-db/CMakeLists.txt => module-db/CMakeLists.txt +8 -1
@@ 176,7 176,14 @@ target_compile_options(${PROJECT_NAME}
    -Wno-error=return-local-addr
)

target_link_libraries(${PROJECT_NAME} module-utils module-vfs )
target_link_libraries(${PROJECT_NAME}
    PUBLIC
    module-utils
    module-vfs

    PRIVATE
    Microsoft.GSL::GSL
)

# Host target configuration(mainly used for unit testing)
if (${ENABLE_TESTS})

M module-db/Database/Database.cpp => module-db/Database/Database.cpp +1 -1
@@ 7,7 7,7 @@
#include "log/log.hpp"

#include <purefs/filesystem_paths.hpp>
#include <gsl/gsl_util>
#include <gsl/util>

#include <cassert>
#include <cstring>

M module-db/Interface/NotificationsRecord.cpp => module-db/Interface/NotificationsRecord.cpp +1 -1
@@ 14,7 14,7 @@

#include <cassert>
#include <vector>
#include <gsl_assert>
#include <gsl/assert>

NotificationsRecord::NotificationsRecord(const NotificationsTableRow &tableRow, std::optional<ContactRecord> record)
    : Record{tableRow.ID}, value{tableRow.value}, contactRecord{std::move(record)}

M module-db/tests/CMakeLists.txt => module-db/tests/CMakeLists.txt +2 -1
@@ 1,4 1,4 @@
if (NOT IS_SYMLINK "${CMAKE_BINARY_DIR}/sys/user")
if (NOT IS_SYMLINK "${CMAKE_BINARY_DIR}/sys/user")
    file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/sys/user")
endif()



@@ 40,5 40,6 @@ add_catch2_executable(
        module-db
    DEPS
        assets
        PurePhone-disk-img
)
add_subdirectory(test-initializer)

M module-db/tests/test-initializer/CMakeLists.txt => module-db/tests/test-initializer/CMakeLists.txt +2 -1
@@ 1,4 1,4 @@
if (NOT IS_SYMLINK "${CMAKE_BINARY_DIR}/sys/user")
if (NOT IS_SYMLINK "${CMAKE_BINARY_DIR}/sys/user")
    file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/sys/user")
endif()



@@ 15,4 15,5 @@ add_catch2_executable(
        module-db
    DEPS
        assets
        PurePhone-disk-img
)

M module-gui/CMakeLists.txt => module-gui/CMakeLists.txt +1 -0
@@ 27,6 27,7 @@ target_link_libraries(${PROJECT_NAME}
        ${TARGET_LIBRARIES} 
    PRIVATE
        pugixml::pugixml
        Microsoft.GSL::GSL
)

# Board specific compilation definitions,options,include directories and features

M module-gui/README.md => module-gui/README.md +1 -0
@@ 189,4 189,5 @@ in a sequence flow analogous to the one presented above. Please find an exemplar

## Widgets

- [Window](WINDOW.md)
- [Text](./gui/widgets/text/HowDoesTextWork.md)

A module-gui/WINDOW.md => module-gui/WINDOW.md +21 -0
@@ 0,0 1,21 @@
# GUI Window

This article describes window used in Pure project. Window is base applications view used 
to display information back to users.

## Structure

Window consist of 4 different segments presented on image below. 

![alt text](./doc/window_structure.png "Window structure png")

* `StatusBar` - Top part of screen displaying system wide information. In example Time, Signal Strength, 
selected sim. Objects in status bar are not focusable and activeable. 
* `Header` - Displaying selected window information. Mainly its title and in addition window particular input actions
descriptions. In example adding object to list, search and emergency calls action. Objects in header are not focusable 
and activeable. Currently that part is not clearly represented in Code and is being refactored.
* `Body` - Main part of window responsible for displaying and manipulating window logic. In example: contact information, 
 sms list manipulations, alarm clock settings. Objects in Body are focusable and activeable. 
* `NavBar` - Bottom part of window displaying input action descriptions assigned to main keyboard keys (Left Function key, 
Enter Key, Right Function Key). In example: accepting prompt, going to previous window, selecting object. Objects in 
NavBar are not focusable and activeable. Currently that part is named BottomBar in Code. 
\ No newline at end of file

A module-gui/doc/window_structure.png => module-gui/doc/window_structure.png +0 -0
M module-gui/gui/dom/Item2JsonSerializingVisitor.cpp => module-gui/gui/dom/Item2JsonSerializingVisitor.cpp +3 -3
@@ 8,7 8,7 @@
#include "Text.hpp"
#include "Window.hpp"
#include "BottomBar.hpp"
#include "TopBar.hpp"
#include "StatusBar.hpp"
#include "ListItem.hpp"

#include "ItemDataNames.hpp"


@@ 86,10 86,10 @@ void Item2JsonSerializingVisitor::visit(gui::BottomBar &item)
    visit(static_cast<gui::Item &>(item));
}

void Item2JsonSerializingVisitor::visit(gui::top_bar::TopBar &item)
void Item2JsonSerializingVisitor::visit(gui::status_bar::StatusBar &item)
{
    if (itemName.empty()) {
        itemName = magic_enum::enum_name(visitor::Names::TopBar);
        itemName = magic_enum::enum_name(visitor::Names::StatusBar);
    }
    visit(static_cast<gui::Item &>(item));
}

M module-gui/gui/dom/Item2JsonSerializingVisitor.hpp => module-gui/gui/dom/Item2JsonSerializingVisitor.hpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 29,7 29,7 @@ namespace gui
        void visit(gui::Window &item) override;
        void visit(gui::Label &item) override;
        void visit(gui::BottomBar &item) override;
        void visit(gui::top_bar::TopBar &item) override;
        void visit(gui::status_bar::StatusBar &item) override;
        void visit(gui::ListItem &item) override;

      public:

M module-gui/gui/dom/ItemDataNames.hpp => module-gui/gui/dom/ItemDataNames.hpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 12,7 12,7 @@ namespace gui::visitor
        Rect,
        Label,
        Text,
        TopBar,
        StatusBar,
        BottomBar,
        Window,
        Children,

M module-gui/gui/input/InputEvent.cpp => module-gui/gui/input/InputEvent.cpp +8 -0
@@ 2,6 2,8 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "InputEvent.hpp"
#include <gsl/assert>

namespace gui
{



@@ 17,4 19,10 @@ namespace gui
        return ss.str();
    }

    auto InputEvent::numericValue() const -> int
    {
        Expects(isDigit());
        return toNumeric(keyCode);
    }

}; // namespace gui

M module-gui/gui/input/InputEvent.hpp => module-gui/gui/input/InputEvent.hpp +2 -7
@@ 6,7 6,6 @@
#include <sstream>
#include <cstdint>
#include <type_traits>
#include <gsl_assert>
#include "bsp/keyboard/key_codes.hpp"
#include "common_data/RawKey.hpp"



@@ 168,14 167,10 @@ namespace gui
            return toNumeric(keyCode) != InvalidNumericKeyCode;
        }

        [[nodiscard]] auto numericValue() const -> int
        {
            Expects(isDigit());
            return toNumeric(keyCode);
        }

        [[nodiscard]] auto str() const -> std::string;

        [[nodiscard]] auto numericValue() const -> int;

      private:
        RawKey rawKey   = {};                     /// RawKey data
        State state     = State::keyPressed;      /// initial translated key state

M module-gui/gui/input/Profile.cpp => module-gui/gui/input/Profile.cpp +1 -1
@@ 5,7 5,7 @@
#include "utf8/UTF8.hpp"
#include "Profile.hpp"
#include <Utils.hpp>
#include <gsl>
#include <gsl/gsl>

namespace gui
{

M module-gui/gui/widgets/CMakeLists.txt => module-gui/gui/widgets/CMakeLists.txt +13 -13
@@ 20,18 20,18 @@ target_sources( ${PROJECT_NAME}
        "${CMAKE_CURRENT_LIST_DIR}/Window.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/BoxLayout.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/BoxLayoutSizeStore.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/SIM.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/BatteryBase.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/BatteryBar.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/BatteryText.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/SignalStrengthBase.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/SignalStrengthBar.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/SignalStrengthText.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/NetworkAccessTechnology.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/PhoneMode.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/Time.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/Lock.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/StatusBar.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/SIM.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/BatteryBase.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/BatteryBar.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/BatteryText.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/SignalStrengthBase.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/SignalStrengthBar.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/SignalStrengthText.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/NetworkAccessTechnology.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/PhoneMode.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/Time.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/Lock.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/Text.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TextBlock.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TextDocument.cpp"


@@ 70,7 70,7 @@ target_sources( ${PROJECT_NAME}
        "${CMAKE_CURRENT_LIST_DIR}/Window.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/BoxLayout.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/Layout.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/StatusBar.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/Text.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/CheckBoxWithLabel.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/CheckBoxWithLabel.hpp"

R module-gui/gui/widgets/TopBar.cpp => module-gui/gui/widgets/StatusBar.cpp +40 -35
@@ 5,20 5,20 @@
#include "Label.hpp"
#include "Image.hpp"
#include "BoxLayout.hpp"
#include "TopBar.hpp"
#include "TopBar/Style.hpp"
#include "TopBar/BatteryBar.hpp"
#include "TopBar/BatteryText.hpp"
#include "TopBar/SignalStrengthBar.hpp"
#include "TopBar/SignalStrengthText.hpp"
#include "TopBar/NetworkAccessTechnology.hpp"
#include "TopBar/PhoneMode.hpp"
#include "TopBar/SIM.hpp"
#include "TopBar/Time.hpp"
#include "TopBar/Lock.hpp"
#include "StatusBar.hpp"
#include "status-bar/Style.hpp"
#include "status-bar/BatteryBar.hpp"
#include "status-bar/BatteryText.hpp"
#include "status-bar/SignalStrengthBar.hpp"
#include "status-bar/SignalStrengthText.hpp"
#include "status-bar/NetworkAccessTechnology.hpp"
#include "status-bar/PhoneMode.hpp"
#include "status-bar/SIM.hpp"
#include "status-bar/Time.hpp"
#include "status-bar/Lock.hpp"
#include "common_data/EventStore.hpp"

namespace gui::top_bar
namespace gui::status_bar
{
    using namespace style::header::status_bar;



@@ 81,7 81,7 @@ namespace gui::top_bar
        indicatorsModifiers[indicator] = std::move(config);
    }

    TopBar::TopBar(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h) : HBox{parent, x, y, w, h}
    StatusBar::StatusBar(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h) : HBox{parent, x, y, w, h}
    {
        prepareWidget();



@@ 92,7 92,7 @@ namespace gui::top_bar
        preBuildDrawListHook = [this](std::list<Command> &) { updateTime(); };
    }

    void TopBar::prepareWidget()
    void StatusBar::prepareWidget()
    {
        // left
        leftBox = new HBox(this, 0, 0, 0, 0);


@@ 136,12 136,12 @@ namespace gui::top_bar
        updatePhoneMode();
    }

    auto TopBar::getConfiguration() const noexcept -> const Configuration &
    auto StatusBar::getConfiguration() const noexcept -> const Configuration &
    {
        return configuration;
    }

    void TopBar::configure(Configuration &&config)
    void StatusBar::configure(Configuration &&config)
    {
        if (config.isEnabled(Indicator::Lock)) {
            // In current implementation, lock and time indicators are mutually exclusive.


@@ 171,7 171,7 @@ namespace gui::top_bar
        resizeItems();
    }

    void TopBar::setIndicatorStatus(Indicator indicator, bool enabled)
    void StatusBar::setIndicatorStatus(Indicator indicator, bool enabled)
    {
        switch (indicator) {
        case Indicator::Signal:


@@ 198,7 198,7 @@ namespace gui::top_bar
        }
    }

    void TopBar::setIndicatorModifier(Indicator indicator, StatusBarVisitor &modifier)
    void StatusBar::setIndicatorModifier(Indicator indicator, StatusBarVisitor &modifier)
    {
        if (indicator == Indicator::SimCard && sim != nullptr) {
            sim->acceptStatusBarVisitor(modifier);


@@ 208,7 208,7 @@ namespace gui::top_bar
        }
    }

    bool TopBar::updateBattery()
    bool StatusBar::updateBattery()
    {
        if (battery == nullptr) {
            return false;


@@ 217,19 217,24 @@ namespace gui::top_bar
        return true;
    }

    void TopBar::showBattery(bool enabled)
    void StatusBar::showBattery(bool enabled)
    {
        battery->update(Store::Battery::get());
        enabled ? battery->show() : battery->hide();
    }

    void TopBar::showSim(bool enabled)
    void StatusBar::showSim(bool enabled)
    {
        sim->update(Store::GSM::get()->sim);
        enabled ? sim->show() : sim->hide();
        if (enabled) {
            sim->update();
            sim->show();
        }
        else {
            sim->hide();
        }
    }

    bool TopBar::updateSim()
    bool StatusBar::updateSim()
    {
        if (sim == nullptr) {
            return false;


@@ 238,14 243,14 @@ namespace gui::top_bar
        return true;
    }

    void TopBar::showSignalStrength(bool enabled)
    void StatusBar::showSignalStrength(bool enabled)
    {
        auto signalStrength = Store::GSM::get()->getSignalStrength();
        signal->update(signalStrength);
        enabled ? signal->show() : signal->hide();
    }

    bool TopBar::updateSignalStrength()
    bool StatusBar::updateSignalStrength()
    {
        if (signal == nullptr) {
            return false;


@@ 254,7 259,7 @@ namespace gui::top_bar
        return true;
    }

    bool TopBar::updatePhoneMode()
    bool StatusBar::updatePhoneMode()
    {
        if (phoneMode == nullptr) {
            return false;


@@ 263,12 268,12 @@ namespace gui::top_bar
        return true;
    }

    void TopBar::showPhoneMode(bool enabled)
    void StatusBar::showPhoneMode(bool enabled)
    {
        enabled ? phoneMode->show() : phoneMode->hide();
    }

    bool TopBar::updateNetworkAccessTechnology()
    bool StatusBar::updateNetworkAccessTechnology()
    {
        if (networkAccessTechnology == nullptr) {
            return false;


@@ 277,13 282,13 @@ namespace gui::top_bar
        return true;
    }

    void TopBar::showNetworkAccessTechnology(bool enabled)
    void StatusBar::showNetworkAccessTechnology(bool enabled)
    {
        networkAccessTechnology->update(Store::GSM::get()->getNetwork().accessTechnology);
        enabled ? networkAccessTechnology->show() : networkAccessTechnology->hide();
    }

    void TopBar::showTime(bool enabled)
    void StatusBar::showTime(bool enabled)
    {
        time->update();
        if (enabled) {


@@ 296,7 301,7 @@ namespace gui::top_bar
        time->hide();
    }

    void TopBar::showLock(bool enabled)
    void StatusBar::showLock(bool enabled)
    {
        if (enabled) {
            centralBox->setMinimumSize(boxes::center::minX, this->drawArea.h);


@@ 307,7 312,7 @@ namespace gui::top_bar
        lock->hide();
    }

    bool TopBar::updateTime()
    bool StatusBar::updateTime()
    {
        if (time == nullptr) {
            return false;


@@ 316,8 321,8 @@ namespace gui::top_bar
        return true;
    }

    void TopBar::accept(GuiVisitor &visitor)
    void StatusBar::accept(GuiVisitor &visitor)
    {
        visitor.visit(*this);
    }
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar.hpp => module-gui/gui/widgets/StatusBar.hpp +14 -14
@@ 15,7 15,7 @@ namespace gui
    class Label;
    class Image;

    namespace top_bar
    namespace status_bar
    {
        class SignalStrengthBase;
        class PhoneMode;


@@ 24,14 24,14 @@ namespace gui
        class SIM;
        class Time;
        class Lock;
    } // namespace top_bar
    } // namespace status_bar
} // namespace gui

class UTF8;

class StatusBarVisitor;

namespace gui::top_bar
namespace gui::status_bar
{

    enum class Indicator


@@ 45,11 45,11 @@ namespace gui::top_bar
        PhoneMode,               /// phone mode
    };

    using Indicators        = std::vector<Indicator>;
    using IndicatorStatuses = std::map<Indicator, bool>;
    using Indicators          = std::vector<Indicator>;
    using IndicatorStatuses   = std::map<Indicator, bool>;
    using IndicatorsModifiers = std::map<Indicator, std::shared_ptr<StatusBarVisitor>>;

    /// Carries the top bar configuration.
    /// Carries the status bar configuration.
    class Configuration
    {
      public:


@@ 113,12 113,12 @@ namespace gui::top_bar
        IndicatorsModifiers indicatorsModifiers;
    };

    /// Top bar widget class.
    /// Status bar widget class.
    /// This is horizontal box with three sections
    /// * left showing signal strenght, NAT info, and/or phone mode
    /// * center showing lock info or digital clock
    /// * right showing sim card and battery status
    class TopBar : public HBox
    class StatusBar : public HBox
    {
      public:
        /// Constructor


@@ 127,7 127,7 @@ namespace gui::top_bar
        /// @param y widget y position
        /// @param w widget width
        /// @param h widget height
        TopBar(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
        StatusBar(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);

        /// Set the configuration basing on the specialized gui::top_bar::Configuration class
        /// @param configuration desired configuration


@@ 155,11 155,11 @@ namespace gui::top_bar
        /// Update NAT widget state depending on the current configuration
        bool updateNetworkAccessTechnology();

        /// Accepts GuiVisitor to update the top bar
        /// Accepts GuiVisitor to update the status bar
        void accept(GuiVisitor &visitor) override;

      protected:
        /// Set up and add all the widgets to the top bar
        /// Set up and add all the widgets to the status bar
        void prepareWidget();

        /// Show/hide sim card status widget


@@ 190,7 190,7 @@ namespace gui::top_bar
        /// @param enabled true to show false to hide the widget
        void showNetworkAccessTechnology(bool enabled);

        /// Sets the status of the specified indicator on the top bar
        /// Sets the status of the specified indicator on the Status bar
        /// @param indicator indicator id
        /// @param enabled enable or disable the specified indicator
        void setIndicatorStatus(Indicator indicator, bool enabled);


@@ 230,8 230,8 @@ namespace gui::top_bar
        /// Pointer to the right horizontal box
        HBox *rightBox = nullptr;

        /// Current configuration of the TopBar
        /// Current configuration of the Statusbar
        Configuration configuration;
    };

} // namespace gui::top_bar
} // namespace gui::status_bar

M module-gui/gui/widgets/Window.hpp => module-gui/gui/widgets/Window.hpp +2 -2
@@ 14,9 14,9 @@ namespace gui
    /// Base window for all UI windows
    ///
    /// It consists of:
    /// 1. TopBar
    /// 1. StatusBar
    /// 2. BottomBar
    /// 3. Body defined per window between TopBar and BottomBar
    /// 3. Body defined per window between StatusBar and BottomBar
    ///
    /// All window switches are done based on Window::name and SwitchData
    /// All windows are statically build at start of application, and removed on application end

R module-gui/gui/widgets/TopBar/BatteryBar.cpp => module-gui/gui/widgets/status-bar/BatteryBar.cpp +2 -2
@@ 7,7 7,7 @@
#include "visitor/GuiVisitor.hpp"
#include <Image.hpp>

namespace gui::top_bar
namespace gui::status_bar
{
    namespace
    {


@@ 67,4 67,4 @@ namespace gui::top_bar
        img->set(batteryChargingReady);
    }

} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/BatteryBar.hpp => module-gui/gui/widgets/status-bar/BatteryBar.hpp +2 -2
@@ 10,7 10,7 @@ namespace gui
    class Image;
}

namespace gui::top_bar
namespace gui::status_bar
{
    class BatteryBar : public BatteryBase
    {


@@ 24,4 24,4 @@ namespace gui::top_bar

        Image *img = nullptr;
    };
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/BatteryBase.cpp => module-gui/gui/widgets/status-bar/BatteryBase.cpp +2 -2
@@ 4,7 4,7 @@
#include "BatteryBase.hpp"
#include "BoxLayout.hpp"

namespace gui::top_bar
namespace gui::status_bar
{
    BatteryBase::BatteryBase(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
        : StatusBarWidgetBase(parent, x, y, w, h)


@@ 29,4 29,4 @@ namespace gui::top_bar
            break;
        }
    }
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/BatteryBase.hpp => module-gui/gui/widgets/status-bar/BatteryBase.hpp +2 -2
@@ 7,7 7,7 @@
#include "BoxLayout.hpp"
#include <common_data/EventStore.hpp>

namespace gui::top_bar
namespace gui::status_bar
{
    class BatteryBase : public StatusBarWidgetBase<gui::HBox>
    {


@@ 19,4 19,4 @@ namespace gui::top_bar
        BatteryBase(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
        void update(const Store::Battery &batteryContext);
    };
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/BatteryText.cpp => module-gui/gui/widgets/status-bar/BatteryText.cpp +4 -4
@@ 6,7 6,7 @@
#include <Utils.hpp>
#include "Style.hpp"

namespace gui::top_bar
namespace gui::status_bar
{
    BatteryText::BatteryText(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
        : BatteryBase(parent, x, y, w, h)


@@ 28,12 28,12 @@ namespace gui::top_bar

    void BatteryText::showBatteryCharging()
    {
        label->setText(utils::translate("topbar_battery_charging"));
        label->setText(utils::translate("statusbar_battery_charging"));
    }

    void BatteryText::showBatteryChargingDone()
    {
        label->setText(utils::translate("topbar_battery_plugged"));
        label->setText(utils::translate("statusbar_battery_plugged"));
    }

} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/BatteryText.hpp => module-gui/gui/widgets/status-bar/BatteryText.hpp +2 -2
@@ 9,7 9,7 @@ namespace gui
{
    class Label;
}
namespace gui::top_bar
namespace gui::status_bar
{
    class BatteryText : public BatteryBase
    {


@@ 22,4 22,4 @@ namespace gui::top_bar
        void showBatteryCharging() override;
        Label *label = nullptr;
    };
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/Lock.cpp => module-gui/gui/widgets/status-bar/Lock.cpp +2 -2
@@ 3,7 3,7 @@

#include "Lock.hpp"

namespace gui::top_bar
namespace gui::status_bar
{
    constexpr auto lock = "lock";



@@ 11,4 11,4 @@ namespace gui::top_bar
    {
        set(lock);
    }
}; // namespace gui::top_bar
}; // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/Lock.hpp => module-gui/gui/widgets/status-bar/Lock.hpp +2 -2
@@ 6,11 6,11 @@
#include "Image.hpp"
#include "StatusBarWidgetBase.hpp"

namespace gui::top_bar
namespace gui::status_bar
{
    class Lock : public StatusBarWidgetBase<Image>
    {
      public:
        Lock(Item *parent, uint32_t x, uint32_t y);
    };
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/NetworkAccessTechnology.cpp => module-gui/gui/widgets/status-bar/NetworkAccessTechnology.cpp +2 -2
@@ 5,7 5,7 @@
#include "Item.hpp"
#include "Style.hpp"

namespace gui::top_bar
namespace gui::status_bar
{
    NetworkAccessTechnology::NetworkAccessTechnology(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
        : StatusBarWidgetBase(parent, x, y, w, h)


@@ 42,4 42,4 @@ namespace gui::top_bar
            break;
        }
    }
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/NetworkAccessTechnology.hpp => module-gui/gui/widgets/status-bar/NetworkAccessTechnology.hpp +2 -2
@@ 7,7 7,7 @@
#include <Label.hpp>
#include <common_data/EventStore.hpp>

namespace gui::top_bar
namespace gui::status_bar
{
    class NetworkAccessTechnology : public StatusBarWidgetBase<Label>
    {


@@ 17,4 17,4 @@ namespace gui::top_bar
        NetworkAccessTechnology(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
        void update(Store::Network::AccessTechnology accessTechnology);
    };
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/PhoneMode.cpp => module-gui/gui/widgets/status-bar/PhoneMode.cpp +2 -2
@@ 9,7 9,7 @@
#include "Item.hpp"
#include "Style.hpp"

namespace gui::top_bar
namespace gui::status_bar
{
    PhoneMode::PhoneMode(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
        : StatusBarWidgetBase(parent, x, y, w, h)


@@ 35,4 35,4 @@ namespace gui::top_bar
            break;
        }
    }
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/PhoneMode.hpp => module-gui/gui/widgets/status-bar/PhoneMode.hpp +4 -4
@@ 6,11 6,11 @@
#include "StatusBarWidgetBase.hpp"
#include <Label.hpp>
#include <common_data/EventStore.hpp>
#include <gui/widgets/TopBar.hpp>
#include <gui/widgets/StatusBar.hpp>

namespace gui::top_bar
namespace gui::status_bar
{
    /// widget drawn on the top bar showing current phone mode:
    /// widget drawn on the status bar showing current phone mode:
    class PhoneMode : public StatusBarWidgetBase<Label>
    {



@@ 28,4 28,4 @@ namespace gui::top_bar
        void setPhoneMode(sys::phone_modes::PhoneMode mode);
    };

} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/SIM.cpp => module-gui/gui/widgets/status-bar/SIM.cpp +6 -6
@@ 3,7 3,7 @@

#include "SIM.hpp"

namespace gui::top_bar
namespace gui::status_bar
{
    using namespace Store;



@@ 17,12 17,12 @@ namespace gui::top_bar
        set(simunknown);
    }

    void SIM::update(const Store::GSM::SIM &state)
    void SIM::update()
    {
        if (state == current) {
        if (current == Store::GSM::get()->sim) {
            return;
        }
        current = state;
        current = Store::GSM::get()->sim;
        switch (current) {
        case GSM::SIM::SIM1:
            set(sim1);


@@ 56,7 56,7 @@ namespace gui::top_bar
    SIMConfiguration::SIMConfiguration(DisplayMode mode) : mode{mode}
    {}

    void SIMConfiguration::visit(gui::top_bar::SIM &widget) const
    void SIMConfiguration::visit(gui::status_bar::SIM &widget) const
    {
        widget.mode = getMode();
    }


@@ 73,4 73,4 @@ namespace gui::top_bar
    {
        StatusBarWidgetBase<Image>::setVisible(true);
    }
}; // namespace gui::top_bar
}; // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/SIM.hpp => module-gui/gui/widgets/status-bar/SIM.hpp +6 -6
@@ 4,10 4,10 @@
#pragma once

#include "Image.hpp"
#include "TopBar/StatusBarWidgetBase.hpp"
#include "status-bar/StatusBarWidgetBase.hpp"
#include <common_data/EventStore.hpp>

namespace gui::top_bar
namespace gui::status_bar
{
    class SIMConfiguration : public StatusBarVisitor
    {


@@ 22,7 22,7 @@ namespace gui::top_bar

        [[nodiscard]] DisplayMode getMode() const noexcept;

        void visit([[maybe_unused]] gui::top_bar::SIM &widget) const override;
        void visit([[maybe_unused]] gui::status_bar::SIM &widget) const override;

      private:
        DisplayMode mode;


@@ 30,7 30,7 @@ namespace gui::top_bar

    class SIM : public StatusBarWidgetBase<Image>
    {
        Store::GSM::SIM current = Store::GSM::SIM::SIM_UNKNOWN;
        Store::GSM::SIM current            = Store::GSM::SIM::SIM_UNKNOWN;
        SIMConfiguration::DisplayMode mode = SIMConfiguration::DisplayMode::AnyState;
        friend class SIMConfiguration;



@@ 38,7 38,7 @@ namespace gui::top_bar
        SIM(Item *parent, uint32_t x, uint32_t y);

        /// check if sim set in state -> if not -> show new sim
        void update(const Store::GSM::SIM &state);
        void update();

        void show() override;



@@ 52,4 52,4 @@ namespace gui::top_bar

        void show() override;
    };
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/SignalStrengthBar.cpp => module-gui/gui/widgets/status-bar/SignalStrengthBar.cpp +3 -3
@@ 6,7 6,7 @@
#include <Image.hpp>
#include <unordered_map>

namespace gui::top_bar
namespace gui::status_bar
{
    namespace
    {


@@ 29,7 29,7 @@ namespace gui::top_bar
    SignalStrengthBar::SignalStrengthBar(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
        : SignalStrengthBase(parent, x, y, w, h)
    {
        img                             = new Image(this, signalMap.at(Store::RssiBar::zero));
        img = new Image(this, signalMap.at(Store::RssiBar::zero));
        setMinimumSize(img->getWidth(), style::header::status_bar::height);
    }



@@ 38,4 38,4 @@ namespace gui::top_bar
        img->set(signalMap.at(signalStrength.rssiBar));
    }

} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/SignalStrengthBar.hpp => module-gui/gui/widgets/status-bar/SignalStrengthBar.hpp +2 -2
@@ 9,7 9,7 @@ namespace gui
{
    class Image;
}
namespace gui::top_bar
namespace gui::status_bar
{
    class SignalStrengthBar : public SignalStrengthBase
    {


@@ 21,4 21,4 @@ namespace gui::top_bar
      public:
        SignalStrengthBar(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
    };
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/SignalStrengthBase.cpp => module-gui/gui/widgets/status-bar/SignalStrengthBase.cpp +2 -2
@@ 3,7 3,7 @@

#include "SignalStrengthBase.hpp"

namespace gui::top_bar
namespace gui::status_bar
{
    SignalStrengthBase::SignalStrengthBase(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
        : StatusBarWidgetBase(parent, x, y, w, h)


@@ 17,4 17,4 @@ namespace gui::top_bar
        signalStrength = data;
        update();
    }
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/SignalStrengthBase.hpp => module-gui/gui/widgets/status-bar/SignalStrengthBase.hpp +2 -2
@@ 7,7 7,7 @@
#include "BoxLayout.hpp"
#include <common_data/EventStore.hpp>

namespace gui::top_bar
namespace gui::status_bar
{
    class SignalStrengthBase : public StatusBarWidgetBase<HBox>
    {


@@ 19,4 19,4 @@ namespace gui::top_bar
        SignalStrengthBase(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
        void update(const Store::SignalStrength &data);
    };
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/SignalStrengthText.cpp => module-gui/gui/widgets/status-bar/SignalStrengthText.cpp +2 -2
@@ 7,7 7,7 @@
#include <Utils.hpp>
#include "Style.hpp"

namespace gui::top_bar
namespace gui::status_bar
{
    SignalStrengthText::SignalStrengthText(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
        : SignalStrengthBase(parent, x, y, w, h)


@@ 27,4 27,4 @@ namespace gui::top_bar
        label->setText(utils::to_string(signalStrength.rssidBm) + " dBm");
    }

} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/SignalStrengthText.hpp => module-gui/gui/widgets/status-bar/SignalStrengthText.hpp +2 -2
@@ 9,7 9,7 @@ namespace gui
{
    class Label;
}
namespace gui::top_bar
namespace gui::status_bar
{
    class SignalStrengthText : public SignalStrengthBase
    {


@@ 22,4 22,4 @@ namespace gui::top_bar
      public:
        SignalStrengthText(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
    };
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/StatusBarWidgetBase.hpp => module-gui/gui/widgets/status-bar/StatusBarWidgetBase.hpp +4 -4
@@ 5,11 5,11 @@

#include <log/log.hpp>

namespace gui::top_bar
namespace gui::status_bar
{
    class SIM;
    class Time;
} // namespace gui::top_bar
} // namespace gui::status_bar

class StatusBarVisitor
{


@@ 19,11 19,11 @@ class StatusBarVisitor
    }

  public:
    virtual void visit([[maybe_unused]] gui::top_bar::SIM &widget) const
    virtual void visit([[maybe_unused]] gui::status_bar::SIM &widget) const
    {
        logError();
    }
    virtual void visit([[maybe_unused]] gui::top_bar::Time &widget) const
    virtual void visit([[maybe_unused]] gui::status_bar::Time &widget) const
    {
        logError();
    }

R module-gui/gui/widgets/TopBar/Style.hpp => module-gui/gui/widgets/status-bar/Style.hpp +0 -0
R module-gui/gui/widgets/TopBar/Time.cpp => module-gui/gui/widgets/status-bar/Time.cpp +3 -3
@@ 5,7 5,7 @@
#include "Style.hpp"

#include <ctime>
namespace gui::top_bar
namespace gui::status_bar
{
    Time::Time(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
        : StatusBarWidgetBase(parent, x, y, w, h), _time{}


@@ 43,11 43,11 @@ namespace gui::top_bar
        return mode;
    }

    void TimeConfiguration::visit(gui::top_bar::Time &widget) const
    void TimeConfiguration::visit(gui::status_bar::Time &widget) const
    {
        using namespace utils::time;
        getMode() == TimeConfiguration::TimeMode::Time12h
            ? widget.setFormat(Locale::format(Locale::TimeFormat::FormatTime12H))
            : widget.setFormat(Locale::format(Locale::TimeFormat::FormatTime24H));
    }
} // namespace gui::top_bar
} // namespace gui::status_bar

R module-gui/gui/widgets/TopBar/Time.hpp => module-gui/gui/widgets/status-bar/Time.hpp +3 -3
@@ 7,7 7,7 @@
#include <time/time_conversion.hpp>
#include <Label.hpp>

namespace gui::top_bar
namespace gui::status_bar
{

    /// Sets time mode (12h/24h) for Time widget


@@ 23,7 23,7 @@ namespace gui::top_bar
        explicit TimeConfiguration(TimeMode mode);

        [[nodiscard]] TimeMode getMode() const noexcept;
        void visit(gui::top_bar::Time &widget) const override;
        void visit(gui::status_bar::Time &widget) const override;

      private:
        TimeMode mode;


@@ 40,4 40,4 @@ namespace gui::top_bar
        void update();
        void acceptStatusBarVisitor(StatusBarVisitor &visitor) override;
    };
} // namespace gui::top_bar
} // namespace gui::status_bar

M module-gui/gui/widgets/visitor/GuiVisitor.hpp => module-gui/gui/widgets/visitor/GuiVisitor.hpp +12 -12
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 13,9 13,9 @@ namespace gui
    class BottomBar;
    class ListItem;

    namespace top_bar
    namespace status_bar
    {
        class TopBar;
        class StatusBar;
    }

    /// The general purpose abstract interface for enabling Double-Dispatch behavior throughout `gui::Item`'s


@@ 23,14 23,14 @@ namespace gui
    class GuiVisitor
    {
      public:
        virtual void visit(gui::Item &item)      = 0;
        virtual void visit(gui::Rect &item)      = 0;
        virtual void visit(gui::Text &item)      = 0;
        virtual void visit(gui::Window &item)    = 0;
        virtual void visit(gui::Label &item)     = 0;
        virtual void visit(gui::BottomBar &item) = 0;
        virtual void visit(gui::top_bar::TopBar &item) = 0;
        virtual void visit(gui::ListItem &item)        = 0;
        virtual ~GuiVisitor()                    = default;
        virtual void visit(gui::Item &item)                  = 0;
        virtual void visit(gui::Rect &item)                  = 0;
        virtual void visit(gui::Text &item)                  = 0;
        virtual void visit(gui::Window &item)                = 0;
        virtual void visit(gui::Label &item)                 = 0;
        virtual void visit(gui::BottomBar &item)             = 0;
        virtual void visit(gui::status_bar::StatusBar &item) = 0;
        virtual void visit(gui::ListItem &item)              = 0;
        virtual ~GuiVisitor()                                = default;
    };
} // namespace gui

M module-gui/test/test-catch-text/CMakeLists.txt => module-gui/test/test-catch-text/CMakeLists.txt +2 -1
@@ 1,4 1,4 @@
# gui tests
# gui tests
add_catch2_executable(
        NAME
                gui-text


@@ 25,4 25,5 @@ add_catch2_executable(
                module-gui
        DEPS
                assets
                PurePhone-disk-img
)

M module-gui/test/test-catch/CMakeLists.txt => module-gui/test/test-catch/CMakeLists.txt +2 -1
@@ 1,4 1,4 @@
# gui tests
# gui tests
add_catch2_executable(
        NAME
                gui


@@ 19,4 19,5 @@ add_catch2_executable(
                module-gui
        DEPS
                assets
                PurePhone-disk-img
)

M module-gui/test/test-google/test-gui-visitor-call.cpp => module-gui/test/test-google/test-gui-visitor-call.cpp +3 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "gtest/gtest.h"


@@ 11,7 11,7 @@
#include "Label.hpp"
#include "Window.hpp"
#include "BottomBar.hpp"
#include "TopBar.hpp"
#include "StatusBar.hpp"
#include "ListItem.hpp"

using ::testing::Matcher;


@@ 26,7 26,7 @@ class VisitorMock : public gui::GuiVisitor
    MOCK_METHOD1(visit, void(gui::Window &item));
    MOCK_METHOD1(visit, void(gui::Label &item));
    MOCK_METHOD1(visit, void(gui::BottomBar &item));
    MOCK_METHOD1(visit, void(gui::top_bar::TopBar &item));
    MOCK_METHOD1(visit, void(gui::status_bar::StatusBar &item));
    MOCK_METHOD1(visit, void(gui::ListItem &item));
};


M module-services/CMakeLists.txt => module-services/CMakeLists.txt +3 -2
@@ 47,8 47,9 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
    module-cellular
    module-audio
    service-fileindexer
        service-antenna
    ${TARGET_LIBRARIES} )
    service-antenna
    ${TARGET_LIBRARIES}
)

# Board specific compilation definitions,options,include directories and features
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_CONFIG_DEFINITIONS})

M module-services/service-cellular/CMakeLists.txt => module-services/service-cellular/CMakeLists.txt +2 -0
@@ 52,6 52,8 @@ target_link_libraries(${PROJECT_NAME}
        service-evtmgr
        module-bsp
        module-cellular
        Microsoft.GSL::GSL
        re2::re2
    )

if (${ENABLE_TESTS})

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +1 -74
@@ 92,7 92,7 @@
#include <vector>
#include "checkSmsCenter.hpp"
#include <service-desktop/Constants.hpp>
#include <gsl/gsl_util>
#include <gsl/util>
#include <ticks.hpp>

#include "ServiceCellularPriv.hpp"


@@ 467,9 467,6 @@ void ServiceCellular::registerMessageHandlers()
        return handleCellularCallerIdMessage(msg);
    });

    connect(typeid(CellularSimProcedureMessage),
            [&](sys::Message *request) -> sys::MessagePointer { return handleCellularSimProcedureMessage(request); });

    connect(typeid(CellularGetIMSIMessage),
            [&](sys::Message *request) -> sys::MessagePointer { return handleCellularGetIMSIMessage(request); });



@@ 639,12 636,6 @@ void ServiceCellular::change_state(cellular::StateChange *msg)
    case State::ST::SanityCheck:
        handle_sim_sanity_check();
        break;
    case State::ST::SimInit:
        handle_sim_init();
        break;
    case State::ST::SimSelect:
        handle_select_sim();
        break;
    case State::ST::ModemOn:
        handle_modem_on();
        break;


@@ 1386,42 1377,6 @@ bool ServiceCellular::handle_sim_sanity_check()
    return ret;
}

bool ServiceCellular::handle_select_sim()
{

    bsp::cellular::sim::simSelect();
    bsp::cellular::sim::hotSwapTrigger();
#if defined(TARGET_Linux)
    DLCChannel *channel = cmux->get(CellularMux::Channel::Commands);
    auto ret            = channel->cmd(at::AT::QSIMSTAT);
    if (!ret) {
        LOG_FATAL("Cant check sim stat status");
    }
    else {
        if (ret.response[0].find("+QSIMSTAT: 1,1") != std::string::npos) {
            // SIM IN - only sim1 mocup
            Store::GSM::get()->sim = Store::GSM::SIM::SIM1;
        }
        else {
            // NO SIM IN
            Store::GSM::get()->sim = Store::GSM::SIM::SIM_FAIL;
        }
        bus.sendUnicast(std::make_shared<sevm::SIMMessage>(), ::service::name::evt_manager);
        bool ready = false;
        while (!ready) {
            auto response = channel->cmd("AT+CPIN?");
            for (auto &line : response.response) {
                if (line.find("+CPIN: READY") == std::string::npos) {
                    ready = true;
                }
            }
        }
        priv->state->set(State::ST::SimInit);
    }
#endif
    return true;
}

bool ServiceCellular::handle_modem_on()
{
    auto channel = cmux->get(CellularMux::Channel::Commands);


@@ 1448,28 1403,6 @@ bool ServiceCellular::handle_URCReady()
    return ret;
}

bool ServiceCellular::handle_sim_init()
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (channel == nullptr) {
        LOG_ERROR("Cant configure sim! no Commands channel!");
        priv->state->set(State::ST::Failed);
        return false;
    }
    bool success  = true;
    auto commands = at::getCommadsSet(at::commadsSet::simInit);

    for (auto command : commands) {
        if (!channel->cmd(command)) {
            LOG_ERROR("SIM initialization failure!");
            return false;
        }
    }

    priv->state->set(State::ST::Ready);
    return success;
}

bool ServiceCellular::handleTextMessagesInit()
{
    auto channel = cmux->get(CellularMux::Channel::Commands);


@@ 2070,12 2003,6 @@ auto ServiceCellular::handleCellularCallerIdMessage(sys::Message *msg) -> std::s
    return sys::MessageNone{};
}

auto ServiceCellular::handleCellularSimProcedureMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
    priv->state->set(State::ST::SimSelect);
    return std::make_shared<CellularResponseMessage>(true);
}

auto ServiceCellular::handleCellularGetIMSIMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
    std::string temp;

M module-services/service-cellular/include/service-cellular/State.hpp => module-services/service-cellular/include/service-cellular/State.hpp +0 -2
@@ 28,8 28,6 @@ namespace cellular::service
            SanityCheck,                 /// prior to ModemOn last sanity checks for one time configurations etc
            ModemOn,   /// modem ready - indicates that modem is fully configured, ( **SIM is not yet configured** )
            URCReady,  /// State indicates that URC handling is enabled
            SimInit,   /// initialize sim card
            SimSelect, /// triggers hw SIM selection (! state now will be **changed on URC** )
            ModemFatalFailure, /// modem full shutdown need
            Failed,
            Ready,            /// Service is fully initialized

M module-services/service-cellular/include/service-cellular/api/notification/notification.hpp => module-services/service-cellular/include/service-cellular/api/notification/notification.hpp +3 -0
@@ 35,4 35,7 @@ namespace cellular::msg::notification
        const unsigned int code;
    };

    struct SimStateUpdate : public msg::Notification
    {};

} // namespace cellular::msg::notification

M module-services/service-cellular/service-cellular/CellularMessage.hpp => module-services/service-cellular/service-cellular/CellularMessage.hpp +0 -8
@@ 41,7 41,6 @@ class CellularMessage : public sys::DataMessage
        PowerStateChange, ///< Change power state of the module

        ListCurrentCalls,
        SimProcedure, // Broadcast on sim state changed
        SimResponse,  // Send to PIN window (show, error state, hide)
        SetVoLTE,
        SetFlightMode,


@@ 570,13 569,6 @@ class CellularListCallsMessage : public CellularMessage
    {}
};

class CellularSimProcedureMessage : public CellularMessage
{
  public:
    CellularSimProcedureMessage() : CellularMessage(Type::SimProcedure)
    {}
};

class CellularGetIMSIMessage : public CellularMessage
{
  public:

M module-services/service-cellular/service-cellular/ServiceCellular.hpp => module-services/service-cellular/service-cellular/ServiceCellular.hpp +0 -5
@@ 189,10 189,6 @@ class ServiceCellular : public sys::Service
    /// check one time modem configuration for sim (hot swap)
    /// if hot swap is not enabled full modem restart is needed (right now at best reboot)
    bool handle_sim_sanity_check();
    /// select sim from settings
    bool handle_select_sim();
    /// initialize sim (GSM commands for initialization)
    bool handle_sim_init();
    /// modem failure handler
    bool handle_failure();
    /// fatal failure handler, if we have power switch - we could handle it here


@@ 278,7 274,6 @@ class ServiceCellular : public sys::Service
    auto handleCellularRingingMessage(CellularRingingMessage *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularIncominCallMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularCallerIdMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularSimProcedureMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularGetIMSIMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularGetOwnNumberMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;
    auto handleCellularGetNetworkInfoMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>;

M module-services/service-cellular/src/ServiceCellularPriv.cpp => module-services/service-cellular/src/ServiceCellularPriv.cpp +18 -5
@@ 21,7 21,7 @@ namespace cellular::internal
    {
        using namespace cellular::msg;
        simCard->onSimReady = [this]() {
            state->set(State::ST::SimInit);
            state->set(State::ST::Ready);
            owner->bus.sendMulticast<notification::SimReady>();
        };
        simCard->onNeedPin = [this](unsigned int attempts) {


@@ 30,10 30,8 @@ namespace cellular::internal
        simCard->onNeedPuk = [this](unsigned int attempts) {
            owner->bus.sendMulticast<notification::SimNeedPuk>(attempts);
        };
        simCard->onSimBlocked = [this]() { owner->bus.sendMulticast<notification::SimBlocked>(); };
        simCard->onSimEvent = [this]() {
            owner->bus.sendUnicast(std::make_shared<sevm::SIMMessage>(), ::service::name::evt_manager);
        };
        simCard->onSimBlocked   = [this]() { owner->bus.sendMulticast<notification::SimBlocked>(); };
        simCard->onSimEvent     = [this]() { owner->bus.sendMulticast<notification::SimStateUpdate>(); };
        simCard->onUnhandledCME = [this](unsigned int code) {
            owner->bus.sendMulticast<notification::UnhandledCME>(code);
        };


@@ 42,6 40,9 @@ namespace cellular::internal
    void ServiceCellularPriv::connectSimCard()
    {
        using namespace cellular::msg;
        /**
         * Request message handlers
         */
        owner->connect(typeid(request::sim::SetActiveSim), [&](sys::Message *request) -> sys::MessagePointer {
            auto msg = static_cast<request::sim::SetActiveSim *>(request);
            return std::make_shared<request::sim::SetActiveSim::Response>(simCard->handleSetActiveSim(msg->sim));


@@ 67,6 68,18 @@ namespace cellular::internal
            auto msg = static_cast<request::sim::PinUnlock *>(request);
            return std::make_shared<request::sim::PinUnlock::Response>(simCard->handlePinUnlock(msg->pin));
        });

        /**
         * Notification message handlers
         */
        owner->connect(typeid(sevm::SIMTrayMessage), [&](sys::Message *request) -> sys::MessagePointer {
            simCard->handleTrayState();
            return sys::MessageNone{};
        });

        /**
         * Internal message handlers
         */
        owner->connect(typeid(internal::msg::HandleATSimStateChange),
                       [&](sys::Message *request) -> sys::MessagePointer {
                           auto msg = static_cast<internal::msg::HandleATSimStateChange *>(request);

M module-services/service-cellular/src/SimCard.cpp => module-services/service-cellular/src/SimCard.cpp +30 -3
@@ 94,13 94,40 @@ namespace cellular
            handleSimState(state);
        }

        void SimCard::handleTrayState()
        {
            bsp::cellular::sim::hotSwapTrigger();
            if (onSimEvent)
                onSimEvent();
        }

        bool SimCard::initSimCard()
        {
            if (!ready()) {
                return false;
            }

            for (const auto &command : at::getCommadsSet(at::commadsSet::simInit)) {
                if (!channel->cmd(command)) {
                    return false;
                }
            }
            return true;
        }

        void SimCard::handleSimState(at::SimState state)
        {
            switch (state) {
            case at::SimState::Ready:
                Store::GSM::get()->sim = Store::GSM::get()->selected;
                if (onSimReady)
                    onSimReady();
                if (initSimCard()) {
                    Store::GSM::get()->sim = Store::GSM::get()->selected;
                    if (onSimReady)
                        onSimReady();
                }
                else {
                    LOG_ERROR("SIM initialization failure!");
                    Store::GSM::get()->sim = Store::GSM::SIM::SIM_FAIL;
                }
                break;
            case at::SimState::NotReady:
                Store::GSM::get()->sim = Store::GSM::SIM::SIM_FAIL;

M module-services/service-cellular/src/SimCard.hpp => module-services/service-cellular/src/SimCard.hpp +11 -1
@@ 84,6 84,11 @@ namespace cellular::service
        bool handlePinUnlock(const api::SimCode &pin);

        /**
         * Notification message handlers
         */
        void handleTrayState();

        /**
         * Internal message handlers
         */
        void handleATSimStateChange(at::SimState state);


@@ 99,8 104,13 @@ namespace cellular::service
        std::function<void(unsigned int code)> onUnhandledCME;

      private:
        /** SIM card initialization sequence
         * \return true on success, false on failure
         */
        bool initSimCard();

        /** Get information about attempts of PIN and PUK for standard sim card (optionally PIN2/PUK2)
         * @return  As optional SimCard::AttemptsCounters, in case of error nullopt. Should be noted that in some case
         * \return  As optional SimCard::AttemptsCounters, in case of error nullopt. Should be noted that in some case
         * could return SIMFailure which could mean 0 attempts (happen if lock during session, on modem/sim reboot again
         * return 0,0);
         */

M module-services/service-cellular/src/State.cpp => module-services/service-cellular/src/State.cpp +0 -4
@@ 32,14 32,10 @@ namespace cellular::service
            return "ModemOn";
        case ST::URCReady:
            return "URCReady";
        case ST::SimSelect:
            return "SimSelect";
        case ST::Failed:
            return "Failed";
        case ST::SanityCheck:
            return "SanityCheck";
        case ST::SimInit:
            return "SimInit";
        case ST::ModemFatalFailure:
            return "ModemFatalFailure";
        case ST::CellularConfProcedure:

M module-services/service-db/test/CMakeLists.txt => module-services/service-db/test/CMakeLists.txt +1 -1
@@ 17,7 17,7 @@ add_catch2_executable(
            module-cellular
            iosyscalls
        DEPS
            disk_image
            PurePhone-disk-img
)

add_catch2_executable(

M module-services/service-db/test/test-settings/CMakeLists.txt => module-services/service-db/test/test-settings/CMakeLists.txt +2 -1
@@ 1,4 1,4 @@
# service-db tests
# service-db tests
add_catch2_executable(
        NAME
            service-db-settings


@@ 12,4 12,5 @@ add_catch2_executable(
            service-cellular
            module-cellular
        DEPS
            PurePhone-disk-img
)

M module-services/service-db/test/test-settings/Database.cpp => module-services/service-db/test/test-settings/Database.cpp +1 -1
@@ 6,7 6,7 @@
#include "log/log.hpp"

#include <purefs/filesystem_paths.hpp>
#include <gsl/gsl_util>
#include <gsl/util>

#include <cassert>
#include <cstring>

M module-services/service-desktop/CMakeLists.txt => module-services/service-desktop/CMakeLists.txt +1 -0
@@ 61,6 61,7 @@ target_link_libraries(${PROJECT_NAME}
        crc32
        microtar
        utils-bootconfig
        Microsoft.GSL::GSL
)

if (${ENABLE_TESTS})

M module-services/service-desktop/endpoints/backup/BackupRestore.cpp => module-services/service-desktop/endpoints/backup/BackupRestore.cpp +1 -1
@@ 18,7 18,7 @@
#include <string>
#include <vector>
#include <sys/statvfs.h>
#include <gsl>
#include <gsl/gsl>

namespace sys
{

M module-services/service-desktop/tests/CMakeLists.txt => module-services/service-desktop/tests/CMakeLists.txt +1 -1
@@ 13,7 13,7 @@ add_catch2_executable(
        module-apps
        iosyscalls
    DEPS
        disk_image
        PurePhone-disk-img
)

add_catch2_executable(

M module-services/service-eink/CMakeLists.txt => module-services/service-eink/CMakeLists.txt +1 -0
@@ 24,6 24,7 @@ add_library(${PROJECT_NAME} STATIC ${SOURCES})
target_link_libraries( ${PROJECT_NAME}
    module-utils
    service-gui
    Microsoft.GSL::GSL
)

target_include_directories(${PROJECT_NAME}

M module-services/service-eink/EinkDisplay.cpp => module-services/service-eink/EinkDisplay.cpp +1 -1
@@ 4,7 4,7 @@
#include "EinkDisplay.hpp"

#include <gui/core/Color.hpp>
#include <gsl/gsl_util>
#include <gsl/util>
#include <bsp/BoardDefinitions.hpp>
#include <cstdio>
#include <cstring>

M module-services/service-eink/ServiceEink.cpp => module-services/service-eink/ServiceEink.cpp +1 -1
@@ 18,7 18,7 @@

#include <cstring>
#include <memory>
#include <gsl_util>
#include <gsl/util>

namespace service::eink
{

M module-services/service-eink/board/linux/renderer/CMakeLists.txt => module-services/service-eink/board/linux/renderer/CMakeLists.txt +0 -2
@@ 43,5 43,3 @@ if(_target_link_flags)
	set_target_properties(${PROJECT_NAME} PROPERTIES LINK_OPTIONS "${_target_link_flags}")
endif()

add_dependencies(${CMAKE_PROJECT_NAME} service_renderer)


M module-services/service-eink/board/linux/renderer/src/RWindow.hpp => module-services/service-eink/board/linux/renderer/src/RWindow.hpp +1 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

M module-services/service-evtmgr/CMakeLists.txt => module-services/service-evtmgr/CMakeLists.txt +2 -0
@@ 11,6 11,7 @@ set(SOURCES
        battery-brownout-detector/BatteryBrownoutDetector.cpp
        screen-light-control/ControlFunctions.cpp
        screen-light-control/ScreenLightControl.cpp
        screen-light-control/ScreenLightControlParameters.cpp
        vibra/Vibra.cpp
)



@@ 33,6 34,7 @@ target_link_libraries(${PROJECT_NAME}
        service-cellular
        service-desktop
        sml::sml
        Microsoft.GSL::GSL
)

if (${ENABLE_TESTS})

M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +5 -4
@@ 31,7 31,6 @@
#include <service-appmgr/Controller.hpp>
#include <service-audio/AudioMessage.hpp>
#include <service-audio/AudioServiceAPI.hpp>
#include <service-cellular/CellularMessage.hpp>
#include <service-db/DBNotificationMessage.hpp>
#include <service-desktop/Constants.hpp>
#include <service-desktop/DesktopMessages.hpp>


@@ 143,9 142,6 @@ sys::MessagePointer EventManager::DataReceivedHandler(sys::DataMessage *msgl, sy
        AudioServiceAPI::SendEvent(this, msg->getEvent());
        handled = true;
    }
    else if (!targetApplication.empty() && dynamic_cast<sevm::SIMMessage *>(msgl) != nullptr) {
        bus.sendUnicast(std::make_shared<sevm::SIMMessage>(), targetApplication);
    }
    else if (msgl->messageType == MessageType::EVMGetBoard) {
        using namespace bsp;



@@ 282,6 278,11 @@ sys::ReturnCodes EventManager::InitHandler()
        return sys::MessageNone{};
    });

    connect(typeid(sevm::SIMTrayMessage), [&](sys::Message *) {
        bus.sendUnicast(std::make_shared<sevm::SIMTrayMessage>(), ServiceCellular::serviceName);
        return sys::MessageNone{};
    });

    connect(typeid(stm::message::UpdateRTCValueFromTmMessage), [&](sys::Message *msg) {
        auto message = static_cast<stm::message::UpdateRTCValueFromTmMessage *>(msg);
        processRTCFromTmRequest(message->getTime());

M module-services/service-evtmgr/WorkerEvent.cpp => module-services/service-evtmgr/WorkerEvent.cpp +1 -2
@@ 21,7 21,6 @@
#include <bsp/light_sensor/light_sensor.hpp>
#include <bsp/vibrator/vibrator.hpp>
#include <bsp/eink_frontlight/eink_frontlight.hpp>
#include <common_data/EventStore.hpp>
#include <common_data/RawKey.hpp>
#include <headset.hpp>
#include <log/log.hpp>


@@ 148,7 147,7 @@ bool WorkerEvent::handleMessage(uint32_t queueID)
        if (notification == bsp::cellular::trayPin) {
            Store::GSM::Tray pinstate = bsp::cellular::sim::getTray();
            LOG_DEBUG("SIM state change: %d", static_cast<int>(pinstate));
            bsp::cellular::sim::hotSwapTrigger();
            service->bus.sendUnicast(std::make_shared<sevm::SIMTrayMessage>(), service::name::evt_manager);
        }

        if (notification == bsp::cellular::ringIndicatorPin) {

M module-services/service-evtmgr/doc/battery_status_notification.svg => module-services/service-evtmgr/doc/battery_status_notification.svg +10 -10
@@ 1,11 1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="486px" preserveAspectRatio="none" style="width:1340px;height:486px;" version="1.1" viewBox="0 0 1340 486" width="1340px" zoomAndPan="magnify"><defs><filter height="300%" id="f1uj3fz6xy4wx1" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><rect fill="#FFFFFF" filter="url(#f1uj3fz6xy4wx1)" height="103.5313" style="stroke:#000000;stroke-width:2.0;" width="468.5" x="411.5" y="190.125"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="68" x2="68" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="263" x2="263" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="481.5" x2="481.5" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="700.5" x2="700.5" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="875" x2="875" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="1001" x2="1001" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="1162.5" x2="1162.5" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="1281.5" x2="1281.5" y1="56.5938" y2="427.1875"/><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="122" x="5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="108" x="12" y="41.292">Battery Charger</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="122" x="5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="108" x="12" y="446.1826">Battery Charger</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="106" x="208" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="92" x="215" y="41.292">Worker Event</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="106" x="208" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="92" x="215" y="446.1826">Worker Event</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="117" x="421.5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="103" x="428.5" y="41.292">Event Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="117" x="421.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="103" x="428.5" y="446.1826">Event Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="129" x="634.5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="641.5" y="41.292">System Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="129" x="634.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="641.5" y="446.1826">System Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="144" x="801" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="130" x="808" y="41.292">Current application</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="144" x="801" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="130" x="808" y="446.1826">Current application</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="64" x="967" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="974" y="41.292">TopBar</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="64" x="967" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="974" y="446.1826">TopBar</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="115" x="1103.5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="101" x="1110.5" y="41.292">Battery Widget</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="115" x="1103.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="101" x="1110.5" y="446.1826">Battery Widget</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="46.5938" style="stroke:#A80036;stroke-width:1.5;" width="94" x="1232.5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="80" x="1239.5" y="24.9951">Event Store</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="1255" y="41.292">Battery</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="46.5938" style="stroke:#A80036;stroke-width:1.5;" width="94" x="1232.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="80" x="1239.5" y="446.1826">Event Store</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="1255" y="462.4795">Battery</text><polygon fill="#A80036" points="251,83.7266,261,87.7266,251,91.7266,255,87.7266" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="68" x2="257" y1="87.7266" y2="87.7266"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="55" x="75" y="82.6606">Interrupt</text><polygon fill="#A80036" points="79,112.8594,69,116.8594,79,120.8594,75,116.8594" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="73" x2="262" y1="116.8594" y2="116.8594"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="171" x="85" y="111.7935">Store status to EventStore</text><polygon fill="#A80036" points="1269.5,141.9922,1279.5,145.9922,1269.5,149.9922,1273.5,145.9922" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="68" x2="1275.5" y1="145.9922" y2="145.9922"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="53" x="75" y="140.9263">modify()</text><polygon fill="#A80036" points="470,171.125,480,175.125,470,179.125,474,175.125" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="263" x2="476" y1="175.125" y2="175.125"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="195" x="270" y="170.0591">BatteryStatusChangeMessage</text><path d="M411.5,190.125 L559.5,190.125 L559.5,197.125 L549.5,207.125 L411.5,207.125 L411.5,190.125 " fill="#EEEEEE" style="stroke:#000000;stroke-width:1.0;"/><rect fill="none" height="103.5313" style="stroke:#000000;stroke-width:2.0;" width="468.5" x="411.5" y="190.125"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="103" x="426.5" y="203.1919">If Discharging</text><polygon fill="#A80036" points="689,224.3906,699,228.3906,689,232.3906,693,228.3906" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="482" x2="695" y1="228.3906" y2="228.3906"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="195" x="489" y="223.3247">BatteryStatusChangeMessage</text><line style="stroke:#A80036;stroke-width:1.0;" x1="701" x2="743" y1="272.6563" y2="272.6563"/><line style="stroke:#A80036;stroke-width:1.0;" x1="743" x2="743" y1="272.6563" y2="285.6563"/><line style="stroke:#A80036;stroke-width:1.0;" x1="702" x2="743" y1="285.6563" y2="285.6563"/><polygon fill="#A80036" points="712,281.6563,702,285.6563,712,289.6563,708,285.6563" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="160" x="708" y="252.4575">If State::ShutdownReady:</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="154" x="712" y="267.5903">state = State:Shutdown</text><polygon fill="#A80036" points="863,317.7891,873,321.7891,863,325.7891,867,321.7891" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="482" x2="869" y1="321.7891" y2="321.7891"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="195" x="489" y="316.7231">BatteryStatusChangeMessage</text><polygon fill="#A80036" points="989,346.9219,999,350.9219,989,354.9219,993,350.9219" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="875" x2="995" y1="350.9219" y2="350.9219"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="102" x="882" y="345.856">updateBattery()</text><polygon fill="#A80036" points="1012,376.0547,1002,380.0547,1012,384.0547,1008,380.0547" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="1269.5,376.0547,1279.5,380.0547,1269.5,384.0547,1273.5,380.0547" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="1006" x2="1275.5" y1="380.0547" y2="380.0547"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="31" x="1018" y="374.9888">get()</text><polygon fill="#A80036" points="1151,405.1875,1161,409.1875,1151,413.1875,1155,409.1875" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="1001" x2="1157" y1="409.1875" y2="409.1875"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="138" x="1008" y="404.1216">show(batteryContext)</text><!--MD5=[c6c243b94a88456e8572e27fdc18c06d]
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="486px" preserveAspectRatio="none" style="width:1340px;height:486px;" version="1.1" viewBox="0 0 1340 486" width="1340px" zoomAndPan="magnify"><defs><filter height="300%" id="f1uj3fz6xy4wx1" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><rect fill="#FFFFFF" filter="url(#f1uj3fz6xy4wx1)" height="103.5313" style="stroke:#000000;stroke-width:2.0;" width="468.5" x="411.5" y="190.125"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="68" x2="68" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="263" x2="263" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="481.5" x2="481.5" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="700.5" x2="700.5" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="875" x2="875" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="1001" x2="1001" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="1162.5" x2="1162.5" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="1281.5" x2="1281.5" y1="56.5938" y2="427.1875"/><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="122" x="5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="108" x="12" y="41.292">Battery Charger</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="122" x="5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="108" x="12" y="446.1826">Battery Charger</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="106" x="208" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="92" x="215" y="41.292">Worker Event</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="106" x="208" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="92" x="215" y="446.1826">Worker Event</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="117" x="421.5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="103" x="428.5" y="41.292">Event Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="117" x="421.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="103" x="428.5" y="446.1826">Event Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="129" x="634.5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="641.5" y="41.292">System Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="129" x="634.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="641.5" y="446.1826">System Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="144" x="801" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="130" x="808" y="41.292">Current application</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="144" x="801" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="130" x="808" y="446.1826">Current application</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="64" x="967" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="974" y="41.292">StatusBar</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="64" x="967" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="974" y="446.1826">StatusBar</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="115" x="1103.5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="101" x="1110.5" y="41.292">Battery Widget</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="115" x="1103.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="101" x="1110.5" y="446.1826">Battery Widget</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="46.5938" style="stroke:#A80036;stroke-width:1.5;" width="94" x="1232.5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="80" x="1239.5" y="24.9951">Event Store</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="1255" y="41.292">Battery</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="46.5938" style="stroke:#A80036;stroke-width:1.5;" width="94" x="1232.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="80" x="1239.5" y="446.1826">Event Store</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="1255" y="462.4795">Battery</text><polygon fill="#A80036" points="251,83.7266,261,87.7266,251,91.7266,255,87.7266" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="68" x2="257" y1="87.7266" y2="87.7266"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="55" x="75" y="82.6606">Interrupt</text><polygon fill="#A80036" points="79,112.8594,69,116.8594,79,120.8594,75,116.8594" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="73" x2="262" y1="116.8594" y2="116.8594"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="171" x="85" y="111.7935">Store status to EventStore</text><polygon fill="#A80036" points="1269.5,141.9922,1279.5,145.9922,1269.5,149.9922,1273.5,145.9922" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="68" x2="1275.5" y1="145.9922" y2="145.9922"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="53" x="75" y="140.9263">modify()</text><polygon fill="#A80036" points="470,171.125,480,175.125,470,179.125,474,175.125" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="263" x2="476" y1="175.125" y2="175.125"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="195" x="270" y="170.0591">BatteryStatusChangeMessage</text><path d="M411.5,190.125 L559.5,190.125 L559.5,197.125 L549.5,207.125 L411.5,207.125 L411.5,190.125 " fill="#EEEEEE" style="stroke:#000000;stroke-width:1.0;"/><rect fill="none" height="103.5313" style="stroke:#000000;stroke-width:2.0;" width="468.5" x="411.5" y="190.125"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="103" x="426.5" y="203.1919">If Discharging</text><polygon fill="#A80036" points="689,224.3906,699,228.3906,689,232.3906,693,228.3906" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="482" x2="695" y1="228.3906" y2="228.3906"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="195" x="489" y="223.3247">BatteryStatusChangeMessage</text><line style="stroke:#A80036;stroke-width:1.0;" x1="701" x2="743" y1="272.6563" y2="272.6563"/><line style="stroke:#A80036;stroke-width:1.0;" x1="743" x2="743" y1="272.6563" y2="285.6563"/><line style="stroke:#A80036;stroke-width:1.0;" x1="702" x2="743" y1="285.6563" y2="285.6563"/><polygon fill="#A80036" points="712,281.6563,702,285.6563,712,289.6563,708,285.6563" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="160" x="708" y="252.4575">If State::ShutdownReady:</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="154" x="712" y="267.5903">state = State:Shutdown</text><polygon fill="#A80036" points="863,317.7891,873,321.7891,863,325.7891,867,321.7891" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="482" x2="869" y1="321.7891" y2="321.7891"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="195" x="489" y="316.7231">BatteryStatusChangeMessage</text><polygon fill="#A80036" points="989,346.9219,999,350.9219,989,354.9219,993,350.9219" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="875" x2="995" y1="350.9219" y2="350.9219"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="102" x="882" y="345.856">updateBattery()</text><polygon fill="#A80036" points="1012,376.0547,1002,380.0547,1012,384.0547,1008,380.0547" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="1269.5,376.0547,1279.5,380.0547,1269.5,384.0547,1273.5,380.0547" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="1006" x2="1275.5" y1="380.0547" y2="380.0547"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="31" x="1018" y="374.9888">get()</text><polygon fill="#A80036" points="1151,405.1875,1161,409.1875,1151,413.1875,1155,409.1875" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="1001" x2="1157" y1="409.1875" y2="409.1875"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="138" x="1008" y="404.1216">show(batteryContext)</text><!--MD5=[c6c243b94a88456e8572e27fdc18c06d]
@startuml
participant "Battery Charger" as bc
participant "Worker Event" as we
participant "Event Manager" as evm
participant "System Manager" as sm
participant "Current application" as ca
participant "TopBar" as tb
participant "StatusBar" as tb
participant "Battery Widget" as bw
participant "Event Store\nBattery" as es



@@ 23,12 23,12 @@ tb <-> es : get()
tb -> bw : show(batteryContext)

@enduml

PlantUML version 1.2021.00(Sun Jan 10 11:25:05 CET 2021)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Default Encoding: UTF-8
Language: pl
Country: PL

PlantUML version 1.2021.00(Sun Jan 10 11:25:05 CET 2021)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Default Encoding: UTF-8
Language: pl
Country: PL
--></g></svg>
\ No newline at end of file

M module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp => module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp +1 -0
@@ 2,6 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ScreenLightControl.hpp"
#include "ScreenLightControlParameters.hpp"
#include <module-sys/Timers/TimerFactory.hpp>
#include <Service/Service.hpp>


A module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.cpp => module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.cpp +21 -0
@@ 0,0 1,21 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ScreenLightControlParameters.hpp"

#include <gsl/assert>

namespace screen_light_control
{
    auto Parameters::getAutoModeParams() const noexcept -> const AutomaticModeParameters &
    {
        Expects(hasAutoModeParams());
        return autoModeParams.value();
    }

    auto Parameters::getManualModeParams() const noexcept -> ManualModeParameters
    {
        Expects(hasManualModeParams());
        return manualModeParams.value();
    }
} // namespace screen_light_control

M module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp => module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp +2 -11
@@ 4,7 4,6 @@
#pragma once

#include "ControlFunctions.hpp"
#include <gsl_assert>
#include <optional>

namespace screen_light_control


@@ 67,21 66,13 @@ namespace screen_light_control
            return manualModeParams.has_value();
        }

        [[nodiscard]] auto getManualModeParams() const noexcept -> ManualModeParameters
        {
            Expects(hasManualModeParams());
            return manualModeParams.value();
        }
        [[nodiscard]] auto getManualModeParams() const noexcept -> ManualModeParameters;

        [[nodiscard]] bool hasAutoModeParams() const noexcept
        {
            return autoModeParams.has_value();
        }

        [[nodiscard]] auto getAutoModeParams() const noexcept -> const AutomaticModeParameters &
        {
            Expects(hasAutoModeParams());
            return autoModeParams.value();
        }
        [[nodiscard]] auto getAutoModeParams() const noexcept -> const AutomaticModeParameters &;
    };
} // namespace screen_light_control

M module-services/service-evtmgr/service-evtmgr/EVMessages.hpp => module-services/service-evtmgr/service-evtmgr/EVMessages.hpp +2 -2
@@ 40,10 40,10 @@ namespace sevm
        uint32_t timestamp = 0;
    };

    class SIMMessage : public sys::DataMessage
    class SIMTrayMessage : public sys::DataMessage
    {
      public:
        SIMMessage() : DataMessage(MessageType::SIMTrayEvent)
        SIMTrayMessage() : DataMessage(MessageType::SIMTrayEvent)
        {}
    };
    /*

M module-services/service-gui/ServiceGUI.cpp => module-services/service-gui/ServiceGUI.cpp +1 -1
@@ 20,7 20,7 @@
#include <Timers/TimerFactory.hpp>
#include <SystemManager/SystemManager.hpp>

#include <gsl/gsl_util>
#include <gsl/util>
#include <purefs/filesystem_paths.hpp>

namespace service::gui

M module-sys/CMakeLists.txt => module-sys/CMakeLists.txt +7 -3
@@ 51,14 51,18 @@ target_include_directories(bus PRIVATE ${BOARD_DIR_INCLUDES})
target_include_directories(bus PRIVATE ${PROJECT_INCLUDES})
target_link_options(bus PRIVATE ${TARGET_LINK_OPTIONS})

add_library(${PROJECT_NAME} STATIC ${SOURCES} ${BOARD_SOURCES})
add_library(module-sys)
target_sources(module-sys PRIVATE ${SOURCES} ${BOARD_SOURCES})

target_link_libraries(${PROJECT_NAME}
target_link_libraries(module-sys
    PRIVATE
        bus
        service-evtmgr
        messagetype
        magic_enum
    PUBLIC
        module-os)
        module-os
    )

# Board specific compilation definitions,options,include directories and features
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_CONFIG_DEFINITIONS})

M module-sys/Service/Message.hpp => module-sys/Service/Message.hpp +3 -2
@@ 3,11 3,12 @@

#pragma once

#include <magic_enum.hpp>
#include "Common.hpp"
#include "MessageType.hpp"
#include "MessageForward.hpp"

#include <MessageType.hpp>
#include <magic_enum.hpp>

#include <cstdint>
#include <memory>
#include <string>

M module-utils/CMakeLists.txt => module-utils/CMakeLists.txt +0 -2
@@ 49,7 49,6 @@ add_library(${PROJECT_NAME} STATIC ${SOURCES} ${BOARD_SOURCES})
include(segger/rtt/CMakeLists.txt)

# add third party libs
include(third-party/re2.cmake)
include(third-party/libphonenumber.cmake)

# link against libphonenumber


@@ 81,7 80,6 @@ target_include_directories(${PROJECT_NAME}
        PUBLIC

        ${CMAKE_CURRENT_SOURCE_DIR}
        ${CMAKE_CURRENT_SOURCE_DIR}/gsl
)

if((${PROJECT_TARGET} STREQUAL "TARGET_RT1051") AND (${SYSTEM_VIEW_ENABLED}))

D module-utils/CrashDebug => module-utils/CrashDebug +0 -1
@@ 1,1 0,0 @@
Subproject commit 0104eb5480d9213d9fe944f13958f785a311a191

M module-utils/board/cross/log_rt1051.cpp => module-utils/board/cross/log_rt1051.cpp +0 -1
@@ 3,7 3,6 @@

#include <board.h>
#include <critical.hpp>
#include <gsl/gsl_util>
#include <macros.h>
#include "log/log.hpp"
#include "log/Logger.hpp"

M module-utils/bootconfig/CMakeLists.txt => module-utils/bootconfig/CMakeLists.txt +1 -0
@@ 21,4 21,5 @@ target_link_libraries( ${PROJECT_NAME}
      module-utils
      module-vfs
      crc32
      Microsoft.GSL::GSL
)

M module-utils/bootconfig/src/bootconfig.cpp => module-utils/bootconfig/src/bootconfig.cpp +1 -1
@@ 3,7 3,7 @@
#include <boot/bootconfig.hpp>
#include <boot/bootconstants.hpp>

#include <module-utils/gsl/gsl_util>
#include <gsl/util>
#include <limits.h>
#include <purefs/filesystem_paths.hpp>
#include <source/version.hpp>

D module-utils/gsl/gsl => module-utils/gsl/gsl +0 -29
@@ 1,29 0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef GSL_GSL_H
#define GSL_GSL_H

#include <gsl/gsl_algorithm> // copy
#include <gsl/gsl_assert>    // Ensures/Expects
#include <gsl/gsl_byte>      // byte
#include <gsl/gsl_util>      // finally()/narrow()/narrow_cast()...
#include <gsl/multi_span>    // multi_span, strided_span...
#include <gsl/pointers>      // owner, not_null
#include <gsl/span>          // span
#include <gsl/string_span>   // zstring, string_span, zstring_builder...

#endif // GSL_GSL_H

D module-utils/gsl/gsl_algorithm => module-utils/gsl/gsl_algorithm +0 -61
@@ 1,61 0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef GSL_ALGORITHM_H
#define GSL_ALGORITHM_H

#include <gsl/gsl_assert> // for Expects
#include <gsl/span>       // for dynamic_extent, span

#include <algorithm>   // for copy_n
#include <cstddef>     // for ptrdiff_t
#include <type_traits> // for is_assignable

#ifdef _MSC_VER
#pragma warning(push)

// turn off some warnings that are noisy about our Expects statements
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4996) // unsafe use of std::copy_n

#endif // _MSC_VER

namespace gsl
{
// Note: this will generate faster code than std::copy using span iterator in older msvc+stl
// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915)
template <class SrcElementType, std::ptrdiff_t SrcExtent, class DestElementType,
          std::ptrdiff_t DestExtent>
void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest)
{
    static_assert(std::is_assignable<decltype(*dest.data()), decltype(*src.data())>::value,
                  "Elements of source span can not be assigned to elements of destination span");
    static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent ||
                      (SrcExtent <= DestExtent),
                  "Source range is longer than target range");

    Expects(dest.size() >= src.size());
    GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute
    std::copy_n(src.data(), src.size(), dest.data());
}

} // namespace gsl

#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER

#endif // GSL_ALGORITHM_H

D module-utils/gsl/gsl_assert => module-utils/gsl/gsl_assert +0 -177
@@ 1,177 0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef GSL_CONTRACTS_H
#define GSL_CONTRACTS_H

#include <exception>
#include <stdexcept> // for logic_error

//
// make suppress attributes parse for some compilers
// Hopefully temporary until suppression standardization occurs
//
#if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else
#if defined(_MSC_VER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x)
#endif // _MSC_VER
#endif // __clang__

//
// Temporary until MSVC STL supports no-exceptions mode.
// Currently terminate is a no-op in this mode, so we add termination behavior back
//
#if defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
#include <intrin.h>
#define RANGE_CHECKS_FAILURE 0

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winvalid-noreturn"
#endif

#endif

//
// There are three configuration options for this GSL implementation's behavior
// when pre/post conditions on the GSL types are violated:
//
// 1. GSL_TERMINATE_ON_CONTRACT_VIOLATION: std::terminate will be called (default)
// 2. GSL_THROW_ON_CONTRACT_VIOLATION: a gsl::fail_fast exception will be thrown
// 3. GSL_UNENFORCED_ON_CONTRACT_VIOLATION: nothing happens
//
#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) || defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) ||  \
      defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION))
#define GSL_TERMINATE_ON_CONTRACT_VIOLATION
#endif

#define GSL_STRINGIFY_DETAIL(x) #x
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)

#if defined(__clang__) || defined(__GNUC__)
#define GSL_LIKELY(x) __builtin_expect(!!(x), 1)
#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define GSL_LIKELY(x) (!!(x))
#define GSL_UNLIKELY(x) (!!(x))
#endif

//
// GSL_ASSUME(cond)
//
// Tell the optimizer that the predicate cond must hold. It is unspecified
// whether or not cond is actually evaluated.
//
#ifdef _MSC_VER
#define GSL_ASSUME(cond) __assume(cond)
#elif defined(__GNUC__)
#define GSL_ASSUME(cond) ((cond) ? static_cast<void>(0) : __builtin_unreachable())
#else
#define GSL_ASSUME(cond) static_cast<void>((cond) ? 0 : 0)
#endif

//
// GSL.assert: assertions
//

namespace gsl
{
struct fail_fast : public std::logic_error
{
    explicit fail_fast(char const* const message) : std::logic_error(message) {}
};

namespace details
{
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)

    typedef void  (__cdecl *terminate_handler)();

    GSL_SUPPRESS(f.6) // NO-FORMAT: attribute
    [[noreturn]] inline void __cdecl default_terminate_handler()
    {
        __fastfail(RANGE_CHECKS_FAILURE);
    }

    inline gsl::details::terminate_handler& get_terminate_handler() noexcept
    {
        static terminate_handler handler = &default_terminate_handler;
        return handler;
    }

#endif

    [[noreturn]] inline void terminate() noexcept
    {
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
        (*gsl::details::get_terminate_handler())();
#else
        std::terminate();
#endif
    }

#if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)

    template <typename Exception>
    [[noreturn]] void throw_exception(Exception&&) noexcept
    {
        gsl::details::terminate();
    }

#else

    template <typename Exception>
    [[noreturn]] void throw_exception(Exception&& exception)
    {
        throw std::forward<Exception>(exception);
    }

#endif // GSL_TERMINATE_ON_CONTRACT_VIOLATION

} // namespace details
} // namespace gsl

#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)

#define GSL_CONTRACT_CHECK(type, cond)                                                             \
    (GSL_LIKELY(cond) ? static_cast<void>(0)                                                       \
                      : gsl::details::throw_exception(gsl::fail_fast(                              \
                            "GSL: " type " failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__))))

#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)

#define GSL_CONTRACT_CHECK(type, cond)                                                             \
    (GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())

#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)

#define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond)

#endif // GSL_THROW_ON_CONTRACT_VIOLATION

#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond)
#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)

#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__)
#pragma clang diagnostic pop
#endif

#endif // GSL_CONTRACTS_H

D module-utils/gsl/gsl_byte => module-utils/gsl/gsl_byte +0 -203
@@ 1,203 0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef GSL_BYTE_H
#define GSL_BYTE_H

//
// make suppress attributes work for some compilers
// Hopefully temporary until suppression standardization occurs
//
#if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else
#if defined(_MSC_VER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x)
#endif // _MSC_VER
#endif // __clang__

#include <type_traits>

#ifdef _MSC_VER

#pragma warning(push)

// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates does not always work

#ifndef GSL_USE_STD_BYTE
// this tests if we are under MSVC and the standard lib has std::byte and it is enabled
#if defined(_HAS_STD_BYTE) && _HAS_STD_BYTE

#define GSL_USE_STD_BYTE 1

#else // defined(_HAS_STD_BYTE) && _HAS_STD_BYTE

#define GSL_USE_STD_BYTE 0

#endif // defined(_HAS_STD_BYTE) && _HAS_STD_BYTE
#endif // GSL_USE_STD_BYTE

#else // _MSC_VER

#ifndef GSL_USE_STD_BYTE
// this tests if we are under GCC or Clang with enough -std:c++1z power to get us std::byte
// also check if libc++ version is sufficient (> 5.0) or libstc++ actually contains std::byte
#if defined(__cplusplus) && (__cplusplus >= 201703L) && \
  (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603)  || \
   defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))

#define GSL_USE_STD_BYTE 1
#include <cstddef>

#else // defined(__cplusplus) && (__cplusplus >= 201703L) &&
      //   (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603)  ||
      //    defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))

#define GSL_USE_STD_BYTE 0

#endif //defined(__cplusplus) && (__cplusplus >= 201703L) &&
       //   (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603)  ||
       //    defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#endif // GSL_USE_STD_BYTE

#endif // _MSC_VER

// Use __may_alias__ attribute on gcc and clang
#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5)
#define byte_may_alias __attribute__((__may_alias__))
#else // defined __clang__ || defined __GNUC__
#define byte_may_alias
#endif // defined __clang__ || defined __GNUC__

namespace gsl
{
#if GSL_USE_STD_BYTE

using std::byte;
using std::to_integer;

#else // GSL_USE_STD_BYTE

// This is a simple definition for now that allows
// use of byte within span<> to be standards-compliant
enum class byte_may_alias byte : unsigned char
{
};

template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
{
    return b = byte(static_cast<unsigned char>(b) << shift);
}

template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator<<(byte b, IntegerType shift) noexcept
{
    return byte(static_cast<unsigned char>(b) << shift);
}

template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
{
    return b = byte(static_cast<unsigned char>(b) >> shift);
}

template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator>>(byte b, IntegerType shift) noexcept
{
    return byte(static_cast<unsigned char>(b) >> shift);
}

constexpr byte& operator|=(byte& l, byte r) noexcept
{
    return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}

constexpr byte operator|(byte l, byte r) noexcept
{
    return byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}

constexpr byte& operator&=(byte& l, byte r) noexcept
{
    return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}

constexpr byte operator&(byte l, byte r) noexcept
{
    return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}

constexpr byte& operator^=(byte& l, byte r) noexcept
{
    return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}

constexpr byte operator^(byte l, byte r) noexcept
{
    return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}

constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); }

template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr IntegerType to_integer(byte b) noexcept
{
    return static_cast<IntegerType>(b);
}

#endif // GSL_USE_STD_BYTE

template <bool E, typename T>
constexpr byte to_byte_impl(T t) noexcept
{
    static_assert(
        E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. "
           "If you are calling to_byte with an integer contant use: gsl::to_byte<t>() version.");
    return static_cast<byte>(t);
}
template <>
// NOTE: need suppression since c++14 does not allow "return {t}"
// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work
constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept
{
    return byte(t);
}

template <typename T>
constexpr byte to_byte(T t) noexcept
{
    return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t);
}

template <int I>
constexpr byte to_byte() noexcept
{
    static_assert(I >= 0 && I <= 255,
                  "gsl::byte only has 8 bits of storage, values must be in range 0-255");
    return static_cast<byte>(I);
}

} // namespace gsl

#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER

#endif // GSL_BYTE_H

D module-utils/gsl/gsl_util => module-utils/gsl/gsl_util +0 -175
@@ 1,175 0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef GSL_UTIL_H
#define GSL_UTIL_H

#include <gsl/gsl_assert> // for Expects

#include <array>
#include <cstddef>          // for ptrdiff_t, size_t
#include <exception>        // for exception
#include <initializer_list> // for initializer_list
#include <type_traits>      // for is_signed, integral_constant
#include <utility>          // for forward

#if defined(_MSC_VER) && !defined(__clang__)

#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant

#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
#endif            // _MSC_VER < 1910
#endif            // _MSC_VER

#if (defined(_MSC_VER) && _MSC_VER < 1910) || (!defined(__clang__) && defined(__GNUC__) && __GUNC__ < 6)
#define GSL_CONSTEXPR_NARROW 0
#else
#define GSL_CONSTEXPR_NARROW 1
#endif

namespace gsl
{
//
// GSL.util: utilities
//

// index type for all container indexes/subscripts/sizes
using index = std::ptrdiff_t;

// final_action allows you to ensure something gets run at the end of a scope
template <class F>
class final_action
{
public:
    explicit final_action(F f) noexcept : f_(std::move(f)) {}

    final_action(final_action&& other) noexcept : f_(std::move(other.f_)), invoke_(other.invoke_)
    {
        other.invoke_ = false;
    }

    final_action(const final_action&) = delete;
    final_action& operator=(const final_action&) = delete;
    final_action& operator=(final_action&&) = delete;

    GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws
    ~final_action() noexcept
    {
        if (invoke_) f_();
    }

private:
    F f_;
    bool invoke_{true};
};

// finally() - convenience function to generate a final_action
template <class F>
final_action<F> finally(const F& f) noexcept
{
    return final_action<F>(f);
}

template <class F>
final_action<F> finally(F&& f) noexcept
{
    return final_action<F>(std::forward<F>(f));
}

// narrow_cast(): a searchable way to do narrowing casts of values
template <class T, class U>
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
constexpr T narrow_cast(U&& u) noexcept
{
    return static_cast<T>(std::forward<U>(u));
}

struct narrowing_error : public std::exception
{
};

namespace details
{
    template <class T, class U>
    struct is_same_signedness
        : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>
    {
    };
} // namespace details

// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U>
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
#if GSL_CONSTEXPR_NARROW
constexpr
#endif
T narrow(U u) noexcept(false)
{
    T t = narrow_cast<T>(u);
    if (static_cast<U>(t) != u) gsl::details::throw_exception(narrowing_error());
    if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))
        gsl::details::throw_exception(narrowing_error());
    return t;
}

//
// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
//
template <class T, std::size_t N>
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
constexpr T& at(T (&arr)[N], const index i)
{
    Expects(i >= 0 && i < narrow_cast<index>(N));
    return arr[narrow_cast<std::size_t>(i)];
}

template <class Cont>
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
{
    Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
    using size_type = decltype(cont.size());
    return cont[narrow_cast<size_type>(i)];
}

template <class T>
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr T at(const std::initializer_list<T> cont, const index i)
{
    Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
    return *(cont.begin() + i);
}

} // namespace gsl

#if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER < 1910
#undef constexpr
#pragma pop_macro("constexpr")

#endif // _MSC_VER < 1910

#pragma warning(pop)

#endif // _MSC_VER

#endif // GSL_UTIL_H

D module-utils/gsl/multi_span => module-utils/gsl/multi_span +0 -2293
@@ 1,2293 0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef GSL_MULTI_SPAN_H
#define GSL_MULTI_SPAN_H

#include <gsl/gsl_assert> // for Expects
#include <gsl/gsl_byte>   // for byte
#include <gsl/gsl_util>   // for narrow_cast

#include <algorithm> // for transform, lexicographical_compare
#include <array>     // for array
#include <cassert>
#include <cstddef>          // for ptrdiff_t, size_t, nullptr_t
#include <cstdint>          // for PTRDIFF_MAX
#include <functional>       // for divides, multiplies, minus, negate, plus
#include <initializer_list> // for initializer_list
#include <iterator>         // for iterator, random_access_iterator_tag
#include <limits>           // for numeric_limits
#include <new>
#include <numeric>
#include <stdexcept>
#include <string>      // for basic_string
#include <type_traits> // for enable_if_t, remove_cv_t, is_same, is_co...
#include <utility>

#if defined(_MSC_VER) && !defined(__clang__)

// turn off some warnings that are noisy about our Expects statements
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4702) // unreachable code

// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
#pragma warning(disable : 26495) // uninitalized member when constructor calls constructor
#pragma warning(disable : 26473) // in some instantiations we cast to the same type
#pragma warning(disable : 26490) // TODO: bug in parser - attributes and templates
#pragma warning(disable : 26465) // TODO: bug - suppression does not work on template functions

#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/

#endif                          // _MSC_VER < 1910
#endif                          // _MSC_VER

// GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t)
// While there is a conversion from signed to unsigned, it happens at
// compiletime, so the compiler wouldn't have to warn indiscriminently, but
// could check if the source value actually doesn't fit into the target type
// and only warn in those cases.
#if defined(__GNUC__) && __GNUC__ > 6
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif

namespace gsl
{

/*
** begin definitions of index and bounds
*/
namespace details
{
    template <typename SizeType>
    struct SizeTypeTraits
    {
        static const SizeType max_value = std::numeric_limits<SizeType>::max();
    };

    template <typename... Ts>
    class are_integral : public std::integral_constant<bool, true>
    {
    };

    template <typename T, typename... Ts>
    class are_integral<T, Ts...>
        : public std::integral_constant<bool,
                                        std::is_integral<T>::value && are_integral<Ts...>::value>
    {
    };
} // namespace details

template <std::size_t Rank>
class multi_span_index final
{
    static_assert(Rank > 0, "Rank must be greater than 0!");

    template <std::size_t OtherRank>
    friend class multi_span_index;

public:
    static const std::size_t rank = Rank;
    using value_type = std::ptrdiff_t;
    using size_type = value_type;
    using reference = std::add_lvalue_reference_t<value_type>;
    using const_reference = std::add_lvalue_reference_t<std::add_const_t<value_type>>;

    constexpr multi_span_index() noexcept {}

    constexpr multi_span_index(const value_type (&values)[Rank]) noexcept
    {
        GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
        GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
        std::copy(values, values + Rank, elems);
    }

    template <typename... Ts, typename = std::enable_if_t<(sizeof...(Ts) == Rank) &&
                                                          details::are_integral<Ts...>::value>>
    constexpr multi_span_index(Ts... ds) noexcept : elems{narrow_cast<value_type>(ds)...}
    {}

    constexpr multi_span_index(const multi_span_index& other) noexcept = default;

    constexpr multi_span_index& operator=(const multi_span_index& rhs) noexcept = default;

    // Preconditions: component_idx < rank
    GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    constexpr reference operator[](std::size_t component_idx)
    {
        Expects(component_idx < Rank); // Component index must be less than rank
        return elems[component_idx];
    }

    // Preconditions: component_idx < rank
    GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    constexpr const_reference operator[](std::size_t component_idx) const 
    {
        Expects(component_idx < Rank); // Component index must be less than rank
        return elems[component_idx];
    }

    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
    constexpr bool operator==(const multi_span_index& rhs) const
    {
        return std::equal(elems, elems + rank, rhs.elems);
    }

    constexpr bool operator!=(const multi_span_index& rhs) const
    {
        return !(*this == rhs);
    }

    constexpr multi_span_index operator+() const noexcept { return *this; }

    constexpr multi_span_index operator-() const
    {
        multi_span_index ret = *this;
        std::transform(ret, ret + rank, ret, std::negate<value_type>{});
        return ret;
    }

    constexpr multi_span_index operator+(const multi_span_index& rhs) const
    {
        multi_span_index ret = *this;
        ret += rhs;
        return ret;
    }

    constexpr multi_span_index operator-(const multi_span_index& rhs) const
    {
        multi_span_index ret = *this;
        ret -= rhs;
        return ret;
    }

    constexpr multi_span_index& operator+=(const multi_span_index& rhs)
    {
        GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
        GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
        std::transform(elems, elems + rank, rhs.elems, elems,
                       std::plus<value_type>{});
        return *this;
    }

    constexpr multi_span_index& operator-=(const multi_span_index& rhs)
    {
        GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
        GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
        std::transform(elems, elems + rank, rhs.elems, elems, std::minus<value_type>{});
        return *this;
    }

    constexpr multi_span_index operator*(value_type v) const
    {
        multi_span_index ret = *this;
        ret *= v;
        return ret;
    }

    constexpr multi_span_index operator/(value_type v) const
    {
        multi_span_index ret = *this;
        ret /= v;
        return ret;
    }

    friend constexpr multi_span_index operator*(value_type v, const multi_span_index& rhs)
    {
        return rhs * v;
    }

    constexpr multi_span_index& operator*=(value_type v)
    {
        GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
        GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
        std::transform(elems, elems + rank, elems,
                       [v](value_type x) { return std::multiplies<value_type>{}(x, v); });
        return *this;
    }

    constexpr multi_span_index& operator/=(value_type v)
    {
        GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
        GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
        std::transform(elems, elems + rank, elems,
                       [v](value_type x) { return std::divides<value_type>{}(x, v); });
        return *this;
    }

private:
    value_type elems[Rank] = {};
};

#if !defined(_MSC_VER) || _MSC_VER >= 1910

struct static_bounds_dynamic_range_t
{
    template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
    constexpr operator T() const noexcept
    {
        return narrow_cast<T>(-1);
    }
};

constexpr bool operator==(static_bounds_dynamic_range_t, static_bounds_dynamic_range_t) noexcept
{
    return true;
}

constexpr bool operator!=(static_bounds_dynamic_range_t, static_bounds_dynamic_range_t) noexcept
{
    return false;
}

template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
constexpr bool operator==(static_bounds_dynamic_range_t, T other) noexcept
{
    return narrow_cast<T>(-1) == other;
}

template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
constexpr bool operator==(T left, static_bounds_dynamic_range_t right) noexcept
{
    return right == left;
}

template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
constexpr bool operator!=(static_bounds_dynamic_range_t, T other) noexcept
{
    return narrow_cast<T>(-1) != other;
}

template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
constexpr bool operator!=(T left, static_bounds_dynamic_range_t right) noexcept
{
    return right != left;
}

constexpr static_bounds_dynamic_range_t dynamic_range{};
#else
const std::ptrdiff_t dynamic_range = -1;
#endif

struct generalized_mapping_tag
{
};
struct contiguous_mapping_tag : generalized_mapping_tag
{
};

namespace details
{

    template <std::ptrdiff_t Left, std::ptrdiff_t Right>
    struct LessThan
    {
        static const bool value = Left < Right;
    };

    template <std::ptrdiff_t... Ranges>
    struct BoundsRanges
    {
        using size_type = std::ptrdiff_t;
        static const size_type Depth = 0;
        static const size_type DynamicNum = 0;
        static const size_type CurrentRange = 1;
        static const size_type TotalSize = 1;

        // TODO : following signature is for work around VS bug
        template <typename OtherRange>
        constexpr BoundsRanges(const OtherRange&, bool /* firstLevel */)
        {}

        constexpr BoundsRanges(const std::ptrdiff_t* const) {}
        constexpr BoundsRanges() noexcept = default;

        template <typename T, std::size_t Dim>
        constexpr void serialize(T&) const
        {}

        template <typename T, std::size_t Dim>
        constexpr size_type linearize(const T&) const
        {
            return 0;
        }

        template <typename T, std::size_t Dim>
        constexpr size_type contains(const T&) const
        {
            return -1;
        }

        constexpr size_type elementNum(std::size_t) const noexcept { return 0; }

        constexpr size_type totalSize() const noexcept { return TotalSize; }

        constexpr bool operator==(const BoundsRanges&) const noexcept { return true; }
    };

    template <std::ptrdiff_t... RestRanges>
    struct BoundsRanges<dynamic_range, RestRanges...> : BoundsRanges<RestRanges...>
    {
        using Base = BoundsRanges<RestRanges...>;
        using size_type = std::ptrdiff_t;
        static const std::size_t Depth = Base::Depth + 1;
        static const std::size_t DynamicNum = Base::DynamicNum + 1;
        static const size_type CurrentRange = dynamic_range;
        static const size_type TotalSize = dynamic_range;

    private:
        size_type m_bound;

    public:
        GSL_SUPPRESS(f.23) // NO-FORMAT: attribute // this pointer type is cannot be assigned nullptr - issue in not_null
        GSL_SUPPRESS(bounds.1)  // NO-FORMAT: attribute
        constexpr BoundsRanges(const std::ptrdiff_t* const arr)
            : Base(arr + 1), m_bound(*arr * this->Base::totalSize())
        {
            Expects(0 <= *arr);
        }

        constexpr BoundsRanges() noexcept : m_bound(0) {}

        template <std::ptrdiff_t OtherRange, std::ptrdiff_t... RestOtherRanges>
        constexpr BoundsRanges(const BoundsRanges<OtherRange, RestOtherRanges...>& other,
                     bool /* firstLevel */ = true)
            : Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false)
            , m_bound(other.totalSize())
        {}

        template <typename T, std::size_t Dim = 0>
        constexpr void serialize(T& arr) const
        {
            arr[Dim] = elementNum();
            this->Base::template serialize<T, Dim + 1>(arr);
        }

        template <typename T, std::size_t Dim = 0>
        GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
        constexpr size_type linearize(const T& arr) const
        {
            const size_type index = this->Base::totalSize() * arr[Dim];
            Expects(index < m_bound);
            return index + this->Base::template linearize<T, Dim + 1>(arr);
        }

        template <typename T, std::size_t Dim = 0>
        constexpr size_type contains(const T& arr) const
        {
            const ptrdiff_t last = this->Base::template contains<T, Dim + 1>(arr);
            if (last == -1) return -1;
            const ptrdiff_t cur = this->Base::totalSize() * arr[Dim];
            return cur < m_bound ? cur + last : -1;
        }

        GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
        constexpr size_type totalSize() const noexcept
        {
            return m_bound;
        }

        GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
        constexpr size_type elementNum() const noexcept
        {
            return totalSize() / this->Base::totalSize();
        }

        GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
        constexpr size_type elementNum(std::size_t dim) const noexcept
        {
            if (dim > 0)
                return this->Base::elementNum(dim - 1);
            else
                return elementNum();
        }

        constexpr bool operator==(const BoundsRanges& rhs) const noexcept
        {
            return m_bound == rhs.m_bound &&
                   static_cast<const Base&>(*this) == static_cast<const Base&>(rhs);
        }
    };

    template <std::ptrdiff_t CurRange, std::ptrdiff_t... RestRanges>
    struct BoundsRanges<CurRange, RestRanges...> : BoundsRanges<RestRanges...>
    {
        using Base = BoundsRanges<RestRanges...>;
        using size_type = std::ptrdiff_t;
        static const std::size_t Depth = Base::Depth + 1;
        static const std::size_t DynamicNum = Base::DynamicNum;
        static const size_type CurrentRange = CurRange;
        static const size_type TotalSize =
            Base::TotalSize == dynamic_range ? dynamic_range : CurrentRange * Base::TotalSize;

        constexpr BoundsRanges(const std::ptrdiff_t* const arr) : Base(arr) {}
        constexpr BoundsRanges() = default;

        template <std::ptrdiff_t OtherRange, std::ptrdiff_t... RestOtherRanges>
        constexpr BoundsRanges(const BoundsRanges<OtherRange, RestOtherRanges...>& other,
                     bool firstLevel = true)
            : Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false)
        {
            GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive
            (void) firstLevel;
        }

        template <typename T, std::size_t Dim = 0>
        constexpr void serialize(T& arr) const
        {
            arr[Dim] = elementNum();
            this->Base::template serialize<T, Dim + 1>(arr);
        }

        template <typename T, std::size_t Dim = 0>
        constexpr size_type linearize(const T& arr) const
        {
            GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
            Expects(arr[Dim] >= 0 && arr[Dim] < CurrentRange); // Index is out of range
            GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
            const ptrdiff_t d = arr[Dim];
            return this->Base::totalSize() * d +
                   this->Base::template linearize<T, Dim + 1>(arr);
        }

        template <typename T, std::size_t Dim = 0>
        constexpr size_type contains(const T& arr) const
        {
            if (arr[Dim] >= CurrentRange) return -1;
            const size_type last = this->Base::template contains<T, Dim + 1>(arr);
            if (last == -1) return -1;
            return this->Base::totalSize() * arr[Dim] + last;
        }

        GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
        constexpr size_type totalSize() const noexcept
        {
            return CurrentRange * this->Base::totalSize();
        }

        GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
        constexpr size_type elementNum() const noexcept
        {
            return CurrentRange;
        }

        GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
        constexpr size_type elementNum(std::size_t dim) const noexcept
        {
            if (dim > 0)
                return this->Base::elementNum(dim - 1);
            else
                return elementNum();
        }

        constexpr bool operator==(const BoundsRanges& rhs) const noexcept
        {
            return static_cast<const Base&>(*this) == static_cast<const Base&>(rhs);
        }
    };

    template <typename SourceType, typename TargetType>
    struct BoundsRangeConvertible
        : public std::integral_constant<bool, (SourceType::TotalSize >= TargetType::TotalSize ||
                                               TargetType::TotalSize == dynamic_range ||
                                               SourceType::TotalSize == dynamic_range ||
                                               TargetType::TotalSize == 0)>
    {
    };

    template <typename TypeChain>
    struct TypeListIndexer
    {
        const TypeChain& obj_;
        constexpr TypeListIndexer(const TypeChain& obj) : obj_(obj) {}

        template <std::size_t N>
        constexpr const TypeChain& getObj(std::true_type)
        {
            return obj_;
        }

        template <std::size_t N, typename MyChain = TypeChain,
                  typename MyBase = typename MyChain::Base>
        constexpr auto getObj(std::false_type)
            -> decltype(TypeListIndexer<MyBase>(static_cast<const MyBase&>(obj_)).template get<N>())
        {
            return TypeListIndexer<MyBase>(static_cast<const MyBase&>(obj_)).template get<N>();
        }

        template <std::size_t N>
        constexpr auto get() -> decltype(getObj<N - 1>(std::integral_constant<bool, N == 0>()))
        {
            return getObj<N - 1>(std::integral_constant<bool, N == 0>());
        }
    };

    template <typename TypeChain>
    constexpr TypeListIndexer<TypeChain> createTypeListIndexer(const TypeChain& obj)
    {
        return TypeListIndexer<TypeChain>(obj);
    }

    template <std::size_t Rank, bool Enabled = (Rank > 1),
              typename Ret = std::enable_if_t<Enabled, multi_span_index<Rank - 1>>>
    constexpr Ret shift_left(const multi_span_index<Rank>& other) noexcept
    {
        Ret ret{};
        for (std::size_t i = 0; i < Rank - 1; ++i)
        {
            GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
                ret[i] = other[i + 1];
        }
        return ret;
    }
} // namespace details

template <typename IndexType>
class bounds_iterator;

template <std::ptrdiff_t... Ranges>
class static_bounds
{
public:
    static_bounds(const details::BoundsRanges<Ranges...>&) {}
};

template <std::ptrdiff_t FirstRange, std::ptrdiff_t... RestRanges>
class static_bounds<FirstRange, RestRanges...>
{
    using MyRanges = details::BoundsRanges<FirstRange, RestRanges...>;

    MyRanges m_ranges;
    constexpr static_bounds(const MyRanges& range) noexcept : m_ranges(range) {}

    template <std::ptrdiff_t... OtherRanges>
    friend class static_bounds;

public:
    static const std::size_t rank = MyRanges::Depth;
    static const std::size_t dynamic_rank = MyRanges::DynamicNum;
    static const std::ptrdiff_t static_size = MyRanges::TotalSize;

    using size_type = std::ptrdiff_t;
    using index_type = multi_span_index<rank>;
    using const_index_type = std::add_const_t<index_type>;
    using iterator = bounds_iterator<const_index_type>;
    using const_iterator = bounds_iterator<const_index_type>;
    using difference_type = std::ptrdiff_t;
    using sliced_type = static_bounds<RestRanges...>;
    using mapping_type = contiguous_mapping_tag;

    constexpr static_bounds() /*noexcept*/ = default;

    template <typename SourceType, typename TargetType, std::size_t Rank>
    struct BoundsRangeConvertible2;

    template <std::size_t Rank, typename SourceType, typename TargetType,
              typename Ret = BoundsRangeConvertible2<typename SourceType::Base,
                                                     typename TargetType::Base, Rank>>
    static auto helpBoundsRangeConvertible(SourceType, TargetType, std::true_type) -> Ret;

    template <std::size_t Rank, typename SourceType, typename TargetType>
    static auto helpBoundsRangeConvertible(SourceType, TargetType, ...) -> std::false_type;

    template <typename SourceType, typename TargetType, std::size_t Rank>
    struct BoundsRangeConvertible2
        : decltype(helpBoundsRangeConvertible<Rank - 1>(
              SourceType(), TargetType(),
              std::integral_constant<bool,
                                     SourceType::Depth == TargetType::Depth &&
                                         (SourceType::CurrentRange == TargetType::CurrentRange ||
                                          TargetType::CurrentRange == dynamic_range ||
                                          SourceType::CurrentRange == dynamic_range)>()))
    {
    };

    template <typename SourceType, typename TargetType>
    struct BoundsRangeConvertible2<SourceType, TargetType, 0> : std::true_type
    {
    };

    template <typename SourceType, typename TargetType, std::ptrdiff_t Rank = TargetType::Depth>
    struct BoundsRangeConvertible
        : decltype(helpBoundsRangeConvertible<Rank - 1>(
              SourceType(), TargetType(),
              std::integral_constant<bool,
                                     SourceType::Depth == TargetType::Depth &&
                                         (!details::LessThan<SourceType::CurrentRange,
                                                             TargetType::CurrentRange>::value ||
                                          TargetType::CurrentRange == dynamic_range ||
                                          SourceType::CurrentRange == dynamic_range)>()))
    {
    };

    template <typename SourceType, typename TargetType>
    struct BoundsRangeConvertible<SourceType, TargetType, 0> : std::true_type
    {
    };

    template <std::ptrdiff_t... Ranges,
              typename = std::enable_if_t<details::BoundsRangeConvertible<
                  details::BoundsRanges<Ranges...>,
                  details::BoundsRanges<FirstRange, RestRanges...>>::value>>
    constexpr static_bounds(const static_bounds<Ranges...>& other) : m_ranges(other.m_ranges)
    {
        Expects((MyRanges::DynamicNum == 0 && details::BoundsRanges<Ranges...>::DynamicNum == 0) ||
                MyRanges::DynamicNum > 0 || other.m_ranges.totalSize() >= m_ranges.totalSize());
    }

    constexpr static_bounds(std::initializer_list<size_type> il) : m_ranges(il.begin())
    {
        // Size of the initializer list must match the rank of the array
        Expects((MyRanges::DynamicNum == 0 && il.size() == 1 && *il.begin() == static_size) ||
                MyRanges::DynamicNum == il.size());
        // Size of the range must be less than the max element of the size type
        Expects(m_ranges.totalSize() <= PTRDIFF_MAX);
    }

    constexpr sliced_type slice() const noexcept
    {
        return sliced_type{static_cast<const details::BoundsRanges<RestRanges...>&>(m_ranges)};
    }

    constexpr size_type stride() const noexcept { return rank > 1 ? slice().size() : 1; }

    constexpr size_type size() const noexcept { return m_ranges.totalSize(); }

    constexpr size_type total_size() const noexcept { return m_ranges.totalSize(); }

    constexpr size_type linearize(const index_type& idx) const { return m_ranges.linearize(idx); }

    constexpr bool contains(const index_type& idx) const noexcept
    {
        return m_ranges.contains(idx) != -1;
    }

    constexpr size_type operator[](std::size_t idx) const noexcept
    {
        return m_ranges.elementNum(idx);
    }

    template <std::size_t Dim = 0>
    constexpr size_type extent() const noexcept
    {
        static_assert(Dim < rank,
                      "dimension should be less than rank (dimension count starts from 0)");
        return details::createTypeListIndexer(m_ranges).template get<Dim>().elementNum();
    }

    template <typename IntType>
    constexpr size_type extent(IntType dim) const
    {
        static_assert(std::is_integral<IntType>::value,
                      "Dimension parameter must be supplied as an integral type.");
        auto real_dim = narrow_cast<std::size_t>(dim);
        Expects(real_dim < rank);

        return m_ranges.elementNum(real_dim);
    }

    constexpr index_type index_bounds() const noexcept
    {
        size_type extents[rank] = {};
        m_ranges.serialize(extents);
        return {extents};
    }

    template <std::ptrdiff_t... Ranges>
    constexpr bool operator==(const static_bounds<Ranges...>& rhs) const noexcept
    {
        return this->size() == rhs.size();
    }

    template <std::ptrdiff_t... Ranges>
    constexpr bool operator!=(const static_bounds<Ranges...>& rhs) const noexcept
    {
        return !(*this == rhs);
    }

    constexpr const_iterator begin() const noexcept
    {
        return const_iterator(*this, index_type{});
    }

    constexpr const_iterator end() const noexcept
    {
        return const_iterator(*this, this->index_bounds());
    }
};

template <std::size_t Rank>
class strided_bounds {
    template <std::size_t OtherRank>
    friend class strided_bounds;

public:
    static const std::size_t rank = Rank;
    using value_type = std::ptrdiff_t;
    using reference = std::add_lvalue_reference_t<value_type>;
    using const_reference = std::add_const_t<reference>;
    using size_type = value_type;
    using difference_type = value_type;
    using index_type = multi_span_index<rank>;
    using const_index_type = std::add_const_t<index_type>;
    using iterator = bounds_iterator<const_index_type>;
    using const_iterator = bounds_iterator<const_index_type>;
    static const value_type dynamic_rank = rank;
    static const value_type static_size = dynamic_range;
    using sliced_type = std::conditional_t<rank != 0, strided_bounds<rank - 1>, void>;
    using mapping_type = generalized_mapping_tag;

    constexpr strided_bounds(const strided_bounds&) noexcept = default;

    constexpr strided_bounds& operator=(const strided_bounds&) noexcept = default;

    constexpr strided_bounds(const value_type (&values)[rank], index_type strides)
        : m_extents(values), m_strides(std::move(strides))
    {}

    constexpr strided_bounds(const index_type& extents, const index_type& strides) noexcept
        : m_extents(extents), m_strides(strides)
    {
    }

    constexpr index_type strides() const noexcept { return m_strides; }

    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    constexpr size_type total_size() const noexcept
    {
        size_type ret = 0;
        for (std::size_t i = 0; i < rank; ++i) { ret += (m_extents[i] - 1) * m_strides[i]; }
        return ret + 1;
    }

    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    constexpr size_type size() const noexcept
    {
        size_type ret = 1;
        for (std::size_t i = 0; i < rank; ++i) { ret *= m_extents[i]; }
        return ret;
    }

    constexpr bool contains(const index_type& idx) const noexcept
    {
        for (std::size_t i = 0; i < rank; ++i)
        {
            if (idx[i] < 0 || idx[i] >= m_extents[i]) return false;
        }
        return true;
    }

    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    constexpr size_type linearize(const index_type& idx) const
    {
        size_type ret = 0;
        for (std::size_t i = 0; i < rank; i++)
        {
            Expects(idx[i] < m_extents[i]); // index is out of bounds of the array
            ret += idx[i] * m_strides[i];
        }
        return ret;
    }

    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    constexpr size_type stride() const noexcept { return m_strides[0]; }

    template <bool Enabled = (rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
    constexpr sliced_type slice() const
    {
        return {details::shift_left(m_extents), details::shift_left(m_strides)};
    }

    template <std::size_t Dim = 0>

    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    constexpr size_type extent() const noexcept
    {
        static_assert(Dim < Rank,
                      "dimension should be less than rank (dimension count starts from 0)");
        return m_extents[Dim];
    }

    constexpr index_type index_bounds() const noexcept { return m_extents; }

    constexpr const_iterator begin() const noexcept { return const_iterator{*this, index_type{}}; }

    constexpr const_iterator end() const noexcept { return const_iterator{*this, index_bounds()}; }

private:
    index_type m_extents;
    index_type m_strides;
};

template <typename T>
struct is_bounds : std::integral_constant<bool, false>
{
};
template <std::ptrdiff_t... Ranges>
struct is_bounds<static_bounds<Ranges...>> : std::integral_constant<bool, true>
{
};
template <std::size_t Rank>
struct is_bounds<strided_bounds<Rank>> : std::integral_constant<bool, true>
{
};

template <typename IndexType>
class bounds_iterator
{
public:
    static const std::size_t rank = IndexType::rank;
    using iterator_category = std::random_access_iterator_tag;
    using value_type = IndexType;
    using difference_type = std::ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;
    using index_type = value_type;
    using index_size_type = typename IndexType::value_type;
    template <typename Bounds>
    explicit bounds_iterator(const Bounds& bnd, value_type curr) noexcept
        : boundary_(bnd.index_bounds()), curr_(std::move(curr))
    {
        static_assert(is_bounds<Bounds>::value, "Bounds type must be provided");
    }

    constexpr reference operator*() const noexcept { return curr_; }

    constexpr pointer operator->() const noexcept { return &curr_; }

    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
    constexpr bounds_iterator& operator++() noexcept

    {
        for (std::size_t i = rank; i-- > 0;)
        {
            if (curr_[i] < boundary_[i] - 1)
            {
                curr_[i]++;
                return *this;
            }
            curr_[i] = 0;
        }
        // If we're here we've wrapped over - set to past-the-end.
        curr_ = boundary_;
        return *this;
    }

    constexpr bounds_iterator operator++(int) noexcept
    {
        auto ret = *this;
        ++(*this);
        return ret;
    }

    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    constexpr bounds_iterator& operator--()
    {
        if (!less(curr_, boundary_))
        {
            // if at the past-the-end, set to last element
            for (std::size_t i = 0; i < rank; ++i) { curr_[i] = boundary_[i] - 1; }
            return *this;
        }
        for (std::size_t i = rank; i-- > 0;)
        {
            if (curr_[i] >= 1)
            {
                curr_[i]--;
                return *this;
            }
            curr_[i] = boundary_[i] - 1;
        }
        // If we're here the preconditions were violated
        // "pre: there exists s such that r == ++s"
        Expects(false);
        return *this;
    }

    constexpr bounds_iterator operator--(int) noexcept
    {
        auto ret = *this;
        --(*this);
        return ret;
    }

    constexpr bounds_iterator operator+(difference_type n) const noexcept
    {
        bounds_iterator ret{*this};
        return ret += n;
    }

    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    constexpr bounds_iterator& operator+=(difference_type n)
    {
        auto linear_idx = linearize(curr_) + n;
        std::remove_const_t<value_type> stride = 0;
        stride[rank - 1] = 1;
        for (std::size_t i = rank - 1; i-- > 0;) { stride[i] = stride[i + 1] * boundary_[i + 1]; }
        for (std::size_t i = 0; i < rank; ++i)
        {
            curr_[i] = linear_idx / stride[i];
            linear_idx = linear_idx % stride[i];
        }
        // index is out of bounds of the array
        Expects(!less(curr_, index_type{}) && !less(boundary_, curr_));
        return *this;
    }

    constexpr bounds_iterator operator-(difference_type n) const noexcept
    {
        bounds_iterator ret{*this};
        return ret -= n;
    }

    constexpr bounds_iterator& operator-=(difference_type n) noexcept { return *this += -n; }

    constexpr difference_type operator-(const bounds_iterator& rhs) const noexcept
    {
        return linearize(curr_) - linearize(rhs.curr_);
    }

    constexpr value_type operator[](difference_type n) const noexcept { return *(*this + n); }

    constexpr bool operator==(const bounds_iterator& rhs) const noexcept
    {
        return curr_ == rhs.curr_;
    }


    constexpr bool operator!=(const bounds_iterator& rhs) const noexcept { return !(*this == rhs); }

    constexpr bool operator<(const bounds_iterator& rhs) const noexcept
    {
        return less(curr_, rhs.curr_);
    }

    constexpr bool operator<=(const bounds_iterator& rhs) const noexcept { return !(rhs < *this); }

    constexpr bool operator>(const bounds_iterator& rhs) const noexcept { return rhs < *this; }

    constexpr bool operator>=(const bounds_iterator& rhs) const noexcept { return !(rhs > *this); }

    void swap(bounds_iterator& rhs) noexcept
    {
        std::swap(boundary_, rhs.boundary_);
        std::swap(curr_, rhs.curr_);
    }

private:

    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    constexpr bool less(index_type& one, index_type& other) const noexcept
    {
        for (std::size_t i = 0; i < rank; ++i)
        {
            if (one[i] < other[i]) return true;
        }
        return false;
    }

    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    constexpr index_size_type linearize(const value_type& idx) const noexcept
    {
        // TODO: Smarter impl.
        // Check if past-the-end
        index_size_type multiplier = 1;
        index_size_type res = 0;
        if (!less(idx, boundary_))
        {
            res = 1;
            for (std::size_t i = rank; i-- > 0;)
            {
                res += (idx[i] - 1) * multiplier;
                multiplier *= boundary_[i];
            }
        }
        else
        {
            for (std::size_t i = rank; i-- > 0;)
            {
                res += idx[i] * multiplier;
                multiplier *= boundary_[i];
            }
        }
        return res;
    }

    value_type boundary_;
    std::remove_const_t<value_type> curr_;
};

template <typename IndexType>
bounds_iterator<IndexType> operator+(typename bounds_iterator<IndexType>::difference_type n,
                                     const bounds_iterator<IndexType>& rhs) noexcept
{
    return rhs + n;
}

namespace details
{
    template <typename Bounds>
    constexpr std::enable_if_t<
        std::is_same<typename Bounds::mapping_type, generalized_mapping_tag>::value,
        typename Bounds::index_type>
    make_stride(const Bounds& bnd) noexcept
    {
        return bnd.strides();
    }

    // Make a stride vector from bounds, assuming contiguous memory.
    template <typename Bounds>
    constexpr std::enable_if_t<
        std::is_same<typename Bounds::mapping_type, contiguous_mapping_tag>::value,
        typename Bounds::index_type>
    make_stride(const Bounds& bnd) noexcept
    {
        auto extents = bnd.index_bounds();
        typename Bounds::size_type stride[Bounds::rank] = {};

        stride[Bounds::rank - 1] = 1;
        for (std::size_t i = 1; i < Bounds::rank; ++i)
        {
            GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
            GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
            stride[Bounds::rank - i - 1] = stride[Bounds::rank - i] * extents[Bounds::rank - i];
        }
        return {stride};
    }

    template <typename BoundsSrc, typename BoundsDest>
    void verifyBoundsReshape(const BoundsSrc& src, const BoundsDest& dest)
    {
        static_assert(is_bounds<BoundsSrc>::value && is_bounds<BoundsDest>::value,
                      "The src type and dest type must be bounds");
        static_assert(std::is_same<typename BoundsSrc::mapping_type, contiguous_mapping_tag>::value,
                      "The source type must be a contiguous bounds");
        static_assert(BoundsDest::static_size == dynamic_range ||
                          BoundsSrc::static_size == dynamic_range ||
                          BoundsDest::static_size == BoundsSrc::static_size,
                      "The source bounds must have same size as dest bounds");
        Expects(src.size() == dest.size());
    }

} // namespace details

template <typename Span>
class contiguous_span_iterator;
template <typename Span>
class general_span_iterator;

template <std::ptrdiff_t DimSize = dynamic_range>
struct dim_t
{
    static const std::ptrdiff_t value = DimSize;
};
template <>
struct dim_t<dynamic_range>
{
    static const std::ptrdiff_t value = dynamic_range;
    const std::ptrdiff_t dvalue;
    constexpr dim_t(std::ptrdiff_t size) noexcept : dvalue(size) {}
};

template <std::ptrdiff_t N, class = std::enable_if_t<(N >= 0)>>
constexpr dim_t<N> dim() noexcept
{
    return dim_t<N>();
}

template <std::ptrdiff_t N = dynamic_range, class = std::enable_if_t<N == dynamic_range>>
constexpr dim_t<N> dim(std::ptrdiff_t n) noexcept
{
    return dim_t<>(n);
}

template <typename ValueType, std::ptrdiff_t FirstDimension = dynamic_range,
          std::ptrdiff_t... RestDimensions>
class multi_span;
template <typename ValueType, std::size_t Rank>
class strided_span;

namespace details
{
    template <typename T, typename = std::true_type>
    struct SpanTypeTraits
    {
        using value_type = T;
        using size_type = std::size_t;
    };

    template <typename Traits>
    struct SpanTypeTraits<Traits, typename std::is_reference<typename Traits::span_traits&>::type>
    {
        using value_type = typename Traits::span_traits::value_type;
        using size_type = typename Traits::span_traits::size_type;
    };

    template <typename T, std::ptrdiff_t... Ranks>
    struct SpanArrayTraits
    {
        using type = multi_span<T, Ranks...>;
        using value_type = T;
        using bounds_type = static_bounds<Ranks...>;
        using pointer = T*;
        using reference = T&;
    };
    template <typename T, std::ptrdiff_t N, std::ptrdiff_t... Ranks>
    struct SpanArrayTraits<T[N], Ranks...> : SpanArrayTraits<T, Ranks..., N>
    {
    };

    template <typename BoundsType>
    BoundsType newBoundsHelperImpl(std::ptrdiff_t totalSize, std::true_type) // dynamic size
    {
        Expects(totalSize >= 0 && totalSize <= PTRDIFF_MAX);
        return BoundsType{totalSize};
    }
    template <typename BoundsType>
    BoundsType newBoundsHelperImpl(std::ptrdiff_t totalSize, std::false_type) // static size
    {
        Expects(BoundsType::static_size <= totalSize);
        return {};
    }
    template <typename BoundsType>
    BoundsType newBoundsHelper(std::ptrdiff_t totalSize)
    {
        static_assert(BoundsType::dynamic_rank <= 1, "dynamic rank must less or equal to 1");
        return newBoundsHelperImpl<BoundsType>(
            totalSize, std::integral_constant<bool, BoundsType::dynamic_rank == 1>());
    }

    struct Sep
    {
    };

    template <typename T, typename... Args>
    T static_as_multi_span_helper(Sep, Args... args)
    {
        return T{narrow_cast<typename T::size_type>(args)...};
    }
    template <typename T, typename Arg, typename... Args>
    std::enable_if_t<
        !std::is_same<Arg, dim_t<dynamic_range>>::value && !std::is_same<Arg, Sep>::value, T>
    static_as_multi_span_helper(Arg, Args... args)
    {
        return static_as_multi_span_helper<T>(args...);
    }
    template <typename T, typename... Args>
    T static_as_multi_span_helper(dim_t<dynamic_range> val, Args... args)
    {
        return static_as_multi_span_helper<T>(args..., val.dvalue);
    }

    template <typename... Dimensions>
    struct static_as_multi_span_static_bounds_helper
    {
        using type = static_bounds<(Dimensions::value)...>;
    };

    template <typename T>
    struct is_multi_span_oracle : std::false_type
    {
    };

    template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
    struct is_multi_span_oracle<multi_span<ValueType, FirstDimension, RestDimensions...>>
        : std::true_type
    {
    };

    template <typename ValueType, std::ptrdiff_t Rank>
    struct is_multi_span_oracle<strided_span<ValueType, Rank>> : std::true_type
    {
    };

    template <typename T>
    struct is_multi_span : is_multi_span_oracle<std::remove_cv_t<T>>
    {
    };
} // namespace details

template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
class multi_span
{
    // TODO do we still need this?
    template <typename ValueType2, std::ptrdiff_t FirstDimension2,
              std::ptrdiff_t... RestDimensions2>
    friend class multi_span;

public:
    using bounds_type = static_bounds<FirstDimension, RestDimensions...>;
    static const std::size_t Rank = bounds_type::rank;
    using size_type = typename bounds_type::size_type;
    using index_type = typename bounds_type::index_type;
    using value_type = ValueType;
    using const_value_type = std::add_const_t<value_type>;
    using pointer = std::add_pointer_t<value_type>;
    using reference = std::add_lvalue_reference_t<value_type>;
    using iterator = contiguous_span_iterator<multi_span>;
    using const_span = multi_span<const_value_type, FirstDimension, RestDimensions...>;
    using const_iterator = contiguous_span_iterator<const_span>;
    using reverse_iterator = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using sliced_type =
        std::conditional_t<Rank == 1, value_type, multi_span<value_type, RestDimensions...>>;

private:
    pointer data_;
    bounds_type bounds_;

    friend iterator;
    friend const_iterator;

public:
    // default constructor - same as constructing from nullptr_t
    GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
    constexpr multi_span() noexcept
        : multi_span(nullptr, bounds_type{})
    {
        static_assert(bounds_type::dynamic_rank != 0 ||
                          (bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0),
                      "Default construction of multi_span<T> only possible "
                      "for dynamic or fixed, zero-length spans.");
    }

    // construct from nullptr - get an empty multi_span
    GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
    constexpr multi_span(std::nullptr_t) noexcept
        : multi_span(nullptr, bounds_type{})
    {
        static_assert(bounds_type::dynamic_rank != 0 ||
                          (bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0),
                      "nullptr_t construction of multi_span<T> only possible "
                      "for dynamic or fixed, zero-length spans.");
    }

    // construct from nullptr with size of 0 (helps with template function calls)
    template <class IntType, typename = std::enable_if_t<std::is_integral<IntType>::value>>

    // GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive // TODO: parser bug
    constexpr multi_span(std::nullptr_t, IntType size) : multi_span(nullptr, bounds_type{})
    {
        static_assert(bounds_type::dynamic_rank != 0 ||
                          (bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0),
                      "nullptr_t construction of multi_span<T> only possible "
                      "for dynamic or fixed, zero-length spans.");
        Expects(size == 0);
    }

    // construct from a single element

    GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
    constexpr multi_span(reference data) noexcept
        : multi_span(&data, bounds_type{1})
    {
        static_assert(bounds_type::dynamic_rank > 0 || bounds_type::static_size == 0 ||
                          bounds_type::static_size == 1,
                      "Construction from a single element only possible "
                      "for dynamic or fixed spans of length 0 or 1.");
    }

    // prevent constructing from temporaries for single-elements
    constexpr multi_span(value_type&&) = delete;

    // construct from pointer + length
    GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
    constexpr multi_span(pointer ptr, size_type size)
        : multi_span(ptr, bounds_type{size})
    {}

    // construct from pointer + length - multidimensional
    constexpr multi_span(pointer data, bounds_type bounds)
        : data_(data), bounds_(std::move(bounds))
    {
        Expects((bounds_.size() > 0 && data != nullptr) || bounds_.size() == 0);
    }

    // construct from begin,end pointer pair
    template <typename Ptr,
              typename = std::enable_if_t<std::is_convertible<Ptr, pointer>::value &&
                                          details::LessThan<bounds_type::dynamic_rank, 2>::value>>
    constexpr multi_span(pointer begin, Ptr end)
        : multi_span(begin,
                     details::newBoundsHelper<bounds_type>(static_cast<pointer>(end) - begin))
    {
        Expects(begin != nullptr && end != nullptr && begin <= static_cast<pointer>(end));
    }

    // construct from n-dimensions static array
    template <typename T, std::size_t N, typename Helper = details::SpanArrayTraits<T, N>>
    constexpr multi_span(T (&arr)[N])
        : multi_span(reinterpret_cast<pointer>(arr), bounds_type{typename Helper::bounds_type{}})
    {
        static_assert(std::is_convertible<typename Helper::value_type(*)[], value_type(*)[]>::value,
                      "Cannot convert from source type to target multi_span type.");
        static_assert(std::is_convertible<typename Helper::bounds_type, bounds_type>::value,
                      "Cannot construct a multi_span from an array with fewer elements.");
    }

    // construct from n-dimensions dynamic array (e.g. new int[m][4])
    // (precedence will be lower than the 1-dimension pointer)
    template <typename T, typename Helper = details::SpanArrayTraits<T, dynamic_range>>
    constexpr multi_span(T* const& data, size_type size)
        : multi_span(reinterpret_cast<pointer>(data), typename Helper::bounds_type{size})
    {
        static_assert(std::is_convertible<typename Helper::value_type(*)[], value_type(*)[]>::value,
                      "Cannot convert from source type to target multi_span type.");
    }

    // construct from std::array
    template <typename T, std::size_t N>
    constexpr multi_span(std::array<T, N>& arr)
        : multi_span(arr.data(), bounds_type{static_bounds<N>{}})
    {
        static_assert(
            std::is_convertible<T(*)[], typename std::remove_const_t<value_type>(*)[]>::value,
            "Cannot convert from source type to target multi_span type.");
        static_assert(std::is_convertible<static_bounds<N>, bounds_type>::value,
                      "You cannot construct a multi_span from a std::array of smaller size.");
    }

    // construct from const std::array
    template <typename T, std::size_t N>
    constexpr multi_span(const std::array<T, N>& arr)
        : multi_span(arr.data(), bounds_type{static_bounds<N>{}})
    {
        static_assert(
            std::is_convertible<T(*)[], typename std::remove_const_t<value_type>(*)[]>::value,
            "Cannot convert from source type to target multi_span type.");
        static_assert(std::is_convertible<static_bounds<N>, bounds_type>::value,
                      "You cannot construct a multi_span from a std::array of smaller size.");
    }

    // prevent constructing from temporary std::array
    template <typename T, std::size_t N>
    constexpr multi_span(std::array<T, N>&& arr) = delete;

    // construct from containers
    // future: could use contiguous_iterator_traits to identify only contiguous containers
    // type-requirements: container must have .size(), operator[] which are value_type compatible
    template <typename Cont, typename DataType = typename Cont::value_type,
              typename = std::enable_if_t<
                  !details::is_multi_span<Cont>::value &&
                  std::is_convertible<DataType (*)[], value_type (*)[]>::value &&
                  std::is_same<std::decay_t<decltype(std::declval<Cont>().size(),
                                                     *std::declval<Cont>().data())>,
                               DataType>::value>>
    constexpr multi_span(Cont& cont)
        : multi_span(static_cast<pointer>(cont.data()),
                     details::newBoundsHelper<bounds_type>(narrow_cast<size_type>(cont.size())))
    {}

    // prevent constructing from temporary containers
    template <typename Cont, typename DataType = typename Cont::value_type,
              typename = std::enable_if_t<
                  !details::is_multi_span<Cont>::value &&
                  std::is_convertible<DataType (*)[], value_type (*)[]>::value &&
                  std::is_same<std::decay_t<decltype(std::declval<Cont>().size(),
                                                     *std::declval<Cont>().data())>,
                               DataType>::value>>
    explicit constexpr multi_span(Cont&& cont) = delete;

    // construct from a convertible multi_span
    template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
              typename OtherBounds = static_bounds<OtherDimensions...>,
              typename = std::enable_if_t<std::is_convertible<OtherValueType, ValueType>::value &&
                                          std::is_convertible<OtherBounds, bounds_type>::value>>
    constexpr multi_span(multi_span<OtherValueType, OtherDimensions...> other)
        : data_(other.data_), bounds_(other.bounds_)
    {}

    // trivial copy and move
    constexpr multi_span(const multi_span&) = default;
    constexpr multi_span(multi_span&&) = default;

    // trivial assignment
    constexpr multi_span& operator=(const multi_span&) = default;
    constexpr multi_span& operator=(multi_span&&) = default;

    // first() - extract the first Count elements into a new multi_span
    template <std::ptrdiff_t Count>

    constexpr multi_span<ValueType, Count> first() const
    {
        static_assert(Count >= 0, "Count must be >= 0.");
        static_assert(bounds_type::static_size == dynamic_range ||
                          Count <= bounds_type::static_size,
                      "Count is out of bounds.");

        Expects(bounds_type::static_size != dynamic_range || Count <= this->size());
        return {this->data(), Count};
    }

    // first() - extract the first count elements into a new multi_span
    constexpr multi_span<ValueType, dynamic_range> first(size_type count) const
    {
        Expects(count >= 0 && count <= this->size());
        return {this->data(), count};
    }

    // last() - extract the last Count elements into a new multi_span
    template <std::ptrdiff_t Count>
    constexpr multi_span<ValueType, Count> last() const
    {
        static_assert(Count >= 0, "Count must be >= 0.");
        static_assert(bounds_type::static_size == dynamic_range ||
                          Count <= bounds_type::static_size,
                      "Count is out of bounds.");

        Expects(bounds_type::static_size != dynamic_range || Count <= this->size());
        return {this->data() + this->size() - Count, Count};
    }

    // last() - extract the last count elements into a new multi_span
    constexpr multi_span<ValueType, dynamic_range> last(size_type count) const
    {
        Expects(count >= 0 && count <= this->size());
        return {this->data() + this->size() - count, count};
    }

    // subspan() - create a subview of Count elements starting at Offset
    template <std::ptrdiff_t Offset, std::ptrdiff_t Count>
    constexpr multi_span<ValueType, Count> subspan() const
    {
        static_assert(Count >= 0, "Count must be >= 0.");
        static_assert(Offset >= 0, "Offset must be >= 0.");
        static_assert(bounds_type::static_size == dynamic_range ||
                          ((Offset <= bounds_type::static_size) &&
                           Count <= bounds_type::static_size - Offset),
                      "You must describe a sub-range within bounds of the multi_span.");

        Expects(bounds_type::static_size != dynamic_range ||
                (Offset <= this->size() && Count <= this->size() - Offset));
        return {this->data() + Offset, Count};
    }

    // subspan() - create a subview of count elements starting at offset
    // supplying dynamic_range for count will consume all available elements from offset
    constexpr multi_span<ValueType, dynamic_range> subspan(size_type offset,
                                                           size_type count = dynamic_range) const
    {
        Expects((offset >= 0 && offset <= this->size()) &&
                (count == dynamic_range || (count <= this->size() - offset)));
        return {this->data() + offset, count == dynamic_range ? this->length() - offset : count};
    }

    // section - creates a non-contiguous, strided multi_span from a contiguous one
    constexpr strided_span<ValueType, Rank> section(index_type origin,
                                                    index_type extents) const
    {
        const size_type size = this->bounds().total_size() - this->bounds().linearize(origin);
        return {&this->operator[](origin), size,
                strided_bounds<Rank>{extents, details::make_stride(bounds())}};
    }

    // length of the multi_span in elements
    constexpr size_type size() const noexcept { return bounds_.size(); }

    // length of the multi_span in elements
    constexpr size_type length() const noexcept { return this->size(); }

    // length of the multi_span in bytes
    constexpr size_type size_bytes() const noexcept
    {
        return narrow_cast<size_type>(sizeof(value_type)) * this->size();
    }

    // length of the multi_span in bytes
    constexpr size_type length_bytes() const noexcept { return this->size_bytes(); }

    constexpr bool empty() const noexcept { return this->size() == 0; }

    static constexpr std::size_t rank() { return Rank; }

    template <std::size_t Dim = 0>
    constexpr size_type extent() const noexcept
    {
        static_assert(Dim < Rank,
                      "Dimension should be less than rank (dimension count starts from 0).");
        return bounds_.template extent<Dim>();
    }

    template <typename IntType>
    constexpr size_type extent(IntType dim) const
    {
        return bounds_.extent(dim);
    }

    constexpr bounds_type bounds() const noexcept { return bounds_; }

    constexpr pointer data() const noexcept { return data_; }

    template <typename FirstIndex>
    constexpr reference operator()(FirstIndex idx)
    {
        return this->operator[](narrow_cast<std::ptrdiff_t>(idx));
    }

    template <typename FirstIndex, typename... OtherIndices>
    constexpr reference operator()(FirstIndex firstIndex, OtherIndices... indices)
    {
        const index_type idx = {narrow_cast<std::ptrdiff_t>(firstIndex),
                                narrow_cast<std::ptrdiff_t>(indices)...};
        return this->operator[](idx);
    }

    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    constexpr reference operator[](const index_type& idx) const
    {
        return data_[bounds_.linearize(idx)];
    }

    template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>

    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    constexpr Ret operator[](size_type idx) const
    {
        Expects(idx >= 0 && idx < bounds_.size()); // index is out of bounds of the array
        const size_type ridx = idx * bounds_.stride();

        // index is out of bounds of the underlying data
        Expects(ridx < bounds_.total_size());
        return Ret{data_ + ridx, bounds_.slice()};
    }

    constexpr iterator begin() const noexcept { return iterator{this, true}; }

    constexpr iterator end() const noexcept { return iterator{this, false}; }

    GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
    constexpr const_iterator cbegin() const noexcept
    {
        return const_iterator{reinterpret_cast<const const_span*>(this), true};
    }

    constexpr const_iterator cend() const noexcept
    {
        return const_iterator{reinterpret_cast<const const_span*>(this), false};
    }

    constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }

    constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }

    constexpr const_reverse_iterator crbegin() const noexcept
    {
        return const_reverse_iterator{cend()};
    }

    constexpr const_reverse_iterator crend() const noexcept
    {
        return const_reverse_iterator{cbegin()};
    }

    template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator==(const multi_span<OtherValueType, OtherDimensions...>& other) const
    {
        return bounds_.size() == other.bounds_.size() &&
               (data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin()));
    }

    template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator!=(const multi_span<OtherValueType, OtherDimensions...>& other) const
    {
        return !(*this == other);
    }

    template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator<(const multi_span<OtherValueType, OtherDimensions...>& other) const
    {
        return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end());
    }

    template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator<=(const multi_span<OtherValueType, OtherDimensions...>& other) const
    {
        return !(other < *this);
    }

    template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator>(const multi_span<OtherValueType, OtherDimensions...>& other) const
        noexcept
    {
        return (other < *this);
    }

    template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator>=(const multi_span<OtherValueType, OtherDimensions...>& other) const
    {
        return !(*this < other);
    }
};

//
// Free functions for manipulating spans
//

// reshape a multi_span into a different dimensionality
// DimCount and Enabled here are workarounds for a bug in MSVC 2015
template <typename SpanType, typename... Dimensions2, std::size_t DimCount = sizeof...(Dimensions2),
          bool Enabled = (DimCount > 0), typename = std::enable_if_t<Enabled>>
constexpr auto as_multi_span(SpanType s, Dimensions2... dims)
    -> multi_span<typename SpanType::value_type, Dimensions2::value...>
{
    static_assert(details::is_multi_span<SpanType>::value,
                  "Variadic as_multi_span() is for reshaping existing spans.");
    using BoundsType =
        typename multi_span<typename SpanType::value_type, (Dimensions2::value)...>::bounds_type;
    const auto tobounds = details::static_as_multi_span_helper<BoundsType>(dims..., details::Sep{});
    details::verifyBoundsReshape(s.bounds(), tobounds);
    return {s.data(), tobounds};
}

// convert a multi_span<T> to a multi_span<const byte>
template <typename U, std::ptrdiff_t... Dimensions>
multi_span<const byte, dynamic_range> as_bytes(multi_span<U, Dimensions...> s) noexcept
{
    static_assert(std::is_trivial<std::decay_t<U>>::value,
                  "The value_type of multi_span must be a trivial type.");
    return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
}

// convert a multi_span<T> to a multi_span<byte> (a writeable byte multi_span)
// this is not currently a portable function that can be relied upon to work
// on all implementations. It should be considered an experimental extension
// to the standard GSL interface.
template <typename U, std::ptrdiff_t... Dimensions>
multi_span<byte> as_writeable_bytes(multi_span<U, Dimensions...> s) noexcept
{
    static_assert(std::is_trivial<std::decay_t<U>>::value,
                  "The value_type of multi_span must be a trivial type.");
    return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
}

// convert a multi_span<const byte> to a multi_span<const T>
// this is not currently a portable function that can be relied upon to work
// on all implementations. It should be considered an experimental extension
// to the standard GSL interface.
template <typename U, std::ptrdiff_t... Dimensions>
constexpr auto as_multi_span(multi_span<const byte, Dimensions...> s) -> multi_span<
    const U, static_cast<std::ptrdiff_t>(
                 multi_span<const byte, Dimensions...>::bounds_type::static_size != dynamic_range
                     ? (static_cast<std::size_t>(
                            multi_span<const byte, Dimensions...>::bounds_type::static_size) /
                        sizeof(U))
                     : dynamic_range)>
{
    using ConstByteSpan = multi_span<const byte, Dimensions...>;
    static_assert(
        std::is_trivial<std::decay_t<U>>::value &&
            (ConstByteSpan::bounds_type::static_size == dynamic_range ||
             ConstByteSpan::bounds_type::static_size % narrow_cast<std::ptrdiff_t>(sizeof(U)) == 0),
        "Target type must be a trivial type and its size must match the byte array size");

    Expects((s.size_bytes() % narrow_cast<std::ptrdiff_t>(sizeof(U))) == 0 &&
            (s.size_bytes() / narrow_cast<std::ptrdiff_t>(sizeof(U))) < PTRDIFF_MAX);
    return {reinterpret_cast<const U*>(s.data()),
            s.size_bytes() / narrow_cast<std::ptrdiff_t>(sizeof(U))};
}

// convert a multi_span<byte> to a multi_span<T>
// this is not currently a portable function that can be relied upon to work
// on all implementations. It should be considered an experimental extension
// to the standard GSL interface.
template <typename U, std::ptrdiff_t... Dimensions>
constexpr auto as_multi_span(multi_span<byte, Dimensions...> s)
    -> multi_span<U, narrow_cast<std::ptrdiff_t>(
                         multi_span<byte, Dimensions...>::bounds_type::static_size != dynamic_range
                             ? static_cast<std::size_t>(
                                   multi_span<byte, Dimensions...>::bounds_type::static_size) /
                                   sizeof(U)
                             : dynamic_range)>
{
    using ByteSpan = multi_span<byte, Dimensions...>;
    static_assert(std::is_trivial<std::decay_t<U>>::value &&
                      (ByteSpan::bounds_type::static_size == dynamic_range ||
                       ByteSpan::bounds_type::static_size % sizeof(U) == 0),
                  "Target type must be a trivial type and its size must match the byte array size");

    Expects((s.size_bytes() % sizeof(U)) == 0);
    return {reinterpret_cast<U*>(s.data()),
            s.size_bytes() / narrow_cast<std::ptrdiff_t>(sizeof(U))};
}

template <typename T, std::ptrdiff_t... Dimensions>
constexpr auto as_multi_span(T* const& ptr, dim_t<Dimensions>... args)
    -> multi_span<std::remove_all_extents_t<T>, Dimensions...>
{
    return {reinterpret_cast<std::remove_all_extents_t<T>*>(ptr),
            details::static_as_multi_span_helper<static_bounds<Dimensions...>>(args...,
                                                                               details::Sep{})};
}

template <typename T>
constexpr auto as_multi_span(T* arr, std::ptrdiff_t len) ->
    typename details::SpanArrayTraits<T, dynamic_range>::type
{
    return {reinterpret_cast<std::remove_all_extents_t<T>*>(arr), len};
}

template <typename T, std::size_t N>
constexpr auto as_multi_span(T (&arr)[N]) -> typename details::SpanArrayTraits<T, N>::type
{
    return {arr};
}

template <typename T, std::size_t N>
constexpr multi_span<const T, N> as_multi_span(const std::array<T, N>& arr)
{
    return {arr};
}

template <typename T, std::size_t N>
constexpr multi_span<const T, N> as_multi_span(const std::array<T, N>&&) = delete;

template <typename T, std::size_t N>
constexpr multi_span<T, N> as_multi_span(std::array<T, N>& arr)
{
    return {arr};
}

template <typename T>
constexpr multi_span<T, dynamic_range> as_multi_span(T* begin, T* end)
{
    return {begin, end};
}

template <typename Cont>
constexpr auto as_multi_span(Cont& arr) -> std::enable_if_t<
    !details::is_multi_span<std::decay_t<Cont>>::value,
    multi_span<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>>
{
    Expects(arr.size() < PTRDIFF_MAX);
    return {arr.data(), narrow_cast<std::ptrdiff_t>(arr.size())};
}

template <typename Cont>
constexpr auto as_multi_span(Cont&& arr) -> std::enable_if_t<
    !details::is_multi_span<std::decay_t<Cont>>::value,
    multi_span<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>> = delete;

// from basic_string which doesn't have nonconst .data() member like other contiguous containers
template <typename CharT, typename Traits, typename Allocator>
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
constexpr auto as_multi_span(std::basic_string<CharT, Traits, Allocator>& str)
    -> multi_span<CharT, dynamic_range>
{
    Expects(str.size() < PTRDIFF_MAX);
    return {&str[0], narrow_cast<std::ptrdiff_t>(str.size())};
}

// strided_span is an extension that is not strictly part of the GSL at this time.
// It is kept here while the multidimensional interface is still being defined.
template <typename ValueType, std::size_t Rank>
class strided_span
{
public:
    using bounds_type = strided_bounds<Rank>;
    using size_type = typename bounds_type::size_type;
    using index_type = typename bounds_type::index_type;
    using value_type = ValueType;
    using const_value_type = std::add_const_t<value_type>;
    using pointer = std::add_pointer_t<value_type>;
    using reference = std::add_lvalue_reference_t<value_type>;
    using iterator = general_span_iterator<strided_span>;
    using const_strided_span = strided_span<const_value_type, Rank>;
    using const_iterator = general_span_iterator<const_strided_span>;
    using reverse_iterator = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using sliced_type =
        std::conditional_t<Rank == 1, value_type, strided_span<value_type, Rank - 1>>;

private:
    pointer data_;
    bounds_type bounds_;

    friend iterator;
    friend const_iterator;
    template <typename OtherValueType, std::size_t OtherRank>
    friend class strided_span;

public:
    // from raw data
    constexpr strided_span(pointer ptr, size_type size, bounds_type bounds)
        : data_(ptr), bounds_(std::move(bounds))
    {
        Expects((bounds_.size() > 0 && ptr != nullptr) || bounds_.size() == 0);
        // Bounds cross data boundaries
        Expects(this->bounds().total_size() <= size);
        GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive
        (void) size;
    }

    // from static array of size N
    template <size_type N>
    constexpr strided_span(value_type (&values)[N], bounds_type bounds)
        : strided_span(values, N, std::move(bounds))
    {}

    // from array view
    template <typename OtherValueType, std::ptrdiff_t... Dimensions,
              bool Enabled1 = (sizeof...(Dimensions) == Rank),
              bool Enabled2 = std::is_convertible<OtherValueType*, ValueType*>::value,
              typename = std::enable_if_t<Enabled1 && Enabled2>>
    constexpr strided_span(multi_span<OtherValueType, Dimensions...> av, bounds_type bounds)
        : strided_span(av.data(), av.bounds().total_size(), std::move(bounds))
    {}

    // convertible
    template <typename OtherValueType, typename = std::enable_if_t<std::is_convertible<
                                           OtherValueType (*)[], value_type (*)[]>::value>>
    constexpr strided_span(const strided_span<OtherValueType, Rank>& other)
        : data_(other.data_), bounds_(other.bounds_)
    {}

    // convert from bytes
    template <typename OtherValueType>
    constexpr strided_span<
        typename std::enable_if<std::is_same<value_type, const byte>::value, OtherValueType>::type,
        Rank>
    as_strided_span() const
    {
        static_assert((sizeof(OtherValueType) >= sizeof(value_type)) &&
                          (sizeof(OtherValueType) % sizeof(value_type) == 0),
                      "OtherValueType should have a size to contain a multiple of ValueTypes");
        auto d = narrow_cast<size_type>(sizeof(OtherValueType) / sizeof(value_type));

        const size_type size = this->bounds().total_size() / d;

        GSL_SUPPRESS(type.3) // NO-FORMAT: attribute
        return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())),
                size,
                bounds_type{resize_extent(this->bounds().index_bounds(), d),
                            resize_stride(this->bounds().strides(), d)}};
    }

    constexpr strided_span section(index_type origin, index_type extents) const
    {
        const size_type size = this->bounds().total_size() - this->bounds().linearize(origin);
        return {&this->operator[](origin), size,
                bounds_type{extents, details::make_stride(bounds())}};
    }

    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    constexpr reference operator[](const index_type& idx) const
    {
        return data_[bounds_.linearize(idx)];
    }

    template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    constexpr Ret operator[](size_type idx) const
    {
        Expects(idx < bounds_.size()); // index is out of bounds of the array
        const size_type ridx = idx * bounds_.stride();

        // index is out of bounds of the underlying data
        Expects(ridx < bounds_.total_size());
        return {data_ + ridx, bounds_.slice().total_size(), bounds_.slice()};
    }

    constexpr bounds_type bounds() const noexcept { return bounds_; }

    template <std::size_t Dim = 0>
    constexpr size_type extent() const noexcept
    {
        static_assert(Dim < Rank,
                      "dimension should be less than Rank (dimension count starts from 0)");
        return bounds_.template extent<Dim>();
    }

    constexpr size_type size() const noexcept { return bounds_.size(); }

    constexpr pointer data() const noexcept { return data_; }

    constexpr bool empty() const noexcept { return this->size() == 0; }

    constexpr explicit operator bool() const noexcept { return data_ != nullptr; }

    constexpr iterator begin() const { return iterator{this, true}; }

    constexpr iterator end() const { return iterator{this, false}; }

    constexpr const_iterator cbegin() const
    {
        return const_iterator{reinterpret_cast<const const_strided_span*>(this), true};
    }

    constexpr const_iterator cend() const
    {
        return const_iterator{reinterpret_cast<const const_strided_span*>(this), false};
    }

    constexpr reverse_iterator rbegin() const { return reverse_iterator{end()}; }

    constexpr reverse_iterator rend() const { return reverse_iterator{begin()}; }

    constexpr const_reverse_iterator crbegin() const { return const_reverse_iterator{cend()}; }

    constexpr const_reverse_iterator crend() const { return const_reverse_iterator{cbegin()}; }

    template <typename OtherValueType, std::ptrdiff_t OtherRank,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator==(const strided_span<OtherValueType, OtherRank>& other) const
    {
        return bounds_.size() == other.bounds_.size() &&
               (data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin()));
    }

    template <typename OtherValueType, std::ptrdiff_t OtherRank,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator!=(const strided_span<OtherValueType, OtherRank>& other) const
    {
        return !(*this == other);
    }

    template <typename OtherValueType, std::ptrdiff_t OtherRank,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator<(const strided_span<OtherValueType, OtherRank>& other) const
    {
        return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end());
    }

    template <typename OtherValueType, std::ptrdiff_t OtherRank,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator<=(const strided_span<OtherValueType, OtherRank>& other) const
    {
        return !(other < *this);
    }

    template <typename OtherValueType, std::ptrdiff_t OtherRank,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator>(const strided_span<OtherValueType, OtherRank>& other) const
    {
        return (other < *this);
    }

    template <typename OtherValueType, std::ptrdiff_t OtherRank,
              typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>,
                                                       std::remove_cv_t<OtherValueType>>::value>>
    constexpr bool operator>=(const strided_span<OtherValueType, OtherRank>& other) const
    {
        return !(*this < other);
    }

private:
    static index_type resize_extent(const index_type& extent, std::ptrdiff_t d)
    {
        // The last dimension of the array needs to contain a multiple of new type elements
        GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
        Expects(extent[Rank - 1] >= d && (extent[Rank - 1] % d == 0));

        index_type ret = extent;
        ret[Rank - 1] /= d;

        return ret;
    }

    template <bool Enabled = (Rank == 1), typename = std::enable_if_t<Enabled>>
    static index_type resize_stride(const index_type& strides, std::ptrdiff_t, void* = nullptr)
    {
        // Only strided arrays with regular strides can be resized
        GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
        Expects(strides[Rank - 1] == 1);

        return strides;
    }

    template <bool Enabled = (Rank > 1), typename = std::enable_if_t<Enabled>>
    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    static index_type resize_stride(const index_type& strides, std::ptrdiff_t d)
    {
        // Only strided arrays with regular strides can be resized
        Expects(strides[Rank - 1] == 1);
        // The strides must have contiguous chunks of
        // memory that can contain a multiple of new type elements
        Expects(strides[Rank - 2] >= d && (strides[Rank - 2] % d == 0));

        for (std::size_t i = Rank - 1; i > 0; --i)
        {
            // Only strided arrays with regular strides can be resized
            Expects((strides[i - 1] >= strides[i]) && (strides[i - 1] % strides[i] == 0));
        }

        index_type ret = strides / d;
        ret[Rank - 1] = 1;

        return ret;
    }
};

template <class Span>
class contiguous_span_iterator
{
public:
    using iterator_category = std::random_access_iterator_tag;
    using value_type = typename Span::value_type;
    using difference_type = std::ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

private:
    template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
    friend class multi_span;

    pointer data_;
    const Span* m_validator;

    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    void validateThis() const {
        // iterator is out of range of the array
        Expects(data_ >= m_validator->data_ && data_ < m_validator->data_ + m_validator->size());
    }

    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    contiguous_span_iterator(const Span* container, bool isbegin)
        : data_(isbegin ? container->data_ : container->data_ + container->size())
        , m_validator(container)
    {}

public:
    reference operator*() const
    {
        validateThis();
        return *data_;
    }
    pointer operator->() const
    {
        validateThis();
        return data_;
    }

    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    contiguous_span_iterator& operator++() noexcept
    {
        ++data_;
        return *this;
    }
    contiguous_span_iterator operator++(int) noexcept
    {
        auto ret = *this;
        ++(*this);
        return ret;
    }

    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    contiguous_span_iterator& operator--() noexcept
    {
        --data_;
        return *this;
    }
    contiguous_span_iterator operator--(int) noexcept
    {
        auto ret = *this;
        --(*this);
        return ret;
    }
    contiguous_span_iterator operator+(difference_type n) const noexcept
    {
        contiguous_span_iterator ret{*this};
        return ret += n;
    }
    contiguous_span_iterator& operator+=(difference_type n) noexcept
    {
        data_ += n;
        return *this;
    }
    contiguous_span_iterator operator-(difference_type n) const noexcept
    {
        contiguous_span_iterator ret{*this};
        return ret -= n;
    }

    contiguous_span_iterator& operator-=(difference_type n) { return *this += -n; }
    difference_type operator-(const contiguous_span_iterator& rhs) const
    {
        Expects(m_validator == rhs.m_validator);
        return data_ - rhs.data_;
    }
    reference operator[](difference_type n) const { return *(*this + n); }
    bool operator==(const contiguous_span_iterator& rhs) const
    {
        Expects(m_validator == rhs.m_validator);
        return data_ == rhs.data_;
    }

    bool operator!=(const contiguous_span_iterator& rhs) const { return !(*this == rhs); }

    bool operator<(const contiguous_span_iterator& rhs) const
    {
        Expects(m_validator == rhs.m_validator);
        return data_ < rhs.data_;
    }

    bool operator<=(const contiguous_span_iterator& rhs) const { return !(rhs < *this); }
    bool operator>(const contiguous_span_iterator& rhs) const { return rhs < *this; }
    bool operator>=(const contiguous_span_iterator& rhs) const { return !(rhs > *this); }

    void swap(contiguous_span_iterator& rhs) noexcept
    {
        std::swap(data_, rhs.data_);
        std::swap(m_validator, rhs.m_validator);
    }
};

template <typename Span>
contiguous_span_iterator<Span> operator+(typename contiguous_span_iterator<Span>::difference_type n,
                                         const contiguous_span_iterator<Span>& rhs) noexcept
{
    return rhs + n;
}

template <typename Span>
class general_span_iterator {
public:
    using iterator_category = std::random_access_iterator_tag;
    using value_type = typename Span::value_type;
    using difference_type = std::ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

private:
    template <typename ValueType, std::size_t Rank>
    friend class strided_span;

    const Span* m_container;
    typename Span::bounds_type::iterator m_itr;
    general_span_iterator(const Span* container, bool isbegin)
        : m_container(container)
        , m_itr(isbegin ? m_container->bounds().begin() : m_container->bounds().end())
    {}

public:
    reference operator*() noexcept { return (*m_container)[*m_itr]; }
    pointer operator->() noexcept { return &(*m_container)[*m_itr]; }
    general_span_iterator& operator++() noexcept
    {
        ++m_itr;
        return *this;
    }
    general_span_iterator operator++(int) noexcept
    {
        auto ret = *this;
        ++(*this);
        return ret;
    }
    general_span_iterator& operator--() noexcept
    {
        --m_itr;
        return *this;
    }
    general_span_iterator operator--(int) noexcept
    {
        auto ret = *this;
        --(*this);
        return ret;
    }
    general_span_iterator operator+(difference_type n) const noexcept
    {
        general_span_iterator ret{*this};
        return ret += n;
    }
    general_span_iterator& operator+=(difference_type n) noexcept
    {
        m_itr += n;
        return *this;
    }
    general_span_iterator operator-(difference_type n) const noexcept
    {
        general_span_iterator ret{*this};
        return ret -= n;
    }
    general_span_iterator& operator-=(difference_type n) noexcept { return *this += -n; }
    difference_type operator-(const general_span_iterator& rhs) const
    {
        Expects(m_container == rhs.m_container);
        return m_itr - rhs.m_itr;
    }

    GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
    value_type operator[](difference_type n) const { return (*m_container)[m_itr[n]]; }

    bool operator==(const general_span_iterator& rhs) const
    {
        Expects(m_container == rhs.m_container);
        return m_itr == rhs.m_itr;
    }
    bool operator!=(const general_span_iterator& rhs) const { return !(*this == rhs); }
    bool operator<(const general_span_iterator& rhs) const
    {
        Expects(m_container == rhs.m_container);
        return m_itr < rhs.m_itr;
    }
    bool operator<=(const general_span_iterator& rhs) const { return !(rhs < *this); }
    bool operator>(const general_span_iterator& rhs) const { return rhs < *this; }
    bool operator>=(const general_span_iterator& rhs) const { return !(rhs > *this); }
    void swap(general_span_iterator& rhs) noexcept
    {
        std::swap(m_itr, rhs.m_itr);
        std::swap(m_container, rhs.m_container);
    }
};

template <typename Span>
general_span_iterator<Span> operator+(typename general_span_iterator<Span>::difference_type n,
                                      const general_span_iterator<Span>& rhs) noexcept
{
    return rhs + n;
}

} // namespace gsl

#if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER < 1910

#undef constexpr
#pragma pop_macro("constexpr")
#endif // _MSC_VER < 1910

#pragma warning(pop)

#endif // _MSC_VER

#if defined(__GNUC__) && __GNUC__ > 6
#pragma GCC diagnostic pop
#endif // __GNUC__ > 6

#endif // GSL_MULTI_SPAN_H

D module-utils/gsl/pointers => module-utils/gsl/pointers +0 -294
@@ 1,294 0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef GSL_POINTERS_H
#define GSL_POINTERS_H

#include <gsl/gsl_assert>  // for Ensures, Expects

#include <algorithm>    // for forward
#include <iosfwd>       // for ptrdiff_t, nullptr_t, ostream, size_t
#include <memory>       // for shared_ptr, unique_ptr
#include <system_error> // for hash
#include <type_traits>  // for enable_if_t, is_convertible, is_assignable

#if defined(_MSC_VER) && _MSC_VER < 1910 && !defined(__clang__)
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/

#endif                          // defined(_MSC_VER) && _MSC_VER < 1910

namespace gsl
{

//
// GSL.owner: ownership pointers
//
using std::unique_ptr;
using std::shared_ptr;

//
// owner
//
// owner<T> is designed as a bridge for code that must deal directly with owning pointers for some reason
//
// T must be a pointer type
// - disallow construction from any type other than pointer type
//
template <class T, class = std::enable_if_t<std::is_pointer<T>::value>>
using owner = T;

//
// not_null
//
// Restricts a pointer or smart pointer to only hold non-null values.
//
// Has zero size overhead over T.
//
// If T is a pointer (i.e. T == U*) then
// - allow construction from U*
// - disallow construction from nullptr_t
// - disallow default construction
// - ensure construction from null U* fails
// - allow implicit conversion to U*
//
template <class T>
class not_null
{
public:
    static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");

    template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
    constexpr not_null(U&& u) : ptr_(std::forward<U>(u))
    {
        Expects(ptr_ != nullptr);
    }

    template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
    constexpr not_null(T u) : ptr_(u)
    {
        Expects(ptr_ != nullptr);
    }

    template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
    constexpr not_null(const not_null<U>& other) : not_null(other.get())
    {
    }

    not_null(not_null&& other) = default;
    not_null(const not_null& other) = default;
    not_null& operator=(const not_null& other) = default;

    constexpr T get() const
    {
        Ensures(ptr_ != nullptr);
        return ptr_;
    }

    constexpr operator T() const { return get(); }
    constexpr T operator->() const { return get(); }
    constexpr decltype(auto) operator*() const { return *get(); } 

    // prevents compilation when someone attempts to assign a null pointer constant
    not_null(std::nullptr_t) = delete;
    not_null& operator=(std::nullptr_t) = delete;

    // unwanted operators...pointers only point to single objects!
    not_null& operator++() = delete;
    not_null& operator--() = delete;
    not_null operator++(int) = delete;
    not_null operator--(int) = delete;
    not_null& operator+=(std::ptrdiff_t) = delete;
    not_null& operator-=(std::ptrdiff_t) = delete;
    void operator[](std::ptrdiff_t) const = delete;

private:
    T ptr_;
};

template <class T>
auto make_not_null(T&& t) {
    return not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
}

template <class T>
std::ostream& operator<<(std::ostream& os, const not_null<T>& val)
{
    os << val.get();
    return os;
}

template <class T, class U>
auto operator==(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() == rhs.get())
{
    return lhs.get() == rhs.get();
}

template <class T, class U>
auto operator!=(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() != rhs.get())
{
    return lhs.get() != rhs.get();
}

template <class T, class U>
auto operator<(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() < rhs.get())
{
    return lhs.get() < rhs.get();
}

template <class T, class U>
auto operator<=(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() <= rhs.get())
{
    return lhs.get() <= rhs.get();
}

template <class T, class U>
auto operator>(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() > rhs.get())
{
    return lhs.get() > rhs.get();
}

template <class T, class U>
auto operator>=(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() >= rhs.get())
{
    return lhs.get() >= rhs.get();
}

// more unwanted operators
template <class T, class U>
std::ptrdiff_t operator-(const not_null<T>&, const not_null<U>&) = delete;
template <class T>
not_null<T> operator-(const not_null<T>&, std::ptrdiff_t) = delete;
template <class T>
not_null<T> operator+(const not_null<T>&, std::ptrdiff_t) = delete;
template <class T>
not_null<T> operator+(std::ptrdiff_t, const not_null<T>&) = delete;

} // namespace gsl

namespace std
{
template <class T>
struct hash<gsl::not_null<T>>
{
    std::size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value); }
};

} // namespace std

namespace gsl
{

//
// strict_not_null
//
// Restricts a pointer or smart pointer to only hold non-null values,
//
// - provides a strict (i.e. explicit contructor from T) wrapper of not_null
// - to be used for new code that wishes the design to be cleaner and make not_null
//   checks intentional, or in old code that would like to make the transition.
//
//   To make the transition from not_null, incrementally replace not_null
//   by strict_not_null and fix compilation errors
//
//   Expect to
//   - remove all unneded conversions from raw pointer to not_null and back
//   - make API clear by specifyning not_null in parameters where needed
//   - remove unnesessary asserts
//
template <class T>
class strict_not_null: public not_null<T>
{
public:

    template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
    constexpr explicit strict_not_null(U&& u) :
        not_null<T>(std::forward<U>(u))
    {}

    template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
    constexpr explicit strict_not_null(T u) :
        not_null<T>(u)
    {}

    template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
    constexpr strict_not_null(const not_null<U>& other) :
        not_null<T>(other)
    {}

    template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
    constexpr strict_not_null(const strict_not_null<U>& other) :
        not_null<T>(other)
    {}

    strict_not_null(strict_not_null&& other) = default;
    strict_not_null(const strict_not_null& other) = default;
    strict_not_null& operator=(const strict_not_null& other) = default;
    strict_not_null& operator=(const not_null<T>& other)
    {
        not_null<T>::operator=(other);
        return *this;
    }

    // prevents compilation when someone attempts to assign a null pointer constant
    strict_not_null(std::nullptr_t) = delete;
    strict_not_null& operator=(std::nullptr_t) = delete;

    // unwanted operators...pointers only point to single objects!
    strict_not_null& operator++() = delete;
    strict_not_null& operator--() = delete;
    strict_not_null operator++(int) = delete;
    strict_not_null operator--(int) = delete;
    strict_not_null& operator+=(std::ptrdiff_t) = delete;
    strict_not_null& operator-=(std::ptrdiff_t) = delete;
    void operator[](std::ptrdiff_t) const = delete;
};

// more unwanted operators
template <class T, class U>
std::ptrdiff_t operator-(const strict_not_null<T>&, const strict_not_null<U>&) = delete;
template <class T>
strict_not_null<T> operator-(const strict_not_null<T>&, std::ptrdiff_t) = delete;
template <class T>
strict_not_null<T> operator+(const strict_not_null<T>&, std::ptrdiff_t) = delete;
template <class T>
strict_not_null<T> operator+(std::ptrdiff_t, const strict_not_null<T>&) = delete;

template <class T>
auto make_strict_not_null(T&& t) {
    return strict_not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
}

} // namespace gsl

namespace std
{
template <class T>
struct hash<gsl::strict_not_null<T>>
{
    std::size_t operator()(const gsl::strict_not_null<T>& value) const { return hash<T>{}(value); }
};

} // namespace std

#if defined(_MSC_VER) && _MSC_VER < 1910 && !defined(__clang__)

#undef constexpr
#pragma pop_macro("constexpr")

#endif // defined(_MSC_VER) && _MSC_VER < 1910 && !defined(__clang__)

#endif // GSL_POINTERS_H

D module-utils/gsl/span => module-utils/gsl/span +0 -793
@@ 1,793 0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef GSL_SPAN_H
#define GSL_SPAN_H

#include <gsl/gsl_assert> // for Expects
#include <gsl/gsl_byte>   // for byte
#include <gsl/gsl_util>   // for narrow_cast, narrow

#include <algorithm> // for lexicographical_compare
#include <array>     // for array
#include <cstddef>   // for ptrdiff_t, size_t, nullptr_t
#include <iterator>  // for reverse_iterator, distance, random_access_...
#include <limits>
#include <stdexcept>
#include <type_traits> // for enable_if_t, declval, is_convertible, inte...
#include <utility>
#include <memory> // for std::addressof

#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)

// turn off some warnings that are noisy about our Expects statements
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4702) // unreachable code

// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
#pragma warning(disable : 26495) // uninitalized member when constructor calls constructor
#pragma warning(disable : 26446) // parser bug does not allow attributes on some templates

#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND

#endif // _MSC_VER < 1910
#endif // _MSC_VER

// See if we have enough C++17 power to use a static constexpr data member
// without needing an out-of-line definition
#if !(defined(__cplusplus) && (__cplusplus >= 201703L))
#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
#endif // !(defined(__cplusplus) && (__cplusplus >= 201703L))

// GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t)
// While there is a conversion from signed to unsigned, it happens at
// compiletime, so the compiler wouldn't have to warn indiscriminently, but
// could check if the source value actually doesn't fit into the target type
// and only warn in those cases.
#if defined(__GNUC__) && __GNUC__ > 6
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif

namespace gsl
{

// [views.constants], constants
constexpr const std::ptrdiff_t dynamic_extent = -1;

template <class ElementType, std::ptrdiff_t Extent = dynamic_extent>
class span;

// implementation details
namespace details
{
    template <class T>
    struct is_span_oracle : std::false_type
    {
    };

    template <class ElementType, std::ptrdiff_t Extent>
    struct is_span_oracle<gsl::span<ElementType, Extent>> : std::true_type
    {
    };

    template <class T>
    struct is_span : public is_span_oracle<std::remove_cv_t<T>>
    {
    };

    template <class T>
    struct is_std_array_oracle : std::false_type
    {
    };

    template <class ElementType, std::size_t Extent>
    struct is_std_array_oracle<std::array<ElementType, Extent>> : std::true_type
    {
    };

    template <class T>
    struct is_std_array : public is_std_array_oracle<std::remove_cv_t<T>>
    {
    };

    template <std::ptrdiff_t From, std::ptrdiff_t To>
    struct is_allowed_extent_conversion
        : public std::integral_constant<bool, From == To || From == gsl::dynamic_extent ||
                                                  To == gsl::dynamic_extent>
    {
    };

    template <class From, class To>
    struct is_allowed_element_type_conversion
        : public std::integral_constant<bool, std::is_convertible<From (*)[], To (*)[]>::value>
    {
    };

    template <class Span, bool IsConst>
    class span_iterator
    {
        using element_type_ = typename Span::element_type;

    public:
#ifdef _MSC_VER
        // Tell Microsoft standard library that span_iterators are checked.
        using _Unchecked_type = typename Span::pointer;
#endif

        using iterator_category = std::random_access_iterator_tag;
        using value_type = std::remove_cv_t<element_type_>;
        using difference_type = typename Span::index_type;

        using reference = std::conditional_t<IsConst, const element_type_, element_type_>&;
        using pointer = std::add_pointer_t<reference>;

        span_iterator() = default;

        constexpr span_iterator(const Span* span, typename Span::index_type idx) noexcept
            : span_(span), index_(idx)
        {}

        friend span_iterator<Span, true>;
        template <bool B, std::enable_if_t<!B && IsConst>* = nullptr>
        constexpr span_iterator(const span_iterator<Span, B>& other) noexcept
            : span_iterator(other.span_, other.index_)
        {}

        GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
        constexpr reference operator*() const
        {
            Expects(index_ != span_->size());
            return *(span_->data() + index_);
        }

        constexpr pointer operator->() const
        {
            Expects(index_ != span_->size());
            return span_->data() + index_;
        }

        constexpr span_iterator& operator++()
        {
            Expects(0 <= index_ && index_ != span_->size());
            ++index_;
            return *this;
        }

        constexpr span_iterator operator++(int)
        {
            auto ret = *this;
            ++(*this);
            return ret;
        }

        constexpr span_iterator& operator--()
        {
            Expects(index_ != 0 && index_ <= span_->size());
            --index_;
            return *this;
        }

        constexpr span_iterator operator--(int)
        {
            auto ret = *this;
            --(*this);
            return ret;
        }

        constexpr span_iterator operator+(difference_type n) const
        {
            auto ret = *this;
            return ret += n;
        }

        friend constexpr span_iterator operator+(difference_type n, span_iterator const& rhs)
        {
            return rhs + n;
        }

        constexpr span_iterator& operator+=(difference_type n)
        {
            Expects((index_ + n) >= 0 && (index_ + n) <= span_->size());
            index_ += n;
            return *this;
        }

        constexpr span_iterator operator-(difference_type n) const
        {
            auto ret = *this;
            return ret -= n;
        }

        constexpr span_iterator& operator-=(difference_type n) { return *this += -n; }

        constexpr difference_type operator-(span_iterator rhs) const
        {
            Expects(span_ == rhs.span_);
            return index_ - rhs.index_;
        }

        constexpr reference operator[](difference_type n) const { return *(*this + n); }

        constexpr friend bool operator==(span_iterator lhs, span_iterator rhs) noexcept
        {
            return lhs.span_ == rhs.span_ && lhs.index_ == rhs.index_;
        }

        constexpr friend bool operator!=(span_iterator lhs, span_iterator rhs) noexcept
        {
            return !(lhs == rhs);
        }

        constexpr friend bool operator<(span_iterator lhs, span_iterator rhs) noexcept
        {
            return lhs.index_ < rhs.index_;
        }

        constexpr friend bool operator<=(span_iterator lhs, span_iterator rhs) noexcept
        {
            return !(rhs < lhs);
        }

        constexpr friend bool operator>(span_iterator lhs, span_iterator rhs) noexcept
        {
            return rhs < lhs;
        }

        constexpr friend bool operator>=(span_iterator lhs, span_iterator rhs) noexcept
        {
            return !(rhs > lhs);
        }

#ifdef _MSC_VER
        // MSVC++ iterator debugging support; allows STL algorithms in 15.8+
        // to unwrap span_iterator to a pointer type after a range check in STL
        // algorithm calls
        friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept
        { // test that [lhs, rhs) forms a valid range inside an STL algorithm
            Expects(lhs.span_ == rhs.span_        // range spans have to match
                    && lhs.index_ <= rhs.index_); // range must not be transposed
        }

        constexpr void _Verify_offset(const difference_type n) const noexcept
        { // test that the iterator *this + n is a valid range in an STL
            // algorithm call
            Expects((index_ + n) >= 0 && (index_ + n) <= span_->size());
        }

        GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
        constexpr pointer _Unwrapped() const noexcept
        { // after seeking *this to a high water mark, or using one of the
            // _Verify_xxx functions above, unwrap this span_iterator to a raw
            // pointer
            return span_->data() + index_;
        }

        // Tell the STL that span_iterator should not be unwrapped if it can't
        // validate in advance, even in release / optimized builds:
#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
        static constexpr const bool _Unwrap_when_unverified = false;
#else
        static constexpr bool _Unwrap_when_unverified = false;
#endif
        GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive
        constexpr void _Seek_to(const pointer p) noexcept
        { // adjust the position of *this to previously verified location p
            // after _Unwrapped
            index_ = p - span_->data();
        }
#endif

    protected:
        const Span* span_ = nullptr;
        std::ptrdiff_t index_ = 0;
    };

    template <std::ptrdiff_t Ext>
    class extent_type
    {
    public:
        using index_type = std::ptrdiff_t;

        static_assert(Ext >= 0, "A fixed-size span must be >= 0 in size.");

        constexpr extent_type() noexcept {}

        template <index_type Other>
        constexpr extent_type(extent_type<Other> ext)
        {
            static_assert(Other == Ext || Other == dynamic_extent,
                          "Mismatch between fixed-size extent and size of initializing data.");
            Expects(ext.size() == Ext);
        }

        constexpr extent_type(index_type size) { Expects(size == Ext); }

        constexpr index_type size() const noexcept { return Ext; }
    };

    template <>
    class extent_type<dynamic_extent>
    {
    public:
        using index_type = std::ptrdiff_t;

        template <index_type Other>
        explicit constexpr extent_type(extent_type<Other> ext) : size_(ext.size())
        {}

        explicit constexpr extent_type(index_type size) : size_(size) { Expects(size >= 0); }

        constexpr index_type size() const noexcept { return size_; }

    private:
        index_type size_;
    };

    template <class ElementType, std::ptrdiff_t Extent, std::ptrdiff_t Offset, std::ptrdiff_t Count>
    struct calculate_subspan_type
    {
        using type = span<ElementType, Count != dynamic_extent
                                           ? Count
                                           : (Extent != dynamic_extent ? Extent - Offset : Extent)>;
    };
} // namespace details

// [span], class template span
template <class ElementType, std::ptrdiff_t Extent>
class span
{
public:
    // constants and types
    using element_type = ElementType;
    using value_type = std::remove_cv_t<ElementType>;
    using index_type = std::ptrdiff_t;
    using pointer = element_type*;
    using reference = element_type&;

    using iterator = details::span_iterator<span<ElementType, Extent>, false>;
    using const_iterator = details::span_iterator<span<ElementType, Extent>, true>;
    using reverse_iterator = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    using size_type = index_type;

#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
    static constexpr const index_type extent{Extent};
#else
    static constexpr index_type extent{Extent};
#endif

    // [span.cons], span constructors, copy, assignment, and destructor
    template <bool Dependent = false,
              // "Dependent" is needed to make "std::enable_if_t<Dependent || Extent <= 0>" SFINAE,
              // since "std::enable_if_t<Extent <= 0>" is ill-formed when Extent is greater than 0.
              class = std::enable_if_t<(Dependent || Extent <= 0)>>
    constexpr span() noexcept : storage_(nullptr, details::extent_type<0>())
    {}

    constexpr span(pointer ptr, index_type count) : storage_(ptr, count) {}

    constexpr span(pointer firstElem, pointer lastElem)
        : storage_(firstElem, std::distance(firstElem, lastElem))
    {}

    template <std::size_t N>
    constexpr span(element_type (&arr)[N]) noexcept
        : storage_(KnownNotNull{std::addressof(arr[0])}, details::extent_type<N>())
    {}

    template <std::size_t N, class = std::enable_if_t<(N > 0)>>
    constexpr span(std::array<std::remove_const_t<element_type>, N>& arr) noexcept
        : storage_(KnownNotNull{arr.data()}, details::extent_type<N>())
    {
    }

    constexpr span(std::array<std::remove_const_t<element_type>, 0>&) noexcept
        : storage_(static_cast<pointer>(nullptr), details::extent_type<0>())
    {
    }

    template <std::size_t N, class = std::enable_if_t<(N > 0)>>
    constexpr span(const std::array<std::remove_const_t<element_type>, N>& arr) noexcept
        : storage_(KnownNotNull{arr.data()}, details::extent_type<N>())
    {
    }

    constexpr span(const std::array<std::remove_const_t<element_type>, 0>&) noexcept
        : storage_(static_cast<pointer>(nullptr), details::extent_type<0>())
    {
    }

    // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement
    // on Container to be a contiguous sequence container.
    template <class Container,
              class = std::enable_if_t<
                  !details::is_span<Container>::value && !details::is_std_array<Container>::value &&
                  std::is_convertible<typename Container::pointer, pointer>::value &&
                  std::is_convertible<typename Container::pointer,
                                      decltype(std::declval<Container>().data())>::value>>
    constexpr span(Container& cont) : span(cont.data(), narrow<index_type>(cont.size()))
    {}

    template <class Container,
              class = std::enable_if_t<
                  std::is_const<element_type>::value && !details::is_span<Container>::value &&
                  std::is_convertible<typename Container::pointer, pointer>::value &&
                  std::is_convertible<typename Container::pointer,
                                      decltype(std::declval<Container>().data())>::value>>
    constexpr span(const Container& cont) : span(cont.data(), narrow<index_type>(cont.size()))
    {}

    constexpr span(const span& other) noexcept = default;

    template <
        class OtherElementType, std::ptrdiff_t OtherExtent,
        class = std::enable_if_t<
            details::is_allowed_extent_conversion<OtherExtent, Extent>::value &&
            details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>>
    constexpr span(const span<OtherElementType, OtherExtent>& other)
        : storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
    {}

    ~span() noexcept = default;
    constexpr span& operator=(const span& other) noexcept = default;

    // [span.sub], span subviews
    template <std::ptrdiff_t Count>
    constexpr span<element_type, Count> first() const
    {
        Expects(Count >= 0 && Count <= size());
        return {data(), Count};
    }

    template <std::ptrdiff_t Count>
    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    constexpr span<element_type, Count> last() const
    {
        Expects(Count >= 0 && size() - Count >= 0);
        return {data() + (size() - Count), Count};
    }

    template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent>
    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    constexpr auto subspan() const ->
        typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type
    {
        Expects((Offset >= 0 && size() - Offset >= 0) &&
                (Count == dynamic_extent || (Count >= 0 && Offset + Count <= size())));

        return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
    }

    constexpr span<element_type, dynamic_extent> first(index_type count) const
    {
        Expects(count >= 0 && count <= size());
        return {data(), count};
    }

    constexpr span<element_type, dynamic_extent> last(index_type count) const
    {
        return make_subspan(size() - count, dynamic_extent, subspan_selector<Extent>{});
    }

    constexpr span<element_type, dynamic_extent> subspan(index_type offset,
                                                         index_type count = dynamic_extent) const
    {
        return make_subspan(offset, count, subspan_selector<Extent>{});
    }

    // [span.obs], span observers
    constexpr index_type size() const noexcept { return storage_.size(); }
    constexpr index_type size_bytes() const noexcept
    {
        return size() * narrow_cast<index_type>(sizeof(element_type));
    }
    constexpr bool empty() const noexcept { return size() == 0; }

    // [span.elem], span element access
    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    constexpr reference operator[](index_type idx) const
    {
        Expects(CheckRange(idx, storage_.size()));
        return data()[idx];
    }

    constexpr reference at(index_type idx) const { return this->operator[](idx); }
    constexpr reference operator()(index_type idx) const { return this->operator[](idx); }
    constexpr pointer data() const noexcept { return storage_.data(); }

    // [span.iter], span iterator support
    constexpr iterator begin() const noexcept { return {this, 0}; }
    constexpr iterator end() const noexcept { return {this, size()}; }

    constexpr const_iterator cbegin() const noexcept { return {this, 0}; }
    constexpr const_iterator cend() const noexcept { return {this, size()}; }

    constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
    constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }

    constexpr const_reverse_iterator crbegin() const noexcept
    {
        return const_reverse_iterator{cend()};
    }
    constexpr const_reverse_iterator crend() const noexcept
    {
        return const_reverse_iterator{cbegin()};
    }

#ifdef _MSC_VER
    // Tell MSVC how to unwrap spans in range-based-for
    constexpr pointer _Unchecked_begin() const noexcept { return data(); }
    constexpr pointer _Unchecked_end() const noexcept
    {
        GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
        return data() + size();
    }
#endif // _MSC_VER

private:
    static constexpr bool CheckRange(index_type idx, index_type size) noexcept
    {
        // Optimization:
        //
        // idx >= 0 && idx < size
        // =>
        // static_cast<size_t>(idx) < static_cast<size_t>(size)
        //
        // because size >=0 by span construction, and negative idx will
        // wrap around to a value always greater than size when casted.

        // check if we have enough space to wrap around
#if defined(__cpp_if_constexpr)
        if constexpr (sizeof(index_type) <= sizeof(size_t))
#else
        if (sizeof(index_type) <= sizeof(size_t))
#endif
        {
            return narrow_cast<size_t>(idx) < narrow_cast<size_t>(size);
        }
        else
        {
            return idx >= 0 && idx < size;
        }
    }

    // Needed to remove unnecessary null check in subspans
    struct KnownNotNull
    {
        pointer p;
    };

    // this implementation detail class lets us take advantage of the
    // empty base class optimization to pay for only storage of a single
    // pointer in the case of fixed-size spans
    template <class ExtentType>
    class storage_type : public ExtentType
    {
    public:
        // KnownNotNull parameter is needed to remove unnecessary null check
        // in subspans and constructors from arrays
        template <class OtherExtentType>
        constexpr storage_type(KnownNotNull data, OtherExtentType ext)
            : ExtentType(ext), data_(data.p)
        {
            Expects(ExtentType::size() >= 0);
        }

        template <class OtherExtentType>
        constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data)
        {
            Expects(ExtentType::size() >= 0);
            Expects(data || ExtentType::size() == 0);
        }

        constexpr pointer data() const noexcept { return data_; }

    private:
        pointer data_;
    };

    storage_type<details::extent_type<Extent>> storage_;

    // The rest is needed to remove unnecessary null check
    // in subspans and constructors from arrays
    constexpr span(KnownNotNull ptr, index_type count) : storage_(ptr, count) {}

    template <std::ptrdiff_t CallerExtent>
    class subspan_selector
    {
    };

    template <std::ptrdiff_t CallerExtent>
    span<element_type, dynamic_extent> make_subspan(index_type offset, index_type count,
                                                    subspan_selector<CallerExtent>) const
    {
        const span<element_type, dynamic_extent> tmp(*this);
        return tmp.subspan(offset, count);
    }

    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
    span<element_type, dynamic_extent> make_subspan(index_type offset, index_type count,
                                                    subspan_selector<dynamic_extent>) const
    {
        Expects(offset >= 0 && size() - offset >= 0);

        if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; }

        Expects(count >= 0 && size() - offset >= count);
        return {KnownNotNull{data() + offset}, count};
    }
};

#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
template <class ElementType, std::ptrdiff_t Extent>
constexpr const typename span<ElementType, Extent>::index_type span<ElementType, Extent>::extent;
#endif

// [span.comparison], span comparison operators
template <class ElementType, std::ptrdiff_t FirstExtent, std::ptrdiff_t SecondExtent>
constexpr bool operator==(span<ElementType, FirstExtent> l, span<ElementType, SecondExtent> r)
{
    return std::equal(l.begin(), l.end(), r.begin(), r.end());
}

template <class ElementType, std::ptrdiff_t Extent>
constexpr bool operator!=(span<ElementType, Extent> l, span<ElementType, Extent> r)
{
    return !(l == r);
}

template <class ElementType, std::ptrdiff_t Extent>
constexpr bool operator<(span<ElementType, Extent> l, span<ElementType, Extent> r)
{
    return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
}

template <class ElementType, std::ptrdiff_t Extent>
constexpr bool operator<=(span<ElementType, Extent> l, span<ElementType, Extent> r)
{
    return !(l > r);
}

template <class ElementType, std::ptrdiff_t Extent>
constexpr bool operator>(span<ElementType, Extent> l, span<ElementType, Extent> r)
{
    return r < l;
}

template <class ElementType, std::ptrdiff_t Extent>
constexpr bool operator>=(span<ElementType, Extent> l, span<ElementType, Extent> r)
{
    return !(l < r);
}

namespace details
{
    // if we only supported compilers with good constexpr support then
    // this pair of classes could collapse down to a constexpr function

    // we should use a narrow_cast<> to go to std::size_t, but older compilers may not see it as
    // constexpr
    // and so will fail compilation of the template
    template <class ElementType, std::ptrdiff_t Extent>
    struct calculate_byte_size
        : std::integral_constant<std::ptrdiff_t,
                                 static_cast<std::ptrdiff_t>(sizeof(ElementType) *
                                                             static_cast<std::size_t>(Extent))>
    {
    };

    template <class ElementType>
    struct calculate_byte_size<ElementType, dynamic_extent>
        : std::integral_constant<std::ptrdiff_t, dynamic_extent>
    {
    };
} // namespace details

// [span.objectrep], views of object representation
template <class ElementType, std::ptrdiff_t Extent>
span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
as_bytes(span<ElementType, Extent> s) noexcept
{
    GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
    return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
}

template <class ElementType, std::ptrdiff_t Extent,
          class = std::enable_if_t<!std::is_const<ElementType>::value>>
span<byte, details::calculate_byte_size<ElementType, Extent>::value>
as_writeable_bytes(span<ElementType, Extent> s) noexcept
{
    GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
    return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
}

//
// make_span() - Utility functions for creating spans
//
template <class ElementType>
constexpr span<ElementType> make_span(ElementType* ptr,
                                      typename span<ElementType>::index_type count)
{
    return span<ElementType>(ptr, count);
}

template <class ElementType>
constexpr span<ElementType> make_span(ElementType* firstElem, ElementType* lastElem)
{
    return span<ElementType>(firstElem, lastElem);
}

template <class ElementType, std::size_t N>
constexpr span<ElementType, N> make_span(ElementType (&arr)[N]) noexcept
{
    return span<ElementType, N>(arr);
}

template <class Container>
constexpr span<typename Container::value_type> make_span(Container& cont)
{
    return span<typename Container::value_type>(cont);
}

template <class Container>
constexpr span<const typename Container::value_type> make_span(const Container& cont)
{
    return span<const typename Container::value_type>(cont);
}

template <class Ptr>
constexpr span<typename Ptr::element_type> make_span(Ptr& cont, std::ptrdiff_t count)
{
    return span<typename Ptr::element_type>(cont, count);
}

template <class Ptr>
constexpr span<typename Ptr::element_type> make_span(Ptr& cont)
{
    return span<typename Ptr::element_type>(cont);
}

// Specialization of gsl::at for span
template <class ElementType, std::ptrdiff_t Extent>
constexpr ElementType& at(span<ElementType, Extent> s, index i)
{
    // No bounds checking here because it is done in span::operator[] called below
    return s[i];
}

} // namespace gsl

#if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER < 1910
#undef constexpr
#pragma pop_macro("constexpr")

#endif // _MSC_VER < 1910

#pragma warning(pop)
#endif // _MSC_VER

#if defined(__GNUC__) && __GNUC__ > 6
#pragma GCC diagnostic pop
#endif // __GNUC__ > 6

#endif // GSL_SPAN_H

D module-utils/gsl/string_span => module-utils/gsl/string_span +0 -722
@@ 1,722 0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef GSL_STRING_SPAN_H
#define GSL_STRING_SPAN_H

#include <gsl/gsl_assert> // for Ensures, Expects
#include <gsl/gsl_util>   // for narrow_cast
#include <gsl/span>       // for operator!=, operator==, dynamic_extent
#include <gsl/pointers>   // for not_null

#include <algorithm> // for equal, lexicographical_compare
#include <array>     // for array
#include <cstddef>   // for ptrdiff_t, size_t, nullptr_t
#include <cstdint>   // for PTRDIFF_MAX
#include <cstring>
#include <string>      // for basic_string, allocator, char_traits
#include <type_traits> // for declval, is_convertible, enable_if_t, add_...

#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)

// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
#pragma warning(disable : 26446) // TODO: bug in parser - attributes and templates
#pragma warning(disable : 26481) // TODO: suppress does not work inside templates sometimes

#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/

#endif // _MSC_VER < 1910
#endif // _MSC_VER

namespace gsl
{
//
// czstring and wzstring
//
// These are "tag" typedefs for C-style strings (i.e. null-terminated character arrays)
// that allow static analysis to help find bugs.
//
// There are no additional features/semantics that we can find a way to add inside the
// type system for these types that will not either incur significant runtime costs or
// (sometimes needlessly) break existing programs when introduced.
//

template <typename CharT, std::ptrdiff_t Extent = dynamic_extent>
using basic_zstring = CharT*;

template <std::ptrdiff_t Extent = dynamic_extent>
using czstring = basic_zstring<const char, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using cwzstring = basic_zstring<const wchar_t, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using cu16zstring = basic_zstring<const char16_t, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using cu32zstring = basic_zstring<const char32_t, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using zstring = basic_zstring<char, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using wzstring = basic_zstring<wchar_t, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using u16zstring = basic_zstring<char16_t, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using u32zstring = basic_zstring<char32_t, Extent>;

namespace details
{
    template <class CharT>
    std::ptrdiff_t string_length(const CharT* str, std::ptrdiff_t n)
    {
        if (str == nullptr || n <= 0) return 0;

        const span<const CharT> str_span{str, n};

        std::ptrdiff_t len = 0;
        while (len < n && str_span[len]) len++;

        return len;
    }
} // namespace details

//
// ensure_sentinel()
//
// Provides a way to obtain an span from a contiguous sequence
// that ends with a (non-inclusive) sentinel value.
//
// Will fail-fast if sentinel cannot be found before max elements are examined.
//
template <typename T, const T Sentinel>
span<T, dynamic_extent> ensure_sentinel(T* seq, std::ptrdiff_t max = PTRDIFF_MAX)
{
    Ensures(seq != nullptr);

    GSL_SUPPRESS(f.23) // NO-FORMAT: attribute // TODO: false positive // TODO: suppress does not work
    auto cur = seq;
    Ensures(cur != nullptr); // workaround for removing the warning

    GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // TODO: suppress does not work
    while ((cur - seq) < max && *cur != Sentinel) ++cur;
    Ensures(*cur == Sentinel);
    return {seq, cur - seq};
}

//
// ensure_z - creates a span for a zero terminated strings.
// Will fail fast if a null-terminator cannot be found before
// the limit of size_type.
//
template <typename CharT>
span<CharT, dynamic_extent> ensure_z(CharT* const& sz, std::ptrdiff_t max = PTRDIFF_MAX)
{
    return ensure_sentinel<CharT, CharT(0)>(sz, max);
}

template <typename CharT, std::size_t N>
span<CharT, dynamic_extent> ensure_z(CharT (&sz)[N])
{
    return ensure_z(&sz[0], narrow_cast<std::ptrdiff_t>(N));
}

template <class Cont>
span<typename std::remove_pointer<typename Cont::pointer>::type, dynamic_extent>
ensure_z(Cont& cont)
{
    return ensure_z(cont.data(), narrow_cast<std::ptrdiff_t>(cont.size()));
}

template <typename CharT, std::ptrdiff_t>
class basic_string_span;

namespace details {
    template <typename T>
    struct is_basic_string_span_oracle : std::false_type
    {
    };

    template <typename CharT, std::ptrdiff_t Extent>
    struct is_basic_string_span_oracle<basic_string_span<CharT, Extent>> : std::true_type
    {
    };

    template <typename T>
    struct is_basic_string_span : is_basic_string_span_oracle<std::remove_cv_t<T>>
    {
    };
} // namespace details

//
// string_span and relatives
//
template <typename CharT, std::ptrdiff_t Extent = dynamic_extent>
class basic_string_span
{
public:
    using element_type = CharT;
    using value_type = std::remove_cv_t<element_type>;
    using pointer = std::add_pointer_t<element_type>;
    using reference = std::add_lvalue_reference_t<element_type>;
    using const_reference = std::add_lvalue_reference_t<std::add_const_t<element_type>>;
    using impl_type = span<element_type, Extent>;

    using index_type = typename impl_type::index_type;
    using iterator = typename impl_type::iterator;
    using const_iterator = typename impl_type::const_iterator;
    using reverse_iterator = typename impl_type::reverse_iterator;
    using const_reverse_iterator = typename impl_type::const_reverse_iterator;

    using size_type = index_type;

    // default (empty)
    constexpr basic_string_span() noexcept = default;

    // copy
    constexpr basic_string_span(const basic_string_span& other) noexcept = default;

    // assign
    constexpr basic_string_span& operator=(const basic_string_span& other) noexcept = default;

    constexpr basic_string_span(pointer ptr, index_type length) : span_(ptr, length) {}
    constexpr basic_string_span(pointer firstElem, pointer lastElem) : span_(firstElem, lastElem) {}

    // From static arrays - if 0-terminated, remove 0 from the view
    // All other containers allow 0s within the length, so we do not remove them
    template <std::size_t N>
    constexpr basic_string_span(element_type (&arr)[N]) : span_(remove_z(arr))
    {}

    template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
    constexpr basic_string_span(std::array<ArrayElementType, N>& arr) noexcept : span_(arr)
    {}

    template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
    constexpr basic_string_span(const std::array<ArrayElementType, N>& arr) noexcept : span_(arr)
    {}

    // Container signature should work for basic_string after C++17 version exists
    template <class Traits, class Allocator>
    // GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug
    constexpr basic_string_span(std::basic_string<element_type, Traits, Allocator>& str)
        : span_(&str[0], narrow_cast<std::ptrdiff_t>(str.length()))
    {}

    template <class Traits, class Allocator>
    constexpr basic_string_span(const std::basic_string<element_type, Traits, Allocator>& str)
        : span_(&str[0], str.length())
    {}

    // from containers. Containers must have a pointer type and data() function signatures
    template <class Container,
              class = std::enable_if_t<
                  !details::is_basic_string_span<Container>::value &&
                  std::is_convertible<typename Container::pointer, pointer>::value &&
                  std::is_convertible<typename Container::pointer,
                                      decltype(std::declval<Container>().data())>::value>>
    constexpr basic_string_span(Container& cont) : span_(cont)
    {}

    template <class Container,
              class = std::enable_if_t<
                  !details::is_basic_string_span<Container>::value &&
                  std::is_convertible<typename Container::pointer, pointer>::value &&
                  std::is_convertible<typename Container::pointer,
                                      decltype(std::declval<Container>().data())>::value>>
    constexpr basic_string_span(const Container& cont) : span_(cont)
    {}

    // from string_span
    template <
        class OtherValueType, std::ptrdiff_t OtherExtent,
        class = std::enable_if_t<std::is_convertible<
            typename basic_string_span<OtherValueType, OtherExtent>::impl_type, impl_type>::value>>
    constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other)
        : span_(other.data(), other.length())
    {}

    template <index_type Count>
    constexpr basic_string_span<element_type, Count> first() const
    {
        return {span_.template first<Count>()};
    }

    constexpr basic_string_span<element_type, dynamic_extent> first(index_type count) const
    {
        return {span_.first(count)};
    }

    template <index_type Count>
    constexpr basic_string_span<element_type, Count> last() const
    {
        return {span_.template last<Count>()};
    }

    constexpr basic_string_span<element_type, dynamic_extent> last(index_type count) const
    {
        return {span_.last(count)};
    }

    template <index_type Offset, index_type Count>
    constexpr basic_string_span<element_type, Count> subspan() const
    {
        return {span_.template subspan<Offset, Count>()};
    }

    constexpr basic_string_span<element_type, dynamic_extent>
    subspan(index_type offset, index_type count = dynamic_extent) const
    {
        return {span_.subspan(offset, count)};
    }

    constexpr reference operator[](index_type idx) const { return span_[idx]; }
    constexpr reference operator()(index_type idx) const { return span_[idx]; }

    constexpr pointer data() const { return span_.data(); }

    constexpr index_type length() const noexcept { return span_.size(); }
    constexpr index_type size() const noexcept { return span_.size(); }
    constexpr index_type size_bytes() const noexcept { return span_.size_bytes(); }
    constexpr index_type length_bytes() const noexcept { return span_.length_bytes(); }
    constexpr bool empty() const noexcept { return size() == 0; }

    constexpr iterator begin() const noexcept { return span_.begin(); }
    constexpr iterator end() const noexcept { return span_.end(); }

    constexpr const_iterator cbegin() const noexcept { return span_.cbegin(); }
    constexpr const_iterator cend() const noexcept { return span_.cend(); }

    constexpr reverse_iterator rbegin() const noexcept { return span_.rbegin(); }
    constexpr reverse_iterator rend() const noexcept { return span_.rend(); }

    constexpr const_reverse_iterator crbegin() const noexcept { return span_.crbegin(); }
    constexpr const_reverse_iterator crend() const noexcept { return span_.crend(); }

private:
    static impl_type remove_z(pointer const& sz, std::ptrdiff_t max)
    {
        return {sz, details::string_length(sz, max)};
    }

    template <std::size_t N>
    static impl_type remove_z(element_type (&sz)[N])
    {
        return remove_z(&sz[0], narrow_cast<std::ptrdiff_t>(N));
    }

    impl_type span_;
};

template <std::ptrdiff_t Extent = dynamic_extent>
using string_span = basic_string_span<char, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using cstring_span = basic_string_span<const char, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using wstring_span = basic_string_span<wchar_t, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using cwstring_span = basic_string_span<const wchar_t, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using u16string_span = basic_string_span<char16_t, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using cu16string_span = basic_string_span<const char16_t, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using u32string_span = basic_string_span<char32_t, Extent>;

template <std::ptrdiff_t Extent = dynamic_extent>
using cu32string_span = basic_string_span<const char32_t, Extent>;

//
// to_string() allow (explicit) conversions from string_span to string
//

template <typename CharT, std::ptrdiff_t Extent>
std::basic_string<typename std::remove_const<CharT>::type>
to_string(basic_string_span<CharT, Extent> view)
{
    return {view.data(), narrow_cast<std::size_t>(view.length())};
}

template <typename CharT, typename Traits = typename std::char_traits<CharT>,
          typename Allocator = std::allocator<CharT>, typename gCharT, std::ptrdiff_t Extent>
std::basic_string<CharT, Traits, Allocator> to_basic_string(basic_string_span<gCharT, Extent> view)
{
    return {view.data(), narrow_cast<std::size_t>(view.length())};
}

template <class ElementType, std::ptrdiff_t Extent>
basic_string_span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
as_bytes(basic_string_span<ElementType, Extent> s) noexcept
{
    GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
    return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
}

template <class ElementType, std::ptrdiff_t Extent,
          class = std::enable_if_t<!std::is_const<ElementType>::value>>
basic_string_span<byte, details::calculate_byte_size<ElementType, Extent>::value>
as_writeable_bytes(basic_string_span<ElementType, Extent> s) noexcept
{
    GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
    return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
}

// zero-terminated string span, used to convert
// zero-terminated spans to legacy strings
template <typename CharT, std::ptrdiff_t Extent = dynamic_extent>
class basic_zstring_span {
public:
    using value_type = CharT;
    using const_value_type = std::add_const_t<CharT>;

    using pointer = std::add_pointer_t<value_type>;
    using const_pointer = std::add_pointer_t<const_value_type>;

    using zstring_type = basic_zstring<value_type, Extent>;
    using const_zstring_type = basic_zstring<const_value_type, Extent>;

    using impl_type = span<value_type, Extent>;
    using string_span_type = basic_string_span<value_type, Extent>;

    constexpr basic_zstring_span(impl_type s) : span_(s)
    {
        // expects a zero-terminated span
        Expects(s[s.size() - 1] == '\0');
    }

    // copy
    constexpr basic_zstring_span(const basic_zstring_span& other) = default;

    // move
    constexpr basic_zstring_span(basic_zstring_span&& other) = default;

    // assign
    constexpr basic_zstring_span& operator=(const basic_zstring_span& other) = default;

    // move assign
    constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default;

    constexpr bool empty() const noexcept { return span_.size() == 0; }

    constexpr string_span_type as_string_span() const noexcept
    {
        const auto sz = span_.size();
        return {span_.data(), sz > 1 ? sz - 1 : 0};
    }
    constexpr string_span_type ensure_z() const { return gsl::ensure_z(span_); }

    constexpr const_zstring_type assume_z() const noexcept { return span_.data(); }

private:
    impl_type span_;
};

template <std::ptrdiff_t Max = dynamic_extent>
using zstring_span = basic_zstring_span<char, Max>;

template <std::ptrdiff_t Max = dynamic_extent>
using wzstring_span = basic_zstring_span<wchar_t, Max>;

template <std::ptrdiff_t Max = dynamic_extent>
using u16zstring_span = basic_zstring_span<char16_t, Max>;

template <std::ptrdiff_t Max = dynamic_extent>
using u32zstring_span = basic_zstring_span<char32_t, Max>;

template <std::ptrdiff_t Max = dynamic_extent>
using czstring_span = basic_zstring_span<const char, Max>;

template <std::ptrdiff_t Max = dynamic_extent>
using cwzstring_span = basic_zstring_span<const wchar_t, Max>;

template <std::ptrdiff_t Max = dynamic_extent>
using cu16zstring_span = basic_zstring_span<const char16_t, Max>;

template <std::ptrdiff_t Max = dynamic_extent>
using cu32zstring_span = basic_zstring_span<const char32_t, Max>;

// operator ==
template <class CharT, std::ptrdiff_t Extent, class T,
          class = std::enable_if_t<
              details::is_basic_string_span<T>::value ||
              std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::value>>
bool operator==(const gsl::basic_string_span<CharT, Extent>& one, const T& other)
{
    const gsl::basic_string_span<std::add_const_t<CharT>> tmp(other);
    return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end());
}

template <class CharT, std::ptrdiff_t Extent, class T,
          class = std::enable_if_t<
              !details::is_basic_string_span<T>::value &&
              std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::value>>
bool operator==(const T& one, const gsl::basic_string_span<CharT, Extent>& other)
{
    const gsl::basic_string_span<std::add_const_t<CharT>> tmp(one);
    return std::equal(tmp.begin(), tmp.end(), other.begin(), other.end());
}

// operator !=
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
          typename = std::enable_if_t<std::is_convertible<
              T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
    return !(one == other);
}

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename = std::enable_if_t<
        std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
        !gsl::details::is_basic_string_span<T>::value>>
bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
    return !(one == other);
}

// operator<
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
          typename = std::enable_if_t<std::is_convertible<
              T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
    const gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
    return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end());
}

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename = std::enable_if_t<
        std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
        !gsl::details::is_basic_string_span<T>::value>>
bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
    gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
    return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end());
}

#ifndef _MSC_VER

// VS treats temp and const containers as convertible to basic_string_span,
// so the cases below are already covered by the previous operators

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename DataType = typename T::value_type,
    typename = std::enable_if_t<
        !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
        std::is_convertible<DataType*, CharT*>::value &&
        std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
                     DataType>::value>>
bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
    gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
    return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end());
}

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename DataType = typename T::value_type,
    typename = std::enable_if_t<
        !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
        std::is_convertible<DataType*, CharT*>::value &&
        std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
                     DataType>::value>>
bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
    gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
    return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end());
}
#endif

// operator <=
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
          typename = std::enable_if_t<std::is_convertible<
              T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
    return !(other < one);
}

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename = std::enable_if_t<
        std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
        !gsl::details::is_basic_string_span<T>::value>>
bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
    return !(other < one);
}

#ifndef _MSC_VER

// VS treats temp and const containers as convertible to basic_string_span,
// so the cases below are already covered by the previous operators

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename DataType = typename T::value_type,
    typename = std::enable_if_t<
        !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
        std::is_convertible<DataType*, CharT*>::value &&
        std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
                     DataType>::value>>
bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
    return !(other < one);
}

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename DataType = typename T::value_type,
    typename = std::enable_if_t<
        !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
        std::is_convertible<DataType*, CharT*>::value &&
        std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
                     DataType>::value>>
bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
    return !(other < one);
}
#endif

// operator>
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
          typename = std::enable_if_t<std::is_convertible<
              T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
    return other < one;
}

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename = std::enable_if_t<
        std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
        !gsl::details::is_basic_string_span<T>::value>>
bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
    return other < one;
}

#ifndef _MSC_VER

// VS treats temp and const containers as convertible to basic_string_span,
// so the cases below are already covered by the previous operators

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename DataType = typename T::value_type,
    typename = std::enable_if_t<
        !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
        std::is_convertible<DataType*, CharT*>::value &&
        std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
                     DataType>::value>>
bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
    return other < one;
}

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename DataType = typename T::value_type,
    typename = std::enable_if_t<
        !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
        std::is_convertible<DataType*, CharT*>::value &&
        std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
                     DataType>::value>>
bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
    return other < one;
}
#endif

// operator >=
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
          typename = std::enable_if_t<std::is_convertible<
              T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
    return !(one < other);
}

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename = std::enable_if_t<
        std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
        !gsl::details::is_basic_string_span<T>::value>>
bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
    return !(one < other);
}

#ifndef _MSC_VER

// VS treats temp and const containers as convertible to basic_string_span,
// so the cases below are already covered by the previous operators

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename DataType = typename T::value_type,
    typename = std::enable_if_t<
        !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
        std::is_convertible<DataType*, CharT*>::value &&
        std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
                     DataType>::value>>
bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{
    return !(one < other);
}

template <
    typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
    typename DataType = typename T::value_type,
    typename = std::enable_if_t<
        !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
        std::is_convertible<DataType*, CharT*>::value &&
        std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
                     DataType>::value>>
bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{
    return !(one < other);
}
#endif
} // namespace gsl

#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)

#if _MSC_VER < 1910
#undef constexpr
#pragma pop_macro("constexpr")

#endif // _MSC_VER < 1910
#endif // _MSC_VER

#endif // GSL_STRING_SPAN_H

M module-utils/log/Logger.cpp => module-utils/log/Logger.cpp +1 -1
@@ 3,7 3,7 @@

#include "critical.hpp"
#include <fstream>
#include <gsl/gsl_util>
#include <gsl/util>
#include "LockGuard.hpp"
#include "Logger.hpp"
#include "macros.h"

D module-utils/re2 => module-utils/re2 +0 -1
@@ 1,1 0,0 @@
Subproject commit a583c1f7d5d20be34856032ad76510691631c760

M module-utils/test/CMakeLists.txt => module-utils/test/CMakeLists.txt +2 -2
@@ 64,7 64,7 @@ add_catch2_executable(
        module-utils
        iosyscalls
    DEPS
        disk_image
        PurePhone-disk-img
)

# utils tests


@@ 77,7 77,7 @@ add_catch2_executable(
        module-utils
        iosyscalls
    DEPS
        disk_image
        PurePhone-disk-img
)

# Math tests

M module-utils/third-party/libphonenumber.cmake => module-utils/third-party/libphonenumber.cmake +6 -10
@@ 58,16 58,12 @@ set_source_files_properties (${LIBPHONENUMBER}/asyoutypeformatter.cc
# add include directory path
target_include_directories (${LIBPHONENUMBER_TARGET} PUBLIC ${LIBPHONENUMBER_SRCDIR})

# module-os dependency (locking support)
target_link_libraries (${LIBPHONENUMBER_TARGET} PUBLIC module-os)

# RE2 dependency
if (NOT RE2_TARGET)
        message (FATAL_ERROR "RE2 is required for libphonenumber")
endif ()
target_link_libraries (${LIBPHONENUMBER_TARGET} PUBLIC ${RE2_TARGET})

target_link_libraries (${LIBPHONENUMBER_TARGET} PUBLIC protobuf::libprotobuf-lite)
target_link_libraries (${LIBPHONENUMBER_TARGET} 
        PRIVATE 
                re2::re2
        PUBLIC 
                protobuf::libprotobuf-lite
)

# turn on optimization in debug
third_party_source_optimization (${LIBPHONENUMBER_SOURCES})

D module-utils/third-party/re2.cmake => module-utils/third-party/re2.cmake +0 -56
@@ 1,56 0,0 @@
include (thirdparty)

# add re2 library sources
set (RE2_SRCDIR ${CMAKE_CURRENT_SOURCE_DIR}/re2)
set (RE2_SOURCES
        ${RE2_SRCDIR}/re2/bitstate.cc
        ${RE2_SRCDIR}/re2/compile.cc
        ${RE2_SRCDIR}/re2/dfa.cc
        ${RE2_SRCDIR}/re2/filtered_re2.cc
        ${RE2_SRCDIR}/re2/mimics_pcre.cc
        ${RE2_SRCDIR}/re2/nfa.cc
        ${RE2_SRCDIR}/re2/onepass.cc
        ${RE2_SRCDIR}/re2/parse.cc
        ${RE2_SRCDIR}/re2/perl_groups.cc
        ${RE2_SRCDIR}/re2/prefilter.cc
        ${RE2_SRCDIR}/re2/prefilter_tree.cc
        ${RE2_SRCDIR}/re2/prog.cc
        ${RE2_SRCDIR}/re2/re2.cc
        ${RE2_SRCDIR}/re2/regexp.cc
        ${RE2_SRCDIR}/re2/set.cc
        ${RE2_SRCDIR}/re2/simplify.cc
        ${RE2_SRCDIR}/re2/stringpiece.cc
        ${RE2_SRCDIR}/re2/tostring.cc
        ${RE2_SRCDIR}/re2/unicode_casefold.cc
        ${RE2_SRCDIR}/re2/unicode_groups.cc
        ${RE2_SRCDIR}/util/rune.cc
        ${RE2_SRCDIR}/util/strutil.cc
)

# create static library for the third party
set (RE2_TARGET re2)
add_library (${RE2_TARGET} STATIC ${RE2_SOURCES})

# setup flags for the third party
third_party_target_setup (${RE2_TARGET})

# use FreeRTOS cpp wrapper to provide thread safety
target_compile_definitions (${RE2_TARGET}
	PUBLIC
	RE2_USE_RTOS_WRAPPER
)

# suppress warning for RE2 to avoid big changes in the original library
set_source_files_properties (${RE2_SRCDIR}/re2/perl_groups.cc
        PROPERTIES COMPILE_FLAGS
        -Wno-missing-field-initializers
)

# add include directory path
target_include_directories(${RE2_TARGET} PUBLIC ${RE2_SRCDIR})

# module-os dependency (locking support)
target_link_libraries (${RE2_TARGET} PUBLIC module-os)

# optimize thirdy party sources in dbeug
third_party_source_optimization(${RE2_SOURCES})

M module-vfs/CMakeLists.txt => module-vfs/CMakeLists.txt +13 -15
@@ 5,8 5,6 @@ project(module-vfs VERSION 1.0

module_is_test_entity()

add_subdirectory(thirdparty/lfsfs)

set(FF_FAT_SOURCES_THIRDPARTY
        ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/fatfs/source/ff.c
        ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/fatfs/source/ffunicode.c


@@ 51,7 49,6 @@ endif()

add_library(${PROJECT_NAME} STATIC ${SOURCES} ${BOARD_SOURCES})


# Board specific compilation definitions,options,include directories and features
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_CONFIG_DEFINITIONS})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_TARGET})


@@ 63,26 60,27 @@ target_compile_features(${PROJECT_NAME} PUBLIC ${TARGET_COMPILE_FEATURES})
target_compile_options(${PROJECT_NAME} PUBLIC ${TARGET_COMPILE_OPTIONS})
target_link_options(${PROJECT_NAME} PUBLIC ${TARGET_LINK_OPTIONS})

target_compile_definitions(${PROJECT_NAME}
        PUBLIC
)

target_include_directories(${PROJECT_NAME}
        PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}/include/user
    PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}/include/user/
        ${CMAKE_CURRENT_SOURCE_DIR}/drivers/include
)

target_include_directories(${PROJECT_NAME}
        PRIVATE
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/include/internal
        ${CMAKE_CURRENT_SOURCE_DIR}/drivers/include/thirdparty/fatfs
        ${CMAKE_CURRENT_SOURCE_DIR}/drivers/include/thirdparty
        ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/fatfs/source
)

target_link_libraries(${PROJECT_NAME} PUBLIC ${TARGET_LIBRARIES} module-os module-sys module-bsp module-utils)
target_link_libraries(${PROJECT_NAME} PRIVATE littlefs)
target_link_libraries(${PROJECT_NAME} 
    PUBLIC 
        ${TARGET_LIBRARIES} 
        module-os
        module-sys
        module-bsp 
        module-utils
    PRIVATE 
        littlefs::littlefs
)

if (${ENABLE_TESTS})
    add_subdirectory(tests)

M module-vfs/drivers/include/purefs/fs/drivers/directory_handle_littlefs.hpp => module-vfs/drivers/include/purefs/fs/drivers/directory_handle_littlefs.hpp +2 -2
@@ 1,10 1,10 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <purefs/fs/directory_handle.hpp>
#include <littlefs/lfs.h>
#include <lfs.h>

namespace purefs::fs::drivers
{

M module-vfs/drivers/include/purefs/fs/drivers/file_handle_littlefs.hpp => module-vfs/drivers/include/purefs/fs/drivers/file_handle_littlefs.hpp +2 -2
@@ 1,10 1,10 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <purefs/fs/file_handle.hpp>
#include <littlefs/lfs.h>
#include <lfs.h>

namespace purefs::fs::drivers
{

M module-vfs/drivers/include/purefs/fs/drivers/mount_point_littlefs.hpp => module-vfs/drivers/include/purefs/fs/drivers/mount_point_littlefs.hpp +2 -2
@@ 1,8 1,8 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include <purefs/fs/mount_point.hpp>
#include <littlefs/lfs.h>
#include <lfs.h>

namespace purefs::fs::drivers
{

M module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp => module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp +1 -1
@@ 9,7 9,7 @@
#include <purefs/blkdev/disk_manager.hpp>
#include <purefs/blkdev/disk_handle.hpp>
#include <purefs/fs/mount_flags.hpp>
#include <littlefs/lfs.h>
#include <lfs.h>
#include <log/log.hpp>

#include <climits>

M module-vfs/drivers/src/thirdparty/littlefs/lfs_glue.cpp => module-vfs/drivers/src/thirdparty/littlefs/lfs_glue.cpp +1 -1
@@ 1,7 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <littlefs/volume_mapper.hpp>
#include <littlefs/lfs.h>
#include <lfs.h>
#include <purefs/blkdev/disk_handle.hpp>
#include <purefs/blkdev/disk_manager.hpp>
#include <log/log.hpp>

D module-vfs/thirdparty/lfsfs/CMakeLists.txt => module-vfs/thirdparty/lfsfs/CMakeLists.txt +0 -40
@@ 1,40 0,0 @@
cmake_minimum_required(VERSION 3.14)

project(littlefs LANGUAGES C)

include(thirdparty OPTIONAL)

set(LIBLITTLEFS_SRCDIR littlefs)
set(LIBLITTLEFS_INCDIR include)
set(LIBLITTLEFS_TARGET ${PROJECT_NAME})

set(LIBLITTLEFS_SOURCES
        ${LIBLITTLEFS_SRCDIR}/lfs.c
        ${LIBLITTLEFS_SRCDIR}/lfs_util.c
        ${LIBLITTLEFS_SRCDIR}/bd/lfs_filebd.c
        ${LIBLITTLEFS_SRCDIR}/bd/lfs_rambd.c
        ${LIBLITTLEFS_SRCDIR}/bd/lfs_testbd.c
)

set( LIBLITTLEFS_PUBLIC_INCLUDES  ${LIBLITTLEFS_INCDIR} )
set( LIBLITTLEFS_PRIVATE_INCLUDES ${LIBLITTLEFS_SRCDIR} )


add_library( ${LIBLITTLEFS_TARGET} STATIC ${LIBLITTLEFS_SOURCES} )

#target_compile_definitions(${LIBLITTLEFS_TARGET} PRIVATE LFS_YES_TRACE )
target_compile_definitions(${LIBLITTLEFS_TARGET} PUBLIC LFS_THREADSAFE )

if( COMMAND third_party_target_setup )
    third_party_target_setup( ${LIBLITTLEFS_TARGET} )
endif()

target_include_directories( ${LIBLITTLEFS_TARGET}
        PUBLIC
        ${LIBLITTLEFS_PUBLIC_INCLUDES}
        PRIVATE
        ${LIBLITTLEFS_PRIVATE_INCLUDES}
)
if( COMMAND third_party_source_optimization )
    third_party_source_optimization( ${LIBLITTLEFS_SOURCES} )
endif()

D module-vfs/thirdparty/lfsfs/littlefs => module-vfs/thirdparty/lfsfs/littlefs +0 -1
@@ 1,1 0,0 @@
Subproject commit 1a59954ec64ca168828a15242cc6de94ac75f9d1

R source/main.cpp => products/BellHybrid/BellHybridMain.cpp +1 -1
@@ 179,7 179,7 @@ int main()
                sysmgr.get());
        });

    LOG_PRINTF("Launching PurePhone \n");
    LOG_PRINTF("Launching BellHybrid \n");
    LOG_PRINTF("commit: %s tag: %s branch: %s\n", GIT_REV, GIT_TAG, GIT_BRANCH);
    cpp_freertos::Thread::StartScheduler();


A products/BellHybrid/CMakeLists.txt => products/BellHybrid/CMakeLists.txt +82 -0
@@ 0,0 1,82 @@
add_executable(BellHybrid)

add_custom_target(Bell
    DEPENDS BellHybrid BellHybrid.img
    )

target_link_directories(BellHybrid PRIVATE ${PROJECT_LIB_DIRECTORY})

target_compile_definitions(BellHybrid
    PRIVATE
        ${PROJECT_CONFIG_DEFINITIONS}
        ${TARGET_COMPILE_DEFINITIONS}
        ${PROJECT_TARGET}
    )

target_compile_features(BellHybrid
    PRIVATE
        ${TARGET_COMPILE_FEATURES}
    )

target_compile_options(BellHybrid
    PRIVATE
        $<$<COMPILE_LANGUAGE:C>:-Wno-discarded-qualifiers>
        "-Wno-error=deprecated-declarations"
    )


target_sources(BellHybrid
    PRIVATE
        ${TARGET_SOURCES}
        BellHybridMain.cpp
    )

target_include_directories(BellHybrid
    PRIVATE
        ${TARGET_DIR_INCLUDES}
        ${PROJECT_INCLUDES}
        ${CMAKE_BINARY_DIR}
)

set_target_properties(BellHybrid
    PROPERTIES
        SUFFIX ".elf"
        LINK_FLAGS "-Xlinker -Map=${CMAKE_BINARY_DIR}/BellHybrid.map "
    )

target_link_libraries(BellHybrid
    PRIVATE
        module-apps
        service-desktop
        service-bluetooth
        service-lwip
        ${LWIP_LIBRARIES}
        messagetype
        "$<$<STREQUAL:${PROJECT_TARGET},TARGET_Linux>:iosyscalls>"
        "$<$<STREQUAL:${PROJECT_TARGET},TARGET_RT1051>:CrashCatcher::CrashCatcher>"
    )

target_link_options(BellHybrid PRIVATE ${TARGET_LINK_OPTIONS})

if (${PROJECT_TARGET} STREQUAL "TARGET_Linux")
    add_dependencies(Bell service_renderer)
endif()

set_source_files_properties(BellHybridMain.cpp PROPERTIES COMPILE_DEFINITIONS "${ENABLED_APPS_DEFINES}")


strip_executable(BellHybrid)


add_dependencies(BellHybrid version)

include(AddBootBin)
add_boot_bin(BellHybrid)
add_image(BellHybrid)

include(AddHexTarget)
add_hex_target(BellHybrid)

add_standalone_image(BellHybrid)
add_update_package(BellHybrid)


R module-vfs/thirdparty/lfsfs/include/littlefs/lfs.h => products/BellHybrid/config.h +3 -2
@@ 1,5 1,6 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include "../../littlefs/lfs.h"

#define ENABLE_GSM (0)

A products/CMakeLists.txt => products/CMakeLists.txt +2 -0
@@ 0,0 1,2 @@
add_subdirectory(PurePhone)
add_subdirectory(BellHybrid)

A products/PurePhone/CMakeLists.txt => products/PurePhone/CMakeLists.txt +84 -0
@@ 0,0 1,84 @@
add_executable(PurePhone)

add_custom_target(Pure
    DEPENDS PurePhone PurePhone.img
    )


target_link_directories(PurePhone PUBLIC ${PROJECT_LIB_DIRECTORY})

target_compile_definitions(PurePhone
    PRIVATE
        ${PROJECT_CONFIG_DEFINITIONS}
        ${TARGET_COMPILE_DEFINITIONS}
        ${PROJECT_TARGET}
    )

define_serial(PurePhone)

target_compile_features(PurePhone
    PRIVATE
        ${TARGET_COMPILE_FEATURES}
    )

target_compile_options(PurePhone
    PRIVATE
        $<$<COMPILE_LANGUAGE:C>:-Wno-discarded-qualifiers>
        "-Wno-error=deprecated-declarations"
    )

target_sources(PurePhone
    PRIVATE
        ${TARGET_SOURCES}
        PurePhoneMain.cpp
    )

target_include_directories(PurePhone
    PRIVATE
        ${TARGET_DIR_INCLUDES}
        ${PROJECT_INCLUDES}
        ${CMAKE_BINARY_DIR}
    )

set_target_properties(PurePhone
    PROPERTIES
        SUFFIX ".elf"
        LINK_FLAGS "-Xlinker -Map=${CMAKE_BINARY_DIR}/PurePhone.map "
    )

target_link_libraries(PurePhone
    PRIVATE
        module-apps
        service-desktop
        service-bluetooth
        service-lwip
        ${LWIP_LIBRARIES}
        messagetype
        "$<$<STREQUAL:${PROJECT_TARGET},TARGET_Linux>:iosyscalls>"
        "$<$<STREQUAL:${PROJECT_TARGET},TARGET_RT1051>:CrashCatcher::CrashCatcher>"
    )

target_link_options(PurePhone PUBLIC ${TARGET_LINK_OPTIONS})

if (${PROJECT_TARGET} STREQUAL "TARGET_Linux")
    add_dependencies(Pure service_renderer)
endif()

set_source_files_properties(PurePhoneMain.cpp PROPERTIES COMPILE_DEFINITIONS "${ENABLED_APPS_DEFINES}")

strip_executable(PurePhone)

message_serial_status()

add_dependencies(PurePhone version)

include(AddBootBin)
add_boot_bin(PurePhone)
add_image(PurePhone)

include(AddHexTarget)
add_hex_target(PurePhone)

add_standalone_image(PurePhone)
add_update_package(PurePhone)


A products/PurePhone/PurePhoneMain.cpp => products/PurePhone/PurePhoneMain.cpp +189 -0
@@ 0,0 1,189 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "config.h"

// applications
#include <application-antenna/ApplicationAntenna.hpp>
#include <application-call/ApplicationCall.hpp>
#include <application-calllog/ApplicationCallLog.hpp>
#include <application-desktop/ApplicationDesktop.hpp>
#include <application-messages/ApplicationMessages.hpp>
#include <application-notes/ApplicationNotes.hpp>
#include <application-phonebook/ApplicationPhonebook.hpp>
#include <application-settings/ApplicationSettings.hpp>
#include <application-settings-new/ApplicationSettings.hpp>
#include <application-special-input/ApplicationSpecialInput.hpp>
#include <application-calendar/ApplicationCalendar.hpp>
#include <application-music-player/ApplicationMusicPlayer.hpp>
#include <application-meditation/ApplicationMeditation.hpp>
#include <application-calculator/ApplicationCalculator.hpp>
#include <application-alarm-clock/ApplicationAlarmClock.hpp>
#include <application-onboarding/ApplicationOnBoarding.hpp>

// services
#include <service-appmgr/model/ApplicationManager.hpp>
#include <service-audio/ServiceAudio.hpp>
#include <service-bluetooth/ServiceBluetooth.hpp>
#include <service-db/ServiceDB.hpp>
#include <service-evtmgr/EventManager.hpp>
#include <service-lwip/ServiceLwIP.hpp>
#include <service-time/ServiceTime.hpp>
#include <Service/ServiceCreator.hpp>
#include <service-gui/ServiceGUI.hpp>
#include <service-gui/Common.hpp>
#include <module-services/service-eink/ServiceEink.hpp>
#include <service-fileindexer/Constants.hpp>
#include <service-fileindexer/ServiceFileIndexer.hpp>
#include <service-desktop/ServiceDesktop.hpp>

#if ENABLE_GSM == 1
#include <service-fota/ServiceFota.hpp>
#include <service-cellular/ServiceCellular.hpp>
#include <service-antenna/ServiceAntenna.hpp>
#endif

#include <bsp/bsp.hpp>
#include <Application.hpp>
#include <ApplicationLauncher.hpp>
#include <log/log.hpp>
#include <log/Logger.hpp>
#include <phonenumbers/phonenumberutil.h>
#include <source/version.hpp>
#include <SystemManager/SystemManager.hpp>
#include <SystemWatchdog/SystemWatchdog.hpp>
#include <thread.hpp>
#include <purefs/vfs_subsystem.hpp>

#include <memory>
#include <vector>

int main()
{

#if SYSTEM_VIEW_ENABLED
    SEGGER_SYSVIEW_Conf();
    SEGGER_SYSVIEW_DisableEvents(SYSVIEW_EVTMASK_ISR_ENTER);
    SEGGER_SYSVIEW_DisableEvents(SYSVIEW_EVTMASK_ISR_EXIT);
    SEGGER_SYSVIEW_DisableEvents(SYSVIEW_EVTMASK_ISR_TO_SCHEDULER);
    SEGGER_SYSVIEW_WaitForConnection();
    SEGGER_SYSVIEW_Start();
#endif

    bsp::BoardInit();

    purefs::subsystem::vfs_handle_t vfs;
    if (!sys::SystemWatchdog::getInstance().init()) {
        LOG_ERROR("System watchdog failed to initialize");
        // wait for the hardware watchdog (initialized in reset ISR) to reset the system
        while (1)
            ;
    }

    std::vector<std::unique_ptr<sys::BaseServiceCreator>> systemServices;
    systemServices.emplace_back(sys::CreatorFor<EventManager>());
#if ENABLE_FILEINDEXER_SERVICE
    systemServices.emplace_back(sys::CreatorFor<service::ServiceFileIndexer>());
#endif
    systemServices.emplace_back(sys::CreatorFor<ServiceDB>());
#if ENABLE_GSM == 0
    // For now disable permanently Service cellular when there is no GSM configured
    LOG_INFO("ServiceCellular (GSM) - Disabled");
#else
    systemServices.emplace_back(sys::CreatorFor<ServiceAntenna>());
    systemServices.emplace_back(sys::CreatorFor<ServiceCellular>());
    systemServices.emplace_back(sys::CreatorFor<FotaService::Service>());
#endif
    systemServices.emplace_back(sys::CreatorFor<ServiceAudio>());
    systemServices.emplace_back(sys::CreatorFor<ServiceBluetooth>());
    systemServices.emplace_back(sys::CreatorFor<ServiceLwIP>());
    systemServices.emplace_back(sys::CreatorFor<ServiceDesktop>());
    systemServices.emplace_back(sys::CreatorFor<stm::ServiceTime>());
    systemServices.emplace_back(sys::CreatorFor<service::eink::ServiceEink>());
    systemServices.emplace_back(sys::CreatorFor<service::gui::ServiceGUI>());

    auto sysmgr = std::make_shared<sys::SystemManager>(std::move(systemServices));
    sysmgr->StartSystem(
        [&vfs]() {
            vfs     = purefs::subsystem::initialize();
            int err = purefs::subsystem::mount_defaults();
            if (err) {
                LOG_FATAL("VFS subystem fatal error %i", err);
                std::abort();
            }
            Log::Logger::get().init();
            /// force initialization of PhonenumberUtil because of its stack usage
            /// otherwise we would end up with an init race and PhonenumberUtil could
            /// be initiated in a task with stack not big enough to handle it
            i18n::phonenumbers::PhoneNumberUtil::GetInstance();
            return true;
        },
        [sysmgr]() {
            // vector with launchers to applications
            std::vector<std::unique_ptr<app::ApplicationLauncher>> applications;
#ifdef ENABLE_APP_DESKTOP
            applications.push_back(
                app::CreateLauncher<app::ApplicationDesktop>(app::name_desktop, app::Closeable::False));
#endif
#ifdef ENABLE_APP_CALL
            applications.push_back(app::CreateLauncher<app::ApplicationCall>(app::name_call, app::Closeable::False));
#endif
#ifdef ENABLE_APP_SETTINGS
            applications.push_back(app::CreateLauncher<app::ApplicationSettings>(app::name_settings));
#endif
#ifdef ENABLE_APP_SETTINGS_NEW
            applications.push_back(app::CreateLauncher<app::ApplicationSettingsNew>(app::name_settings_new));
#endif
#ifdef ENABLE_APP_NOTES
            applications.push_back(app::CreateLauncher<app::ApplicationNotes>(app::name_notes));
#endif
#ifdef ENABLE_APP_CALLLOG
            applications.push_back(app::CreateLauncher<app::ApplicationCallLog>(app::CallLogAppStr));
#endif
#ifdef ENABLE_APP_PHONEBOOK
            applications.push_back(app::CreateLauncher<app::ApplicationPhonebook>(app::name_phonebook));
#endif
#ifdef ENABLE_APP_MESSAGES
            applications.push_back(app::CreateLauncher<app::ApplicationMessages>(app::name_messages));
#endif
#ifdef ENABLE_APP_SPECIAL_INPUT
            applications.push_back(
                app::CreateLauncher<app::ApplicationSpecialInput>(app::special_input, app::Closeable::False));
#endif
#ifdef ENABLE_APP_ANTENNA
            applications.push_back(app::CreateLauncher<app::ApplicationAntenna>(app::name_antenna));
#endif
#ifdef ENABLE_APP_CALENDAR
            applications.push_back(app::CreateLauncher<app::ApplicationCalendar>(app::name_calendar));
#endif
#ifdef ENABLE_APP_MUSIC_PLAYER
            applications.push_back(app::CreateLauncher<app::ApplicationMusicPlayer>(app::name_music_player));
#endif
#ifdef ENABLE_APP_MEDITATION
            applications.push_back(
                app::CreateLauncher<app::ApplicationMeditation>(app::name_meditation, app::Closeable::True));
#endif
#ifdef ENABLE_APP_CALCULATOR
            applications.push_back(app::CreateLauncher<app::ApplicationCalculator>(app::name_calculator));
#endif
#ifdef ENABLE_APP_ALARM_CLOCK
            applications.push_back(app::CreateLauncher<app::ApplicationAlarmClock>(app::name_alarm_clock));
#endif
#ifdef ENABLE_APP_ONBOARDING
            applications.push_back(app::CreateLauncher<app::ApplicationOnBoarding>(app::name_onboarding));
#endif
            // start application manager
            return sysmgr->RunSystemService(
                std::make_shared<app::manager::ApplicationManager>(
                    app::manager::ApplicationManager::ServiceName, std::move(applications), app::name_desktop),
                sysmgr.get());
        });

    LOG_PRINTF("Launching PurePhone \n");
    LOG_PRINTF("commit: %s tag: %s branch: %s\n", GIT_REV, GIT_TAG, GIT_BRANCH);
    cpp_freertos::Thread::StartScheduler();

    purefs::subsystem::unmount_all();

    return 0;
}

R source/config.h => products/PurePhone/config.h +0 -0
A source/CMakeLists.txt => source/CMakeLists.txt +6 -0
@@ 0,0 1,6 @@
add_library(messagetype INTERFACE)
target_sources(messagetype
    PUBLIC
        MessageType.hpp
    )
target_include_directories(messagetype INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

M source/MessageType.hpp => source/MessageType.hpp +1 -4
@@ 1,8 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#ifndef SOURCE_MESSAGETYPE_HPP_
#define SOURCE_MESSAGETYPE_HPP_
#pragma once

enum class MessageType
{


@@ 165,5 164,3 @@ enum class MessageType
    // Quotes messages
    Quotes,
};

#endif /* SOURCE_MESSAGETYPE_HPP_ */

M test/pytest/test_auto_lock.py => test/pytest/test_auto_lock.py +1 -1
@@ 78,7 78,7 @@ def contains_value_recursively(body: dict, attr_name, attr_value):
def get_dom(harness):
    body = {"ui": True, "getWindow": True}
    result = harness.endpoint_request("developerMode", "get", body)
    # log.info("data {}".format(find_item_depth_first(result['body']['dom'], 'TopBar')))
    # log.info("data {}".format(find_item_depth_first(result['body']['dom'], 'StatusBar')))
    assert result['body']
    assert 'Window' in result['body']['dom']
    return result

M third-party/CMakeLists.txt => third-party/CMakeLists.txt +6 -2
@@ 1,4 1,3 @@

add_subdirectory(crc32)
add_subdirectory(magic_enum)
add_subdirectory(microtar)


@@ 10,4 9,9 @@ add_subdirectory(minimp3)
add_subdirectory(tinyexpr)
add_subdirectory(parallel-hashmap)
add_subdirectory(protobuf)

add_subdirectory(littlefs)
add_subdirectory(gsl)
add_subdirectory(re2)
if (${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
    add_subdirectory(CrashDebug)
endif()

A third-party/CrashDebug/CMakeLists.txt => third-party/CrashDebug/CMakeLists.txt +19 -0
@@ 0,0 1,19 @@
include(ExternalProject)

ExternalProject_Add(CrashDebug
    SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src
    CONFIGURE_COMMAND ""
    BUILD_COMMAND make -C ${CMAKE_CURRENT_SOURCE_DIR}/src CrashDebug
    INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/bin && ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/src/bins/lin64/CrashDebug ${CMAKE_CURRENT_BINARY_DIR}/bin
)

add_library(CrashCatcher INTERFACE)
add_library(CrashCatcher::CrashCatcher ALIAS CrashCatcher)

target_include_directories(CrashCatcher
    INTERFACE
        src/CrashCatcher/include
        src/CrashCatcher/Core/src
)

target_sources(CrashCatcher INTERFACE src/CrashCatcher/Core/src/CrashCatcher.c)

A third-party/CrashDebug/src => third-party/CrashDebug/src +1 -0
@@ 0,0 1,1 @@
Subproject commit 0104eb5480d9213d9fe944f13958f785a311a191

A third-party/gsl => third-party/gsl +1 -0
@@ 0,0 1,1 @@
Subproject commit b26f6d5ec7b043f9d459c1dfdd6da4d930d4e9b4

A third-party/littlefs/CMakeLists.txt => third-party/littlefs/CMakeLists.txt +29 -0
@@ 0,0 1,29 @@
cmake_minimum_required(VERSION 3.13)

add_library(littlefs STATIC)
add_library(littlefs::littlefs ALIAS littlefs)

target_sources(littlefs
    PRIVATE
        src/lfs.c
        src/lfs_util.c
        src/bd/lfs_filebd.c
        src/bd/lfs_rambd.c
        src/bd/lfs_testbd.c
    PUBLIC
        src/lfs.h
        src/lfs_util.h
        src/bd/lfs_filebd.h
        src/bd/lfs_rambd.h
        src/bd/lfs_testbd.h
)

target_compile_definitions(littlefs 
    PUBLIC 
        LFS_THREADSAFE 
)

target_include_directories(littlefs
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
)

A third-party/littlefs/src => third-party/littlefs/src +1 -0
@@ 0,0 1,1 @@
Subproject commit 1a59954ec64ca168828a15242cc6de94ac75f9d1

A third-party/re2/CMakeLists.txt => third-party/re2/CMakeLists.txt +7 -0
@@ 0,0 1,7 @@
add_subdirectory(src)

target_compile_definitions(re2 PUBLIC RE2_USE_RTOS_WRAPPER)

target_compile_options (re2 PRIVATE -Wno-missing-field-initializers)

target_link_libraries(re2 PUBLIC module-os)

A third-party/re2/src => third-party/re2/src +1 -0
@@ 0,0 1,1 @@
Subproject commit 9d3b376ba3a41b498f13264131102d48c4b3271a

A tools/generate_update_image.sh => tools/generate_update_image.sh +99 -0
@@ 0,0 1,99 @@
#!/bin/bash -e
# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#create update image

function help() {
cat <<- EOF
	Create Update Image for the SOURCE_TARGET. This script should be run from build directory.
	
	${0} <SOURCE_TARGET> <VERSION> <PLATFORM>
	
	    SOURCE_TARGET    - Name of the target (usually PurePhone or BellHybrid)
	    VERSION          - version number to attach to file name
	    PLATFORM         - RT1051 or Linux
	
    In the current work dir, the script will create update image named from this template:
	<SOURCE_TARGET>-<VERSION>-<PLATFORM>-Update.tar
	
	
	
EOF
}

function setVars() {
    SOURCE_TARGET=${1}
    VERSION=${2}
    PLATFORM=${3}
    STAGEING_DIR="${SOURCE_TARGET}-${VERSION}-${PLATFORM}-Update"
    PACKAGE_FILE="${STAGEING_DIR}.tar"
    DEPS=(
        "sys/current/assets"
        "sys/user"
        "sys/current/${SOURCE_TARGET}-boot.bin"
        "sys/current/country-codes.db"
        "sys/current/Luts.bin"
        "version.json"
        "ecoboot.bin"
        )
}

function checkForDeps() {
    local DEPS=${1}
    I=0
    DEPS_COUNT=${#DEPS[@]}
    while [[ I -lt ${DEPS_COUNT} ]]; do
        ITEM=${DEPS[${I}]}
        if [[ ! -e "${ITEM}" ]]; then
            echo "Couldn't find dependency: \"${ITEM}\"" 
            echo exti 2
        fi
        I=$(( I + 1))
    done
    echo "Deps-OK"
}

function cleanStagingDir(){
    local STAGEING_DIR=${1}
    if [[ -d ${STAGEING_DIR} ]]; then
        rm -Rf ${STAGEING_DIR}
    fi
    mkdir ${STAGEING_DIR} -v
}

function linkInStageing(){
    pushd ${STAGEING_DIR} 1> /dev/null
    ln -s ../sys/current/assets
    ln -s ../sys/user
    ln -s ../sys/current/${SOURCE_TARGET}-boot.bin boot.bin
    ln -s ../sys/current/country-codes.db
    ln -s ../sys/current/Luts.bin
    ln -s ../ecoboot.bin
    ln -s ../version.json
    popd 1> /dev/null
}

function addChecksums() {
    pushd ${STAGEING_DIR} 1> /dev/null
    rhash -u checksums.txt -r .
    popd 1> /dev/null
}

function compress() {
    tar chf ${PACKAGE_FILE} -C ${STAGEING_DIR} .
}

if [[ $# -ne 3 ]]; then
    help
    exit 1
fi

setVars "${1}" "${2}" "${3}"
checkForDeps ${DEPS}
cleanStagingDir ${STAGEING_DIR}
linkInStageing
addChecksums
compress