std.mem
はプリミティブなメモリ操作を提供します。いくつか有用なものを紹介します。
fn copy(comptime T: type, dest: []mut T, source: []T) void
source
スライスをdest
スライスへコピーします。
呼び出し側は、次のことを保証しなければなりません。
dest
はsource
以上のサイズのスライスであること、つまり、source.len <= dest.len
を満たすことdest.ptr <= source.ptr
であることexamples/ch09-std/mem/src/mem.zen:5:13
const mem = std.mem;
test "mem.copy" {
const src = "hello";
var dest = [_]u8{0} ** 5;
mem.copy(u8, &mut dest, src);
equalSlices(u8, &dest, "hello");
}
fn copyBackwards(comptime T: type, dest: []mut T, source: []T) void
source
スライスをdest
スライスへコピーしますが、スライスを後ろから順番にコピーします。
呼び出し側は、次のことを保証しなければなりません。
dest
はsource
以上のサイズのスライスであること、つまり、source.len <= dest.len
を満たすことdest.ptr >= source.ptr
であることfn set(comptime T: type, dest: []mut T, value: T) void
スライス (dest
) の全ての要素にvalue
を書き込みます。
fn secureZero(comptime T: type, s: []mut T) void
スライス (s
) の全ての領域に0
を書き込みます。
examples/ch09-std/mem/src/mem.zen:15:26
test "mem.secureZero" {
const Point = struct {
x: u64,
y: u64,
};
// x => 10, y => 20 の Point が10個連続する配列
var p = [_]Point{Point{ .x = 10, .y = 20 }} ** 10;
mem.secureZero(Point, &mut p);
ok(p[0].x == 0);
ok(p[9].y == 0);
}
fn equal(comptime T: type, a: []T, b: []T) bool
a
とb
が同じ内容を含むスライスかどうか比較します。T
は整数型、浮動小数点型、ブール型、型です。
実行時のメモリ比較はもちろん、コンパイル時であれば、次のような比較も可能です。
examples/ch09-std/mem/src/mem.zen:28:34
test "mem.equal" {
comptime {
var a = [_]type{ f64, f32 };
var b = [_]type{ f64, f32, f16 };
_ = mem.equal(type, a[0..1], b[0..1]);
}
}
fn swap(comptime T: type, a: *mut T, b: *mut T) void
a
とb
が指しているメモリの内容を交換します。
fn reverse(comptime T: type, items: []mut T) void
スライスの中身を前後、逆にします。
examples/ch09-std/mem/src/mem.zen:36:41
test "mem.reverse" {
var arr = [_]i32{ 1, 2, 3, 4, 5 };
mem.reverse(i32, arr[0..]);
equalSlices(i32, &arr, &[_]i32{ 5, 4, 3, 2, 1 });
}
fn startsWith(comptime T: type, haystack: []T, needle: []T) bool
haystack
が、needle
から始まるスライスかどうかを調べます。
fn endsWith(comptime T: type, haystack: []T, needle: []T) bool
haystack
が、needle
で終わるスライスかどうかを調べます。
fn len(ptr: anytype) usize
ptr
に指定したデータの要素数を返します。
ptr
には配列、配列へのポインタ、終端値付き配列へのポインタ、スライスが指定できます。
終端値付き配列の場合は終端値を含まない要素数を返します。C言語の文字列のポインタを指定した場合は終端値がNULL文字の終端値付き配列として扱います。
fn slice(ptr: anytype) Slice(@TypeOf(ptr))
ptr
に指定したポインタをスライスに変換します。
ptr
には配列へのポインタ、終端値付き配列へのポインタ、スライスが指定できます。
主に C言語との相互運用時にNULL文字終端された配列をスライスに変換する場合などに使用します。
fn separate(buffer: []u8, delimiter: []u8) SplitIterator
バイト列 (buffer
) をデリミタ (delimiter
) で区切ります。戻り値型は、区切られたバイト列を順にアクセスできるイテレータです。
examples/ch09-std/mem/src/mem.zen:43:50
test "mem.separate" {
var it = mem.separate("abc|def||ghi", "|");
equalSlices(u8, it.next().?, "abc");
equalSlices(u8, it.next().?, "def");
equalSlices(u8, it.next().?, "");
equalSlices(u8, it.next().?, "ghi");
ok(it.next() == null);
}
デリミタは、複数バイトでもかまいません。
fn tokenize(buffer: []u8, delimiter_bytes: []u8) TokenIterator
バイト列 (buffer
) をデリミタ (delimiter_bytes
) のいずれかのバイトで区切ります。戻り値型は、区切られたバイト列を順にアクセスできるイテレータです。
examples/ch09-std/mem/src/mem.zen:52:59
test "mem.tokenize" {
var it = mem.tokenize("a|b,c/d", "/,|");
equalSlices(u8, it.next().?, "a");
equalSlices(u8, it.next().?, "b");
equalSlices(u8, it.next().?, "c");
equalSlices(u8, it.next().?, "d");
ok(it.next() == null);
}
fn writeInt(comptime T: type, buffer: *mut [@divExact(T.bit_count, 8)]u8, value: T, endian: builtin.Endian) void
整数型 (T
) をendian
のエンディアンで、配列へのポインタ (buffer
) に書き込みます。ビット表現は2の補数表現です。
examples/ch09-std/mem/src/mem.zen:62:81
test "mem.writeInt" {
var buf1: [4]u8 = undefined;
mem.writeInt(u32, &mut buf1, 0x12345678, .Little);
equalSlices(u8, &buf1, &[_]u8{ 0x78, 0x56, 0x34, 0x12 });
mem.writeInt(u32, &mut buf1, 0x12345678, .Big);
equalSlices(u8, &buf1, &[_]u8{ 0x12, 0x34, 0x56, 0x78 });
// x86_64 is big endian
mem.writeInt(u32, &mut buf1, 0x12345678, builtin.endian);
equalSlices(u8, &buf1, &[_]u8{ 0x78, 0x56, 0x34, 0x12 });
// 2の補数表現で格納する。`-1`は`0xffff_ffff`
mem.writeInt(i32, &mut buf1, -1, .Little);
equalSlices(u8, &buf1, &[_]u8{ 0xff, 0xff, 0xff, 0xff });
// 8ビットで割り切れるビット幅であればOK
var buf2: [3]u8 = undefined;
mem.writeInt(u24, &mut buf2, 0x123456, .Little);
equalSlices(u8, &buf2, &[_]u8{ 0x56, 0x34, 0x12 });
}
下の関数は、エンディアンを引数として指定せずに使える関数です。
writeIntNative
: ネイティブエンディアン (ストア命令になる)writeIntForeign
: ネイティブとは逆のエンディアン (@byteSwap後ストア)writeIntLittle
: リトルエンディアン (コンパイル時にwriteIntNative
かwriteIntForeign
をエイリアスする)writeIntBig
: ビッグエンディアン (コンパイル時にwriteIntNative
かwriteIntForeign
をエイリアスする)fn readInt(comptime T: type, bytes: *[@divExact(T.bit_count, 8)]u8, endian: builtin.Endian) T
配列へのポインタ (buffer
) から endian
のエンディアネスで、整数型 (T
) を読み込みます。
examples/ch09-std/mem/src/mem.zen:83:98
test "mem.readInt" {
var buf: [4]u8 = undefined;
mem.writeInt(u32, &mut buf, 0x12345678, .Little);
var result = mem.readInt(u32, &mut buf, .Little);
ok(result == 0x12345678);
result = mem.readInt(u32, &mut buf, .Big);
ok(result == 0x78563412);
mem.writeInt(i32, &mut buf, -1, .Little);
result = mem.readInt(u32, &mut buf, .Little);
ok(result == 0xffff_ffff);
var signed = mem.readInt(i32, &mut buf, .Little);
ok(signed == -1);
}
下の関数は、エンディアンを引数として指定せずに使える関数です。
readIntNative
: ネイティブエンディアン (ロード命令になる)readIntForeign
: ネイティブとは逆のエンディアン (ロード後@byteSwap)readIntLittle
: リトルエンディアン (コンパイル時にreadIntNative
かreadIntForeign
をエイリアスする)readIntBig
: ビッグエンディアン (コンパイル時にreadIntNative
かreadIntForeign
をエイリアスする)fn trimLeft(comptime T: type, items: []T, values_to_strip: []T) []T
fn trimRight(comptime T: type, items: []T, values_to_strip: []T) []T
fn trim(comptime T: type, items: []T, values_to_strip: []T) []T
スライスの先頭、末尾から指定した値を取り除きます。trimLeft
、trimRight
、trim
はそれぞれ、スライスの先頭から、スライスの末尾から、スライスの先頭、末尾の両側から values_to_strip
に指定した値を取り除いたスライスを返す関数です。
examples/ch09-std/mem/src/mem.zen:100:108
test "mem.trim" {
// それぞれスペースと改行を取り除く
equalSlices(u8, "foo\n ", mem.trimLeft(u8, " foo\n ", " \n"));
equalSlices(u8, " foo", mem.trimRight(u8, " foo\n ", " \n"));
equalSlices(u8, "foo", mem.trim(u8, " foo\n ", " \n"));
// 先頭、末尾以外には影響しない
equalSlices(u8, "foo bar", mem.trim(u8, " foo bar\n ", " \n"));
}
fn indexOfScalar(comptime T: type, items: []T, value: T) ?usize
fn lastIndexOfScalar(comptime T: type, items: []T, value: T) ?usize
fn indexOf(comptime T: type, haystack: []T, needle: []T) ?usize
fn lastIndexOf(comptime T: type, haystack: []T, needle: []T) ?usize
fn indexOfAny(comptime T: type, items: []T, values: []T) ?usize
fn lastIndexOfAny(comptime T: type, items: []T, values: []T) ?usize
スライスに、スカラ値またはサブスライスが含まれているかどうかを探し、見つかった場合にはそのインデックスを、見つからなかった場合にはnull
を返します。
examples/ch09-std/mem/src/mem.zen:110:122
test "mem.indexOf" {
// 見つからない場合、`null`が返る
ok(mem.indexOfScalar(u8, "boo", 'a') == null);
ok(mem.indexOfScalar(u8, "boo", 'o').? == 1);
ok(mem.lastIndexOfScalar(u8, "boo", 'o').? == 2);
ok(mem.indexOf(u8, "one two three four", "four").? == 14);
ok(mem.lastIndexOf(u8, "one two three two four", "two").? == 14);
ok(mem.indexOfAny(u8, "boo, cat", "abo").? == 0);
ok(mem.lastIndexOfAny(u8, "boo, cat", "abo").? == 6);
}
fn rotate(comptime T: type, items: []mut T, amount: usize) void
スライス (items
) の中身を、amount
分、回転させます。amount <= items.len
であることを前提としています。
examples/ch09-std/mem/src/mem.zen:124:129
test "mem.rotate" {
var array = [_]i32{ 1, 2, 3, 4, 5 };
mem.rotate(i32, array[0..], 2);
equalSlices(i32, &[_]i32{ 3, 4, 5, 1, 2 }, &array);
}
fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T
T
の値をネイティブエンディアンから、desired_endianness
に変換します。T
は整数型でなければなりません。
examples/ch09-std/mem/src/mem.zen:131:134
test "nativeTo" {
const native: u32 = 0x12345678;
ok(mem.nativeTo(u32, native, .Big) == 0x78563412);
}
エンディアンを引数として渡さなく良い関数もあります。
fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T
T
の値をendianness_of_x
から、ネイティブエンディアンに変換します。T
は整数型でなければなりません。
examples/ch09-std/mem/src/mem.zen:136:139
test "toNative" {
const native: u32 = 0x78563412;
ok(mem.toNative(u32, native, .Big) == 0x12345678);
}
エンディアンを引数として渡さなく良い関数もあります。
☰ 人の生きた証は永遠に残るよう ☰
Copyright © 2018-2020 connectFree Corporation. All rights reserved. | 特定商取引法に基づく表示
Zen, the Zen three-circles logo and The Zen Programming Language are trademarks of connectFree corporation in Japan and other countries.