October 20, 2023

Hi,

I have a string wrapper called SlicedString. What it does is very simple: Returning each piece as a slice with a assured separator at compile time by used indexOf() ! Here it is:

struct SlicedString(string E)
{
  long index, back, next = -1;
  string data;

  auto length() const
  {
    import std.array : split;
    import std.range : walkLength;
    return data.split(E).walkLength;
  }

  auto popIndex(ref SlicedString!E range)
  {
    scope(exit) range.popFront();
    return [range.back, range.next];
  }

  auto elementsPos()
  {
    long[][] result;
    auto r = SlicedString!E(index, back, next, data);

    while(!r.empty)
    {
      result ~= popIndex(r);
    }
    return result;
  }

  bool empty() { return index == 0; }
  auto front() { return data[back..next]; }
  void popFront()
  {
    import std.string : find = indexOf;
    --index;
    back = ++next;
    next = data.find(E, next);
    if(next == -1)
    {
      next = data.length;
    }
  }
}

auto sliceOff(string E = " ")(string data)
{
  SlicedString!E s;
  s.data = data;
  s.popFront();

  return s;
}

// UNIT TESTS:

void main()
{
  auto str = "abc def ghi";
  auto slc =  str.sliceOff;

  auto len = slc.length;
  slc.index = len;

  import std.stdio, std.algorithm: equal;
  assert(slc.equal(["abc", "def", "ghi"]));

  // Print range:
  foreach(s; slc) s.write;
  writeln;

  // Print Elements Position
  slc.elementsPos.writeln;
  slc.elementsPos.writeln;
}

The unit tests work as I want, but I find calculating the length with split() too expensive; despite walkLength()...

Is there a more accurate method? Last year, Ali Çehreli told me that splitter() was also possible, but then he did something with map(). I really don't understand these!

Thanks...

SDB@79

October 20, 2023

Good news!

I collected them in a template with the condition of running split() once at compile time. The result seems perfect? What are your thoughts?

void main()
{
  auto slc = sliceOff!"abc def ghi";

  auto len = slc.length;
  slc.index = len;

  import std.stdio, std.algorithm: equal;
  assert(slc.equal(["abc", "def", "ghi"]));

  foreach(s; slc) s.write;
  writeln; // abcdefghi

  // Push Test
  with(slc)
  {
    string test = "jkl";
    push(test);

    auto p = elementsPos[$ - 1];
    assert(data[p[0]..p[1]] == test);
  }

  foreach(s; slc) s.write;
  writeln; // abcdefghijkl

  auto tmp = slc.dup;
  assert(tmp.front == "abc");
  tmp.popFront;
  assert(slc.front == "abc");
  assert(tmp.front == "def");
}

template sliceOff(string STR, string SEP = " ")
{
  auto sliceOff()
  {
    SlicedString s;
    s.popFront();
    return s;
  }

  import std.array : split;
  import std.range : walkLength;
  enum LEN = STR.split(SEP).walkLength;

  struct SlicedString
  {
    long index, back, next = -1;
    size_t len = LEN;
    string data = STR;

    auto push(string data)
    {
      this.data ~= SEP ~ data;
      len++;
      index++;
    }

    auto elementsPos()
    {
      long[][] result;
      auto r = this.dup;
      while(!r.empty)
      {
        result ~= [r.back, r.next];
        r.popFront();
      }
      return result;
    }

    alias dup = save;
    auto save() { return this; }
    auto length() { return len; }
    bool empty() { return index == 0; }
    auto front() { return data[back..next]; }
    void popFront()
    {
      import std.string : find = indexOf;
      --index;
      back = ++next;
      next = data.find(SEP, next);
      if(next == -1)
      {
        next = data.length;
      }
    }
  }
}

SDB@79