private object ReadType(CtfStruct strct, object[] result, CtfMetadataType type) { Align(type.Align); switch (type.CtfType) { case CtfTypes.Array: CtfArray array = (CtfArray)type; int len = array.GetLength(strct, result); object[] ret = new object[len]; for (int j = 0; j < len; j++) { ret[j] = ReadType(null, null, array.Type); } return(ret); case CtfTypes.Enum: return(ReadType(strct, result, ((CtfEnum)type).Type)); case CtfTypes.Float: CtfFloat flt = (CtfFloat)type; ReadBits(flt.Exp + flt.Mant); return(0f); // TODO: Not implemented. case CtfTypes.Integer: CtfInteger ctfInt = (CtfInteger)type; return(ReadInteger(ctfInt)); case CtfTypes.String: bool ascii = ((CtfString)type).IsAscii; return(ReadString(ascii)); case CtfTypes.Struct: return(ReadStruct((CtfStruct)type)); case CtfTypes.Variant: CtfVariant var = (CtfVariant)type; int i = strct.GetFieldIndex(var.Switch); CtfField field = strct.Fields[i]; CtfEnum enumType = (CtfEnum)field.Type; int value = strct.GetFieldValue <int>(result, i); string name = enumType.GetName(value); field = var.Union.Where(f => f.Name == name).Single(); return(ReadType(strct, result, field.Type)); default: throw new InvalidOperationException(); } }
public IEnumerable <CtfEventHeader> EnumerateEventHeaders() { CtfStruct header = _streamDefinition.EventHeader; CtfVariant v = (CtfVariant)header.GetField("v").Type; CtfStruct extended = (CtfStruct)v.GetVariant("extended").Type; CtfStruct compact = (CtfStruct)v.GetVariant("compact").Type; ulong lowMask = 0, highMask = 0, overflowBit = 0; ulong lastTimestamp = 0; StringBuilder processName = new StringBuilder(); while (!_eof) { if (_readHeader) { throw new InvalidOperationException("Must read an events data before reading the header again."); } _header.Clear(); ResetBuffer(); object[] result = ReadStruct(header); if (_eof) { break; } ulong timestamp; CtfEnum en = (CtfEnum)header.GetField("id").Type; uint event_id = header.GetFieldValue <uint>(result, "id"); result = header.GetFieldValue <object[]>(result, "v"); if (en.GetName((int)event_id) == "extended") { event_id = extended.GetFieldValue <uint>(result, "id"); timestamp = extended.GetFieldValue <ulong>(result, "timestamp"); } else { if (overflowBit == 0) { CtfInteger compactTimestamp = (CtfInteger)compact.GetField("timestamp").Type; overflowBit = (1ul << compactTimestamp.Size); lowMask = overflowBit - 1; highMask = ~lowMask; } ulong uint27timestamp = compact.GetFieldValue <ulong>(result, "timestamp"); ulong prevLowerBits = lastTimestamp & lowMask; if (prevLowerBits < uint27timestamp) { timestamp = (lastTimestamp & highMask) | uint27timestamp; } else { timestamp = (lastTimestamp & highMask) | uint27timestamp; timestamp += overflowBit; } } lastTimestamp = timestamp; CtfEvent evt = _streamDefinition.Events[(int)event_id]; _header.Event = evt; _header.Timestamp = timestamp; CtfStruct eventContext = _streamDefinition.EventContext; if (eventContext != null) { result = ReadStruct(eventContext); _header.Pid = eventContext.GetFieldValue <int>(result, "_vpid"); _header.Tid = eventContext.GetFieldValue <int>(result, "_vtid"); int procnameIndex = eventContext.GetFieldIndex("_procname"); object[] procname = (object[])(result[procnameIndex]); processName.Clear(); for (int i = 0; i < 17; i++) { sbyte b = (sbyte)procname[i]; if (b == 0) { break; } processName.Append((char)b); } _header.ProcessName = processName.ToString(); } _readHeader = true; yield return(_header); } }