diff --git a/Makefile b/Makefile index e260d8b..08330c2 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,10 @@ build: goimports bak: mv -f autogenpb autogenpb.last +redo-protobuf: + rm -f *.pb.go + autogenpb --proto file.proto --package main + install: test GO111MODULE=off go install \ -ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}" diff --git a/example/fruit.proto b/example/fruit.proto index d43a741..65e36f1 100644 --- a/example/fruit.proto +++ b/example/fruit.proto @@ -15,24 +15,24 @@ package main; import "google/protobuf/timestamp.proto"; // Import the well-known type for Timestamp -message Apple { // `autogenpb:marshal` +message Apple { string name = 1; // `autogenpb:unique` // generates SortByxxx() and AppendUnique() functions string genus = 2; // `autogenpb:unique` // generates same thing here but SortByGenus() google.protobuf.Timestamp ctime = 3; // when the apple was born } -message Pear { +message Pear { // `autogenpb:nomutex` string name = 1; // `autogenpb:sort` string favorite = 2; // `autogenpb:sort` `autogenpb:unique` } -message Banana { +message Banana { // `autogenpb:nomutex` repeated string name = 1; // `autogenpb:sort` string favorite = 2; // `autogenpb:sort` `autogenpb:unique` string country = 3; // `autogenpb:sort` } -message Basket { +message Basket { // `autogenpb:nomutex` repeated string name = 1; // `autogenpb:sort` `autogenpb:unique` string favorite = 2; // `autogenpb:sort` `autogenpb:unique` int64 price = 3; // `autogenpb:sort` @@ -42,7 +42,7 @@ message Basket { } // "Fruit" must exist. you can put anything in it -message Fruit { // `autogenpb:marshal` +message Fruit { string brand = 1; // `autogenpb:unique` `autogenpb:sort` repeated Apple apples = 2; repeated Pear pears = 3; diff --git a/file.proto b/file.proto index f2f6887..591e15f 100644 --- a/file.proto +++ b/file.proto @@ -45,6 +45,7 @@ message MsgName { repeated MsgVar vars = 9; // store all the vars in the message bool needIter = 10; // true if the sort iterator has not been generated yet bool needAll = 11; // true if the sort iterator has not been generated yet + bool noMutex = 12; // only use the global mutex } message Sort { diff --git a/generate.go b/generate.go index 43e5092..7e42447 100644 --- a/generate.go +++ b/generate.go @@ -60,7 +60,13 @@ func (pb *Files) makeNewSortfile(pf *File) error { APPLE := s.VarType APPLES := s.VarName LOCK := s.Lockname - funcdef := newIterAll(wSort, FRUIT, APPLE, APPLES, LOCK) + + msg := pf.findMsg(s.VarType) + if msg == nil { + return fmt.Errorf("failed to find struct %s", s.VarType) + } + + funcdef := msg.newIterAll(wSort, FRUIT, APPLE, APPLES, LOCK) log.Printf("JUNK: %-2d %20s %20s %20s %20s %s\n", i, FRUIT, APPLE, "", LOCK, funcdef) } log.Printf("\n") @@ -73,7 +79,12 @@ func (pb *Files) makeNewSortfile(pf *File) error { VARNAME := s.VarName LOCK := s.Lockname - funcdef := addSelectAll(wSort, PARENT, CHILD, VARNAME, LOCK) + msg := pf.findMsg(s.VarType) + if msg == nil { + return fmt.Errorf("failed to find struct %s", s.VarType) + } + + funcdef := msg.addSelectAll(wSort, PARENT, CHILD, VARNAME, LOCK) log.Printf("SORT: %-2d %20s %20s %20s %20s %s\n", i, PARENT, CHILD, VARNAME, LOCK, funcdef) } log.Printf("END SELECT\n") @@ -121,7 +132,7 @@ func (pb *Files) makeNewSortfile(pf *File) error { } sortname := s.VarType + v.VarName selectName := "selectAll" + VARNAME - funcdef := newSortBy(wSort, PARENT, s.VarType, sortname, sortby, selectName) + funcdef := newSortBy(wSort, PARENT, s.VarType, sortname, sortby, selectName, v.VarName) log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcdef) } else { funcname := "func (x *" + FUNCTYPE + ") SortBy" + v.VarName + "(" + v.VarType + ") *[]iter" + s.VarType + " # can not do this yet" diff --git a/generateFind.go b/generateFind.go index 7d8637d..a0fd743 100644 --- a/generateFind.go +++ b/generateFind.go @@ -7,17 +7,6 @@ import ( // generates Find() and some other stuff -func (msg *MsgName) getLockname(s string) string { - // leave this function stubbed in for development of autogenpb - // if argv.Mutex { - // // use the mutex lock from the modified protoc.pb.go file - // return s + ".Lock" - // // return s // causes Marshal() to panic? always use the variable name 'Lock'? - // } - // a single global lock by struct name - return msg.Lockname -} - func (msg *MsgName) generateFindBy(w io.Writer, FUNCNAME, STRUCT, VARNAME, VARTYPE, COLOR string) string { LOCK := msg.getLockname("x") funcdef := "func (x *" + STRUCT + ") " + FUNCNAME + "(s string) *" + VARTYPE diff --git a/generateMutex.go b/generateMutex.go index 45d0d2e..790816b 100644 --- a/generateMutex.go +++ b/generateMutex.go @@ -13,8 +13,19 @@ import ( "go.wit.com/log" ) +func (msg *MsgName) getLockname(s string) string { + // leave this function stubbed in for development of autogenpb + // if argv.Mutex { + // // use the mutex lock from the modified protoc.pb.go file + // return s + ".Lock" + // // return s // causes Marshal() to panic? always use the variable name 'Lock'? + // } + // a single global lock by struct name + return msg.Lockname +} + func (pf *File) syncLock(w io.Writer) { - var LOCK string = pf.Base.Lockname // if the Marshall code changes, this will have to change + var LOCK string = pf.Filebase + "Mu" // this should be lowercase. do not export the Mutex fmt.Fprintln(w, "// a simple global lock") fmt.Fprintln(w, "var "+LOCK+" sync.RWMutex") @@ -110,7 +121,6 @@ func (pf *File) structMatch(line string) bool { start = "type " + msg.Name + " struct {" if strings.HasPrefix(line, start) { msg.MutexFound = true - msg.Lockname = "x.Lock" return true } @@ -120,7 +130,7 @@ func (pf *File) structMatch(line string) bool { start = "type " + msg.Name + " struct {" if strings.HasPrefix(line, start) { msg.MutexFound = true - // msg.Lockname = "x.Lock" + msg.Lockname = "x.Lock" return true } @@ -128,7 +138,11 @@ func (pf *File) structMatch(line string) bool { start = "type " + msg.Name + " struct {" if strings.HasPrefix(line, start) { msg.MutexFound = true - // msg.Lockname = "x.Lock" + if msg.NoMutex { + msg.Lockname = pf.Filebase + "Mu" // this should be lowercase. do not export the Mutex + } else { + msg.Lockname = "x.Lock" + } return true } } diff --git a/generateSort.go b/generateSort.go index b92a4b1..3f14e21 100644 --- a/generateSort.go +++ b/generateSort.go @@ -5,7 +5,9 @@ import ( "io" ) -func newIterAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) string { +func (msg *MsgName) newIterAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) string { + LOCK = msg.getLockname("x") + funcdef := "func (x *" + FRUIT + ") all" + APPLES + "() []*" + APPLE + " {" fmt.Fprintln(w, "// safely returns a slice of pointers to the FRUIT protobufs") @@ -35,7 +37,9 @@ func newIter(w io.Writer, msg *MsgName) string { msg.NeedIter = false APPLE := msg.Name - funcdef := "func New" + APPLE + "Iterator(things []*" + APPLE + ") *" + APPLE + "Iterator" + // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here + // in this file where it is "new or "New". I changed it to lower case 2025.01.12 + funcdef := "func new" + APPLE + "Iterator(things []*" + APPLE + ") *" + APPLE + "Iterator" fmt.Fprintln(w, "// DEFINE THE", APPLE, "ITERATOR.") fmt.Fprintln(w, "// itializes a new iterator.") @@ -76,6 +80,8 @@ func newIter(w io.Writer, msg *MsgName) string { // TODO; figure out what types this actually works on // TODO; add timestamppb compare func newSortType(w io.Writer, STRUCT, VARNAME string) string { + + // Can these be lower case? Should they be lower case? maybe sort.Sort() requires upper case? fmt.Fprintln(w, "// sort struct by", VARNAME) fmt.Fprintln(w, "type "+STRUCT+VARNAME+" []*"+STRUCT+"") fmt.Fprintln(w, "") @@ -87,16 +93,21 @@ func newSortType(w io.Writer, STRUCT, VARNAME string) string { return "type " + STRUCT + VARNAME + " []*" + STRUCT + " // { return a[i]." + VARNAME + " < a[j]." + VARNAME + " }" } -func newSortBy(w io.Writer, STRUCT, ITER, SORTNAME, SORTBY, SELECT string) string { +func newSortBy(w io.Writer, STRUCT, ITER, SORTNAME, SORTBY, SELECT, VARNAME string) string { funcdef := "func (x *" + STRUCT + ") " + SORTBY + "() *" + ITER + "Iterator" fmt.Fprintln(w, funcdef, "{") + fmt.Fprintln(w, " // copy the pointers as fast as possible.") fmt.Fprintln(w, " things := x."+SELECT+"()") fmt.Fprintln(w, "") + fmt.Fprintln(w, "// todo: try slices.SortFunc() instead to see what happens") fmt.Fprintln(w, " sort.Sort("+SORTNAME+"(things))") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " iterator := New"+ITER+"Iterator(things)") - fmt.Fprintln(w, " return iterator") + fmt.Fprintln(w, "// slices.SortFunc(things, func(a, b *"+STRUCT+") bool {") + fmt.Fprintln(w, "// return a."+VARNAME+" < b."+VARNAME+" // Sort by ??. let the compiler work it out??") + fmt.Fprintln(w, "// })") + // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here + // in this file where it is "new or "New". I changed it to lower case 2025.01.12 + fmt.Fprintln(w, " return new"+ITER+"Iterator(things)") fmt.Fprintln(w, "}") return funcdef @@ -108,7 +119,9 @@ func addAllFunc(w io.Writer, FRUIT, APPLE, APPLES string) string { fmt.Fprintln(w, funcdef) fmt.Fprintln(w, " "+APPLE+"Pointers := x.selectAll"+APPLES+"()") fmt.Fprintln(w, "") - fmt.Fprintln(w, " iterator := New"+APPLE+"Iterator("+APPLE+"Pointers)") + // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here. I think there are only 3 places + // in this file where it is "new or "New". I changed it to lower case 2025.01.12 + fmt.Fprintln(w, " iterator := new"+APPLE+"Iterator("+APPLE+"Pointers)") fmt.Fprintln(w, " return iterator") fmt.Fprintln(w, "}") fmt.Fprintln(w, "") @@ -130,7 +143,9 @@ func addLenFunc(w io.Writer, FRUIT, APPLES, LOCK string) string { return funcdef } -func addSelectAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) string { +func (msg *MsgName) addSelectAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) string { + LOCK = msg.getLockname("x") + funcdef := "func (x *" + FRUIT + ") selectAll" + APPLES + "() []*" + APPLE fmt.Fprintln(w, "// safely returns a slice of pointers to the "+APPLE+" protobufs") fmt.Fprintln(w, funcdef, "{") diff --git a/main.go b/main.go index df6d00d..d066507 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ import ( var VERSION string var BUILDTIME string -var fsort *os.File // the sort.pb.go output file +// var fsort *os.File // the sort.pb.go output file func main() { pp := arg.MustParse(&argv) diff --git a/protoParse.go b/protoParse.go index 1e4cf79..8b6a313 100644 --- a/protoParse.go +++ b/protoParse.go @@ -265,6 +265,10 @@ func (pf *File) parseForMessage(line string) *MsgName { msg.DoMutex = true log.Info("Added Mutex=true:", msg.Name) } + if strings.Contains(line, "`autogenpb:nomutex`") { + msg.NoMutex = true + log.Info("Added Mutex=true:", msg.Name) + } if strings.Contains(line, "`autogenpb:marshal`") { msg.DoMarshal = true log.Info("Added Marshal=true:", msg.Name)