diff --git a/.gitignore b/.gitignore index 7d8b0da..dbd2075 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ bin/ lib/ -CMakeLists.txt.user - +cpputil.creator +cpputil.creator.user +cpputil.files +cpputil.includes +cpputil.config \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100755 index 4f85f53..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(CMAKE_BUILD_TYPE DEBUG) - -if(WIN32) - set(CMAKE_CXX_FLAGS " /D _VARIADIC_MAX=10") -else() - set(CMAKE_CXX_FLAGS "-std=c++11") - set(CMAKE_CXX_FLAGS_DEBUG "-g -O0") - set(CMAKE_CXX_FLAGS_RELEASE "-O2") -endif() - -set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin) -set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/lib) -set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/usr) - -include_directories(include) - -add_subdirectory(src) -add_subdirectory(test) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b6a093d --- /dev/null +++ b/Makefile @@ -0,0 +1,58 @@ +# assembler +AS = /home/selim/progs/bin/fasm +ASFLAGS = +#LINKER = ld +#ASLDFLAGS = -lc -e main -dynamic-linker /lib64/ld-linux-x86-64.so.2 + +# Target platform +ARCH = x86_64 +OS = linux + +# C++ compier +CXX = g++ +CXXFLAGS = -MMD -c -g -Og -Wall -Werror -std=c++11 -Iinclude -Isrc/asm/include +LDFLAGS = -lgtest + +# Archiver +AR = ar + +BINDIR = bin +LIBDIR = lib +OBJDIR = obj + +CPPUTIL_CXX_SOURCES = $(wildcard src/*.cpp) +CPPUTIL_ASM_SOURCES = $(wildcard src/asm/$(OS)/$(ARCH)/*.s) +CPPUTIL_OBJECTS = $(CPPUTIL_CXX_SOURCES:%.cpp=$(OBJDIR)/%.o) $(CPPUTIL_ASM_SOURCES:%.s=$(OBJDIR)/%.o) +CPPUTIL_DEPS = $(CPPUTIL_CXX_SOURCES:%.cpp=$(OBJDIR)/%.d) + +TEST_SOURCES = $(wildcard test/*.cpp) +TEST_OBJECTS = $(TEST_SOURCES:%.cpp=$(OBJDIR)/%.o) +TEST_DEPS = $(TEST_SOURCES:%.cpp=$(OBJDIR)/%.d) + +all: $(BINDIR)/cpputil_test $(LIBDIR)/libcpputil.a + +$(BINDIR)/cpputil_test: bindir $(TEST_OBJECTS) lib/libcpputil.a + $(CXX) $(LDFLAGS) -o $(BINDIR)/cpputil_test $(TEST_OBJECTS) $(LIBDIR)/libcpputil.a + +$(LIBDIR)/libcpputil.a: libdir $(CPPUTIL_OBJECTS) + $(AR) rcs $(LIBDIR)/libcpputil.a $(CPPUTIL_OBJECTS) + +-include $(CPPUTIL_DEPS) $(TEST_DEPS) + +$(OBJDIR)/%.o: %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ + +$(OBJDIR)/%.o: %.s + $(AS) $(ASFLAGS) $< $@ + +bindir: objdir + mkdir -p $(BINDIR) + +libdir: objdir + mkdir -p $(LIBDIR) + +objdir: + mkdir -p $(dir $(CPPUTIL_OBJECTS) $(TEST_OBJECTS)) + +clean: + rm -rf $(LIBDIR) $(BINDIR) $(OBJDIR) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100755 index 652ddb2..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(MAIN_PROJECT_NAME "cpputil") -set(SRC_DIR ".") -set(INCLUDE_DIR "../include") - -project(${MAIN_PROJECT_NAME} CXX) -aux_source_directory(${SRC_DIR} SRC_FILES) -include_directories(${INCLUDE_DIR}) -add_library(${MAIN_PROJECT_NAME} STATIC ${SRC_FILES}) -target_link_libraries(${MAIN_PROJECT_NAME}) - -install(TARGETS ${MAIN_PROJECT_NAME} - RUNTIME DESTINATION bin - ARCHIVE DESTINATION lib) - -install(DIRECTORY ${INCLUDE_DIR}/ - DESTINATION include/${PROJECT_NAME} - FILES_MATCHING PATTERN "*.h") diff --git a/src/asm/include/ustring_asm.h b/src/asm/include/ustring_asm.h new file mode 100644 index 0000000..b6f8c4c --- /dev/null +++ b/src/asm/include/ustring_asm.h @@ -0,0 +1,9 @@ +#ifndef _USTRING_ASM_ +#define _USTRING_ASM_ + +extern "C" +{ + const char32_t* _asm_ucs4_strstr(const char32_t* srcStr, std::size_t srcLen, const char32_t* subStr, std::size_t subStrLen); +} + +#endif // _USTRING_ASM_ \ No newline at end of file diff --git a/src/asm/linux/x86_64/ustring_asm.s b/src/asm/linux/x86_64/ustring_asm.s new file mode 100644 index 0000000..d03bc5f --- /dev/null +++ b/src/asm/linux/x86_64/ustring_asm.s @@ -0,0 +1,97 @@ +format ELF64 + +; +; public exported functions +; + +public _asm_ucs4_strstr +public _asm_ucs4_strchr + +; +; code section +; + +section '.text' executable + +; constants + +npos = -1 + +;================================================================================ +; +; Поиск подстроки в строке UCS-4 (алгоритм "в лоб", подойдет для коротких строк) +; +; rdi: указатель на исходную строку +; rsi: длина исходной строки символах +; rdx: указатель на искомую подстроку +; rcx: длина подстроки в символах +; +;================================================================================ + +_asm_ucs4_strstr: + + xor r8, r8 + mov r9d, dword [rdx] + + strstr_try_next_symbol: + + cmp r9d, dword [rdi + r8*4] + je strstr_init_counter + inc r8 + cmp rsi, r8 + jne strstr_try_next_symbol + mov rax, 0 + ret + + strstr_init_counter: + + xor r10, r10 + + strstr_symbol_found: + + inc r10 + cmp r10, rcx + je strstr_the_end + lea rax, [r8 + r10] + mov r11d, dword [rdi + rax*4] + cmp r11d, dword [rdx + r10*4] + je strstr_symbol_found + inc r8 + jmp strstr_try_next_symbol + + strstr_the_end: + + lea rax, [rdi + r8*4] + + 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 14f6bc3..1e7148f 100755 --- a/src/ustring.cpp +++ b/src/ustring.cpp @@ -1,4 +1,5 @@ #include "ustring.h" +#include "ustring_asm.h" #include #include @@ -381,11 +382,18 @@ std::size_t ustring::find(const ustring& str, std::size_t pos /* = 0 */) const } #ifdef __GNUC__ + /* char32_t* fpos = reinterpret_cast(memmem(_pData + pos, (_len - pos)*sizeof(char32_t), str._pData, str._len*sizeof(char32_t))); if(fpos) { return (fpos - _pData); } + */ + const char32_t* fpos = _asm_ucs4_strstr(_pData + pos, (_len - pos), str._pData, str._len); + if(fpos) + { + return (fpos - _pData); + } #else const char32_t* pStr = str._pData; const std::size_t len = _len - str.length(); diff --git a/src/utf.cpp b/src/utf.cpp index 45a6c68..28d47ce 100755 --- a/src/utf.cpp +++ b/src/utf.cpp @@ -301,7 +301,6 @@ std::size_t ucs4_get_utf8_str_bytes(const char32_t* str, bool needEscape) */ std::size_t utf8_get_symbol_size(const char* str, bool needUnescape) { - uint32_t s = 0; if(needUnescape && *str == '\\') // UCS unescape { if(*(str + 1) == 'u') @@ -371,7 +370,6 @@ std::size_t ucs4_get_utf8_symbol_size(const char32_t symbol, bool needEscape) std::size_t sBits = significant_bits(symbol); std::size_t sixBitBytes = sBits / 6; std::size_t restBits = sBits % 6; - uint32_t s = static_cast(symbol); if(sBits <= 7) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100755 index 792cc69..0000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(TEST_PROJECT_NAME "cpputil_test") -set(SRC_DIR ".") -set(REQUIRED_LIBRARIES cpputil) - -if(WIN32) - INCLUDE(ExternalProject) - SET_DIRECTORY_PROPERTIES(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/ThirdParty) - - ExternalProject_Add( - googletest - SVN_REPOSITORY http://googletest.googlecode.com/svn/trunk/ - TIMEOUT 100 - CMAKE_ARGS -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG:PATH=Debug - -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE:PATH=Release - -Dgtest_force_shared_crt=ON - -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - INSTALL_COMMAND "" - LOG_DOWNLOAD ON - LOG_CONFIGURE ON - LOG_BUILD ON) - - ExternalProject_Get_Property(googletest source_dir) - ExternalProject_Get_Property(googletest binary_dir) - INCLUDE_DIRECTORIES(${source_dir}/include) - #link_directories(${binary_dir}/Debug) -else() - FIND_PACKAGE(GTest REQUIRED) - if(NOT GTEST_FOUND) - message(SEND_ERROR "Failed to find Google Test Framework") - return() - else() - include_directories(${GTEST_INCLUDE_DIRS}) - endif() -endif() - -project(${TEST_PROJECT_NAME} CXX) -aux_source_directory(${SRC_DIR} 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) - -if(WIN32) - target_link_libraries(${TEST_PROJECT_NAME} ${REQUIRED_LIBRARIES} - debug ${binary_dir}/Debug/gtest.lib - optimized ${binary_dir}/Release/gtest.lib) -else() - target_link_libraries(${TEST_PROJECT_NAME} ${REQUIRED_LIBRARIES} gtest) -endif() - -install(TARGETS ${TEST_PROJECT_NAME} - RUNTIME DESTINATION bin - ARCHIVE DESTINATION lib) diff --git a/test/main.cpp b/test/main.cpp index 7948a91..011da48 100755 --- a/test/main.cpp +++ b/test/main.cpp @@ -439,6 +439,7 @@ 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)); }