func main() { if len(os.Args) == 1 { fmt.Println("Usage: parser [INFILE] [[OUTFILE]]") os.Exit(1) } logFilename := os.Args[1] outFilename := OUT_FILENAME if len(os.Args) == 3 { outFilename = os.Args[2] } // Open the input file logFile, err := os.Open(logFilename) errhandler.Handle("Error opening data: ", err) defer logFile.Close() // Copy the input file into a buffer logBuf := bytes.NewBuffer(nil) logBuf.ReadFrom(logFile) // Create a list for parsed sessions sessions := make([]Session, 0) done := false for !done { // Create and read a raw session var raw RawSession err := raw.Read(logBuf) if err != io.EOF { errhandler.Handle("Error parsing session: ", err) } // If we hit EOF after the last session, no more data to read if err == io.EOF { done = true } // Parse the raw session and store it in the sessions list session, err := raw.Parse() errhandler.Handle("Error parsing session: ", err) sessions = append(sessions, session) } // Create the output file and encode the session list to json outFile, err := os.Create(outFilename) errhandler.Handle("Error creating output file: ", err) defer outFile.Close() jsonEncoder := json.NewEncoder(outFile) err = jsonEncoder.Encode(sessions) errhandler.Handle("Error encoding json output: ", err) }
// Reads raw session data func (s *RawSession) Read(r *bytes.Buffer) error { // Get a line and trim space tmp, err := r.ReadString('\n') errhandler.Handle("Error reading line: ", err) tmp = strings.TrimSpace(tmp) // If the line is a session header if sessionRegex.MatchString(tmp) { // Parse session header matches := sessionRegex.FindStringSubmatch(tmp) s.Info = matches[1] s.Channel = matches[2] // Consume following lines until we find another session for { tmp, err := r.ReadString('\n') if err != io.EOF && err != nil { return err } // Found another session, unread the line and break loop if sessionRegex.MatchString(tmp) { *r = *AppendBefore(r, tmp) break } // Found a payload line, append it to the payload if len(tmp) > 0 { s.Payload = append(s.Payload, strings.TrimSpace(tmp)) } if err == io.EOF { return err } } } return nil }
// Reads a string, the length of the string is read first (signed 16-bit int), then the string characters. func ReadString(r io.Reader) string { result := make([]byte, ReadShort(r)) _, err := r.Read(result) errhandler.Handle("Error reading String: ", err) return string(result) }
func init() { var err error sessionRegex, err = regexp.CompilePOSIX(SESSION_REGEX) errhandler.Handle("Error compiling regex: ", err) }
// Reads a 64-bit IEEE-754 floating point value. func ReadDouble(r io.Reader) (i float64) { err := binary.Read(r, binary.BigEndian, &i) errhandler.Handle("Error reading Double: ", err) return }
// Reads a byte array, the array length (signed 32-bit int) is read first, then the array of bytes. func ReadByteArray(r io.Reader) (i []byte) { i = make([]byte, ReadInt(r)) _, err := r.Read(i) errhandler.Handle("Error reading Byte Array: ", err) return }
// Reads a 32-bit IEEE-754 floating point value. func ReadFloat(r io.Reader) (i float32) { err := binary.Read(r, binary.BigEndian, &i) errhandler.Handle("Error reading Float: ", err) return }
// Reads a signed 64-bit integer. func ReadLong(r io.Reader) (i int64) { err := binary.Read(r, binary.BigEndian, &i) errhandler.Handle("Error reading Long: ", err) return }
// Reads a signed 32-bit integer. func ReadInt(r io.Reader) (i int32) { err := binary.Read(r, binary.BigEndian, &i) errhandler.Handle("Error reading Int: ", err) return }
// Reads a signed 16-bit integer. func ReadShort(r io.Reader) (i int16) { err := binary.Read(r, binary.BigEndian, &i) errhandler.Handle("Error reading Short: ", err) return }
// Reads a single byte. func ReadByte(r io.Reader) (i byte) { err := binary.Read(r, binary.BigEndian, &i) errhandler.Handle("Error reading Byte: ", err) return }