www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - attribute length missing in std.array: Appender

reply "Andre" <andre s-e-a-p.de> writes:
Hi,

I implement a network protocol and use an Appender!(ubyte[])().
I have following issue. The first three bytes I have to fill,
the following bytes are reserved and must be 0. In this example
the overall header length must be 8.

import std.array: appender;
const HEADER_LENGTH = 8;
	
auto app = appender!(ubyte[])();
app.put(cast(ubyte)40);
app.put(cast(ubyte)5);
app.put(cast(ubyte)234);
// ... add 5 times 0
// variable length body will follow

In case of dynamic array I can simple set the length to 8.
Appender doesn't have a length attribute.

Is there some other nice D functionaliy I can use?
Maybe some functionality in std.array is missing: app.fill(0, 
HEADER_LENGTH)?
Currently I do a work around with a for loop.

Kind regards
André
Nov 27 2014
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Thursday, 27 November 2014 at 16:08:13 UTC, Andre wrote:
 Hi,

 I implement a network protocol and use an Appender!(ubyte[])().
 I have following issue. The first three bytes I have to fill,
 the following bytes are reserved and must be 0. In this example
 the overall header length must be 8.

 import std.array: appender;
 const HEADER_LENGTH = 8;
 	
 auto app = appender!(ubyte[])();
 app.put(cast(ubyte)40);
 app.put(cast(ubyte)5);
 app.put(cast(ubyte)234);
 // ... add 5 times 0
 // variable length body will follow

 In case of dynamic array I can simple set the length to 8.
 Appender doesn't have a length attribute.

 Is there some other nice D functionaliy I can use?
 Maybe some functionality in std.array is missing: app.fill(0, 
 HEADER_LENGTH)?
 Currently I do a work around with a for loop.

 Kind regards
 André
You can initialize the appender with an existing array, or put an entire array into it at once: import std.array: appender; ubyte[] temp; temp.reserve(8); // reserve first, so that only one allocation happens temp[0 .. 3] = [40, 5, 234]; temp.length = 8; auto app = appender!(ubyte[])(temp); // or: app.put(temp); The array will not be copied when the appender is constructed.
Nov 27 2014
parent "andre" <Andre s-e-a-p.de> writes:
Thanks a lot for the help.

Kind regards
André



On Thursday, 27 November 2014 at 17:29:50 UTC, Marc Schütz wrote:
 On Thursday, 27 November 2014 at 16:08:13 UTC, Andre wrote:
 Hi,

 I implement a network protocol and use an Appender!(ubyte[])().
 I have following issue. The first three bytes I have to fill,
 the following bytes are reserved and must be 0. In this example
 the overall header length must be 8.

 import std.array: appender;
 const HEADER_LENGTH = 8;
 	
 auto app = appender!(ubyte[])();
 app.put(cast(ubyte)40);
 app.put(cast(ubyte)5);
 app.put(cast(ubyte)234);
 // ... add 5 times 0
 // variable length body will follow

 In case of dynamic array I can simple set the length to 8.
 Appender doesn't have a length attribute.

 Is there some other nice D functionaliy I can use?
 Maybe some functionality in std.array is missing: app.fill(0, 
 HEADER_LENGTH)?
 Currently I do a work around with a for loop.

 Kind regards
 André
You can initialize the appender with an existing array, or put an entire array into it at once: import std.array: appender; ubyte[] temp; temp.reserve(8); // reserve first, so that only one allocation happens temp[0 .. 3] = [40, 5, 234]; temp.length = 8; auto app = appender!(ubyte[])(temp); // or: app.put(temp); The array will not be copied when the appender is constructed.
Nov 27 2014
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/27/2014 08:08 AM, Andre wrote:

 import std.array: appender;
 const HEADER_LENGTH = 8;

 auto app = appender!(ubyte[])();
 app.put(cast(ubyte)40);
 app.put(cast(ubyte)5);
 app.put(cast(ubyte)234);
 // ... add 5 times 0
A fancy way: :) import std.range; // ... app.put(repeat(cast(ubyte)0).take(5)); Ali
Nov 28 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Ali Çehreli:

 auto app = appender!(ubyte[])();
 app.put(cast(ubyte)40);
 app.put(cast(ubyte)5);
 app.put(cast(ubyte)234);
 // ... add 5 times 0
A fancy way: :) import std.range; // ... app.put(repeat(cast(ubyte)0).take(5));
Now we have a better syntax for implicit casts: void main() { import std.array, std.range; Appender!(ubyte[]) app; app.put(ubyte(0).repeat.take(5)); } Single line, but not lazy: void main() { import std.array, std.range; Appender!(ubyte[]) app = ubyte(0).repeat.take(5).array; } But I have a question too. What's the best way to append several lazy items to a dynamic array? This doesn't work: void main() { import std.array, std.range; int[] arr; arr.put(only(1, 2, 3)); } Bye, bearophile
Nov 28 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/28/2014 12:44 AM, bearophile wrote:

 Now we have a better syntax for implicit casts:
[...]
      app.put(ubyte(0).repeat.take(5));
Much better! :)
 But I have a question too. What's the best way to append several lazy
 items to a dynamic array? This doesn't work:

 void main() {
      import std.array, std.range;
      int[] arr;
      arr.put(only(1, 2, 3));
 }
I don't think there is a better way in Phobos. (?) The following trivial function would do as long as the array has room at the end, which requires that it is "safe to append": void expandWith(A, R)(ref A arr, R range) { foreach (e; range) { arr ~= e; } } void main() { import std.range; int[] arr = [ 42 ]; // Ensure that there is room for new elements arr.reserve(100); assumeSafeAppend(arr); const oldPlace = arr.ptr; arr.expandWith(only(1, 2, 3)); const newPlace = arr.ptr; assert(newPlace == oldPlace); } Ali
Nov 28 2014
parent "bearophile" <bearophileHUGS lycos.com> writes:
Ali Çehreli:

 void expandWith(A, R)(ref A arr, R range)
 {
     foreach (e; range) {
         arr ~= e;
     }
 }
I'd like a function like that in Phobos (with a little improvement: when the length of the given range is available inside expandWith, it should first extend the capacity to increase performance a little). But I'd call it "extend" as in Python. Bye, bearophile
Nov 28 2014