Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 105 additions & 4 deletions cpuinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,24 @@ func parseCPUInfoX86(info []byte) ([]CPUInfo, error) {
return cpuinfo, nil
}

func formatSteppingARM(variant, revision string) string {
if variant == "" && revision == "" {
return ""
}
varNum, errV := strconv.ParseUint(variant, 0, 64)
revNum, errR := strconv.ParseUint(revision, 0, 64)
if errV == nil && errR == nil {
return fmt.Sprintf("r%dp%d", varNum, revNum)
}
if errV == nil {
return fmt.Sprintf("r%d", varNum)
}
if errR == nil {
return fmt.Sprintf("p%d", revNum)
}
return fmt.Sprintf("r%sp%s", variant, revision)
}

func parseCPUInfoARM(info []byte) ([]CPUInfo, error) {
scanner := bufio.NewScanner(bytes.NewReader(info))

Expand All @@ -199,6 +217,8 @@ func parseCPUInfoARM(info []byte) ([]CPUInfo, error) {
cpuinfo := []CPUInfo{}
featuresLine := ""
commonCPUInfo := CPUInfo{}
variants := make(map[int]string)
revisions := make(map[int]string)
i := 0
if strings.TrimSpace(field[0]) == "Processor" {
commonCPUInfo = CPUInfo{ModelName: field[1]}
Expand All @@ -212,12 +232,26 @@ func parseCPUInfoARM(info []byte) ([]CPUInfo, error) {
cpuinfo = []CPUInfo{firstcpu}
}

updateStepping := func(idx int) {
v := variants[idx]
r := revisions[idx]
stepping := formatSteppingARM(v, r)
if idx == -1 {
commonCPUInfo.Stepping = stepping
} else {
cpuinfo[idx].Stepping = stepping
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a big fan of this inline function. Is there a cleaner way to handle this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored to eliminate the inline closure completely. Variant and revision values are captured directly during scanning and stepping formatting is resolved in a single post-scanning pass across the parsed entries. Verified clean against unit tests and go vet.


for scanner.Scan() {
line := scanner.Text()
if !strings.Contains(line, ":") {
continue
}
field := strings.SplitN(line, ": ", 2)
if len(field) < 2 {
continue
}
switch strings.TrimSpace(field[0]) {
case "processor":
cpuinfo = append(cpuinfo, commonCPUInfo) // start of the next processor
Expand All @@ -241,12 +275,79 @@ func parseCPUInfoARM(info []byte) ([]CPUInfo, error) {
case "Features":
featuresLine = line
case "model name":
cpuinfo[i].ModelName = field[1]
if i == -1 {
commonCPUInfo.ModelName = field[1]
} else {
cpuinfo[i].ModelName = field[1]
}
case "CPU implementer", "cpu implementer":
val := strings.TrimSpace(field[1])
if i == -1 {
commonCPUInfo.VendorID = val
} else {
cpuinfo[i].VendorID = val
}
case "CPU architecture", "cpu architecture":
val := strings.TrimSpace(field[1])
if i == -1 {
commonCPUInfo.CPUFamily = val
} else {
cpuinfo[i].CPUFamily = val
}
case "CPU part", "cpu part":
val := strings.TrimSpace(field[1])
if i == -1 {
commonCPUInfo.Model = val
} else {
cpuinfo[i].Model = val
}
case "CPU variant", "cpu variant":
val := strings.TrimSpace(field[1])
if i == -1 {
variants[-1] = val
updateStepping(-1)
} else {
variants[i] = val
updateStepping(i)
}
case "CPU revision", "cpu revision":
val := strings.TrimSpace(field[1])
if i == -1 {
revisions[-1] = val
updateStepping(-1)
} else {
revisions[i] = val
updateStepping(i)
}
}
}
fields := strings.SplitN(featuresLine, ": ", 2)
for i := range cpuinfo {
cpuinfo[i].Flags = strings.Fields(fields[1])

if len(cpuinfo) > 0 && cpuinfo[0].VendorID == "" && cpuinfo[len(cpuinfo)-1].VendorID != "" {
last := cpuinfo[len(cpuinfo)-1]
for j := range cpuinfo {
if cpuinfo[j].VendorID == "" {
cpuinfo[j].VendorID = last.VendorID
}
if cpuinfo[j].CPUFamily == "" {
cpuinfo[j].CPUFamily = last.CPUFamily
}
if cpuinfo[j].Model == "" {
cpuinfo[j].Model = last.Model
}
if cpuinfo[j].Stepping == "" {
cpuinfo[j].Stepping = last.Stepping
}
}
}

if featuresLine != "" {
fields := strings.SplitN(featuresLine, ": ", 2)
if len(fields) > 1 {
flags := strings.Fields(fields[1])
for i := range cpuinfo {
cpuinfo[i].Flags = flags
}
}
}
return cpuinfo, nil
}
Expand Down
Loading
Loading