Browse Source

faster BamRead.toString

remotes/georgeg/no_streams
lomereiter 9 years ago
parent
commit
02ad9dff11
  1. 46
      bio/bam/read.d
  2. 55
      bio/bam/tagvalue.d
  3. 75
      bio/core/utils/format.d

46
bio/bam/read.d

@ -44,6 +44,7 @@
module bio.bam.read;
import bio.core.base;
import bio.core.utils.format;
import bio.bam.abstractreader;
import bio.bam.writer;
@ -146,7 +147,8 @@ struct CigarOperation {
///
void toString(scope void delegate(const(char)[]) sink) const {
sink.formattedWrite("%s%s", length, type);
sink.putInteger(length);
sink.putChar(type);
}
}
@ -710,18 +712,28 @@ struct BamRead {
///
void toString(scope void delegate(const(char)[]) sink) const {
sink(name);
sink("\t");
sink.formattedWrite("%d\t", flag);
sink.putChar('\t');
sink.putInteger(flag);
sink.putChar('\t');
if (ref_id == -1 || _reader is null)
sink("*");
sink.putChar('*');
else
sink(_reader.reference_sequences[ref_id].name);
sink.formattedWrite("\t%d\t%d\t", position + 1, mapping_quality);
sink.putChar('\t');
sink.putInteger(position + 1);
sink.putChar('\t');
sink.putInteger(mapping_quality);
sink.putChar('\t');
if (cigar.length == 0)
sink("*\t");
sink.putChar('*');
else
sink.formattedWrite("%(%s%)\t", cigar);
foreach (op; cigar)
op.toString(sink);
sink.putChar('\t');
if (mate_ref_id == ref_id) {
if (mate_ref_id == -1)
sink("*\t");
@ -737,24 +749,28 @@ struct BamRead {
}
}
sink.formattedWrite("%d\t%d\t", mate_position + 1, template_length);
sink.putInteger(mate_position + 1);
sink.putChar('\t');
sink.putInteger(template_length);
sink.putChar('\t');
if (sequence_length == 0)
sink("*");
sink.putChar('*');
else
foreach (char c; sequence)
sink.formattedWrite("%c", c);
sink("\t");
sink.putChar(c);
sink.putChar('\t');
if (base_qualities.length == 0 || base_qualities[0] == 0xFF)
sink("*");
sink.putChar('*');
else
foreach (qual; base_qualities)
sink.formattedWrite("%s", cast(char)(qual + 33));
sink.putChar(cast(char)(qual + 33));
foreach (k, v; this) {
sink("\t");
sink.putChar('\t');
sink(k);
sink(":");
sink.putChar(':');
v.formatSam(sink);
}
}

55
bio/bam/tagvalue.d

@ -48,6 +48,7 @@ public import std.conv;
import std.typetuple;
import std.exception;
import std.format;
import bio.core.utils.format;
import bio.bam.thirdparty.msgpack;
@ -452,27 +453,39 @@ struct Value {
}
void formatSam(scope void delegate(const(char)[]) sink) const {
switch (_tag) {
case GetTypeId!byte: sink.formattedWrite("i:%s", *cast(byte*)(&u)); break;
case GetTypeId!ubyte: sink.formattedWrite("i:%s", *cast(ubyte*)(&u)); break;
case GetTypeId!short: sink.formattedWrite("i:%s", *cast(short*)(&u)); break;
case GetTypeId!ushort: sink.formattedWrite("i:%s", *cast(ushort*)(&u)); break;
case GetTypeId!int: sink.formattedWrite("i:%s", *cast(int*)(&u)); break;
case GetTypeId!uint: sink.formattedWrite("i:%s", *cast(uint*)(&u)); break;
case GetTypeId!float: sink.formattedWrite("f:%s", *cast(float*)(&u)); break;
case GetTypeId!string: sink("Z:"); sink(*cast(const(char)[]*)(&u)); break;
case hexStringTag: sink("H:"); sink(*cast(const(char)[]*)(&u)); break;
case GetTypeId!char: sink.formattedWrite("A:%c", *cast(char*)(&u)); break;
case GetTypeId!(byte[]): sink.formattedWrite("B:c,%(%s,%)", *cast(byte[]*)(&u)); break;
case GetTypeId!(ubyte[]): sink.formattedWrite("B:C,%(%s,%)", *cast(ubyte[]*)(&u)); break;
case GetTypeId!(short[]): sink.formattedWrite("B:s,%(%s,%)", *cast(short[]*)(&u)); break;
case GetTypeId!(ushort[]): sink.formattedWrite("B:S,%(%s,%)", *cast(ushort[]*)(&u)); break;
case GetTypeId!(int[]): sink.formattedWrite("B:i,%(%s,%)", *cast(int[]*)(&u)); break;
case GetTypeId!(uint[]): sink.formattedWrite("B:I,%(%s,%)", *cast(uint[]*)(&u)); break;
case GetTypeId!(float[]): sink.formattedWrite("B:f,%(%s,%)", *cast(float[]*)(&u)); break;
default: break;
if (is_integer) {
sink("i:");
switch (_tag) {
case GetTypeId!byte: sink.putInteger(*cast(byte*)(&u)); break;
case GetTypeId!ubyte: sink.putInteger(*cast(ubyte*)(&u)); break;
case GetTypeId!short: sink.putInteger(*cast(short*)(&u)); break;
case GetTypeId!ushort: sink.putInteger(*cast(ushort*)(&u)); break;
case GetTypeId!int: sink.putInteger(*cast(int*)(&u)); break;
case GetTypeId!uint: sink.putInteger(*cast(uint*)(&u)); break;
default: break;
}
} else if (is_numeric_array) {
sink("B:");
sink.putChar(bam_typeid);
sink.putChar(',');
switch (_tag) {
case GetTypeId!(byte[]): sink.putArray(*cast(byte[]*)(&u), ','); break;
case GetTypeId!(ubyte[]): sink.putArray(*cast(ubyte[]*)(&u), ','); break;
case GetTypeId!(short[]): sink.putArray(*cast(short[]*)(&u), ','); break;
case GetTypeId!(ushort[]): sink.putArray(*cast(ushort[]*)(&u), ','); break;
case GetTypeId!(int[]): sink.putArray(*cast(int[]*)(&u), ','); break;
case GetTypeId!(uint[]): sink.putArray(*cast(uint[]*)(&u), ','); break;
case GetTypeId!(float[]): sink.putArray(*cast(float[]*)(&u), ','); break;
default: break;
}
} else {
switch (_tag) {
case GetTypeId!float: sink("f:"); sink.putFloat(*cast(float*)(&u)); break;
case GetTypeId!string: sink("Z:"); sink(*cast(const(char)[]*)(&u)); break;
case hexStringTag: sink("H:"); sink(*cast(const(char)[]*)(&u)); break;
case GetTypeId!char: sink("A:"); sink.putChar(*cast(char*)(&u)); break;
default: break;
}
}
}
}

75
bio/core/utils/format.d

@ -245,3 +245,78 @@ unittest {
append(p, "%g", 8.9);
assert(s[0 .. p - s] == "12345678.9");
}
void putFloat(T)(scope void delegate(const(char)[]) sink, T number)
if (isFloatingPoint!T)
{
char[1024] buffer = void;
int count;
auto p = buffer.ptr;
auto psize = buffer.length;
for (;;)
{
version(Win32)
{
count = _snprintf(p,psize,"%g", cast(double)number);
if (count != -1)
break;
psize *= 2;
p = cast(char *) alloca(psize);
}
version(Posix)
{
count = snprintf(p,psize,"%g", cast(double)number);
if (count == -1)
psize *= 2;
else if (count >= psize)
psize = count + 1;
else
break;
p = cast(char *) alloca(psize);
}
}
sink(p[0 .. count]);
}
void putInteger(T)(scope void delegate(const(char)[]) sink, T integer)
if (isIntegral!T)
{
char[64] buf = void;
auto len = itoa(integer, buf.ptr);
sink(buf[0 .. len]);
}
void putChar(T)(scope void delegate(const(char)[]) sink, T c)
if (isSomeChar!T)
{
char[1] buf = void;
buf[0] = c;
sink(buf[0 .. 1]);
}
void put(T)(scope void delegate(const(char)[]) sink, T value) {
static if (isIntegral!T)
putInteger(sink, value);
else static if (isFloatingPoint!T)
putFloat(sink, value);
else static if (isSomeChar!T)
putChar(sink, value);
else static if (isSomeString!T)
sink(cast(const(char)[])value);
else static assert(false);
}
void putArray(T, U)(scope void delegate(const(char)[]) sink, T array, U delimiter)
if (isArray!T && (isSomeChar!U || isSomeString!U) && __traits(compiles, put(sink, array[0])))
{
if (array.length == 0)
return;
foreach (elem; array[0 .. $ - 1]) {
sink.put(elem);
sink.put(delimiter);
}
sink.put(array[$ - 1]);
}
Loading…
Cancel
Save