File: split.h

package info (click to toggle)
darkradiant 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 41,080 kB
  • sloc: cpp: 264,743; ansic: 10,659; python: 1,852; xml: 1,650; sh: 92; makefile: 21
file content (64 lines) | stat: -rw-r--r-- 2,065 bytes parent folder | download | duplicates (3)
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
#pragma once

#include <string>
#include <iterator>
#include <vector>

namespace string
{

/**
 * Splits the given string into pieces based on the given delimiters, storing
 * the tokens at the end the given token container (which might be any container 
 * supporting insert iterators (std::vector, std::list, std::set, etc.)
 */
template <typename ContainerType>
inline void split(ContainerType& tokens, const std::string& subject, const std::string& delimiters,
                  bool trimEmpty = true)
{
	std::string::size_type lastPos = 0;
	std::string::size_type length = subject.length();

	// Construct an output iterator which inserts elements at the end of the container
	std::insert_iterator<ContainerType> output = std::inserter(tokens, tokens.end());

	while (lastPos < length + 1)
	{
		// Find the next occurrence of any of the delimiters
		std::string::size_type pos = subject.find_first_of(delimiters, lastPos);

		// Nothing found, set the pos to trigger an exit
		if (pos == std::string::npos)
		{
			pos = length;
		}

		// If the found position is different from the last occurrence, we have a non-empty token
		// If the position is the same, this is an empty token, in which case we need to check the flag
		if (pos != lastPos || !trimEmpty)
		{
			// Copy the range [lastPos..pos] from the subject and insert it into our token container
			output = typename ContainerType::value_type(
				subject.data() + lastPos, 
				static_cast<typename ContainerType::size_type>(pos - lastPos));
		}

		// Advance the cursor by one to skip the found delimiter
		lastPos = pos + 1;
	}
}

/**
 * @brief Split the given string into parts, returning the result as a std::vector.
 *
 * Convenience wrapper for split() which does not require an existing container variable.
 */
inline std::vector<std::string> splitToVec(const std::string& subject,
                                           const std::string& delimiters, bool trimEmpty = true)
{
    std::vector<std::string> result;
    split(result, subject, delimiters, trimEmpty);
    return result;
}

}