github.com/platinasystems/nvram@v1.0.1-0.20190709235807-51a23abd5aec/layout.go (about)

     1  package nvram
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  )
     7  
     8  type CMOSEnumItem struct {
     9  	id    uint
    10  	value uint
    11  	text  string
    12  }
    13  
    14  func (i CMOSEnumItem) String() string {
    15  	return fmt.Sprintf("%d %d %s", i.id, i.value, i.text)
    16  }
    17  
    18  func (i CMOSEnumItem) Id() uint {
    19  	return i.id
    20  }
    21  
    22  func (i CMOSEnumItem) Value() uint {
    23  	return i.value
    24  }
    25  
    26  func (i CMOSEnumItem) Text() string {
    27  	return i.text
    28  }
    29  
    30  type CMOSEnum struct {
    31  	itos map[uint]string
    32  	stoi map[string]uint
    33  }
    34  
    35  type Layout struct {
    36  	enums        map[uint]*CMOSEnum
    37  	entries      map[string]*CMOSEntry
    38  	entrieslist  []*CMOSEntry
    39  	cmosChecksum *CMOSChecksum
    40  }
    41  
    42  func NewLayout() *Layout {
    43  	c, _ := NewCMOSChecksum(392, 1007, 1008)
    44  	return &Layout{
    45  		enums:        make(map[uint]*CMOSEnum),
    46  		entries:      make(map[string]*CMOSEntry),
    47  		cmosChecksum: c}
    48  }
    49  
    50  func (l *Layout) AddCMOSEntry(entry *CMOSEntry) (err error) {
    51  	// Verify CMOS Entry
    52  	err = verifyCMOSEntry(entry)
    53  	if err != nil {
    54  		return
    55  	}
    56  
    57  	// Add entries to entry list sorted by starting bit.
    58  	var pos int = 0
    59  	for i, e := range l.entrieslist {
    60  		pos = i
    61  		if entry.bit < e.bit {
    62  			break
    63  		}
    64  	}
    65  
    66  	// Check if new entry overlaps current entry in sorted list.
    67  	if len(l.entrieslist) > 0 {
    68  		if pos > 0 {
    69  			if entry.IsOverlap(l.entrieslist[pos-1]) {
    70  				err = fmt.Errorf("Entry %s overlaps %s", *entry, l.entrieslist[pos-1])
    71  				return
    72  			}
    73  		}
    74  
    75  		if entry.IsOverlap(l.entrieslist[pos]) {
    76  			err = fmt.Errorf("Entry %s overlaps %s", *entry, l.entrieslist[pos])
    77  			return
    78  		}
    79  	}
    80  
    81  	// Add new entry to list at correct position
    82  	l.entrieslist = append(l.entrieslist, nil)
    83  	copy(l.entrieslist[pos+1:], l.entrieslist[pos:])
    84  	l.entrieslist[pos] = entry
    85  
    86  	// Add entry to enteries map
    87  	l.entries[entry.name] = entry
    88  	return
    89  }
    90  
    91  func (l *Layout) GetCMOSEntriesList() []*CMOSEntry {
    92  	// Return a copy of the sorted CMOS entry list.
    93  	return l.entrieslist
    94  }
    95  
    96  func (l *Layout) FindCMOSEntry(name string) (entry *CMOSEntry, ok bool) {
    97  	entry, ok = l.entries[name]
    98  	return
    99  }
   100  
   101  func (l *Layout) AddCMOSEnum(item *CMOSEnumItem) {
   102  
   103  	// Create new CMOS Enum for each item's id.
   104  	enum, ok := l.enums[item.id]
   105  	if !ok {
   106  		enum = new(CMOSEnum)
   107  		// Create maps to search by enum name or value.
   108  		enum.itos = make(map[uint]string)
   109  		enum.stoi = make(map[string]uint)
   110  		l.enums[item.id] = enum
   111  	}
   112  
   113  	// Add item text and value to maps
   114  	enum.itos[item.value] = item.text
   115  	enum.stoi[item.text] = item.value
   116  }
   117  
   118  func (l *Layout) FindCMOSEnumText(id uint, value uint) (text string, ok bool) {
   119  	var enum *CMOSEnum
   120  
   121  	// Find CMOS Enum by id
   122  	enum, ok = l.enums[id]
   123  	if !ok {
   124  		return "", false
   125  	}
   126  
   127  	// Find CMOS Enum text from value
   128  	text, ok = enum.itos[value]
   129  	return
   130  }
   131  
   132  func (l *Layout) FindCMOSEnumValue(id uint, text string) (value uint, ok bool) {
   133  	var enum *CMOSEnum
   134  
   135  	// Find CMOS Enum by id
   136  	enum, ok = l.enums[id]
   137  	if !ok {
   138  		return 0, false
   139  	}
   140  
   141  	// Find CMOS Enum value from text.
   142  	value, ok = enum.stoi[text]
   143  	return
   144  }
   145  
   146  func (l *Layout) GetCMOSEnumItemsById(id uint) (items []CMOSEnumItem, ok bool) {
   147  
   148  	// Find CMOS Enum by id
   149  	enum, ok := l.enums[id]
   150  	if !ok {
   151  		return
   152  	}
   153  
   154  	// Create sorted list of Enum values
   155  	var values []int
   156  	for value := range enum.itos {
   157  		values = append(values, int(value))
   158  	}
   159  	sort.Ints(values)
   160  
   161  	// Add CMOS Itmes to list sorted by value
   162  	for _, value := range values {
   163  		var text string
   164  		text, ok = enum.itos[uint(value)]
   165  		if !ok {
   166  			continue
   167  		}
   168  		items = append(items, CMOSEnumItem{uint(id), uint(value), text})
   169  	}
   170  
   171  	return
   172  }
   173  
   174  func (l *Layout) GetCMOSEnumItems() (items []CMOSEnumItem) {
   175  	// Create sorted list of enum ids.	
   176  	var ids []int
   177  	for id := range l.enums {
   178  		ids = append(ids, int(id))
   179  	}
   180  	sort.Ints(ids)
   181  
   182  	// Add all enum items for all ids to list
   183  	for _, id := range ids {
   184  		items_for_id, _ := l.GetCMOSEnumItemsById(uint(id))
   185  		items = append(items, items_for_id...)
   186  	}
   187  
   188  	return
   189  }
   190  
   191  func (l *Layout) GetCheckChecksum() CMOSChecksum {
   192  	return *l.cmosChecksum
   193  }