| |
|
russhy
Posted in reply to Ola Fosheim Grøstad
| Here is mine
import std;
void main()
{
string a = "abc;def;ab";
writeln("a => ", a);
foreach(item; split(a, ';'))
writeln("\t", item);
string b = "abc; def ;ab";
writeln("a => ", b);
foreach(item; split(b, ';', SplitOption.TRIM))
writeln("\t", item);
string c= "abc; ; ;def ;ab";
writeln("a => ",c);
foreach(item; split(c, ';', SplitOption.TRIM | SplitOption.REMOVE_EMPTY))
writeln("\t", item);
}
SplitIterator!T split(T)(const(T)[] buffer, const(T) delimiter, SplitOption option = SplitOption.NONE)
{
return SplitIterator!T(buffer, delimiter, option);
}
struct SplitIterator(T)
{
const(T)[] buffer;
const(T) delimiter;
SplitOption option;
int index = 0;
int count()
{
int c = 0;
foreach(line; this)
{
c++;
}
index = 0;
return c;
}
const(T) get(int index)
{
return buffer[index];
}
int opApply(scope int delegate(const(T)[]) dg)
{
auto length = buffer.length;
for (int i = 0; i < length; i++)
{
if (buffer[i] == '\0')
{
length = i;
break;
}
}
int result = 0;
for (int i = index; i < length; i++)
{
int entry(int start, int end)
{
// trim only if we got something
if ((end - start > 0) && (option & SplitOption.TRIM))
{
for (int j = start; j < end; j++)
if (buffer[j] == ' ')
start += 1;
else
break;
for (int k = end; k >= start; k--)
if (buffer[k - 1] == ' ')
end -= 1;
else
break;
// nothing left
if(start >= end) return 0;
}
//printf("%i to %i :: %i :: total: %lu\n", start, end, index, buffer.length);
return dg(buffer[start .. end]) != 0;
}
auto c = buffer[i];
if (c == delimiter)
{
if (i == index && (option & SplitOption.REMOVE_EMPTY))
{
// skip if we keep finding the delimiter
index = i + 1;
continue;
}
if ((result = entry(index, i)) != 0)
break;
// skip delimiter for next result
index = i + 1;
}
// handle what's left
if ((i + 1) == length)
{
result = entry(index, i + 1);
}
}
return result;
}
// copy from above, only replace if above has changed
int opApply(scope int delegate(int, const(T)[]) dg)
{
auto length = buffer.length;
for (int i = 0; i < length; i++)
{
if (buffer[i] == '\0')
{
length = i;
break;
}
}
int n = 0;
int result = 0;
for (int i = index; i < length; i++)
{
int entry(int start, int end)
{
// trim only if we got something
if ((end - start > 0) && (option & SplitOption.TRIM))
{
for (int j = start; j < end; j++)
if (buffer[j] == ' ')
start += 1;
else
break;
for (int k = end; k >= start; k--)
if (buffer[k - 1] == ' ')
end -= 1;
else
break;
// nothing left
if(start >= end) return 0;
}
//printf("%i to %i :: %i :: total: %lu\n", start, end, index, buffer.length);
return dg(n++, buffer[start .. end]) != 0;
}
auto c = buffer[i];
if (c == delimiter)
{
if (i == index && (option & SplitOption.REMOVE_EMPTY))
{
// skip if we keep finding the delimiter
index = i + 1;
continue;
}
if ((result = entry(index, i)) != 0)
break;
// skip delimiter for next result
index = i + 1;
}
// handle what's left
if ((i + 1) == length)
{
result = entry(index, i + 1);
}
}
return result;
}
}
enum SplitOption
{
NONE = 0,
REMOVE_EMPTY = 1,
TRIM = 2
}
|