ブロックデーターの実装
    Bitfieldを実装
    BlockDataを実装
ブロック単位でデータを管理するためのコードを書いてみましょう。

Bitfield実装

Bitfieldを実装していきす。 Bitfield Bool値(0, 1)を持つ任意の長さの配列です。
Torrentの場合だと、1がデータを持っている、0がデータを持っていないという事を表します。
1
class BitfieldSample {
2
List<bool> _data = [];
3
BitfieldSample(int length) {
4
_data = new List.filled(length, false);
5
}
6
7
bool operator [](int idx) => _data[idx];
8
void operator []=(int idx, bool value) {
9
_data[idx] = value;
10
}
11
int get length => _data.length;
12
13
}
Copied!
Torrentはこの値をバイト配列として利用するので、変換するメソッドを用意しておきましょう。
1
class Bitfield {
2
....
3
....
4
5
List<int> toBytes() {
6
int bytesLengths = _data.length ~/ 8 + (_data.length % 8 == 0 ? 0 : 1);
7
Uint8List ret = new Uint8List(bytesLengths);
8
for (int i = 0; i < _data.length; i++) {
9
if (this[i] == true) {
10
ret[i ~/ 8] |= 0x80 >> (7 - (i % 8));
11
}
12
}
13
return ret;
14
}
15
}
Copied!
こんな感じです。0x80が先頭Bitで、0x01が末Bit端なのが特徴です。

BlockDataの実装

BlockDataで扱うデータは、メモリーに収まらないことがあります。OSのイメージとかだと1GByteをこえます。ファイルとかで扱うと思います。
しかし、テストを書いたりする場合は、メモリーに収まるデータのみを対象としたほうが扱いやすいですし。場合によっては、ファイルではあるけどねクラウド上のファイルだったりします。
ここでは、以下のような、インターフェイスを利用することにします。
1
abstract class HetimaData {
2
async.Future<int> getLength();
3
async.Future<WriteResult> write(Object buffer, int start);
4
async.Future<ReadResult> read(int offset, int length, {List<int> tmp:null});
5
}
Copied!
BlockDataは、Blockごとにデータの状態を管理します。なので、blockごとにデータを所持しているか、所持していないかを判断できるようにします。
1
class BlockDataSample {
2
BitfieldSample _info = null;
3
HetimaData _data = null;
4
int _blockSize = 0;
5
int _fileSize = 0;
6
BlockDataSample(int fileSize, int blockSize, HetimaData data) {
7
_info = new BitfieldSample(fileSize ~/ blockSize + (fileSize % blockSize == 0 ? 0 : 1));
8
_data = data;
9
_blockSize = blockSize;
10
_fileSize = fileSize;
11
}
12
13
bool operator [](int idx) => _info[idx];
14
int get length => _info.length;
15
}
Copied!
ブロックごとにデータごとにも書き込み、読み込みの機能を追加します。
1
Future<WriteResult> writeBlock(int index, List<int> data) async {
2
WriteResult ret = await _data.write(data, index * _blockSize);
3
_info[index] = true;
4
return ret;
5
}
6
7
Future<ReadResult> readBlock(int index) async {
8
int start = index * _blockSize;
9
int end = (start + _blockSize > _fileSize ? _fileSize : start + _blockSize);
10
return _data.read(start, end - start);
11
}
Copied!
これで完成です。
Last modified 3yr ago