(v0.1.1) Automated packaging of release by Packagr
This commit is contained in:
+163
@@ -0,0 +1,163 @@
|
||||
//
|
||||
// Use and distribution licensed under the Apache license version 2.
|
||||
//
|
||||
// See the COPYING file in the root project directory for full text.
|
||||
//
|
||||
|
||||
package pcidb
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func parseDBFile(db *PCIDB, scanner *bufio.Scanner) error {
|
||||
inClassBlock := false
|
||||
db.Classes = make(map[string]*Class, 20)
|
||||
db.Vendors = make(map[string]*Vendor, 200)
|
||||
db.Products = make(map[string]*Product, 1000)
|
||||
subclasses := make([]*Subclass, 0)
|
||||
progIfaces := make([]*ProgrammingInterface, 0)
|
||||
var curClass *Class
|
||||
var curSubclass *Subclass
|
||||
var curProgIface *ProgrammingInterface
|
||||
vendorProducts := make([]*Product, 0)
|
||||
var curVendor *Vendor
|
||||
var curProduct *Product
|
||||
var curSubsystem *Product
|
||||
productSubsystems := make([]*Product, 0)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
// skip comments and blank lines
|
||||
if line == "" || strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
lineBytes := []rune(line)
|
||||
|
||||
// Lines starting with an uppercase "C" indicate a PCI top-level class
|
||||
// dbrmation block. These lines look like this:
|
||||
//
|
||||
// C 02 Network controller
|
||||
if lineBytes[0] == 'C' {
|
||||
if curClass != nil {
|
||||
// finalize existing class because we found a new class block
|
||||
curClass.Subclasses = subclasses
|
||||
subclasses = make([]*Subclass, 0)
|
||||
}
|
||||
inClassBlock = true
|
||||
classID := string(lineBytes[2:4])
|
||||
className := string(lineBytes[6:])
|
||||
curClass = &Class{
|
||||
ID: classID,
|
||||
Name: className,
|
||||
Subclasses: subclasses,
|
||||
}
|
||||
db.Classes[curClass.ID] = curClass
|
||||
continue
|
||||
}
|
||||
|
||||
// Lines not beginning with an uppercase "C" or a TAB character
|
||||
// indicate a top-level vendor dbrmation block. These lines look like
|
||||
// this:
|
||||
//
|
||||
// 0a89 BREA Technologies Inc
|
||||
if lineBytes[0] != '\t' {
|
||||
if curVendor != nil {
|
||||
// finalize existing vendor because we found a new vendor block
|
||||
curVendor.Products = vendorProducts
|
||||
vendorProducts = make([]*Product, 0)
|
||||
}
|
||||
inClassBlock = false
|
||||
vendorID := string(lineBytes[0:4])
|
||||
vendorName := string(lineBytes[6:])
|
||||
curVendor = &Vendor{
|
||||
ID: vendorID,
|
||||
Name: vendorName,
|
||||
Products: vendorProducts,
|
||||
}
|
||||
db.Vendors[curVendor.ID] = curVendor
|
||||
continue
|
||||
}
|
||||
|
||||
// Lines beginning with only a single TAB character are *either* a
|
||||
// subclass OR are a device dbrmation block. If we're in a class
|
||||
// block (i.e. the last parsed block header was for a PCI class), then
|
||||
// we parse a subclass block. Otherwise, we parse a device dbrmation
|
||||
// block.
|
||||
//
|
||||
// A subclass dbrmation block looks like this:
|
||||
//
|
||||
// \t00 Non-VGA unclassified device
|
||||
//
|
||||
// A device dbrmation block looks like this:
|
||||
//
|
||||
// \t0002 PCI to MCA Bridge
|
||||
if len(lineBytes) > 1 && lineBytes[1] != '\t' {
|
||||
if inClassBlock {
|
||||
if curSubclass != nil {
|
||||
// finalize existing subclass because we found a new subclass block
|
||||
curSubclass.ProgrammingInterfaces = progIfaces
|
||||
progIfaces = make([]*ProgrammingInterface, 0)
|
||||
}
|
||||
subclassID := string(lineBytes[1:3])
|
||||
subclassName := string(lineBytes[5:])
|
||||
curSubclass = &Subclass{
|
||||
ID: subclassID,
|
||||
Name: subclassName,
|
||||
ProgrammingInterfaces: progIfaces,
|
||||
}
|
||||
subclasses = append(subclasses, curSubclass)
|
||||
} else {
|
||||
if curProduct != nil {
|
||||
// finalize existing product because we found a new product block
|
||||
curProduct.Subsystems = productSubsystems
|
||||
productSubsystems = make([]*Product, 0)
|
||||
}
|
||||
productID := string(lineBytes[1:5])
|
||||
productName := string(lineBytes[7:])
|
||||
productKey := curVendor.ID + productID
|
||||
curProduct = &Product{
|
||||
VendorID: curVendor.ID,
|
||||
ID: productID,
|
||||
Name: productName,
|
||||
}
|
||||
vendorProducts = append(vendorProducts, curProduct)
|
||||
db.Products[productKey] = curProduct
|
||||
}
|
||||
} else {
|
||||
// Lines beginning with two TAB characters are *either* a subsystem
|
||||
// (subdevice) OR are a programming interface for a PCI device
|
||||
// subclass. If we're in a class block (i.e. the last parsed block
|
||||
// header was for a PCI class), then we parse a programming
|
||||
// interface block, otherwise we parse a subsystem block.
|
||||
//
|
||||
// A programming interface block looks like this:
|
||||
//
|
||||
// \t\t00 UHCI
|
||||
//
|
||||
// A subsystem block looks like this:
|
||||
//
|
||||
// \t\t0e11 4091 Smart Array 6i
|
||||
if inClassBlock {
|
||||
progIfaceID := string(lineBytes[2:4])
|
||||
progIfaceName := string(lineBytes[6:])
|
||||
curProgIface = &ProgrammingInterface{
|
||||
ID: progIfaceID,
|
||||
Name: progIfaceName,
|
||||
}
|
||||
progIfaces = append(progIfaces, curProgIface)
|
||||
} else {
|
||||
vendorID := string(lineBytes[2:6])
|
||||
subsystemID := string(lineBytes[7:11])
|
||||
subsystemName := string(lineBytes[13:])
|
||||
curSubsystem = &Product{
|
||||
VendorID: vendorID,
|
||||
ID: subsystemID,
|
||||
Name: subsystemName,
|
||||
}
|
||||
productSubsystems = append(productSubsystems, curSubsystem)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user