From 5b3805e61cec77e98cd95b53af0a42ddf6597afa Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Fri, 7 Nov 2014 23:09:54 +0300 Subject: [PATCH] =?UTF-8?q?=D0=90=D0=B4=D0=B0=D0=BF=D1=82=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BB=20=D0=B0=D1=81=D1=81=D0=B5=D0=BC=D0=B1?= =?UTF-8?q?=D0=BB=D0=B5=D1=80=D0=BD=D1=8B=D0=B9=20=D0=BA=D0=BE=D0=B4=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20OS=20X.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BF=D1=80=D0=BE=D1=81=D1=82=D0=BE=D0=B9=20?= =?UTF-8?q?=D1=8D=D1=85=D0=BE=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=20?= =?UTF-8?q?=D0=BD=D0=B0=20boost.asio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CMakeLists.txt | 11 +- src/asm/darwin/x86_64/ustring_asm.asm | 101 +++++ src/ustring.cpp | 2 +- test/CMakeLists.txt | 17 +- test/main.cpp | 617 -------------------------- test/server/main.cpp | 10 + test/server/server.cpp | 41 ++ test/server/server.h | 29 ++ test/server/session.cpp | 41 ++ test/server/session.h | 27 ++ 10 files changed, 274 insertions(+), 622 deletions(-) create mode 100644 src/asm/darwin/x86_64/ustring_asm.asm delete mode 100755 test/main.cpp create mode 100644 test/server/main.cpp create mode 100644 test/server/server.cpp create mode 100644 test/server/server.h create mode 100644 test/server/session.cpp create mode 100644 test/server/session.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 83b01f4..5e94e7e 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,10 +3,19 @@ cmake_minimum_required(VERSION 2.8) set(MAIN_PROJECT_NAME "cpputil") set(SRC_DIR ".") set(INCLUDE_DIR ../include ./asm/include) +set(ARCH "x86_64") + +if(APPLE) + set(SYSTEM "darwin") +else() + set(SYSTEM "linux") +endif() + +SET(CMAKE_ASM_NASM_COMPILER yasm) project(${MAIN_PROJECT_NAME} CXX ASM_NASM) aux_source_directory(${SRC_DIR} SRC_FILES) -file(GLOB_RECURSE ASM_SRC_FILES "${SRC_DIR}/asm/linux/x86_64" "*.asm") +file(GLOB_RECURSE ASM_SRC_FILES "${SRC_DIR}/asm/${SYSTEM}/${ARCH}" "*.asm") set(SRC_FILES ${SRC_FILES} ${ASM_SRC_FILES}) include_directories(${INCLUDE_DIR}) add_library(${MAIN_PROJECT_NAME} STATIC ${SRC_FILES}) diff --git a/src/asm/darwin/x86_64/ustring_asm.asm b/src/asm/darwin/x86_64/ustring_asm.asm new file mode 100644 index 0000000..229cafb --- /dev/null +++ b/src/asm/darwin/x86_64/ustring_asm.asm @@ -0,0 +1,101 @@ +; +; public exported functions +; + +global __asm_ucs4_strstr +global __asm_ucs4_strchr + +; +; code section +; + +section .text + +; constants + +npos db -1 + +;================================================================================ +; +; Поиск подстроки в строке UCS-4 (алгоритм "в лоб", подойдет для коротких строк) +; +; rdi: указатель на исходную строку +; rsi: длина исходной строки символах +; rdx: указатель на искомую подстроку +; rcx: длина подстроки в символах +; +;================================================================================ + +__asm_ucs4_strstr: + + push r12 + mov r9d, dword [rdx] + mov rax, rdx + lea r8, [rdi + rsi*4] + lea r10, [rdx + rcx*4] + + strstr_try_next_symbol: + + cmp r9d, dword [rdi] + je strstr_init_counter + add rdi, 4 + cmp rdi, r8 + jne strstr_try_next_symbol + pop r12 + mov rax, 0 + ret + + strstr_init_counter: + + mov rdx, rax + mov r12, rdi + + strstr_symbol_found: + + add rdx, 4 + cmp rdx, r10 + je strstr_the_end + add r12, 4 + mov r11d, dword [r12] + cmp r11d, dword [rdx] + je strstr_symbol_found + add rdi, 4 + jmp strstr_try_next_symbol + + strstr_the_end: + + pop r12 + mov rax, rdi + + ret + +;================================================================================ +; +; Поиск символа в строке UCS-4 +; +; rdi: указатель на исходную строку +; rsi: длина исходной строки символах +; rdx: искомый символ +; +;================================================================================ + +__asm_ucs4_strchr: + + xor r8, r8 + + try_next_symbol: + + cmp rdx, [rdi] + je symbol_found + add rdi, 4 + inc r8 + cmp rsi, r8 + jne try_next_symbol + mov rax, 0 + ret + + symbol_found: + + mov rax, rdi + + ret diff --git a/src/ustring.cpp b/src/ustring.cpp index 5007516..6880a89 100755 --- a/src/ustring.cpp +++ b/src/ustring.cpp @@ -381,7 +381,7 @@ std::size_t ustring::find(const ustring& str, std::size_t pos /* = 0 */) const return npos; } -#if defined(__GNUC__) && !defined(__clang__) +#if defined(__GNUC__) // GCC and clang /* char32_t* fpos = reinterpret_cast(memmem(_pData + pos, (_len - pos)*sizeof(char32_t), str._pData, str._len*sizeof(char32_t))); if(fpos) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a543e3e..64b5da6 100755 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 2.8) set(TEST_PROJECT_NAME "cpputil_test") +set(TEST_SERVER_PROJECT_NAME "server_test") +set(TEST_CLIENT_PROJECT_NAME "client_test") set(SRC_DIR ".") set(REQUIRED_LIBRARIES cpputil) set(boost_version 1.56.0) @@ -45,13 +47,22 @@ ExternalProject_Add( LOG_BUILD ON ) +ExternalProject_Get_Property( boost source_dir ) +set(BOOST_INCLUDE_DIR ${source_dir}) +INCLUDE_DIRECTORIES(${BOOST_INCLUDE_DIR}) + project(${TEST_PROJECT_NAME} CXX) -aux_source_directory(${SRC_DIR} TEST_SRC) +aux_source_directory(${SRC_DIR}/cpputil TEST_SRC) add_executable(${TEST_PROJECT_NAME} ${TEST_SRC}) SET_TARGET_PROPERTIES(${TEST_PROJECT_NAME} PROPERTIES ENABLE_EXPORTS TRUE) -ADD_DEPENDENCIES(${TEST_PROJECT_NAME} googletest cpputil boost) +ADD_DEPENDENCIES(${TEST_PROJECT_NAME} googletest cpputil) +target_link_libraries(${TEST_PROJECT_NAME} ${REQUIRED_LIBRARIES} ${CMAKE_SOURCE_DIR}/lib/libgtest.a) -target_link_libraries(${TEST_PROJECT_NAME} ${REQUIRED_LIBRARIES} ${CMAKE_SOURCE_DIR}/lib/libgtest.a ${CMAKE_SOURCE_DIR}/lib/libboost_coroutine.a) +project(${TEST_SERVER_PROJECT_NAME} CXX) +aux_source_directory(${SRC_DIR}/server TEST_SERVER_SRC) +add_executable(${TEST_SERVER_PROJECT_NAME} ${TEST_SERVER_SRC}) +add_dependencies(${TEST_SERVER_PROJECT_NAME} boost cpputil) +target_link_libraries(${TEST_SERVER_PROJECT_NAME} cpputil ${CMAKE_SOURCE_DIR}/lib/libboost_system.a ${CMAKE_SOURCE_DIR}/lib/libboost_coroutine.a) install(TARGETS ${TEST_PROJECT_NAME} RUNTIME DESTINATION bin diff --git a/test/main.cpp b/test/main.cpp deleted file mode 100755 index 0cd01fb..0000000 --- a/test/main.cpp +++ /dev/null @@ -1,617 +0,0 @@ -#include "ustring.h" -#include "utf.h" -#include "logger.h" -#include "threadpool.h" -#include -#include -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////////////////////// -// -// Данные для тестов -// - -// UTF-8 -const unsigned char helloStrUtf8[] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x0a, 0xd0, 0x9f, 0xd1, - 0x80, 0xd0, 0xb8, 0xd0, 0xb2, 0xd0, 0xb5, 0xd1, 0x82, 0x2c, 0x20, 0xd0, 0x9c, 0xd0, 0xb8, 0xd1, - 0x80, 0x21, 0x0a, 0xe2, 0x88, 0x86, 0x20, 0x3d, 0x20, 0xf0, 0x9d, 0x9b, 0xbb, 0xc2, 0xb2, 0x0a, - 0x00 }; - -// UTF-16LE -const unsigned char helloStrUtf16le[] = { 0x48, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x57, 0x00, 0x6f, 0x00, - 0x72, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x21, 0x00, 0x0a, 0x00, 0x1f, 0x04, 0x40, 0x04, 0x38, 0x04, - 0x32, 0x04, 0x35, 0x04, 0x42, 0x04, 0x2c, 0x00, 0x20, 0x00, 0x1c, 0x04, 0x38, 0x04, 0x40, 0x04, - 0x21, 0x00, 0x0a, 0x00, 0x06, 0x22, 0x20, 0x00, 0x3d, 0x00, 0x20, 0x00, 0x35, 0xd8, 0xfb, 0xde, - 0xb2, 0x00, 0x0a, 0x00, 0x00, 0x00 }; - -// UTF-16BE -const unsigned char helloStrUtf16be[] = { 0x00, 0x48, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x57, 0x00, 0x6f, - 0x00, 0x72, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x21, 0x00, 0x0a, 0x04, 0x1f, 0x04, 0x40, 0x04, 0x38, - 0x04, 0x32, 0x04, 0x35, 0x04, 0x42, 0x00, 0x2c, 0x00, 0x20, 0x04, 0x1c, 0x04, 0x38, 0x04, 0x40, - 0x00, 0x21, 0x00, 0x0a, 0x22, 0x06, 0x00, 0x20, 0x00, 0x3d, 0x00, 0x20, 0xd8, 0x35, 0xde, 0xfb, - 0x00, 0xb2, 0x00, 0x0a, 0x00, 0x00 }; - -// UCS-4 (UTF-32LE на x86) -const unsigned char helloStrUcs4[] = { 0x48, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, - 0x6f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x38, 0x04, 0x00, 0x00, - 0x32, 0x04, 0x00, 0x00, 0x35, 0x04, 0x00, 0x00, 0x42, 0x04, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x1c, 0x04, 0x00, 0x00, 0x38, 0x04, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x22, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x3d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xfb, 0xd6, 0x01, 0x00, 0xb2, 0x00, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -// UTF-32BE -const unsigned char helloStrUtf32be[] = { 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6c, - 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x6f, - 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x21, - 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x04, 0x1f, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x04, 0x38, - 0x00, 0x00, 0x04, 0x32, 0x00, 0x00, 0x04, 0x35, 0x00, 0x00, 0x04, 0x42, 0x00, 0x00, 0x00, 0x2c, - 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x04, 0x38, 0x00, 0x00, 0x04, 0x40, - 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x22, 0x06, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0xd6, 0xfb, 0x00, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00 }; - -// Escaped -const char helloStrEscaped[] = "Hello World!\n\\u041F\\u0440\\u0438\\u0432\\u0435\\u0442, \\u041C\\u0438\\u0440!\n\\u2206 = \\U0001D6FB\\u00B2\n"; - -// Длина тестовой строки в символах -const std::size_t helloStrLen = 33; - -// Некорректные строки для теста обработки ошибок -const unsigned char badStrUtf8[] = { 0xd0, 0xdf, 0x00 }; -const unsigned char badStr2Utf8[] = { 0xf8, 0x9f, 0x00 }; -const unsigned char badStrUcs4[] = { 0xf8, 0x9f, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char badStrUtf16le[] = { 0x35, 0xc8, 0xfb, 0xde, 0x00, 0x00 }; -const unsigned char badStr2Utf16le[] = { 0x35, 0xd8, 0xfb, 0xce, 0x00, 0x00 }; - -// Для теста конкатенации -// "Hello " -const unsigned char helloPart1Ucs4[] = { 0x48, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, - 0x6f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -// "big" -const unsigned char helloPart2Ucs4[] = { 0x62, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -// " world" -const unsigned char helloPart3Ucs4[] = { 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, - 0x6c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -// "Hello big world" -const unsigned char helloResultUcs4[] = { 0x48, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, - 0x6f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, - 0x67, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -/////////////////////////////////////////////////////////////////////////////////////////// -// -// Тесты -// - -// -// Определение длины символа UTF-8 -// - -TEST(Convert, utf8_symbol_size) -{ - ASSERT_EQ(1, utf8_get_symbol_size((const char*)&helloStrUtf8[0], false)); - ASSERT_EQ(2, utf8_get_symbol_size((const char*)&helloStrUtf8[15], false)); - ASSERT_EQ(4, utf8_get_symbol_size((const char*)&helloStrUtf8[41], false)); -} - -// -// Определение длины символа UTF-8 по символу UCS-4 -// - -TEST(Convert, utf8_symbol_size_by_ucs4_symbol) -{ - ASSERT_EQ(1, ucs4_get_utf8_symbol_size(*(const char32_t*)&helloStrUcs4[0], false)); - ASSERT_EQ(2, ucs4_get_utf8_symbol_size(*(const char32_t*)&helloStrUcs4[52], false)); - ASSERT_EQ(4, ucs4_get_utf8_symbol_size(*(const char32_t*)&helloStrUcs4[120], false)); -} - -// -// Определение длины строки UTF-8 -// - -TEST(Convert, utf8_length) -{ - ASSERT_EQ(helloStrLen, utf8_str_len((const char*)helloStrUtf8, false)); -} - -// -// Определение длины строки UTF-8 по строке UCS-4 -// - -TEST(Convert, utf8_str_len_by_ucs4_str) -{ - ASSERT_EQ(sizeof(helloStrUtf8) - 1, ucs4_get_utf8_str_bytes((const char32_t*)helloStrUcs4, false)); -} - -// -// Определение длины символа UTF-16LE -// - -TEST(Convert, utf16le_symbol_size) -{ - ASSERT_EQ(2, utf16_get_symbol_size((const char16_t*)&helloStrUtf16le[0])); - ASSERT_EQ(4, utf16_get_symbol_size((const char16_t*)&helloStrUtf16le[60])); -} - -// -// Определение длины символа UTF-16BE -// - -TEST(Convert, utf16be_symbol_size) -{ - ASSERT_EQ(2, utf16_get_symbol_size((const char16_t*)&helloStrUtf16be[0], BYTE_ORDER_BIG_ENDIAN)); - ASSERT_EQ(4, utf16_get_symbol_size((const char16_t*)&helloStrUtf16be[60], BYTE_ORDER_BIG_ENDIAN)); -} - -// -// Определение длины символа UTF-16 по символу UCS-4 -// - -TEST(Convert, utf16_symbol_size_by_ucs4_symbol) -{ - ASSERT_EQ(2, ucs4_get_utf16_symbol_size(*(const char32_t*)&helloStrUcs4[0])); - ASSERT_EQ(4, ucs4_get_utf16_symbol_size(*(const char32_t*)&helloStrUcs4[120])); -} - -// -// Определение длины строки UTF-16LE -// - -TEST(Convert, utf16le_length) -{ - ASSERT_EQ(helloStrLen, utf16_str_len((const char16_t*)helloStrUtf16le)); -} - -// -// Определение длины строки UTF-16BE -// - -TEST(Convert, utf16be_length) -{ - ASSERT_EQ(helloStrLen, utf16_str_len((const char16_t*)helloStrUtf16be, BYTE_ORDER_BIG_ENDIAN)); -} - -TEST(Convert, utf16_str_len_by_ucs4_str) -{ - ASSERT_EQ(sizeof(helloStrUtf16le) - 2, ucs4_get_utf16_str_bytes((const char32_t*)helloStrUcs4)); -} - -// -// Определение длины строки UTF-32 -// - -TEST(Convert, utf32_length) -{ - ASSERT_EQ(helloStrLen, utf32_str_len((const char32_t*)helloStrUcs4)); -} - -// -// Конвертирование UTF-8 в UCS-4 -// -TEST(Convert, utf8_to_ucs4) -{ - std::size_t len = utf8_str_len((const char*)helloStrUtf8, false); - char32_t* data = new char32_t[len]; - utf8_to_ucs4((const char*)helloStrUtf8, data, len, false); - EXPECT_EQ(0, memcmp(helloStrUcs4, data, len*sizeof(char32_t))); - delete[] data; -} - -// -// Конвертирование UCS-4 в UTF-8 -// -TEST(Convert, ucs4_to_utf8) -{ - std::size_t len = ucs4_get_utf8_str_bytes((const char32_t*)helloStrUcs4, false); - std::size_t symbols = utf32_str_len((const char32_t*)helloStrUcs4); - char* data = new char[len]; - ucs4_to_utf8((const char32_t*)helloStrUcs4, data, symbols, false); - EXPECT_EQ(0, memcmp(helloStrUtf8, data, len)); - delete[] data; -} - -// -// Конвертирование UTF-16LE в UCS-4 -// -TEST(Convert, utf16le_to_ucs4) -{ - std::size_t len = utf16_str_len((const char16_t*)helloStrUtf16le); - char32_t* data = new char32_t[len]; - utf16_to_ucs4((const char16_t*)helloStrUtf16le, data, len); - EXPECT_EQ(0, memcmp(helloStrUcs4, data, len*sizeof(char32_t))); - delete[] data; -} - -// -// Конвертирование UCS-4 в UTF-16LE -// -TEST(Convert, ucs4_to_utf16le) -{ - std::size_t len = ucs4_get_utf16_str_bytes((const char32_t*)helloStrUcs4); - std::size_t symbols = utf32_str_len((const char32_t*)helloStrUcs4); - char16_t* data = new char16_t[len]; - ucs4_to_utf16((const char32_t*)helloStrUcs4, data, symbols); - EXPECT_EQ(0, memcmp(helloStrUtf16le, data, len)); - delete[] data; -} - -// -// Конвертирование UTF-16BE в UCS-4 -// -TEST(Convert, utf16be_to_ucs4) -{ - std::size_t len = utf16_str_len((const char16_t*)helloStrUtf16be); - char32_t* data = new char32_t[len]; - utf16_to_ucs4((const char16_t*)helloStrUtf16be, data, len, BYTE_ORDER_BIG_ENDIAN); - EXPECT_EQ(0, memcmp(helloStrUcs4, data, len*sizeof(char32_t))); - delete[] data; -} - -// -// Конвертирование UCS-4 в UTF-16BE -// -TEST(Convert, ucs4_to_utf16be) -{ - std::size_t len = ucs4_get_utf16_str_bytes((const char32_t*)helloStrUcs4); - std::size_t symbols = utf32_str_len((const char32_t*)helloStrUcs4); - char16_t* data = new char16_t[len]; - ucs4_to_utf16((const char32_t*)helloStrUcs4, data, symbols, BYTE_ORDER_BIG_ENDIAN); - EXPECT_EQ(0, memcmp(helloStrUtf16be, data, len)); - delete[] data; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Тесты на ошибки конвертирования -// - -// -// Первый байт двухбайтового символа содержит единицы в пяти старших разрядах -// - -TEST(ConvertError, utf8_length_error) -{ - EXPECT_THROW(utf8_str_len((const char*)badStr2Utf8, false), bad_conversion); -} - -// -// Второй байт двухбайтового символа содержит единицы в двух старших разрядах -// - -TEST(ConvertError, utf8_decode_error) -{ - std::size_t len = utf8_str_len((const char*)badStrUtf8, false); - char32_t* data = new char32_t[len]; - EXPECT_THROW(utf8_to_ucs4((const char*)badStrUtf8, data, len, false), bad_conversion); - delete[] data; -} - -// -// Некорректное перевое слово суррогатной пары -// - -TEST(ConvertError, utf16_decode_error) -{ - std::size_t len = utf16_str_len((const char16_t*)badStrUtf16le); - char32_t* data = new char32_t[len]; - EXPECT_THROW(utf16_to_ucs4((const char16_t*)badStrUtf16le, data, len), bad_conversion); - delete[] data; -} - -// -// Некорректное второе слово суррогатной пары -// - -TEST(ConvertError, utf16_decode_error2) -{ - std::size_t len = utf16_str_len((const char16_t*)badStr2Utf16le); - char32_t* data = new char32_t[len]; - EXPECT_THROW(utf16_to_ucs4((const char16_t*)badStr2Utf16le, data, len), bad_conversion); - delete[] data; -} - -// -// Код символа не входит в диапазон символов UCS-4 -// - -TEST(ConvertError, ucs4_wrong_symbol) -{ - EXPECT_THROW(ucs4_get_utf8_symbol_size(*(const char32_t*)badStrUcs4, false), bad_conversion); - EXPECT_THROW(ucs4_get_utf16_symbol_size(*(const char32_t*)badStrUcs4), bad_conversion); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Тесты класса ustring -// - -// -// Конструктор из UTF-8 -// - -TEST(Ustring, utf8_constructor) -{ - ustring str((const char*)helloStrUtf8); - ustring str2("Hello\\u0020world!", true); - ustring str3("Hello\\u0020world!", false); - ustring str4 = "Hello\\u0020world!"; - - - EXPECT_EQ(0, memcmp(helloStrUcs4, str.utf32_str(), sizeof(helloStrUcs4))); - EXPECT_TRUE(str2 == "Hello world!"); - EXPECT_TRUE(str3 == "Hello\\u0020world!"); - EXPECT_TRUE(str4 == "Hello\\u0020world!"); -} - -// -// Конструктор из UTF-16LE -// - -TEST(Ustring, utf16_constructor) -{ - ustring str((const char16_t*)helloStrUtf16le); - EXPECT_EQ(0, memcmp(helloStrUcs4, str.utf32_str(), sizeof(helloStrUcs4))); -} - -// -// Конструктор из UTF-32LE -// - -TEST(Ustring, utf32_constructor) -{ - ustring str((const char32_t*)helloStrUcs4); - EXPECT_EQ(0, memcmp(helloStrUcs4, str.utf32_str(), sizeof(helloStrUcs4))); -} - -// -// Оператор UTF-8 -// - -TEST(Ustring, utf8_cast_operator) -{ - ustring str((const char32_t*)helloStrUcs4); - EXPECT_EQ(0, memcmp(helloStrUtf8, str.utf8_str(), sizeof(helloStrUtf8))); - EXPECT_EQ(0, memcmp(str.utf8_str(false, true), helloStrEscaped, sizeof(helloStrEscaped))); -} - -// -// Оператор UTF-16LE -// - -TEST(Ustring, utf16_cast_operator) -{ - ustring str((const char32_t*)helloStrUcs4); - EXPECT_EQ(0, memcmp(helloStrUtf16le, str.utf16_str(), sizeof(helloStrUtf16le))); -} - -// -// Конкатенация строк (operator+=) -// - -TEST(Ustring, concat_op_plus_assign) -{ - ustring s1((const char32_t*)helloPart1Ucs4); - ustring s2((const char32_t*)helloPart2Ucs4); - ustring s3((const char32_t*)helloPart3Ucs4); - - s1 += s2; - s1 += s3; - - EXPECT_EQ(0, memcmp(helloResultUcs4, s1.utf32_str(), sizeof(helloResultUcs4))); -} - -// -// Конкатенация строк (operator+) -// - -TEST(Ustring, concat_op_plus) -{ - ustring s1((const char32_t*)helloPart1Ucs4); - //ustring s2((const char32_t*)helloPart2Ucs4); - //ustring s3((const char32_t*)helloPart3Ucs4); - - ustring res = s1 + "big" + " world"; - - EXPECT_EQ(0, memcmp(helloResultUcs4, res.utf32_str(), sizeof(helloResultUcs4))); -} - -// -// Поиск символа в строке -// -TEST(Ustring, find_symbol) -{ - ustring str((const char32_t*)helloResultUcs4); - EXPECT_EQ(4, str.find('o')); - EXPECT_EQ(11, str.find('o', 8)); -} - -// -// Поиск подстроки в строке -// - -TEST(Ustring, find_string) -{ - ustring str = "Hello World! asdf qwerty asdf"; - EXPECT_EQ(13, str.find("asdf")); - EXPECT_EQ(7, str.find("orld")); - EXPECT_EQ(25, str.find("asdf", 14)); -} - -// -// Вывод в поток std::ostream -// - -TEST(Ustring, std_ostream_output) -{ - std::stringstream ss; - ustring str((const char32_t*)helloResultUcs4); - - ss << str; - EXPECT_EQ(0, strcmp(ss.str().c_str(), "Hello big world")); -} - -// -// Ввод из std::istream -// - -TEST(Ustring, std_istream_intput) -{ - std::stringstream ss; - ustring str; - - ss << "big"; - ss >> str; - EXPECT_EQ(0, memcmp(helloPart2Ucs4, str.utf32_str(), sizeof(helloPart2Ucs4))); -} - -// -// Проверка на равенство -// - -TEST(Ustring, equality) -{ - ustring str((const char32_t*)helloResultUcs4); - ustring str2; - - EXPECT_TRUE(str == "Hello big world"); - EXPECT_TRUE(str2 == ""); -} - -// -// Установление нового значения строки -// - -TEST(Ustring, assign_new_value) -{ - ustring s1 = "first string"; - ustring s2 = "second string"; - - s2.assign(s1.utf32_str(false, current_byte_order()) + 6, 6); - EXPECT_TRUE(s2 == "string"); -} - -// -// Возвращение подстроки -// - -TEST(Ustring, substring) -{ - ustring str = "Hello big world!"; - ustring str2 = str.substr(6, 3); - ustring str3 = str.substr(6, ustring::npos); - EXPECT_TRUE(str2 == "big"); - EXPECT_TRUE(str3 == "big world!"); -} - -// -// Стирание части строки -// - -TEST(Ustring, erasing) -{ - ustring str = "Hello big world!"; - str.erase(6,4); - EXPECT_TRUE(str == "Hello world!"); - str.erase(5, ustring::npos); - EXPECT_TRUE(str == "Hello"); -} - -// -// Вставка строки в строку -// - -TEST(Ustring, insert_string) -{ - ustring str = "bla-bla"; - str.insert(0, "begin "); - EXPECT_TRUE(str == "begin bla-bla"); - str.insert(6, "bla "); - EXPECT_TRUE(str == "begin bla bla-bla"); - str.insert(17, " end"); - EXPECT_TRUE(str == "begin bla bla-bla end"); -} - -// -// Замена подстроки строкой -// - -TEST(Ustring, replace_string) -{ - ustring str = "111 hello 111 world 111"; - ustring str2 = str, str3 = str; - - str.replace("111", "2222"); - EXPECT_TRUE(str == "2222 hello 2222 world 2222"); - - str2.replace("111", "22"); - EXPECT_TRUE(str2 == "22 hello 22 world 22"); - - str3.replace("111", "222"); - EXPECT_TRUE(str3 == "222 hello 222 world 222"); - - str2 += " more 22 and 22 more 22"; - str2.replace("22", "33"); - EXPECT_TRUE(str2 == "33 hello 33 world 33 more 33 and 33 more 33"); -} - -/////////////////////////////////////////////////////////////////////////////////////////////// -// -// threadpool demo -// - -void func(std::size_t n) -{ - for(std::size_t j = 0; j < 100; ++j) - { - ulog.log_info("thread %, line %", n, j); - } - - std::cout << "end of thread " << n << std::endl; -} - -int geti(int i) -{ - return i; -} - -class foo -{ -public: - int bar(int n) - { - return n; - } -}; - -void run_threadpool_demo() -{ - threadpool pool(4); - std::vector> vec; - - foo f; - for (std::size_t i = 0; i < 100; ++i) - { - //std::future fut = pool.add_task([i] { return i; }); - std::future fut = pool.add_task(&foo::bar, &f, (int)i); - vec.push_back(std::move(fut)); - } - - for(std::size_t i = 0; i < 100; ++i) - { - std::cout << "res[" << i << "] = " << vec[i].get() << std::endl; - } -} - -int main(int argc, char **argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/test/server/main.cpp b/test/server/main.cpp new file mode 100644 index 0000000..92871cc --- /dev/null +++ b/test/server/main.cpp @@ -0,0 +1,10 @@ +#include "server.h" +#include + +int main() +{ + server srv("0.0.0.0", "12345"); + srv.run(); + + return 0; +} \ No newline at end of file diff --git a/test/server/server.cpp b/test/server/server.cpp new file mode 100644 index 0000000..93a279f --- /dev/null +++ b/test/server/server.cpp @@ -0,0 +1,41 @@ +#include "server.h" +#include +#include + +server::server(const std::string& address, const std::string& port) +{ + tcp::resolver resolver(_io_service); + tcp::resolver::query query(address, port); + _acceptor = new tcp::acceptor(_io_service, *resolver.resolve(query)); +} + +void server::run() +{ + accept(); + _io_service.run(); +} + +void server::accept(boost::system::error_code ec) +{ + if(!ec) + { + reenter(this) for(;;) + { + _session = new session(_io_service); + yield _acceptor->async_accept(_session->_socket, std::bind(&server::accept, this, std::placeholders::_1)); + std::cout << "new connection started" << std::endl; + _session->start(); + } + } + else + { + std::cout << "error: " << ec.message() << std::endl; + } +} + +server::~server() { + if(_socket) delete _socket; + if(_acceptor) delete _acceptor; +} + +#include diff --git a/test/server/server.h b/test/server/server.h new file mode 100644 index 0000000..5f9592a --- /dev/null +++ b/test/server/server.h @@ -0,0 +1,29 @@ +#ifndef _SERVER_H_ +#define _SERVER_H_ + +#include "session.h" +#include + +class server: boost::asio::coroutine +{ +private: + typedef boost::asio::ip::tcp tcp; + +private: + boost::asio::io_service _io_service; + tcp::acceptor* _acceptor; + tcp::socket* _socket; + session* _session; + +public: + server() = delete ; + server(server& srv) = delete; + server(const std::string& address, const std::string& port); + void run(); + ~server(); + +private: + void accept(boost::system::error_code ec = boost::system::error_code()); +}; + +#endif // _SERVER_H_ \ No newline at end of file diff --git a/test/server/session.cpp b/test/server/session.cpp new file mode 100644 index 0000000..ec67e21 --- /dev/null +++ b/test/server/session.cpp @@ -0,0 +1,41 @@ +#include "session.h" + +#include +#include + +session::session(boost::asio::io_service &io_service): boost::asio::coroutine(), _socket(io_service) +{ +} + +session::~session() +{ + std::cout << "session destructor" << std::endl; +} + +void session::start(boost::system::error_code ec, std::size_t bytes_transferred) +{ + if(!ec) + { + reenter(this) for(;;) + { + std::memset(_data, 0, 128); + yield _socket.async_read_some(boost::asio::buffer(_data, 128), std::bind(&session::start, this, std::placeholders::_1, std::placeholders::_2)); + std::cout << "async_read " << bytes_transferred << " bytes" << std::endl; + std::cout << "number: " << std::atoi(_data) << std::endl; + +// yield _pool.add_task([this]{ +// return 42; +// }); + + yield _socket.async_write_some(boost::asio::buffer(_data, 128), std::bind(&session::start, this, std::placeholders::_1, std::placeholders::_2)); + std::cout << "async_write" << std::endl; + } + } + else + { + std::cout << "error: " << ec.message() << std::endl; + delete this; + } +} + +#include diff --git a/test/server/session.h b/test/server/session.h new file mode 100644 index 0000000..d1267a4 --- /dev/null +++ b/test/server/session.h @@ -0,0 +1,27 @@ +#ifndef _SESSION_H_ +#define _SESSION_H_ + +#include "threadpool.h" +#include + +class session: boost::asio::coroutine +{ +private: + typedef boost::asio::ip::tcp tcp; + friend class server; + +private: + tcp::socket _socket; + char _data[128]; + threadpool _pool; + +public: + session() = delete; + session(session&) = delete; + session(boost::asio::io_service& io_service); + void start(boost::system::error_code ec = boost::system::error_code(), std::size_t bytes_transferred = 0); + ~session(); + +}; + +#endif // _SESSION_H_ \ No newline at end of file