summaryrefslogtreecommitdiff
path: root/graphics/asymptote/LspCpp/third_party/uri/src/detail/algorithm_split.hpp
blob: d6de14543adce95783a0e1ee7ebe43ab2e116ebf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
 * Search algorithms
 * @author Lobaskin Vasily
 * @data 31 March 2020
 * @copyright Boost Software License, Version 1.0
 */

#include <type_traits>

namespace network {
namespace algorithm {

template <typename ContainerT, class SequenceT, typename SplitterT,
          typename std::enable_if<std::is_fundamental<SplitterT>::value>::type
              * = nullptr>
bool split(ContainerT &container, SequenceT const &str, SplitterT symbol) {
  using PartT = typename ContainerT::value_type;
  static_assert(std::is_same<typename SequenceT::value_type, SplitterT>::value,
                "Splitter type doesn't match sequence inner type");

  std::size_t sequenceStart = 0;
  for (std::size_t i = 0, len = str.size(); i <= len; ++i) {
    if (str[i] != symbol && i != len) continue;

    std::size_t substrLen = i - sequenceStart;
    if (substrLen > 0) {
      PartT part{str.cbegin() + sequenceStart, str.cbegin() + i};
      container.emplace_back(std::move(part));
    } else {
      container.emplace_back(PartT{});
    }
    sequenceStart = i + 1;
  }

  return true;
}

template <typename ContainerT, class SequenceT, typename SplitterT,
          typename std::enable_if<!std::is_fundamental<SplitterT>::value>::type
              * = nullptr>
bool split(ContainerT &container, SequenceT const &str, SplitterT splitter) {
  using PartT = typename ContainerT::value_type;
  static_assert(
      std::is_same<typename ContainerT::value_type, std::string>::value,
      "Invalid container type, only string is supported");

  bool isEqual = false;
  std::size_t sequenceLen = splitter.size();
  std::size_t sequenceStart = 0;
  for (std::size_t i = 0, len = str.size(); i <= len; ++i) {
    isEqual = true;
    for (std::size_t j = 0; j < sequenceLen; ++j) {
      if (str[i + j] != splitter[j]) {
        isEqual = false;
        break;
      }
    }
    if (!isEqual && i != len) continue;

    std::size_t substrLen = i - sequenceStart;
    if (substrLen > 0) {
      PartT part{str.cbegin() + sequenceStart, str.cbegin() + i};
      container.emplace_back(std::move(part));
    } else {
      container.emplace_back(PartT{});
    }
    sequenceStart = i + sequenceLen;
    i += sequenceLen - 1;
  }

  return true;
}

}  // namespace algorithm
}  // namespace network