#memcpy
1 messages · Page 1 of 1 (latest)
use slices as the arguments, slices have a size
at least one of source and dest must provide a length, and if two lengths are provided, they must be equal.
Do you have an idea?
if you have two many pointers, you'll have to slice one of them
for this specific pattern you might want std.mem.writeInt
i.e. @memcpy(dest[0..len], src); EDITED
dest first
yes. thx
std.mem.writeInt(i32, buffer[offset..][0..4], value, .little)
i'm not sure if that snippet is what you want to do in zig or just a random memcpy example
const std = @import("std");
pub const binarystream = struct {
const Self = *@This();
buff: []u8,
offset: u8,
pub fn writeByte(self: Self, buffs: []const u8) !void {
@memcpy(self.buff[0..buffs.len], buffs);
self.offset += @sizeOf([]u8);
std.debug.print("{any}", .{self.buff});
}
// char readByte() {
// char value;
// memcpy(&value, buffer + offset, sizeof(char));
// offset += sizeof(char);
// return value;
pub fn readByte(self: Self) ![]u8 {
var value: []u8 = undefined;
@memcpy(value[0..value.len], self.buff[0..]);
self.offset += @sizeOf(u8);
return value[0..];
}
};
test "tests" {
var buff: [1024]u8 = undefined;
var binary = binarystream{ .buff = &buff, .offset = 0 };
_ = try binary.writeByte("A");
var intreading = binarystream{ .buff = &buff, .offset = 0 };
const int_test = try intreading.readByte();
std.debug.print("{any}/n", .{int_test});
}
err :
@memcpy(value[0..value.len], self.buff[0..]);
^
const int_test = try intreading.readByte();
^
Any idea why it prevents the code from running?
Consider: where does value point to?
Slices are a pointer+length pair, so they point to their elements.
Where did you set it to point to?
Well - nowhere; in fact it's worse than that.
You initialized it to undefined, which means "I don't want this set to anything; I'm okay with garbage being here" - so it will point to somewhere essentially random in all of memory, with a random element count.
You need to actually get some space from somewhere, and then use that space.
In this particular case though, since the point of the function is to just read a single byte, you can just return that byte by-value:
const b = self.buff[0]; // shouldn't this be based on self.offset?
self.offset += 1;
return b;
@memcpy(self.buff[self.offset..@sizeOf(i32)], @as([]u8, @ptrFromInt(value)));
self.offset += @sizeOf(i32);
note: unsigned 64-bit int cannot represent all possible signed 32-bit values
c++ : ```cpp
memcpy(buffer + offset, &value, sizeof(int));
offset += sizeof(int);
Slicing takes a begin/end, not begin/length.
Given that buff is a []u8, that C++ equivalent code isn't the same
I suspect you actually should be doing this in C++ instead:
buffer[offset] = (uint8_t)value;
offset += 1;
self.buff[self.offset..][0..4]
@memcpy(self.buff[self.offset..@sizeOf(i32)], @as([]u8, @ptrFromInt(value)));
This is like 4 different sorts of wrong; that@ptrFromIntseems very wrong to me
I think I confused slices with char
Do you have any ideas? for this
I'd need more context
Like what is value
value is a 32-bit argument
writeInt makes no sense to me at all
Why? :/
Can you elaborate a bit on what it means to write an int into your buffer?
It takes a i32, ignores most of it, and tries to memcpy just the low byte (1 byte) into a 4 byte space in the buffer
Then advance by 4 bytes
This is contradictory 😄
I can't really help you there unless you tell me what you actually are trying to do with that
By "add", do you mean "I want to turn this i32 into 4 bytes, and write those 4 bytes into buff at offset ?
Exactly
@memcpy(self.buff[self.offset..][0..4], std.mem.asBytes(&value));
Cool
const std = @import("std");
pub const binarystream = struct {
const Self = *@This();
buff: []u8,
offset: u8,
pub fn writeByte(self: Self, buffs: []const u8) !void {
@memcpy(self.buff[self.offset..buffs.len], buffs);
self.offset += @sizeOf([]u8);
}
pub fn readByte(self: Self) ![]u8 {
if (self.offset + 1 > self.buff.len) {
return error.EndOfStream;
}
const value = self.buff[self.offset..][0..1];
self.offset += 1;
return value;
}
pub fn writeInt(self: Self, value: i32) !void {
@memcpy(self.buff[self.offset .. self.offset + 4], std.mem.asBytes(&value));
std.debug.print("{any}\n", .{self.buff});
self.offset += 4;
}
pub fn readInt(self: Self) ![]u8 {
const value: []u8 = self.buff[self.offset..][0..4];
self.offset += 4;
return value;
}
};
pub fn main() !void {
var buff: [1024]u8 = undefined;
var binary = binarystream{ .buff = &buff, .offset = 0 };
_ = try binary.writeByte("A");
_ = try binary.writeInt(50);
var binary2 = binarystream{ .buff = &buff, .offset = 0 };
const bytes = try binary2.readByte();
const int_tst = try binary2.readInt();
std.debug.print("{any}\n", .{bytes});
std.debug.print("{any}\n", .{int_tst});
}
reading :
{ 65 }
{ 170, 170, 170, 170 }
What exactly is the problem, why are some bytes already written?
What is the solution, should std.arraylist be used?
yea fixed
try adding this to your program somewhere: @compileLog(@sizeOf([]u8));
writeByte() should accept a byte, not a slice. that is just confusing imo
like this: pub fn writeByte(self: Self, byte:u8) !void {
and similarly, readInt should return an int instead of a slice
how can convert slice to i32?
i would do it like this: std.mem.readInt(i32, slice[offset..][0..4], .little);
here's how i would write this code: https://zigbin.io/f98eb1
-1431655766
pub fn readInt(self: Self) !i32 {
self.offset += 4;
return std.mem.readInt(i32, self.buff[self.offset..][0..4], .little);
}
you should defer incrementing offset
if you increment before, you're skipping the part you want
defer self.offset += 4;
I had not paid attention
Defers are really good
i agree! they work at scope level, not function level like in go
so you can defer to the end of a scope
Yeah
but in this case that happens to be a fn
you asked earlier if you should use an array list for this. that is one option. ArrayList(u8) has a writer() method which returns an io.Writer. and it has writeByte() and writeInt() methods.
however, for this exact functionality i would use an io.fixedBufferStream() and use its writer()
that way you can write to a static buffer just like in your code
fixed buffer stream also has a reader() you can use
with similar methods
What do you mean by accurate performance?
not sure. where did i say that?
you asked earlier if you should use an array list for this. that is one option. ArrayList(u8) has a writer() method which returns an io.Writer. and it has writeByte() and writeInt() methods.
"that is one option."
i'm saying that std.io.Writer() has these methods. and you can get one from a std.ArrayList(u8) or from a std.io.fixedBufferStream() by calling their writer() methods
and that std.io.fixedBufferStream() also has a reader() method too
Alright
cool

