Track String memory allocations
This commit is contained in:
parent
e5b36f548b
commit
9f9156a752
|
@ -31,7 +31,8 @@ public:
|
||||||
ArrayView(const Iterator& begin, const Iterator& end)
|
ArrayView(const Iterator& begin, const Iterator& end)
|
||||||
: m_pointer(&(*begin)), m_size(end - begin) {}
|
: m_pointer(&(*begin)), m_size(end - begin) {}
|
||||||
|
|
||||||
ArrayView(const std::vector<T>& v)
|
template<typename Alloc>
|
||||||
|
ArrayView(const std::vector<T, Alloc>& v)
|
||||||
: m_pointer(&v[0]), m_size(v.size()) {}
|
: m_pointer(&v[0]), m_size(v.size()) {}
|
||||||
|
|
||||||
ArrayView(const std::initializer_list<T>& v)
|
ArrayView(const std::initializer_list<T>& v)
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
#ifndef completion_hh_INCLUDED
|
#ifndef completion_hh_INCLUDED
|
||||||
#define completion_hh_INCLUDED
|
#define completion_hh_INCLUDED
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "units.hh"
|
#include "units.hh"
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
|
#include "vector.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
|
|
||||||
using CandidateList = std::vector<String>;
|
using CandidateList = Vector<String>;
|
||||||
|
|
||||||
struct Completions
|
struct Completions
|
||||||
{
|
{
|
||||||
|
|
19
src/file.cc
19
src/file.cc
|
@ -4,7 +4,6 @@
|
||||||
#include "buffer.hh"
|
#include "buffer.hh"
|
||||||
#include "buffer_manager.hh"
|
#include "buffer_manager.hh"
|
||||||
#include "buffer_utils.hh"
|
#include "buffer_utils.hh"
|
||||||
#include "completion.hh"
|
|
||||||
#include "debug.hh"
|
#include "debug.hh"
|
||||||
#include "unicode.hh"
|
#include "unicode.hh"
|
||||||
#include "regex.hh"
|
#include "regex.hh"
|
||||||
|
@ -260,7 +259,7 @@ String find_file(StringView filename, ArrayView<String> paths)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Filter>
|
template<typename Filter>
|
||||||
std::vector<String> list_files(StringView prefix, StringView dirname,
|
Vector<String> list_files(StringView prefix, StringView dirname,
|
||||||
Filter filter)
|
Filter filter)
|
||||||
{
|
{
|
||||||
kak_assert(dirname.empty() or dirname.back() == '/');
|
kak_assert(dirname.empty() or dirname.back() == '/');
|
||||||
|
@ -270,8 +269,8 @@ std::vector<String> list_files(StringView prefix, StringView dirname,
|
||||||
|
|
||||||
auto closeDir = on_scope_end([=]{ closedir(dir); });
|
auto closeDir = on_scope_end([=]{ closedir(dir); });
|
||||||
|
|
||||||
std::vector<String> result;
|
Vector<String> result;
|
||||||
std::vector<String> subseq_result;
|
Vector<String> subseq_result;
|
||||||
while (dirent* entry = readdir(dir))
|
while (dirent* entry = readdir(dir))
|
||||||
{
|
{
|
||||||
if (not filter(*entry))
|
if (not filter(*entry))
|
||||||
|
@ -301,7 +300,7 @@ std::vector<String> list_files(StringView prefix, StringView dirname,
|
||||||
return result.empty() ? subseq_result : result;
|
return result.empty() ? subseq_result : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<String> complete_filename(StringView prefix,
|
CandidateList complete_filename(StringView prefix,
|
||||||
const Regex& ignored_regex,
|
const Regex& ignored_regex,
|
||||||
ByteCount cursor_pos)
|
ByteCount cursor_pos)
|
||||||
{
|
{
|
||||||
|
@ -329,14 +328,14 @@ std::vector<String> complete_filename(StringView prefix,
|
||||||
return not check_ignored_regex or
|
return not check_ignored_regex or
|
||||||
not regex_match(entry.d_name, ignored_regex);
|
not regex_match(entry.d_name, ignored_regex);
|
||||||
};
|
};
|
||||||
std::vector<String> res = list_files(fileprefix, dirname, filter);
|
Vector<String> res = list_files(fileprefix, dirname, filter);
|
||||||
for (auto& file : res)
|
for (auto& file : res)
|
||||||
file = dirname + file;
|
file = dirname + file;
|
||||||
std::sort(res.begin(), res.end());
|
std::sort(res.begin(), res.end());
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
||||||
{
|
{
|
||||||
String real_prefix = parse_filename(prefix.substr(0, cursor_pos));
|
String real_prefix = parse_filename(prefix.substr(0, cursor_pos));
|
||||||
|
|
||||||
|
@ -361,7 +360,7 @@ std::vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
||||||
| (st.st_mode & S_IXOTH);
|
| (st.st_mode & S_IXOTH);
|
||||||
return S_ISDIR(st.st_mode) or (S_ISREG(st.st_mode) and executable);
|
return S_ISDIR(st.st_mode) or (S_ISREG(st.st_mode) and executable);
|
||||||
};
|
};
|
||||||
std::vector<String> res = list_files(fileprefix, dirname, filter);
|
Vector<String> res = list_files(fileprefix, dirname, filter);
|
||||||
for (auto& file : res)
|
for (auto& file : res)
|
||||||
file = dirname + file;
|
file = dirname + file;
|
||||||
std::sort(res.begin(), res.end());
|
std::sort(res.begin(), res.end());
|
||||||
|
@ -373,11 +372,11 @@ std::vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
||||||
struct CommandCache
|
struct CommandCache
|
||||||
{
|
{
|
||||||
TimeSpec mtime = {};
|
TimeSpec mtime = {};
|
||||||
std::vector<String> commands;
|
Vector<String> commands;
|
||||||
};
|
};
|
||||||
static UnorderedMap<String, CommandCache> command_cache;
|
static UnorderedMap<String, CommandCache> command_cache;
|
||||||
|
|
||||||
std::vector<String> res;
|
Vector<String> res;
|
||||||
for (auto dir : split(getenv("PATH"), ':'))
|
for (auto dir : split(getenv("PATH"), ':'))
|
||||||
{
|
{
|
||||||
String dirname = dir;
|
String dirname = dir;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef file_hh_INCLUDED
|
#ifndef file_hh_INCLUDED
|
||||||
#define file_hh_INCLUDED
|
#define file_hh_INCLUDED
|
||||||
|
|
||||||
|
#include "completion.hh"
|
||||||
#include "exception.hh"
|
#include "exception.hh"
|
||||||
#include "regex.hh"
|
#include "regex.hh"
|
||||||
|
|
||||||
|
@ -46,12 +47,10 @@ String find_file(StringView filename, ArrayView<String> paths);
|
||||||
|
|
||||||
time_t get_fs_timestamp(StringView filename);
|
time_t get_fs_timestamp(StringView filename);
|
||||||
|
|
||||||
std::vector<String> complete_filename(StringView prefix,
|
CandidateList complete_filename(StringView prefix, const Regex& ignore_regex,
|
||||||
const Regex& ignore_regex,
|
|
||||||
ByteCount cursor_pos = -1);
|
ByteCount cursor_pos = -1);
|
||||||
|
|
||||||
std::vector<String> complete_command(StringView prefix,
|
CandidateList complete_command(StringView prefix, ByteCount cursor_pos = -1);
|
||||||
ByteCount cursor_pos = -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // file_hh_INCLUDED
|
#endif // file_hh_INCLUDED
|
||||||
|
|
|
@ -31,6 +31,13 @@ template<typename T, MemoryDomain domain>
|
||||||
struct Allocator
|
struct Allocator
|
||||||
{
|
{
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
// TODO: remove that once we have a c++11 compliant stdlib
|
||||||
|
using pointer = T*;
|
||||||
|
using const_pointer = const T*;
|
||||||
|
using reference = T&;
|
||||||
|
using const_reference = const T&;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
|
||||||
Allocator() = default;
|
Allocator() = default;
|
||||||
template<typename U>
|
template<typename U>
|
||||||
|
|
|
@ -707,7 +707,7 @@ static String make_info_box(StringView title, StringView message,
|
||||||
assistant_size = { (int)assistant.size(), assistant[0].char_length() };
|
assistant_size = { (int)assistant.size(), assistant[0].char_length() };
|
||||||
|
|
||||||
const CharCount max_bubble_width = max_width - assistant_size.column - 6;
|
const CharCount max_bubble_width = max_width - assistant_size.column - 6;
|
||||||
std::vector<StringView> lines = wrap_lines(message, max_bubble_width);
|
Vector<StringView> lines = wrap_lines(message, max_bubble_width);
|
||||||
|
|
||||||
CharCount bubble_width = title.char_length() + 2;
|
CharCount bubble_width = title.char_length() + 2;
|
||||||
for (auto& line : lines)
|
for (auto& line : lines)
|
||||||
|
|
|
@ -34,8 +34,8 @@ inline void option_from_string(StringView str, bool& opt)
|
||||||
|
|
||||||
constexpr Codepoint list_separator = ':';
|
constexpr Codepoint list_separator = ':';
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, typename Alloc>
|
||||||
String option_to_string(const std::vector<T>& opt)
|
String option_to_string(const std::vector<T, Alloc>& opt)
|
||||||
{
|
{
|
||||||
String res;
|
String res;
|
||||||
for (size_t i = 0; i < opt.size(); ++i)
|
for (size_t i = 0; i < opt.size(); ++i)
|
||||||
|
@ -47,11 +47,11 @@ String option_to_string(const std::vector<T>& opt)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, typename Alloc>
|
||||||
void option_from_string(StringView str, std::vector<T>& opt)
|
void option_from_string(StringView str, std::vector<T, Alloc>& opt)
|
||||||
{
|
{
|
||||||
opt.clear();
|
opt.clear();
|
||||||
std::vector<String> elems = split(str, list_separator, '\\');
|
Vector<String> elems = split(str, list_separator, '\\');
|
||||||
for (auto& elem: elems)
|
for (auto& elem: elems)
|
||||||
{
|
{
|
||||||
T opt_elem;
|
T opt_elem;
|
||||||
|
@ -60,8 +60,8 @@ void option_from_string(StringView str, std::vector<T>& opt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, typename Alloc>
|
||||||
bool option_add(std::vector<T>& opt, const std::vector<T>& vec)
|
bool option_add(std::vector<T, Alloc>& opt, const std::vector<T, Alloc>& vec)
|
||||||
{
|
{
|
||||||
std::copy(vec.begin(), vec.end(), back_inserter(opt));
|
std::copy(vec.begin(), vec.end(), back_inserter(opt));
|
||||||
return not vec.empty();
|
return not vec.empty();
|
||||||
|
@ -88,7 +88,7 @@ void option_from_string(StringView str, UnorderedMap<Key, Value>& opt)
|
||||||
opt.clear();
|
opt.clear();
|
||||||
for (auto& elem : split(str, list_separator, '\\'))
|
for (auto& elem : split(str, list_separator, '\\'))
|
||||||
{
|
{
|
||||||
std::vector<String> pair_str = split(elem, '=', '\\');
|
Vector<String> pair_str = split(elem, '=', '\\');
|
||||||
if (pair_str.size() != 2)
|
if (pair_str.size() != 2)
|
||||||
throw runtime_error("map option expects key=value");
|
throw runtime_error("map option expects key=value");
|
||||||
std::pair<Key, Value> pair;
|
std::pair<Key, Value> pair;
|
||||||
|
|
|
@ -17,9 +17,9 @@ bool operator<(StringView lhs, StringView rhs)
|
||||||
return cmp < 0;
|
return cmp < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<String> split(StringView str, char separator, char escape)
|
Vector<String> split(StringView str, char separator, char escape)
|
||||||
{
|
{
|
||||||
std::vector<String> res;
|
Vector<String> res;
|
||||||
auto it = str.begin();
|
auto it = str.begin();
|
||||||
while (it != str.end())
|
while (it != str.end())
|
||||||
{
|
{
|
||||||
|
@ -48,9 +48,9 @@ std::vector<String> split(StringView str, char separator, char escape)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<StringView> split(StringView str, char separator)
|
Vector<StringView> split(StringView str, char separator)
|
||||||
{
|
{
|
||||||
std::vector<StringView> res;
|
Vector<StringView> res;
|
||||||
auto beg = str.begin();
|
auto beg = str.begin();
|
||||||
for (auto it = beg; it != str.end(); ++it)
|
for (auto it = beg; it != str.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -138,14 +138,14 @@ String expand_tabs(StringView line, CharCount tabstop, CharCount col)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<StringView> wrap_lines(StringView text, CharCount max_width)
|
Vector<StringView> wrap_lines(StringView text, CharCount max_width)
|
||||||
{
|
{
|
||||||
using Utf8It = utf8::iterator<const char*>;
|
using Utf8It = utf8::iterator<const char*>;
|
||||||
Utf8It word_begin{text.begin()};
|
Utf8It word_begin{text.begin()};
|
||||||
Utf8It word_end{word_begin};
|
Utf8It word_end{word_begin};
|
||||||
Utf8It end{text.end()};
|
Utf8It end{text.end()};
|
||||||
CharCount col = 0;
|
CharCount col = 0;
|
||||||
std::vector<StringView> lines;
|
Vector<StringView> lines;
|
||||||
Utf8It line_begin = text.begin();
|
Utf8It line_begin = text.begin();
|
||||||
Utf8It line_end = line_begin;
|
Utf8It line_end = line_begin;
|
||||||
while (word_begin != end)
|
while (word_begin != end)
|
||||||
|
|
|
@ -4,50 +4,55 @@
|
||||||
#include "units.hh"
|
#include "units.hh"
|
||||||
#include "utf8.hh"
|
#include "utf8.hh"
|
||||||
#include "hash.hh"
|
#include "hash.hh"
|
||||||
|
#include "vector.hh"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
class StringView;
|
class StringView;
|
||||||
|
|
||||||
class String : public std::string
|
using StringBase = std::basic_string<char, std::char_traits<char>,
|
||||||
|
Allocator<char, MemoryDomain::String>>;
|
||||||
|
|
||||||
|
class String : public StringBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
String() {}
|
String() {}
|
||||||
String(const char* content) : std::string(content) {}
|
String(const char* content) : StringBase(content) {}
|
||||||
String(std::string content) : std::string(std::move(content)) {}
|
String(StringBase content) : StringBase(std::move(content)) {}
|
||||||
explicit String(char content, CharCount count = 1) : std::string((size_t)(int)count, content) {}
|
template<typename Char, typename Traits, typename Alloc>
|
||||||
|
String(const std::basic_string<Char, Traits, Alloc>& content) : StringBase(content.begin(), content.end()) {}
|
||||||
|
explicit String(char content, CharCount count = 1) : StringBase((size_t)(int)count, content) {}
|
||||||
explicit String(Codepoint cp, CharCount count = 1)
|
explicit String(Codepoint cp, CharCount count = 1)
|
||||||
{
|
{
|
||||||
while (count-- > 0)
|
while (count-- > 0)
|
||||||
utf8::dump(back_inserter(*this), cp);
|
utf8::dump(back_inserter(*this), cp);
|
||||||
}
|
}
|
||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
String(Iterator begin, Iterator end) : std::string(begin, end) {}
|
String(Iterator begin, Iterator end) : StringBase(begin, end) {}
|
||||||
|
|
||||||
std::string& stdstr() { return *this; }
|
StringBase& stdstr() { return *this; }
|
||||||
const std::string& stdstr() const { return *this; }
|
const StringBase& stdstr() const { return *this; }
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
char operator[](ByteCount pos) const { return std::string::operator[]((int)pos); }
|
char operator[](ByteCount pos) const { return StringBase::operator[]((int)pos); }
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
char& operator[](ByteCount pos) { return std::string::operator[]((int)pos); }
|
char& operator[](ByteCount pos) { return StringBase::operator[]((int)pos); }
|
||||||
Codepoint operator[](CharCount pos) { return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); }
|
Codepoint operator[](CharCount pos) { return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); }
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
ByteCount length() const { return ByteCount{(int)std::string::length()}; }
|
ByteCount length() const { return ByteCount{(int)StringBase::length()}; }
|
||||||
CharCount char_length() const { return utf8::distance(begin(), end()); }
|
CharCount char_length() const { return utf8::distance(begin(), end()); }
|
||||||
ByteCount byte_count_to(CharCount count) const { return utf8::advance(begin(), end(), (int)count) - begin(); }
|
ByteCount byte_count_to(CharCount count) const { return utf8::advance(begin(), end(), (int)count) - begin(); }
|
||||||
CharCount char_count_to(ByteCount count) const { return utf8::distance(begin(), begin() + (int)count); }
|
CharCount char_count_to(ByteCount count) const { return utf8::distance(begin(), begin() + (int)count); }
|
||||||
|
|
||||||
String& operator+=(const String& other) { std::string::operator+=(other); return *this; }
|
String& operator+=(const String& other) { StringBase::operator+=(other); return *this; }
|
||||||
String& operator+=(const char* other) { std::string::operator+=(other); return *this; }
|
String& operator+=(const char* other) { StringBase::operator+=(other); return *this; }
|
||||||
String& operator+=(char other) { std::string::operator+=(other); return *this; }
|
String& operator+=(char other) { StringBase::operator+=(other); return *this; }
|
||||||
String& operator+=(Codepoint cp) { utf8::dump(back_inserter(*this), cp); return *this; }
|
String& operator+=(Codepoint cp) { utf8::dump(back_inserter(*this), cp); return *this; }
|
||||||
|
|
||||||
StringView substr(ByteCount pos, ByteCount length = INT_MAX) const;
|
StringView substr(ByteCount pos, ByteCount length = INT_MAX) const;
|
||||||
|
@ -62,7 +67,8 @@ public:
|
||||||
: m_data{data}, m_length{length} {}
|
: m_data{data}, m_length{length} {}
|
||||||
StringView(const char* data) : m_data{data}, m_length{(int)strlen(data)} {}
|
StringView(const char* data) : m_data{data}, m_length{(int)strlen(data)} {}
|
||||||
constexpr StringView(const char* begin, const char* end) : m_data{begin}, m_length{(int)(end - begin)} {}
|
constexpr StringView(const char* begin, const char* end) : m_data{begin}, m_length{(int)(end - begin)} {}
|
||||||
StringView(const std::string& str) : m_data{str.data()}, m_length{(int)str.length()} {}
|
template<typename Char, typename Traits, typename Alloc>
|
||||||
|
StringView(const std::basic_string<Char, Traits, Alloc>& str) : m_data{str.data()}, m_length{(int)str.length()} {}
|
||||||
StringView(const char& c) : m_data(&c), m_length(1) {}
|
StringView(const char& c) : m_data(&c), m_length(1) {}
|
||||||
|
|
||||||
friend bool operator==(StringView lhs, StringView rhs);
|
friend bool operator==(StringView lhs, StringView rhs);
|
||||||
|
@ -112,12 +118,12 @@ public:
|
||||||
if (*end == '\0')
|
if (*end == '\0')
|
||||||
unowned = begin;
|
unowned = begin;
|
||||||
else
|
else
|
||||||
owned = std::string(begin, end);
|
owned = StringBase(begin, end);
|
||||||
}
|
}
|
||||||
operator const char*() const { return unowned ? unowned : owned.c_str(); }
|
operator const char*() const { return unowned ? unowned : owned.c_str(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string owned;
|
StringBase owned;
|
||||||
const char* unowned = nullptr;
|
const char* unowned = nullptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -229,8 +235,8 @@ inline String operator+(const String& lhs, const char* rhs)
|
||||||
return lhs + StringView{rhs};
|
return lhs + StringView{rhs};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<String> split(StringView str, char separator, char escape);
|
Vector<String> split(StringView str, char separator, char escape);
|
||||||
std::vector<StringView> split(StringView str, char separator);
|
Vector<StringView> split(StringView str, char separator);
|
||||||
|
|
||||||
String escape(StringView str, StringView characters, char escape);
|
String escape(StringView str, StringView characters, char escape);
|
||||||
String unescape(StringView str, StringView characters, char escape);
|
String unescape(StringView str, StringView characters, char escape);
|
||||||
|
@ -255,7 +261,7 @@ inline String operator"" _str(const char* str, size_t)
|
||||||
|
|
||||||
inline String codepoint_to_str(Codepoint cp)
|
inline String codepoint_to_str(Codepoint cp)
|
||||||
{
|
{
|
||||||
std::string str;
|
StringBase str;
|
||||||
utf8::dump(back_inserter(str), cp);
|
utf8::dump(back_inserter(str), cp);
|
||||||
return String(str);
|
return String(str);
|
||||||
}
|
}
|
||||||
|
@ -279,7 +285,7 @@ bool subsequence_match(StringView str, StringView subseq);
|
||||||
|
|
||||||
String expand_tabs(StringView line, CharCount tabstop, CharCount col = 0);
|
String expand_tabs(StringView line, CharCount tabstop, CharCount col = 0);
|
||||||
|
|
||||||
std::vector<StringView> wrap_lines(StringView text, CharCount max_width);
|
Vector<StringView> wrap_lines(StringView text, CharCount max_width);
|
||||||
|
|
||||||
inline size_t hash_value(const Kakoune::String& str)
|
inline size_t hash_value(const Kakoune::String& str)
|
||||||
{
|
{
|
||||||
|
|
|
@ -106,14 +106,14 @@ void test_string()
|
||||||
{
|
{
|
||||||
kak_assert(String("youpi ") + "matin" == "youpi matin");
|
kak_assert(String("youpi ") + "matin" == "youpi matin");
|
||||||
|
|
||||||
std::vector<String> splited = split("youpi:matin::tchou\\:kanaky:hihi\\:", ':', '\\');
|
Vector<String> splited = split("youpi:matin::tchou\\:kanaky:hihi\\:", ':', '\\');
|
||||||
kak_assert(splited[0] == "youpi");
|
kak_assert(splited[0] == "youpi");
|
||||||
kak_assert(splited[1] == "matin");
|
kak_assert(splited[1] == "matin");
|
||||||
kak_assert(splited[2] == "");
|
kak_assert(splited[2] == "");
|
||||||
kak_assert(splited[3] == "tchou:kanaky");
|
kak_assert(splited[3] == "tchou:kanaky");
|
||||||
kak_assert(splited[4] == "hihi:");
|
kak_assert(splited[4] == "hihi:");
|
||||||
|
|
||||||
std::vector<StringView> splitedview = split("youpi:matin::tchou\\:kanaky:hihi\\:", ':');
|
Vector<StringView> splitedview = split("youpi:matin::tchou\\:kanaky:hihi\\:", ':');
|
||||||
kak_assert(splitedview[0] == "youpi");
|
kak_assert(splitedview[0] == "youpi");
|
||||||
kak_assert(splitedview[1] == "matin");
|
kak_assert(splitedview[1] == "matin");
|
||||||
kak_assert(splitedview[2] == "");
|
kak_assert(splitedview[2] == "");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user