December 30, 2022
On Friday, 30 December 2022 at 22:02:41 UTC, Ali Çehreli wrote:
> On 12/30/22 13:54, matheus wrote:
>
> > But yes I think it will generate a copy (mutable) based on
> this test:
>
> In this case it does copy but in the case of dchar[] to dchar[], there will be no copy. Similarly, there is no copy from immutable to immutable.

Very interesting I did some testing and you are right. So better to stick with .dup!

Thanks for the info,

Matheus.

December 31, 2022

On Friday, 30 December 2022 at 22:02:41 UTC, Ali Çehreli wrote:

> >

But I couldn't find if the target will be mutable, but I
think it will
be,

The target will always be the type the programmer specifies explicitly. (dchar[] in this case.)

I have one more little question! Is it possible to infer the string without the type the programmer specifies explicitly in the template below?


template Fun(dstring str)/*
template Fun(T)(T str)/* like this */
{
  import std.traits : Unconst;
  alias T = Unconst!(typeof(str[0]));

  auto Fun()
  {
    import std.conv : to;

    auto result = Result();
    result.data = str.to!(T[]);

    return result;
  }
  
  struct Result
  {
    union
    {
      T[str.length] data;
      ubyte[T.sizeof * str.length] bytes;
    }
    string toString()
    {
      import std.format;
      return format("%s: %(%02X-%)", data, bytes);
    }
  }
}

void main()
{
  import std.stdio : writeln;
  Fun!"β€Ş"w.writeln; // type1: wstring
  Fun!"β€Ş"d.writeln; // type2: dstring
}

That is, the compiler can/must infer between type 1-2 or type 3(string) that it knows at compile time, right?

SDB@79

December 31, 2022

On Saturday, 31 December 2022 at 00:42:50 UTC, Salih Dincer wrote:

>

... it possible to infer

Let me save you the torment of code duplication 😀

Thanks everyone. Yes, I guess there is no other way but to overload. This is both the safest and the fastest. It's also short enough like this:

  // D 2.0.83 or higher

  import std.stdio : writeln;
  import std.conv  : to;

auto Fun(string str)() {
  auto result = Values!(char, str.length)();
  result.data = str.to!(char[]);
  return result;
}

auto Fun(wstring str)() {
  auto result = Values!(wchar, str.length)();
  result.data = str.to!(wchar[]);
  return result;
}

auto Fun(dstring str)() {
  auto result = Values!(dchar, str.length)();
  result.data = str.to!(dchar[]);
  return result;
}

struct Values(T, size_t len) {
  union {
    T[len] data;
    ubyte[T.sizeof * len] bytes;
  }
  string toString() {
    import std.format;
    return format("%s: %(%02X-%)", data, bytes);
  }
}

void main()
{
  Fun!"β€Ş".writeln;  // β€Ş: CE-B2-E2-82-AC-C5-9E
  Fun!"β€Ş"w.writeln; // β€Ş: B2-03-AC-20-5E-01
  Fun!"β€Ş"d.writeln; // B2-03-00-00-AC-20-00-00-5E-01-00-00
}

SDB@79

December 30, 2022
On 12/30/22 17:22, Salih Dincer wrote:

> I guess there is no other way but to overload.

Since the bodies of all three overloads are the same except some types, they can easily be templatized.

> This is both the safest and the fastest.

I didn't think Values is fast with string copies that it makes. ;) I think it was only for showing the byte values but you can do the same by casting to ubyte[] as well.

Also, your Fun could work only with string literals; so I used function parameters.

import std.traits : isSomeString;

// isSomeString may or may not be useful below. (?)

auto Fun(S)(S str)
if (isSomeString!S) {
    import std.traits : Unqual;
    import std.conv : to;

    alias T = Unqual!S;

    // Note: The following may or may not copy the string
    //       depending on whether S is the same as T.
    return str.to!T;
}

void printBytes(S)(S str) {
    import std.stdio : writefln;
    import std.conv  : to;

    // The following cast does not copy anything.
    writefln!"%(%02X-%)"(cast(ubyte[])str);
}

void main()
{
    printBytes(Fun("β€Ş"));  // CE-B2-E2-82-AC-C5-9E
    printBytes(Fun("β€Ş"w)); // B2-03-AC-20-5E-01
    printBytes(Fun("β€Ş"d)); // B2-03-00-00-AC-20-00-00-5E-01-00-00
}

Ali

December 31, 2022

On Saturday, 31 December 2022 at 02:15:56 UTC, Ali Çehreli wrote:

>

On 12/30/22 17:22, Salih Dincer wrote:

>

I guess there is no other way but to overload.

Since the bodies of all three overloads are the same except some types, they can easily be templatized.

You took the trouble, thanks, but there is a special reason why I use union. If we want, we can write dynamic version without using std.traits:

struct Values(T, size_t len = 1)
{
  union
  {
    T[len] data;
    ubyte[T.sizeof * len] bytes;
  }

  string toString()
  {
    import std.format;
    return format("%s: %(%02X-%)", data, bytes);
  }
}

  alias Char = Values!char;
  alias Wchar = Values!wchar;
  alias Dchar = Values!dchar;

void main()
{
  import std.stdio : writeln;

  Char[] str1;
  str1 ~= Char('B');
  str1 ~= Char('E');
  str1 ~= Char('$');
  str1.writeln;

  Wchar[] str2;
  str2 ~= Wchar('β');
  str2 ~= Wchar('€');
  str2 ~= Wchar('Ş');
  str2.writeln;

  Dchar[] str3;
  str3 ~= Dchar('β');
  str3 ~= Dchar('€');
  str3 ~= Dchar('$');
  str3.writeln("\n");

  Fun!"β€$".writeln;
}
/*
  [B: 42, E: 45, $: 24]
  [β: B2-03, €: AC-20, Ş: 5E-01]
  [β: B2-03-00-00, €: AC-20-00-00, $: 24-00-00-00]

  β€$: CE-B2-E2-82-AC-24
*/

However, I would like to draw your attention to the last line. Yeah, I won't be able to do that because it's New Year's Eve. But the line is like mixed mode because of the non-char data it contains, right?

Happy New Year...

1 2
Next ›   Last »