ENGINE-588: added strnstr for non-bsd systems sync
authorKrista 'DarthMama' Bennett <krista@pep.foundation>
Fri, 05 Jul 2019 14:06:07 +0200
branchsync
changeset 3901cdfe2dddb5da
parent 3900 c8d13d59a185
child 3902 7eb39c8f2f94
ENGINE-588: added strnstr for non-bsd systems
src/platform_unix.c
src/platform_unix.h
src/platform_windows.cpp
src/platform_windows.h
test/include/StrnstrTests.h
test/src/engine_tests/StrnstrTests.cc
     1.1 --- a/src/platform_unix.c	Fri Jul 05 10:34:52 2019 +0200
     1.2 +++ b/src/platform_unix.c	Fri Jul 05 14:06:07 2019 +0200
     1.3 @@ -198,6 +198,43 @@
     1.4      return retval;
     1.5  }
     1.6  
     1.7 +char *strnstr(const char *big, const char *little, size_t len) {
     1.8 +    if (big == NULL || little == NULL)
     1.9 +        return NULL;
    1.10 +        
    1.11 +    if (*little == '\0')
    1.12 +        return (char*)big;
    1.13 +        
    1.14 +    const char* curr_big = big;
    1.15 +    
    1.16 +    size_t little_len = strlen(little);
    1.17 +    size_t remaining = len;
    1.18 +
    1.19 +    const char* retval = NULL;
    1.20 +    
    1.21 +    for (remaining = len; remaining >= little_len && *curr_big != '\0'; remaining--, curr_big++) {
    1.22 +        // find first-char match
    1.23 +        if (*curr_big != *little) {
    1.24 +            continue;
    1.25 +        }
    1.26 +        retval = curr_big;
    1.27 +
    1.28 +        const char* inner_big = retval + 1;
    1.29 +        const char* curr_little = little + 1;
    1.30 +        int j;
    1.31 +        for (j = 1; j < little_len; j++, inner_big++, curr_little++) {
    1.32 +            if (*inner_big != *curr_little) {
    1.33 +                retval = NULL;
    1.34 +                break;
    1.35 +            }    
    1.36 +        }
    1.37 +        if (retval)
    1.38 +            break;
    1.39 +    }
    1.40 +    return (char*)retval;
    1.41 +}
    1.42 +
    1.43 +
    1.44  #ifdef USE_NETPGP
    1.45  // FIXME: This may cause problems - this is a quick compatibility fix for netpgp code
    1.46  int regnexec(const regex_t* preg, const char* string,
    1.47 @@ -449,4 +486,3 @@
    1.48      return NULL;
    1.49  }
    1.50  #endif
    1.51 -
     2.1 --- a/src/platform_unix.h	Fri Jul 05 10:34:52 2019 +0200
     2.2 +++ b/src/platform_unix.h	Fri Jul 05 14:06:07 2019 +0200
     2.3 @@ -67,6 +67,7 @@
     2.4  #if !defined(BSD) && !defined(__APPLE__)
     2.5  size_t strlcpy(char* dst, const	char* src, size_t size);
     2.6  size_t strlcat(char* dst, const	char* src, size_t size);
     2.7 +char *strnstr(const char *big, const char *little, size_t len);
     2.8  
     2.9  // N.B. This is ifdef'd out because NDK users sometimes have trouble finding regex functions in
    2.10  //      the library in spite of the inclusion of regex.h - this is a FIXME, but since iOS is
     3.1 --- a/src/platform_windows.cpp	Fri Jul 05 10:34:52 2019 +0200
     3.2 +++ b/src/platform_windows.cpp	Fri Jul 05 14:06:07 2019 +0200
     3.3 @@ -283,6 +283,41 @@
     3.4      dst[start_len + size_to_copy] = '\0';
     3.5      return retval;
     3.6  }
     3.7 +char *strnstr(const char *big, const char *little, size_t len) {
     3.8 +    if (big == NULL || little == NULL)
     3.9 +        return NULL;
    3.10 +        
    3.11 +    if (*little == '\0')
    3.12 +        return (char*)big;
    3.13 +        
    3.14 +    const char* curr_big = big;
    3.15 +    
    3.16 +    size_t little_len = strlen(little);
    3.17 +    size_t remaining = len;
    3.18 +
    3.19 +    const char* retval = NULL;
    3.20 +    
    3.21 +    for (remaining = len; remaining >= little_len && *curr_big != '\0'; remaining--, curr_big++) {
    3.22 +        // find first-char match
    3.23 +        if (*curr_big != *little) {
    3.24 +            continue;
    3.25 +        }
    3.26 +        retval = curr_big;
    3.27 +
    3.28 +        const char* inner_big = retval + 1;
    3.29 +        const char* curr_little = little + 1;
    3.30 +        int j;
    3.31 +        for (j = 1; j < little_len; j++, inner_big++, curr_little++) {
    3.32 +            if (*inner_big != *curr_little) {
    3.33 +                retval = NULL;
    3.34 +                break;
    3.35 +            }    
    3.36 +        }
    3.37 +        if (retval)
    3.38 +            break;
    3.39 +    }
    3.40 +    return (char*)retval;
    3.41 +}
    3.42  
    3.43  int mkstemp(char *templ)
    3.44  {
     4.1 --- a/src/platform_windows.h	Fri Jul 05 10:34:52 2019 +0200
     4.2 +++ b/src/platform_windows.h	Fri Jul 05 14:06:07 2019 +0200
     4.3 @@ -74,6 +74,8 @@
     4.4  
     4.5  size_t strlcpy(char* dst, const	char* src, size_t size);
     4.6  size_t strlcat(char* dst, const	char* src, size_t size);
     4.7 +char *strnstr(const char *big, const char *little, size_t len);
     4.8 +
     4.9  
    4.10  const char *windoze_local_db(void);
    4.11  const char *windoze_system_db(void);
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/test/include/StrnstrTests.h	Fri Jul 05 14:06:07 2019 +0200
     5.3 @@ -0,0 +1,35 @@
     5.4 +// This file is under GNU General Public License 3.0
     5.5 +// see LICENSE.txt
     5.6 +
     5.7 +#ifndef STRNSTR_H
     5.8 +#define STRNSTR_H
     5.9 +
    5.10 +#include <string>
    5.11 +#include "EngineTestIndividualSuite.h"
    5.12 +
    5.13 +using namespace std;
    5.14 +
    5.15 +class StrnstrTests : public EngineTestIndividualSuite {
    5.16 +    public:
    5.17 +        StrnstrTests(string test_suite, string test_home_dir);
    5.18 +    private:
    5.19 +        void check_strnstr_equal();
    5.20 +        void check_strnstr_first_null();
    5.21 +        void check_strnstr_second_null();
    5.22 +        void check_strnstr_both_null();
    5.23 +        void check_strnstr_first_empty();
    5.24 +        void check_strnstr_second_empty();
    5.25 +        void check_strnstr_both_empty();
    5.26 +        void check_strnstr_first_letter_only();
    5.27 +        void check_strnstr_first_two_only();
    5.28 +        void check_strnstr_all_but_last();
    5.29 +        void check_strnstr_same_len_all_but_last();
    5.30 +        void check_strnstr_same_len_none();
    5.31 +        void check_strnstr_same_big_smaller();
    5.32 +        void check_strnstr_shift_one_no_match();
    5.33 +        void check_strnstr_shift_to_end();
    5.34 +        void check_strnstr_match_after_end();
    5.35 +        void check_strnstr_equal_but_size_too_small();
    5.36 +};
    5.37 +
    5.38 +#endif
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/src/engine_tests/StrnstrTests.cc	Fri Jul 05 14:06:07 2019 +0200
     6.3 @@ -0,0 +1,154 @@
     6.4 +// This file is under GNU General Public License 3.0
     6.5 +// see LICENSE.txt
     6.6 +
     6.7 +#include <stdlib.h>
     6.8 +#include <cstring>
     6.9 +#include <string>
    6.10 +
    6.11 +#include <cpptest.h>
    6.12 +#include "test_util.h"
    6.13 +
    6.14 +#include "pEpEngine.h"
    6.15 +#include "platform_unix.h"
    6.16 +
    6.17 +#include "EngineTestIndividualSuite.h"
    6.18 +#include "StrnstrTests.h"
    6.19 +
    6.20 +using namespace std;
    6.21 +
    6.22 +StrnstrTests::StrnstrTests(string suitename, string test_home_dir) :
    6.23 +    EngineTestIndividualSuite::EngineTestIndividualSuite(suitename, test_home_dir) {
    6.24 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_equal"),
    6.25 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_equal)));
    6.26 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_first_empty"),
    6.27 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_first_empty)));
    6.28 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_second_empty"),
    6.29 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_second_empty)));
    6.30 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_both_empty"),
    6.31 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_both_empty)));
    6.32 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_first_letter_only"),
    6.33 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_first_letter_only)));
    6.34 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_first_two_only"),
    6.35 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_first_two_only)));
    6.36 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_all_but_last"),
    6.37 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_all_but_last)));
    6.38 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_same_len_all_but_last"),
    6.39 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_same_len_all_but_last)));
    6.40 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_same_len_none"),
    6.41 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_same_len_none)));
    6.42 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_same_big_smaller"),
    6.43 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_same_big_smaller)));
    6.44 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_shift_one_no_match"),
    6.45 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_shift_one_no_match)));
    6.46 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_shift_to_end"),
    6.47 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_shift_to_end)));
    6.48 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_match_after_end"),
    6.49 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_match_after_end)));
    6.50 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("StrnstrTests::check_strnstr_equal_but_size_too_small"),
    6.51 +                                                                      static_cast<Func>(&StrnstrTests::check_strnstr_equal_but_size_too_small)));
    6.52 +}
    6.53 +
    6.54 +void StrnstrTests::check_strnstr_equal() {
    6.55 +    const char* big = "Bob123";
    6.56 +    const char* little = "Bob123";
    6.57 +    size_t size = strlen(big);
    6.58 +    const char* result = strnstr(big, little, size);
    6.59 +    TEST_ASSERT_MSG(result == big, result);
    6.60 +}
    6.61 +
    6.62 +void StrnstrTests::check_strnstr_first_empty() {
    6.63 +    const char* big = "";
    6.64 +    const char* little = "Bob123";
    6.65 +    size_t size = strlen(big);
    6.66 +    const char* result = strnstr(big, little, size);
    6.67 +    TEST_ASSERT_MSG(result == NULL, result);
    6.68 +}
    6.69 +void StrnstrTests::check_strnstr_second_empty() {
    6.70 +    const char* big = "YerMama";
    6.71 +    const char* little = "";
    6.72 +    size_t size = strlen(big);
    6.73 +    const char* result = strnstr(big, little, size);
    6.74 +    TEST_ASSERT_MSG(result == big, result);
    6.75 +    TEST_ASSERT(true);
    6.76 +}
    6.77 +
    6.78 +void StrnstrTests::check_strnstr_both_empty() {
    6.79 +    const char* big = "";
    6.80 +    const char* little = "";
    6.81 +    size_t size = strlen(big);
    6.82 +    const char* result = strnstr(big, little, size);
    6.83 +    TEST_ASSERT_MSG(result == big, result);
    6.84 +    TEST_ASSERT(true);
    6.85 +}
    6.86 +
    6.87 +void StrnstrTests::check_strnstr_first_letter_only() {
    6.88 +    const char* big = "Bob123";
    6.89 +    const char* little = "Beef";
    6.90 +    size_t size = strlen(big);
    6.91 +    const char* result = strnstr(big, little, size);
    6.92 +    TEST_ASSERT_MSG(result == NULL, result);    
    6.93 +}
    6.94 +void StrnstrTests::check_strnstr_first_two_only() {
    6.95 +    const char* big = "Bob123";
    6.96 +    const char* little = "Boof";
    6.97 +    size_t size = strlen(big);
    6.98 +    const char* result = strnstr(big, little, size);
    6.99 +    TEST_ASSERT_MSG(result == NULL, result);    
   6.100 +}
   6.101 +void StrnstrTests::check_strnstr_all_but_last() {
   6.102 +    const char* big = "BeesBeesBees";
   6.103 +    const char* little = "Beef";
   6.104 +    size_t size = strlen(big);
   6.105 +    const char* result = strnstr(big, little, size);
   6.106 +    TEST_ASSERT_MSG(result == NULL, result);    
   6.107 +}
   6.108 +void StrnstrTests::check_strnstr_same_len_all_but_last() {
   6.109 +    const char* big = "Bees";
   6.110 +    const char* little = "Beef";
   6.111 +    size_t size = strlen(big);
   6.112 +    const char* result = strnstr(big, little, size);
   6.113 +    TEST_ASSERT_MSG(result == NULL, result);    
   6.114 +}
   6.115 +void StrnstrTests::check_strnstr_same_len_none() {
   6.116 +    const char* big = "1234";
   6.117 +    const char* little = "Beef";
   6.118 +    size_t size = strlen(big);
   6.119 +    const char* result = strnstr(big, little, size);
   6.120 +    TEST_ASSERT_MSG(result == NULL, result);    
   6.121 +}
   6.122 +void StrnstrTests::check_strnstr_same_big_smaller() {
   6.123 +    const char* big = "Bee";
   6.124 +    const char* little = "Bees";
   6.125 +    size_t size = strlen(big);
   6.126 +    const char* result = strnstr(big, little, size);
   6.127 +    TEST_ASSERT_MSG(result == NULL, result);    
   6.128 +}
   6.129 +void StrnstrTests::check_strnstr_shift_one_no_match() {
   6.130 +    const char* big = "1Bee";
   6.131 +    const char* little = "Bees";
   6.132 +    size_t size = strlen(big);
   6.133 +    const char* result = strnstr(big, little, size);
   6.134 +    TEST_ASSERT_MSG(result == NULL, result);    
   6.135 +}
   6.136 +void StrnstrTests::check_strnstr_shift_to_end() {
   6.137 +    const char* big = "BigBeeWithExtraBeef";
   6.138 +    const char* little = "Beef";
   6.139 +    size_t size = strlen(big);
   6.140 +    const char* result = strnstr(big, little, size);
   6.141 +    TEST_ASSERT_MSG(result == big + 15, result);    
   6.142 +    TEST_ASSERT(true);
   6.143 +}
   6.144 +void StrnstrTests::check_strnstr_match_after_end() {
   6.145 +    const char* big = "EatMoreBeef";
   6.146 +    const char* little = "Beef";
   6.147 +    size_t size = strlen(big);
   6.148 +    const char* result = strnstr(big, little, size - 1);
   6.149 +    TEST_ASSERT_MSG(result == NULL, result);
   6.150 +}
   6.151 +void StrnstrTests::check_strnstr_equal_but_size_too_small() {
   6.152 +    const char* big = "Bob123";
   6.153 +    const char* little = "Bob123";
   6.154 +    size_t size = strlen(big);
   6.155 +    const char* result = strnstr(big, little, size - 1);
   6.156 +    TEST_ASSERT_MSG(result == NULL, result);
   6.157 +}