cxx string_splitter

This commit is contained in:
Kelvin Sherlock 2015-02-01 19:42:16 -05:00
parent d0d1e84162
commit 023d233c40
2 changed files with 98 additions and 31 deletions

View File

@ -59,6 +59,8 @@
#include "loader.h" #include "loader.h"
#include "debugger.h" #include "debugger.h"
#include <cxx/string_splitter.h>
#define LOADER_LOAD #define LOADER_LOAD
@ -687,43 +689,26 @@ std::string find_exe(const std::string &name)
// otherwise, check the Commands variable for locations. // otherwise, check the Commands variable for locations.
std::string command = MPW::GetEnv("Commands"); std::string commands = MPW::GetEnv("Commands");
if (command.empty()) return old_find_exe(name); if (commands.empty()) return old_find_exe(name);
// string is , separated, possibly in MacOS format. // string is , separated, possibly in MacOS format.
std::string::size_type begin = 0;
std::string::size_type end = 0; for (auto iter = string_splitter(commands, ','); iter; ++iter)
for(;;)
{ {
std::string path; if (iter->empty()) continue;
end = command.find(',', begin); std::string path = *iter;
if (end == std::string::npos) { // convert to unix.
path = ToolBox::MacToUnix(path);
if (begin >= command.length()) return ""; // should always have a length...
if (path.length() && path.back() != '/') path.push_back('/');
path = command.substr(begin); path.append(name);
} if (file_exists(path)) return path;
else
{
size_t count = end - begin - 1;
path = command.substr(begin, count);
}
if (!path.empty())
{
// convert to unix.
path = ToolBox::MacToUnix(path);
// should always have a length...
if (path.length() && path.back() != '/') path.push_back('/');
path.append(name);
if (file_exists(path)) return path;
}
if (end == std::string::npos) return "";
begin = end + 1;
} }
return "";
} }

82
cxx/string_splitter.h Normal file
View File

@ -0,0 +1,82 @@
#ifndef __string_splitter__
#define __string_splitter__
#include <string>
class string_splitter {
public:
string_splitter(const std::string &str, char sep) :
_parent(str), _sep(sep)
{
_begin = 0;
_end = _parent.find(_sep);
_str = _parent.substr(_begin, _end);
// _begin is 0, _end is either npos or offset from 0,
// so no need to calculate a count.
}
operator bool() const {
return _begin != npos;
}
string_splitter &operator++() {
increment();
return *this;
}
const std::string &operator *() const {
return _str;
}
const std::string *operator ->() const {
return &_str;
}
private:
void increment() {
_str.clear();
if (_begin == npos) return;
if (_end == npos) { _begin = _end; return; }
_begin = _end + 1;
_end = _parent.find(_sep, _begin);
auto count = _end == npos ? _end : _end - _begin;
_str = _parent.substr(_begin, count);
}
const static auto npos = std::string::npos;
std::string _str;
const std::string &_parent;
char _sep;
std::string::size_type _begin = 0;
std::string::size_type _end = 0;
};
#ifdef TEST
#include <cstdio>
#include <cstring>
int main(int argc, char **argv)
{
if (argc != 3) {
fprintf(stderr, "Usage: %s sep string\n", argv[0]);
return 1;
}
if (strlen(argv[1]) != 1) {
fprintf(stderr, "Separator must be a single character\n");
return 1;
}
char sep = argv[1][0];
std::string str(argv[2]);
for (auto iter = string_splitter(str, sep); iter; ++iter) {
printf("%s\n", iter->c_str());
}
return 0;
}
#endif
#endif