Pike v8.0 release 1738

Method Stdio.Buffer()->rewind_key()


Method rewind_key

RewindKey rewind_on_error()
RewindKey rewind_key()

Description

These functions are very similar. The rewind_on_error edition will create an object that, when it goes out of scope without having been destructed explicitly, will cause the buffer to rewind to the location it had when this function is called.

This will happen if you throw an error or otherwise let the object fall out of scope.

Use destruct(RewindKey) or RewindKey.release to stop the buffer from being rewound.

The second version (rewind_key) requires you to explicitly call RewindKey.rewind to do the rewind.

Take some care with these objects, if you create multiple ones at once the results might be somewhat confusing if you do not release them in the reverse order they were created in (then again, you almost certainly really only need one)

You can call RewindKey.update in the generated object to change where it will be rewound to.

The typical use-case of this functionality is when parsing a packet protocol with variable length packets where the length is not immediately known. It saves you from keeping track of how much to rewind if you had not actually gotten the whole packet yet.

Example
void parse_packet( Stdio.Buffer b )
{
  Stdio.Buffer.RewindKey rewind = b->rewind_on_error();
  b->set_error_mode(1);

  switch( b->read_int8() ) // packet type
  {
    case DATA:
      int channel = b->read_int8();
      Stdio.Buffer data = b->read_hbuffer( 4 );
      // we have read the whole packet, so no longer rewind on error.
      rewind->release();
      return handle_data_packet( channel, data );
  }
}
Note

Just calling rewind_on_error without assigning the return value to something will not do anything. You need to keep the object around while the rewind-to position is still valid.

Keeping the object around forbids the buffer from moving data inside itself, this means that it can only grow. So do not keep the rewind key when it is not needed.