Skip to content
Snippets Groups Projects
Select Git revision
  • 66855fcaf3eb454e324068f46d46e1173ab38b0a
  • master default protected
  • android-7.1.2_r28_klist
  • pie-cts-release
  • pie-vts-release
  • pie-cts-dev
  • oreo-mr1-iot-release
  • sdk-release
  • oreo-m6-s4-release
  • oreo-m4-s12-release
  • pie-release
  • pie-r2-release
  • pie-r2-s1-release
  • oreo-vts-release
  • oreo-cts-release
  • oreo-dev
  • oreo-mr1-dev
  • pie-gsi
  • pie-platform-release
  • pie-dev
  • oreo-cts-dev
  • android-o-mr1-iot-release-1.0.4
  • android-9.0.0_r8
  • android-9.0.0_r7
  • android-9.0.0_r6
  • android-9.0.0_r5
  • android-8.1.0_r46
  • android-8.1.0_r45
  • android-n-iot-release-smart-display-r2
  • android-vts-8.1_r5
  • android-cts-8.1_r8
  • android-cts-8.0_r12
  • android-cts-7.1_r20
  • android-cts-7.0_r24
  • android-o-mr1-iot-release-1.0.3
  • android-cts-9.0_r1
  • android-8.1.0_r43
  • android-8.1.0_r42
  • android-n-iot-release-smart-display
  • android-p-preview-5
  • android-9.0.0_r3
41 results

mls_macros

Blame
  • header.go 3.16 KiB
    package radolan
    
    import (
    	"bufio"
    	"fmt"
    	"strings"
    	"time"
    	"unicode"
    )
    
    // splitHeader splits the given header string into its fields. The returned
    // map is using the field name as key and the field content as value.
    func splitHeader(header string) (m map[string]string) {
    	m = make(map[string]string)
    	var beginKey, endKey, beginValue, endValue int
    	var dispatch bool
    
    	for i, c := range header {
    		if unicode.IsUpper(c) {
    			if dispatch {
    				m[header[beginKey:endKey]] = header[beginValue:endValue]
    				beginKey = i
    				dispatch = false
    			}
    			endKey = i + 1
    		} else {
    			if i == 0 {
    				return // no key prefixing value
    			}
    			if !dispatch {
    				beginValue = i
    				dispatch = true
    			}
    			endValue = i + 1
    		}
    	}
    	m[header[beginKey:endKey]] = header[beginValue:endValue]
    
    	return
    }
    
    // parseHeader parses and the composite header and writes the related fields as
    // described in [1] and [3].
    func (c *Composite) parseHeader(reader *bufio.Reader) error {
    	header, err := reader.ReadString('\x03')
    	if err != nil || len(header) < 22 { // smaller length makes no sense
    		return newError("parseHeader", "header corrupted: too short")
    	}
    
    	// Split header segments
    	section := splitHeader(header[:len(header)-1]) // without delimiter
    
    	// Parse Product - Example: "PG" or "FZ"
    	c.Product = header[:2]
    
    	// Parse DataLength - Example: "BY 405160"
    	if _, err := fmt.Sscanf(section["BY"], "%d", &c.dataLength); err != nil {
    		return newError("parseHeader", "could not parse data length: "+err.Error())
    	}
    	c.dataLength -= len(header) // remove header length including delimiter
    
    	// Parse CaptureTime - Example: "PG262115100000616" or "FZ211615100000716"
    	date := header[2:8] + header[13:17] // cut WMO number
    	c.CaptureTime, err = time.Parse("0215040106", date)
    	if err != nil {
    		return newError("parseHeader", "could not parse capture time: "+err.Error())
    	}
    
    	// Parse ForecastTime - Example: "VV 005"
    	c.ForecastTime = c.CaptureTime
    	if vv, ok := section["VV"]; ok {
    		min := 0
    		if _, err := fmt.Sscanf(vv, "%d", &min); err != nil {
    			return newError("parseHeader", "could not parse forecast time: "+err.Error())
    		}
    		c.ForecastTime = c.CaptureTime.Add(time.Duration(min) * time.Minute)
    	}
    
    	// Parse Dimensions - Example: "GP 450x 450" or "BG460460" or "GP 1500x1400"
    	dim := section["GP"]
    	if bg, ok := section["BG"]; ok {
    		dim = bg[:len(bg)/2] + "x" + bg[len(bg)/2:]
    	}
    
    	if _, err := fmt.Sscanf(dim, "%dx%d", &c.Dy, &c.Dx); err != nil {
    		return newError("parseHeader", "could not parse dimensions: "+err.Error())
    	}
    
    	// Parse Precision - Example: "PR E-01" or "PR E+00"
    	if prec, ok := section["E"]; ok { // not that nice
    		if _, err := fmt.Sscanf(prec, "%d", &c.precision); err != nil {
    			return newError("parseHeader", "could not parse precision: "+err.Error())
    		}
    	}
    
    	// Parse Level - Example "LV 6  1.0 19.0 28.0 37.0 46.0 55.0"
    	if lv, ok := section["LV"]; ok {
    		level := strings.Fields(lv)
    		if len(level) < 2 {
    			return newError("parseHeader", "invalid level count")
    		}
    
    		c.level = make([]DBZ, len(level)-1)
    		for i, f := range level[1:] {
    			if _, err = fmt.Sscanf(f, "%f", &c.level[i]); err != nil {
    				return newError("parseHeader", "invalid level value: "+err.Error())
    			}
    		}
    	}
    
    	return nil
    }