digitalmars.D - toChars buffer access?
- Steven Schveighoffer (27/27) Aug 23 2020 I was about to reach for core.internal.string.signedToTempString [1] to
- Salih Dincer (4/38) Jun 09 2022 I also faced this problem. Anyone have a solution?
- bauss (6/53) Jun 09 2022 .array on the result from .toChars perhaps?
- Steven Schveighoffer (5/13) Jun 09 2022 This allocates. For a temporary array, this is wasteful (it will be
- Salih Dincer (105/109) Jun 09 2022 I have a simple code that works perfectly as well. But I'm having
- Steven Schveighoffer (16/20) Jun 09 2022 I'm not sure if I got all your code, but just to note, the operator
- Salih Dincer (43/48) Jun 09 2022 It's okay, the subject is clearer for me now.
- Steven Schveighoffer (12/21) Jun 10 2022 Ugh, it's not as easy as I thought but...
- Salih Dincer (11/14) Jun 10 2022 Delicious!
- Steven Schveighoffer (3/15) Jun 10 2022 This allocates ;)
I was about to reach for core.internal.string.signedToTempString [1] to convert a number into a temp string yet again. And I thought, maybe there's something in Phobos by now. And lo and behold! There's std.conv.toChars [2] But... it just gives me a range of char, and not an actual string. So my intended purpose (to use it as a string key for an associative array) means I have to copy it to a local buffer anyway. No matter, right? It probably just stores the number and gives me access to each character as it parses. Oh wait, no. It actually stores it as a char[20], but doesn't give me access. Which leaves me with the only option of doing: auto s = someNumber.toChars; char[20] buf; import std.algorithm : copy; copy(s.save, buf[0 .. s.length]); auto v = aa[buf[0 .. s.length]]; But my goodness, it would just be so easy if it gave access to the buffer: auto s = someNumber.toChars; auto v = aa[s.data]; // system access to buffer, unsafe! And this is discounting the fact that I not only am copying the buffer *again*, but doing it one character at a time. So would it be a problem to allow this accessor, even if it's system? Or should I just keep importing core.internal? -Steve [1] https://github.com/dlang/druntime/blob/9f0f6e49fb379841c7934b6049f87dab0adfe53c/src/core/internal/string.d#L113 [2] https://dlang.org/phobos/std_conv.html#toChars
Aug 23 2020
On Sunday, 23 August 2020 at 19:18:51 UTC, Steven Schveighoffer wrote:I was about to reach for core.internal.string.signedToTempString [1] to convert a number into a temp string yet again. And I thought, maybe there's something in Phobos by now. And lo and behold! There's std.conv.toChars [2] But... it just gives me a range of char, and not an actual string. So my intended purpose (to use it as a string key for an associative array) means I have to copy it to a local buffer anyway. No matter, right? It probably just stores the number and gives me access to each character as it parses. Oh wait, no. It actually stores it as a char[20], but doesn't give me access. Which leaves me with the only option of doing: ```d auto s = someNumber.toChars; char[20] buf; import std.algorithm : copy; copy(s.save, buf[0 .. s.length]); auto v = aa[buf[0 .. s.length]]; ``` But my goodness, it would just be so easy if it gave access to the buffer: ```d auto s = someNumber.toChars; auto v = aa[s.data]; // system access to buffer, unsafe! ``` And this is discounting the fact that I not only am copying the buffer *again*, but doing it one character at a time. So would it be a problem to allow this accessor, even if it's system? Or should I just keep importing core.internal? -Steve [1] https://github.com/dlang/druntime/blob/9f0f6e49fb379841c7934b6049f87dab0adfe53c/src/core/internal/string.d#L113 [2] https://dlang.org/phobos/std_conv.html#toCharsI also faced this problem. Anyone have a solution? SDB 79
Jun 09 2022
On Thursday, 9 June 2022 at 14:44:55 UTC, Salih Dincer wrote:On Sunday, 23 August 2020 at 19:18:51 UTC, Steven Schveighoffer wrote:.array on the result from .toChars perhaps? Or is there a specific reason that cannot be done? ```d someNumber.toChars.array ```I was about to reach for core.internal.string.signedToTempString [1] to convert a number into a temp string yet again. And I thought, maybe there's something in Phobos by now. And lo and behold! There's std.conv.toChars [2] But... it just gives me a range of char, and not an actual string. So my intended purpose (to use it as a string key for an associative array) means I have to copy it to a local buffer anyway. No matter, right? It probably just stores the number and gives me access to each character as it parses. Oh wait, no. It actually stores it as a char[20], but doesn't give me access. Which leaves me with the only option of doing: ```d auto s = someNumber.toChars; char[20] buf; import std.algorithm : copy; copy(s.save, buf[0 .. s.length]); auto v = aa[buf[0 .. s.length]]; ``` But my goodness, it would just be so easy if it gave access to the buffer: ```d auto s = someNumber.toChars; auto v = aa[s.data]; // system access to buffer, unsafe! ``` And this is discounting the fact that I not only am copying the buffer *again*, but doing it one character at a time. So would it be a problem to allow this accessor, even if it's system? Or should I just keep importing core.internal? -Steve [1] https://github.com/dlang/druntime/blob/9f0f6e49fb379841c7934b6049f87dab0adfe53c/src/core/internal/string.d#L113 [2] https://dlang.org/phobos/std_conv.html#toCharsI also faced this problem. Anyone have a solution? SDB 79
Jun 09 2022
On 6/9/22 4:31 PM, bauss wrote:.array on the result from .toChars perhaps? Or is there a specific reason that cannot be done? ```d someNumber.toChars.array ```This allocates. For a temporary array, this is wasteful (it will be thrown away immediately). My original example is to look up a key in an AA (not to store one). -Steve
Jun 09 2022
On Thursday, 9 June 2022 at 21:16:48 UTC, Steven Schveighoffer wrote:My original example is to look up a key in an AA (not to store one).I have a simple code that works perfectly as well. But I'm having problems to convert except string. ```d struct HexStack { private { string[ubyte] convert; ubyte index; const ubyte first; } this(ubyte start) { this.index = start; this.first = start; } bool empty() { return index == first; } property top() { return this.convert[first]; } property pop() { if(!empty) --this.index; return this.convert[this.index]; } property push(uint data) { import std.conv; this.convert[index] = toChars!(16, char, LetterCase.upper) (data).to!string; if(index < ubyte.max) this.index++; else this.index = ubyte.max; } } unittest { HexStack foo = 'a'; // x'61' foo.push('A'); // x'41' assert(foo.top == "41"); foo.push('B'); foo.push('C'); assert(foo.pop == "43"); assert(foo.pop == "42"); assert(foo.pop == "41"); assert(foo.empty); assert(foo.pop == "41"); assert(foo.pop == foo.top); HexStack bar = ubyte.max - 1; bar.push('A'); // x'41' assert(bar.top == "41"); bar.push('B'); bar.push('C'); assert(bar.pop == "41"); assert(bar.empty); assert(bar.pop == "41"); assert(bar.pop == bar.top); } ``` So hexstring is ok. When switching to other types, it converts each letter independently of each other and gives the following error:ChArray(Reserved, T = char)neme1234567 den eme 9,8,7,6,5,4,3,2,1,e,m,e,n,e,d, d,e,n,e,m,e,1,2,3,4,5,6,7,8,9, std.conv.ConvException /usr/src/dmd/linux/bin64/../../src/phob s/std/conv.d(1877): Unexpected '0' when converting from type Result to type char ---------------- ```d ??:? pure safe char std.conv.toImpl!(char, std.conv.toChars!(16u, char, 0, uint).toChars(uint).Result).toImpl(std.conv.toChars!(16u, char, 0, uint).toChars(uint).Result) [0x55a583a8c4de] ??:? pure safe char std.conv.to!(char).to!(std.conv.toChars!(16u, char, 0, uint).toChars(uint).Result).to(std.conv.toChars!(16u, char, 0, uint).toChars(uint).Result) [0x55a583a8c201] ??:? pure char (immutable(char)[], char).ChArray.toChar!(10u).toChar() [0x55a583a8bf01] ??:? _Dmain [0x55a583a8018d] Process finished with exit code 1. ``` I also get this error when I use char[]:ChArray.d(180): Error: only one index allowed to index `char`**Test Code:** ```d uint A = 65; auto result = A.toChars!16; //hex '41' auto myCodePage = HexStack('a'); myCodePage.push(A); assert(myCodePage.top == result.to!string); auto test = result.to!char[]; ``` The only solution is to use .array: ```d assert(result.array == ['4', '1']); ``` But I don't like this! SDB 79
Jun 09 2022
On 6/9/22 8:18 PM, Salih Dincer wrote:auto test = result.to!char[];I'm not sure if I got all your code, but just to note, the operator precedence here means it's `(result.to!char)[]`The only solution is to use .array: assert(result.array == ['4', '1']);Well, 2 things. First, you can compare a char[] to a string, so `result.array == "41"` should be fine. Second, you can't use == to compare ranges, you need to use std.algorithm.equal: ```d import std.algorithm : equal; assert(equal(result, "41")); ``` (and yes, this should work for different character types, even though a string is element type dchar). Not sure if this helps, I feel like there was some code missing from your example. -Steve
Jun 09 2022
On Friday, 10 June 2022 at 01:49:25 UTC, Steven Schveighoffer wrote:On 6/9/22 8:18 PM, Salih Dincer wrote:It's okay, the subject is clearer for me now. But I wish I could change each character to hexString without dealing with conversions; I see below is the type of integer(uint) that toChars wants: ```d void main() { import std.algorithm, std.range; import std.conv, std.stdio; string str = "Hello World!"; /* I'd like it to be as simple as a * comment line, but it's not working. */ //str.toChars!(16, string).writeln;/* str.each!(c => c.to!uint .toChars!(16, char, LetterCase.upper) .write("-") ); writeln; str.each!((i, uint c) { c.to!string(16) .writeln(": ", i); } );//*/ } /* Print Out: 48-65-6C-6C-6F-20-57-6F-72-6C-64-21- 48: 0 65: 1 6C: 2 6C: 3 6F: 4 20: 5 57: 6 6F: 7 72: 8 6C: 9 64: 10 21: 11 //*/ ``` SDB 79auto test = result.to!char[];I'm not sure if I got all your code, but just to note, the operator precedence here means it's `(result.to!char)[]` [...]
Jun 09 2022
On 6/10/22 1:07 AM, Salih Dincer wrote:/* I'd like it to be as simple as a * comment line, but it's not working. */ //str.toChars!(16, string).writeln;/* str.each!(c => c.to!uint .toChars!(16, char, LetterCase.upper) .write("-") );Ugh, it's not as easy as I thought but... ```d import std.utf; // option 1 (if you want a range that's usable elsewhere) str.map!(c => uint(c).toChars!(16, char, LetterCase.upper)) .joiner("-".byCodeUnit) // byCodeUnit needed because of autodecoding .writeln; // option 2 (if the point is just to print) writefln("%-(%02X-%)", str); ``` -Steve
Jun 10 2022
On Friday, 10 June 2022 at 14:49:51 UTC, Steven Schveighoffer wrote:// option 2 (if the point is just to print) writefln("%-(%02X-%)", str); ```Delicious! ```d auto str = "Hello World!"; import std.format, std.range : split; auto strArr = str.format!"%-(%02X %)".split; import std.stdio; strArr.writefln!"%-(%s-%)"; ``` SDB 79
Jun 10 2022
On 6/10/22 5:05 PM, Salih Dincer wrote:On Friday, 10 June 2022 at 14:49:51 UTC, Steven Schveighoffer wrote:This allocates ;) -Steve// option 2 (if the point is just to print) writefln("%-(%02X-%)", str); ```Delicious! ```d auto str = "Hello World!"; import std.format, std.range : split; auto strArr = str.format!"%-(%02X %)".split;
Jun 10 2022