www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Some nogc text conversion in Phobos?

reply "bearophile" <bearophileHUGS lycos.com> writes:
This is currently accepted code:


void main() {
     import std.array: appender;
     import std.format: formattedWrite;

     auto writer = appender!string;
     formattedWrite(writer, "%s is the ultimate %s.", 42, 
"answer");
     assert(writer.data == "42 is the ultimate answer.");
}



But there are problems caused by formatting for exception error 
messages:
https://d.puremagic.com/issues/show_bug.cgi?id=12768


An example of the problem:

class UTFException : Exception
{
...
     pure  safe
     this(string msg, size_t index, string file = __FILE__, size_t 
line = __LINE__, Throwable next = null) {
         import std.string;
         super(msg ~ format(" (at index %s)", index), file, line, 
next);
     }


Because of that several Phobos functions can't be  nogc.

So is it a good idea to add to Phobos a function similar to this?


void main() pure nothrow  safe  nogc {
     import std.format: bufferText;

     immutable n = 42;
     immutable s = "answer";
     char[100] buf;
     const Nullable!(char[]) result =
         buf.bufferText(n, " is the ultimate ", s);
     assert(result.get == "42 is the ultimate answer.");
}



That should allow (in theory) code like:

class UTFException : Exception
{
...
     pure  safe  nogc
     this(in char[] msg, string file = __FILE__, size_t line = 
__LINE__, Throwable next = null) {
         super(msg, file, line, next);
     }

...

char[100] buf;
const msg = buf.bufferText("Invalid UTF-8 sequence (at index ", 
i, ')');
if (mgs.isNull)
     new UTFException("Invalid UTF-8 sequence")...
else
     new UTFException(msg.get)...



A problem left is that the ctor of Exception is not yet  pure 
 nothrow  safe  nogc.

Bye,
bearophile
May 28 2014
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 28 May 2014 at 23:27:34 UTC, bearophile wrote:
 This is currently accepted code:


 void main() {
     import std.array: appender;
     import std.format: formattedWrite;

     auto writer = appender!string;
     formattedWrite(writer, "%s is the ultimate %s.", 42, 
 "answer");
     assert(writer.data == "42 is the ultimate answer.");
 }



 But there are problems caused by formatting for exception error 
 messages:
 https://d.puremagic.com/issues/show_bug.cgi?id=12768


 An example of the problem:

 class UTFException : Exception
 {
 ...
     pure  safe
     this(string msg, size_t index, string file = __FILE__, 
 size_t line = __LINE__, Throwable next = null) {
         import std.string;
         super(msg ~ format(" (at index %s)", index), file, 
 line, next);
     }


 Because of that several Phobos functions can't be  nogc.

 So is it a good idea to add to Phobos a function similar to 
 this?


 void main() pure nothrow  safe  nogc {
     import std.format: bufferText;

     immutable n = 42;
     immutable s = "answer";
     char[100] buf;
     const Nullable!(char[]) result =
         buf.bufferText(n, " is the ultimate ", s);
     assert(result.get == "42 is the ultimate answer.");
 }



 That should allow (in theory) code like:

 class UTFException : Exception
 {
 ...
     pure  safe  nogc
     this(in char[] msg, string file = __FILE__, size_t line = 
 __LINE__, Throwable next = null) {
         super(msg, file, line, next);
     }

 ...

 char[100] buf;
 const msg = buf.bufferText("Invalid UTF-8 sequence (at index ", 
 i, ')');
 if (mgs.isNull)
     new UTFException("Invalid UTF-8 sequence")...
 else
     new UTFException(msg.get)...



 A problem left is that the ctor of Exception is not yet  pure 
  nothrow  safe  nogc.

 Bye,
 bearophile

IMHO something like this is better: class MyException : Exception { private char[20] index_buff; // should be enough for size_t.max this(string msg, size_t index, string file = __FILE__, size_t line = __LINE__, Throwable next = null) { super(msg, file, line, next); // in-place conversion of size_t to char[] } void toString(void delegate(const(char)[]) sink) const { sink(msg); sink(" (at index "); sink(index_buff); sink(")"); } } Benefits: no arbitrary message length limit, no string construction unless toString is actually called.
May 28 2014
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
29-May-2014 03:52, Dicebot пишет:
 On Wednesday, 28 May 2014 at 23:27:34 UTC, bearophile wrote:
 This is currently accepted code:


 IMHO something like this is better:

 class MyException : Exception
 {
      private char[20] index_buff; // should be enough for size_t.max

Why not just save 'size_t' right here, and do formattedWrite in the toString? Anyway I think this is what exceptions should do - save the state and only ever format message in toString.
      this(string msg, size_t index, string file = __FILE__, size_t line
 = __LINE__, Throwable next = null)
      {
          super(msg, file, line, next);
      // in-place conversion of size_t to char[]
      }

      void toString(void delegate(const(char)[]) sink) const
      {
          sink(msg);
          sink(" (at index ");
          sink(index_buff);
          sink(")");
      }
 }

 Benefits: no arbitrary message length limit, no string construction
 unless toString is actually called.

Yup. -- Dmitry Olshansky
May 29 2014
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
On Thursday, 29 May 2014 at 18:30:28 UTC, Dmitry Olshansky wrote:
 29-May-2014 03:52, Dicebot пишет:
 On Wednesday, 28 May 2014 at 23:27:34 UTC, bearophile wrote:
 This is currently accepted code:


 IMHO something like this is better:

 class MyException : Exception
 {
     private char[20] index_buff; // should be enough for 
 size_t.max

Why not just save 'size_t' right here, and do formattedWrite in the toString? Anyway I think this is what exceptions should do - save the state and only ever format message in toString.

Yep, you are right.
May 29 2014
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Dicebot:

 Benefits: no arbitrary message length limit, no string 
 construction unless toString is actually called.

A nothrow nogc function like the bufferText I've suggested is also useful in situations like this (currently this can't compile): struct Foo { int[3] data; ref int opIndex(in size_t i) pure nothrow safe nogc in { import std.string: format; assert(i < data.length, format("opIndex, %d >= %d", i, data.length)); } body { return data[i]; } } void main() { Foo f; auto r = f[10]; } Bye, bearophile
May 31 2014