#memcpy

1 messages · Page 1 of 1 (latest)

plush trail
#

I didn't find memcpy in zig like C++:

int value;
memcpy(&value, buffer + offset, sizeof(int));
offset += sizeof(int);
return value;
sacred rivet
plush trail
#

Well, how do we define its size?

#

@sacred rivet

thick peak
#

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.

plush trail
#

Do you have an idea?

proud spindle
#

if you have two many pointers, you'll have to slice one of them

thick peak
proud spindle
#

i.e. @memcpy(dest[0..len], src); EDITED

thick peak
#

dest first

proud spindle
#

yes. thx

thick peak
#

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

plush trail
#
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?

tired cypress
#

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;
plush trail
#
@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);

tired cypress
#

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;
tired cypress
tired cypress
plush trail
#

I think I confused slices with char

tired cypress
plush trail
tired cypress
#

Like what is value

plush trail
plush trail
tired cypress
plush trail
#

Why? :/

tired cypress
#

Can you elaborate a bit on what it means to write an int into your buffer?

tired cypress
# plush trail Why? :/

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

plush trail
#

wowwheeze

#

I want to add integer in a buffer with memcopy

tired cypress
#

By "add", do you mean "I want to turn this i32 into 4 bytes, and write those 4 bytes into buff at offset ?

tired cypress
#

@memcpy(self.buff[self.offset..][0..4], std.mem.asBytes(&value));

plush trail
tired cypress
#

asBytes

#

Then pass &value

plush trail
#

is work

tired cypress
#

Cool

plush trail
#
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?

proud spindle
#

170 == 0xaa. in debug mode all undefined memory is initialized to 0xaa

plush trail
proud spindle
#

self.offset += @sizeOf([]u8);

#

this is wrong

plush trail
proud spindle
#

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

plush trail
proud spindle
#

i would do it like this: std.mem.readInt(i32, slice[offset..][0..4], .little);

plush trail
proud spindle
#

you should defer incrementing offset

#

if you increment before, you're skipping the part you want

#

defer self.offset += 4;

plush trail
plush trail
proud spindle
#

i agree! they work at scope level, not function level like in go

#

so you can defer to the end of a scope

plush trail
#

Yeah

proud spindle
#

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

plush trail
#

What do you mean by accurate performance?

proud spindle
#

not sure. where did i say that?

plush trail
#

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."

proud spindle
#

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

plush trail
#

cool