From 1f9e4a682d3acf36aa7ee1279f1f9cc928bcd5fd Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Sat, 11 Jan 2025 04:03:41 -0600 Subject: rename files --- addMutex.go | 133 --------------------------------------- generate.go | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++ generateFind.go | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++ generateHeader.go | 45 ++++++++++++++ generateMarshal.go | 83 +++++++++++++++++++++++++ generateMutex.go | 133 +++++++++++++++++++++++++++++++++++++++ generateSort.go | 119 +++++++++++++++++++++++++++++++++++ header.go | 45 -------------- marshal.go | 83 ------------------------- sort.go | 166 ------------------------------------------------- sortFunc.go | 119 ----------------------------------- sortNew.go | 169 -------------------------------------------------- 12 files changed, 727 insertions(+), 715 deletions(-) delete mode 100644 addMutex.go create mode 100644 generate.go create mode 100644 generateFind.go create mode 100644 generateHeader.go create mode 100644 generateMarshal.go create mode 100644 generateMutex.go create mode 100644 generateSort.go delete mode 100644 header.go delete mode 100644 marshal.go delete mode 100644 sort.go delete mode 100644 sortFunc.go delete mode 100644 sortNew.go diff --git a/addMutex.go b/addMutex.go deleted file mode 100644 index f9e143e..0000000 --- a/addMutex.go +++ /dev/null @@ -1,133 +0,0 @@ -package main - -// will this help things? -// this is a hack for testing for now -// cram a mutex in the pb.go file - -import ( - "fmt" - "io" - "os" - "strings" - - "go.wit.com/log" -) - -func (pf *File) syncLock(w io.Writer) { - var LOCK string = pf.Base.Lockname // if the Marshall code changes, this will have to change - - fmt.Fprintln(w, "// a simple global lock") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "// this is needed because it seems Marshal() fails if locks are in the structs (?)") - fmt.Fprintln(w, "// this might just be a syntactical runtime error. notsure.") - fmt.Fprintln(w, "// maybe this autogen tool will help someone that actually knows what is going on inside") - fmt.Fprintln(w, "// go/src/google.golang.org/protobuf/proto/proto_methods.go") - fmt.Fprintln(w, "// go/src/google.golang.org/protobuf/proto/encode.go") - fmt.Fprintln(w, "// my guess is that Marshal() needs to be told to ignore sync.RWMutex as it ephemeral and can't be stored") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "var "+LOCK+" sync.RWMutex") - fmt.Fprintln(w, "") -} - -func (pb *Files) addMutex(f *File) error { - fullname := f.Pbfilename - log.Info("pb filename:", fullname) - data, err := os.ReadFile(fullname) - if err != nil { - log.Info("pb filename failed to read:", err) - return err - } - - // check if autogenpb has already looked at this file - for _, line := range strings.Split(string(data), "\n") { - if strings.Contains(line, "autogenpb DO NOT EDIT") { - log.Info("autogenpb has already been run on", fullname) - return nil - } - } - - w, _ := os.OpenFile(f.Pbfilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) - - // the default is to insert a mutex directly into the struct - if argv.Mutex { - pbHeaderComment(w) - } - - lines := strings.Split(string(data), "\n") - for _, line := range lines { - if strings.HasPrefix(line, "package ") { - log.Info("CHANGING package:", line, "to package:", f.Package) - fmt.Fprintln(w, "package "+f.Package) - // log.Info("CHANGING package:", line, "to package:main") - // fmt.Fprintln(w, "package "+"main") - continue - } - // the default is to insert a mutex directly into the struct - if !argv.Mutex { - // mutex is not to be added, only fix the package name - fmt.Fprintln(w, line) - continue - } - - if f.structMatch(line) { - if argv.Mutex { - log.Info("Adding Mutex to:", line) - fmt.Fprintln(w, line) - fmt.Fprintln(w, "\tLock sync.RWMutex // auto-added by go.wit.com/apps/autogenpb") // this must be 'Lock' or Marshal() panics? - // fmt.Fprintln(w, "\t// auto-added by go.wit.com/apps/autogenpb") - // fmt.Fprintln(w, "\tsync.RWMutex") - fmt.Fprintln(w, "") - } else { - log.Info("Skipping. Mutex = false for:", line) - fmt.Fprintln(w, line) - fmt.Fprintln(w, "\t// Lock sync.RWMutex // autogenpb skipped this. needs --mutex command line arg") - fmt.Fprintln(w, "") - } - } else { - fmt.Fprintln(w, line) - } - } - if argv.Mutex { - // verify every structure was found - for _, msg := range f.MsgNames { - if !msg.MutexFound && msg.DoMutex { - return fmt.Errorf("addMutex() parse didn't work for %s", msg.Name) - } - } - } - return nil -} - -// is this struct supposed to have a Mutex added? -func (pf *File) structMatch(line string) bool { - var msg *MsgName - var start string - - msg = pf.Bases - start = "type " + msg.Name + " struct {" - if strings.HasPrefix(line, start) { - msg.MutexFound = true - msg.Lockname = "x.Lock" - return true - } - - // ONLY PASS THIS IF YOU DO NOT WANT TO USE MARSHAL() - - msg = pf.Base - start = "type " + msg.Name + " struct {" - if strings.HasPrefix(line, start) { - msg.MutexFound = true - // msg.Lockname = "x.Lock" - return true - } - - for _, msg = range pf.MsgNames { - start = "type " + msg.Name + " struct {" - if strings.HasPrefix(line, start) { - msg.MutexFound = true - // msg.Lockname = "x.Lock" - return true - } - } - return false -} diff --git a/generate.go b/generate.go new file mode 100644 index 0000000..43a86d4 --- /dev/null +++ b/generate.go @@ -0,0 +1,178 @@ +package main + +import ( + "fmt" + "io" + "os" + + "go.wit.com/log" + "golang.org/x/text/cases" + "golang.org/x/text/language" +) + +// this file is named poorly. It has more than Sort() + +func (pb *Files) makeNewSortfile(pf *File) error { + wSort, _ := os.OpenFile(pf.Filebase+".sort.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + defer wSort.Close() + wFind, _ := os.OpenFile(pf.Filebase+".find.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + defer wFind.Close() + + header(wSort, pf) + + pf.Base.iterTop(wSort) + pf.Base.iterNext(wSort) + pf.selectAllFunc(wSort) + pf.iterSelect(wSort) + + pf.sortByFunc(wSort) + + /* + pf.appendUnique(wFind) // Append() enforce no unique keys + if argv.Delete { + pf.deleteWithCopyFunc(wFind) + } else { + pf.deleteFunc(wFind) + } + pf.findFunc(wFind) + */ + + header(wFind, pf) + pf.syncLock(wFind) + pf.specialBases(wFind) + + // attempt to add sort functions for pf.Base + if err := pf.processMessage(pf.Bases, wSort, wFind); err != nil { + return err + } + if err := pf.processMessage(pf.Base, wSort, wFind); err != nil { + return err + } + return nil +} + +func (pf *File) specialBases(wFind io.Writer) { + var FRUIT string = cases.Title(language.English, cases.NoLower).String(pf.Bases.Name) + var APPLES string = cases.Title(language.English, cases.NoLower).String(pf.Bases.Name) + var APPLE string = cases.Title(language.English, cases.NoLower).String(pf.Base.Name) + + pf.Bases.simpleAppend(wFind, FRUIT, APPLES, APPLE) + +} + +// to simplify being able to read the code, FRUIT, APPLES and APPLE are used +// FRUIT == the string name of the message in the protobuf file +// APPLE == the type of the repeated variable +// APPLES == the variable name of the repeated struct +func (pf *File) processMessage(msg *MsgName, wSort, wFind io.Writer) error { + var FRUIT string = cases.Title(language.English, cases.NoLower).String(msg.Name) + + log.Printf("Generating functions for %s\n", FRUIT) + + for _, v := range msg.Vars { + if !v.IsRepeated { + log.Printf("\tSKIP %s %s\n", v.VarName, v.VarType) + continue + } + log.Printf("\tFOUND REPEATED %s %s\n", v.VarName, v.VarType) + // use easier to read variable names APPLE and APPLES in the code + var APPLE string = v.VarType + var APPLES string = cases.Title(language.English, cases.NoLower).String(v.VarName) + + // try and find the message struct for APPLE + var found *MsgName + if pf.Base.Name == APPLE { + found = pf.Base + } + for _, m := range pf.MsgNames { + if m.Name == APPLE { + found = m + break + } + } + if found == nil { + return fmt.Errorf("failed to find struct %s", APPLE) + } + + log.Printf("FOUND: %s %s for %s\n", APPLES, APPLE, FRUIT) + + found.addFindByMsg(wFind, FRUIT, APPLES, APPLE) + found.addAppendByMsg(wFind, FRUIT, APPLES, APPLE) + found.addDeleteByMsg(wFind, FRUIT, APPLES, APPLE) + found.addInsertByMsg(wFind, FRUIT, APPLES, APPLE) // new idea + + found.addSortByMsg(wSort, FRUIT, APPLES, APPLE) + } + return nil +} + +func (parent *MsgName) addFindByMsg(w io.Writer, FRUIT, APPLES, APPLE string) { + log.Printf("\tINSERT: %s %s for %s\n", APPLES, APPLE, FRUIT) + for _, v := range parent.Vars { + if v.HasUnique { + var COLOR string = cases.Title(language.English, cases.NoLower).String(v.VarName) + log.Printf("\t\t(x %s) InsertBy%s(string) *%s\n", FRUIT, COLOR, APPLE) + parent.findBy(w, FRUIT, APPLES, APPLE, COLOR) + } + } +} + +func (parent *MsgName) addDeleteByMsg(w io.Writer, FRUIT, APPLES, APPLE string) { + log.Printf("\tDELETE: %s %s for %s\n", APPLES, APPLE, FRUIT) + var COLORS []string + for _, v := range parent.Vars { + if !v.HasUnique { + continue + } + var COLOR string = cases.Title(language.English, cases.NoLower).String(v.VarName) + COLORS = append(COLORS, COLOR) + + log.Printf("\t\t(x %s) DeleteBy%s(string) *%s\n", FRUIT, COLOR, APPLE) + if argv.Delete { + parent.deleteByWithCopy(w, FRUIT, APPLES, APPLE, COLOR) + } else { + parent.deleteBy(w, FRUIT, APPLES, APPLE, COLOR) + } + } +} + +func (parent *MsgName) addInsertByMsg(w io.Writer, FRUIT, APPLES, APPLE string) { + log.Printf("\tINSERT: %s %s for %s\n", APPLES, APPLE, FRUIT) + for _, v := range parent.Vars { + if v.HasUnique { + var COLOR string = cases.Title(language.English, cases.NoLower).String(v.VarName) + log.Printf("\t\t(x %s) InsertBy%s(string) *%s\n", FRUIT, COLOR, APPLE) + parent.insertBy(w, FRUIT, APPLES, APPLE, COLOR) + } + } +} + +func (parent *MsgName) addAppendByMsg(w io.Writer, FRUIT, APPLES, APPLE string) { + log.Printf("\tAPPEND!: %s %s for %s\n", APPLES, APPLE, FRUIT) + var COLORS []string + + for _, v := range parent.Vars { + if v.HasUnique { + var COLOR string = cases.Title(language.English, cases.NoLower).String(v.VarName) + COLORS = append(COLORS, COLOR) + + log.Printf("\t\t(x %s) AppendUniqueBy%s(%s)\n", FRUIT, COLOR, APPLE) + parent.appendUniqueBy(w, FRUIT, APPLES, APPLE, COLOR) + } + } + if len(COLORS) > 0 { + parent.appendUnique(w, FRUIT, APPLES, APPLE, COLORS) + } +} + +func (parent *MsgName) addSortByMsg(w io.Writer, FRUIT, APPLES, APPLE string) { + log.Printf("\tSORT!: %s %s for %s\n", APPLES, APPLE, FRUIT) + + for _, v := range parent.Vars { + if v.HasSort { + // log.Printf("\tSort!: %s %s for %s\n", APPLES, APPLE, v.VarName) + newS := cases.Title(language.English, cases.NoLower).String(v.VarName) + log.Printf("\t\t(x %s) SortdBy%s() *%sIter\n", FRUIT, newS, APPLE) + } + } +} diff --git a/generateFind.go b/generateFind.go new file mode 100644 index 0000000..c731fec --- /dev/null +++ b/generateFind.go @@ -0,0 +1,169 @@ +package main + +import ( + "fmt" + "io" + + "go.wit.com/log" +) + +// generates Find() + +// but really it has Append(), Delete() 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) findBy(w io.Writer, FRUIT, APPLES, APPLE, COLOR string) { + LOCK := msg.getLockname("x") + + fmt.Fprintln(w, "// find a dependancy by the go path") + fmt.Fprintln(w, "func (x *"+FRUIT+") FindBy"+COLOR+"(s string) *"+APPLE+" {") + fmt.Fprintln(w, " if x == nil {") + fmt.Fprintln(w, " return nil") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " "+LOCK+".RLock()") + fmt.Fprintln(w, " defer "+LOCK+".RUnlock()") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " for i, _ := range x."+APPLES+" {") + fmt.Fprintln(w, " if x."+APPLES+"[i]."+COLOR+" == s {") + fmt.Fprintln(w, " return x."+APPLES+"[i]") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, " return nil") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") +} + +// I like these functions the best. +func (msg *MsgName) simpleAppend(w io.Writer, FRUIT, APPLES, APPLE string) { + LOCK := msg.getLockname("x") + + log.Printf("\t\t(x %s) APPEND(%s)\n", FRUIT, APPLE) + // append -- no check at all + fmt.Fprintln(w, "// just a simple Append() shortcut (but still uses the mutex lock)") + fmt.Fprintln(w, "func (x *"+FRUIT+") Append(y *"+APPLE+") {") + fmt.Fprintln(w, " "+LOCK+".Lock()") + fmt.Fprintln(w, " defer "+LOCK+".Unlock()") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " x."+APPLES+" = append(x."+APPLES+", y)") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") +} + +func (msg *MsgName) appendUnique(w io.Writer, FRUIT, APPLES, APPLE string, COLORS []string) { + LOCK := msg.getLockname("x") + + fmt.Fprintln(w, "// enforces "+APPLE+" is unique in "+FRUIT+"."+APPLES) + fmt.Fprintln(w, "func (x *"+FRUIT+") AppendUnique(newP *"+APPLE+") bool {") + fmt.Fprintln(w, " "+LOCK+".Lock()") + fmt.Fprintln(w, " defer "+LOCK+".Unlock()") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " for _, p := range x."+APPLES+" {") + for _, COLOR := range COLORS { + fmt.Fprintln(w, " if p."+COLOR+" == newP."+COLOR+" {") + fmt.Fprintln(w, " return false") + fmt.Fprintln(w, " }") + } + fmt.Fprintln(w, " }") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " x."+APPLES+" = append(x."+APPLES+", newP)") + fmt.Fprintln(w, " return true") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") +} + +func (msg *MsgName) appendUniqueBy(w io.Writer, FRUIT, APPLES, APPLE, COLOR string) { + LOCK := msg.getLockname("x") + + fmt.Fprintln(w, "// enforces "+APPLE+"."+COLOR+" is unique in "+FRUIT+"."+APPLES) + fmt.Fprintln(w, "func (x *"+FRUIT+") AppendUniqueBy"+COLOR+"(newP *"+APPLE+") bool {") + fmt.Fprintln(w, " "+LOCK+".Lock()") + fmt.Fprintln(w, " defer "+LOCK+".Unlock()") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " for _, p := range x."+APPLES+" {") + fmt.Fprintln(w, " if p."+COLOR+" == newP."+COLOR+" {") + fmt.Fprintln(w, " return false") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " x."+APPLES+" = append(x."+APPLES+", newP)") + fmt.Fprintln(w, " return true") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") +} + +func (msg *MsgName) deleteBy(w io.Writer, FRUIT, APPLES, APPLE, COLOR string) { + LOCK := msg.getLockname("x") + + fmt.Fprintln(w, "func (x *"+FRUIT+") DeleteBy"+COLOR+"(s string) bool {") + fmt.Fprintln(w, " "+LOCK+".Lock()") + fmt.Fprintln(w, " defer "+LOCK+".Unlock()") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " for i, _ := range x."+APPLES+" {") + fmt.Fprintln(w, " if x."+APPLES+"[i]."+COLOR+" == s {") + fmt.Fprintln(w, " x."+APPLES+"[i] = x."+APPLES+"[len(x."+APPLES+")-1]") + fmt.Fprintln(w, " x."+APPLES+" = x."+APPLES+"[:len(x."+APPLES+")-1]") + fmt.Fprintln(w, " return true") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, " return false") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") +} + +// this tries to return the deleted one but is wrong/gives warning if mutex lock is in struct +func (msg *MsgName) deleteByWithCopy(w io.Writer, FRUIT, APPLES, APPLE, COLOR string) { + LOCK := msg.getLockname("x") + + fmt.Fprintln(w, "// TESTING fails with 'go vet' warning") + fmt.Fprintln(w, "func (x *"+FRUIT+") DeleteBy"+COLOR+"(s string) *"+APPLE+" {") + fmt.Fprintln(w, " "+LOCK+".Lock()") + fmt.Fprintln(w, " defer "+LOCK+".Unlock()") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " var newr "+APPLE) + fmt.Fprintln(w, "") + fmt.Fprintln(w, " for i, _ := range x."+APPLES+" {") + fmt.Fprintln(w, " if x."+APPLES+"[i]."+COLOR+" == s {") + fmt.Fprintln(w, " newr = *x."+APPLES+"[i]") + fmt.Fprintln(w, " x."+APPLES+"[i] = x."+APPLES+"[len(x."+APPLES+")-1]") + fmt.Fprintln(w, " x."+APPLES+" = x."+APPLES+"[:len(x."+APPLES+")-1]") + fmt.Fprintln(w, " return &newr") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, " return nil") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") +} + +func (msg *MsgName) insertBy(w io.Writer, FRUIT, APPLES, APPLE string, COLOR string) { + LOCK := msg.getLockname("x") + + fmt.Fprintln(w, "// useful? remindme:1y") + fmt.Fprintln(w, "// returns an "+APPLE+" if "+COLOR+" matches, otherwise create") + fmt.Fprintln(w, "func (x *"+FRUIT+") InsertBy"+COLOR+" (y string) *"+APPLE+" {") + fmt.Fprintln(w, " "+LOCK+".Lock()") + fmt.Fprintln(w, " defer "+LOCK+".Unlock()") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " for _, p := range x."+APPLES+" {") + fmt.Fprintln(w, " if p."+COLOR+" == y {") + fmt.Fprintln(w, " return p") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " z := new("+APPLE+")") + fmt.Fprintln(w, " z."+COLOR+" = y") + fmt.Fprintln(w, " x."+APPLES+" = append(x."+APPLES+", z)") + fmt.Fprintln(w, " return z") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") +} diff --git a/generateHeader.go b/generateHeader.go new file mode 100644 index 0000000..8d5fbfb --- /dev/null +++ b/generateHeader.go @@ -0,0 +1,45 @@ +package main + +import ( + "fmt" + "io" +) + +func pbHeaderComment(w io.Writer) { + // technically this should be the first line and in this exact format: + fmt.Fprintln(w, "// Code modified by go.wit.com/apps/autogenpb DO NOT EDIT.") + fmt.Fprintln(w, "//") + fmt.Fprintln(w, "// user defined Mutex locks were auto added") + fmt.Fprintln(w, "//") + fmt.Fprintln(w, "// autogenpb version & build time:", VERSION, BUILDTIME) + fmt.Fprintln(w, "// autogenpb auto generates Sort(), Unique() and Marshal() functions") + fmt.Fprintln(w, "// go install go.wit.com/apps/autogenpb@latest") + fmt.Fprintln(w, "") +} + +func headerComment(w io.Writer) { + // technically this should be the first line and in this exact format: + fmt.Fprintln(w, "// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT.") + fmt.Fprintln(w, "// This file was autogenerated with autogenpb", VERSION, BUILDTIME) + fmt.Fprintln(w, "// go install go.wit.com/apps/autogenpb@latest") + fmt.Fprintln(w, "//") + fmt.Fprintln(w, "// define which structs (messages) you want to use in the .proto file") + fmt.Fprintln(w, "// Then sort.pb.go and marshal.pb.go files are autogenerated") + fmt.Fprintln(w, "//") + fmt.Fprintln(w, "// autogenpb uses it and has an example .proto file with instructions") + fmt.Fprintln(w, "//") + fmt.Fprintln(w, "") +} + +func header(w io.Writer, pf *File) { + // header must come first + headerComment(w) + fmt.Fprintf(w, "package %s\n", pf.Package) + fmt.Fprintln(w, "") + fmt.Fprintln(w, "import (") + fmt.Fprintln(w, " \"fmt\"") + fmt.Fprintln(w, " \"sort\"") + fmt.Fprintln(w, " \"sync\"") + fmt.Fprintln(w, ")") + fmt.Fprintln(w, "") +} diff --git a/generateMarshal.go b/generateMarshal.go new file mode 100644 index 0000000..9cb1a4e --- /dev/null +++ b/generateMarshal.go @@ -0,0 +1,83 @@ +package main + +import ( + "fmt" + "io" + "os" + + "go.wit.com/log" +) + +// makes Marshal and Unmarshal functions for protoWIRE protoTEXT and protoJSON +func (pb *Files) marshal(f *File) { + if argv.DryRun { + return + } + + w, _ := os.OpenFile(f.Filebase+".marshal.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + + headerComment(w) + fmt.Fprintf(w, "package %s\n", f.Package) + fmt.Fprintln(w, "import (") + fmt.Fprintln(w, " \"google.golang.org/protobuf/encoding/protojson\"") + fmt.Fprintln(w, " \"google.golang.org/protobuf/encoding/prototext\"") + fmt.Fprintln(w, " \"google.golang.org/protobuf/proto\"") + fmt.Fprintln(w, ")") + fmt.Fprintln(w, "") + + if f.Bases.DoMarshal { + marshalThing(w, f.Bases.Name) + } + + if f.Base.DoMarshal { + marshalThing(w, f.Base.Name) + } + + for _, msg := range f.MsgNames { + if msg.DoMarshal { + marshalThing(w, msg.Name) + } else { + log.Info("Skipping. DoMarshal = false for", msg.Name) + } + } +} + +func marshalThing(w io.Writer, thing string) { + fmt.Fprintln(w, "// human readable JSON") + fmt.Fprintln(w, "func (v *"+thing+") FormatJSON() string {") + fmt.Fprintln(w, " return protojson.Format(v)") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "// marshal json") + fmt.Fprintln(w, "func (v *"+thing+") MarshalJSON() ([]byte, error) {") + fmt.Fprintln(w, " return protojson.Marshal(v)") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "// unmarshal json") + fmt.Fprintln(w, "func (v *"+thing+") UnmarshalJSON(data []byte) error {") + fmt.Fprintln(w, " return protojson.Unmarshal(data, v)") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "// apparently this isn't stable, but it's awesomely better") + fmt.Fprintln(w, "// https://protobuf.dev/reference/go/faq/#unstable-text") + fmt.Fprintln(w, "// it's brilliant for config files!") + fmt.Fprintln(w, "func (v *"+thing+") FormatTEXT() string {") + fmt.Fprintln(w, " return prototext.Format(v)") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "// unmarshalTEXT. This reads the .text config file back in after the user edits it") + fmt.Fprintln(w, "func (v *"+thing+") UnmarshalTEXT(data []byte) error {") + fmt.Fprintln(w, " return prototext.Unmarshal(data, v)") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "// marshal to wire. This is called winning.") + fmt.Fprintln(w, "func (v *"+thing+") Marshal() ([]byte, error) {") + fmt.Fprintln(w, " return proto.Marshal(v)") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "// unmarshal from wire. You have won.") + fmt.Fprintln(w, "func (v *"+thing+") Unmarshal(data []byte) error {") + fmt.Fprintln(w, " return proto.Unmarshal(data, v)") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") +} diff --git a/generateMutex.go b/generateMutex.go new file mode 100644 index 0000000..f9e143e --- /dev/null +++ b/generateMutex.go @@ -0,0 +1,133 @@ +package main + +// will this help things? +// this is a hack for testing for now +// cram a mutex in the pb.go file + +import ( + "fmt" + "io" + "os" + "strings" + + "go.wit.com/log" +) + +func (pf *File) syncLock(w io.Writer) { + var LOCK string = pf.Base.Lockname // if the Marshall code changes, this will have to change + + fmt.Fprintln(w, "// a simple global lock") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "// this is needed because it seems Marshal() fails if locks are in the structs (?)") + fmt.Fprintln(w, "// this might just be a syntactical runtime error. notsure.") + fmt.Fprintln(w, "// maybe this autogen tool will help someone that actually knows what is going on inside") + fmt.Fprintln(w, "// go/src/google.golang.org/protobuf/proto/proto_methods.go") + fmt.Fprintln(w, "// go/src/google.golang.org/protobuf/proto/encode.go") + fmt.Fprintln(w, "// my guess is that Marshal() needs to be told to ignore sync.RWMutex as it ephemeral and can't be stored") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "var "+LOCK+" sync.RWMutex") + fmt.Fprintln(w, "") +} + +func (pb *Files) addMutex(f *File) error { + fullname := f.Pbfilename + log.Info("pb filename:", fullname) + data, err := os.ReadFile(fullname) + if err != nil { + log.Info("pb filename failed to read:", err) + return err + } + + // check if autogenpb has already looked at this file + for _, line := range strings.Split(string(data), "\n") { + if strings.Contains(line, "autogenpb DO NOT EDIT") { + log.Info("autogenpb has already been run on", fullname) + return nil + } + } + + w, _ := os.OpenFile(f.Pbfilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + + // the default is to insert a mutex directly into the struct + if argv.Mutex { + pbHeaderComment(w) + } + + lines := strings.Split(string(data), "\n") + for _, line := range lines { + if strings.HasPrefix(line, "package ") { + log.Info("CHANGING package:", line, "to package:", f.Package) + fmt.Fprintln(w, "package "+f.Package) + // log.Info("CHANGING package:", line, "to package:main") + // fmt.Fprintln(w, "package "+"main") + continue + } + // the default is to insert a mutex directly into the struct + if !argv.Mutex { + // mutex is not to be added, only fix the package name + fmt.Fprintln(w, line) + continue + } + + if f.structMatch(line) { + if argv.Mutex { + log.Info("Adding Mutex to:", line) + fmt.Fprintln(w, line) + fmt.Fprintln(w, "\tLock sync.RWMutex // auto-added by go.wit.com/apps/autogenpb") // this must be 'Lock' or Marshal() panics? + // fmt.Fprintln(w, "\t// auto-added by go.wit.com/apps/autogenpb") + // fmt.Fprintln(w, "\tsync.RWMutex") + fmt.Fprintln(w, "") + } else { + log.Info("Skipping. Mutex = false for:", line) + fmt.Fprintln(w, line) + fmt.Fprintln(w, "\t// Lock sync.RWMutex // autogenpb skipped this. needs --mutex command line arg") + fmt.Fprintln(w, "") + } + } else { + fmt.Fprintln(w, line) + } + } + if argv.Mutex { + // verify every structure was found + for _, msg := range f.MsgNames { + if !msg.MutexFound && msg.DoMutex { + return fmt.Errorf("addMutex() parse didn't work for %s", msg.Name) + } + } + } + return nil +} + +// is this struct supposed to have a Mutex added? +func (pf *File) structMatch(line string) bool { + var msg *MsgName + var start string + + msg = pf.Bases + start = "type " + msg.Name + " struct {" + if strings.HasPrefix(line, start) { + msg.MutexFound = true + msg.Lockname = "x.Lock" + return true + } + + // ONLY PASS THIS IF YOU DO NOT WANT TO USE MARSHAL() + + msg = pf.Base + start = "type " + msg.Name + " struct {" + if strings.HasPrefix(line, start) { + msg.MutexFound = true + // msg.Lockname = "x.Lock" + return true + } + + for _, msg = range pf.MsgNames { + start = "type " + msg.Name + " struct {" + if strings.HasPrefix(line, start) { + msg.MutexFound = true + // msg.Lockname = "x.Lock" + return true + } + } + return false +} diff --git a/generateSort.go b/generateSort.go new file mode 100644 index 0000000..e5cfa20 --- /dev/null +++ b/generateSort.go @@ -0,0 +1,119 @@ +package main + +import ( + "fmt" + "io" +) + +func (msg *MsgName) iterTop(w io.Writer) { + var BASE string = msg.Name + + fmt.Fprintln(w, "type "+BASE+"Iterator struct {") + fmt.Fprintln(w, " sync.RWMutex") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " things []*"+BASE) + fmt.Fprintln(w, " index int") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "// New"+BASE+"Iterator initializes a new iterator.") + fmt.Fprintln(w, "func New"+BASE+"Iterator(things []*"+BASE+") *"+BASE+"Iterator {") + fmt.Fprintln(w, " return &"+BASE+"Iterator{things: things}") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "// Scan moves to the next element and returns false if there are no more things.") + fmt.Fprintln(w, "// Use Scan() in a loop, similar to a while loop") + fmt.Fprintln(w, "//") + fmt.Fprintln(w, "// for iterator.Scan() ") + fmt.Fprintln(w, "// d := iterator.Next(") + fmt.Fprintln(w, "// fmt.Println(\"found UUID:\", d.Uuid") + fmt.Fprintln(w, "// }") + fmt.Fprintln(w, "func (it *"+BASE+"Iterator) Scan() bool {") + fmt.Fprintln(w, " if it.index >= len(it.things) {") + fmt.Fprintln(w, " return false") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, " it.index++") + fmt.Fprintln(w, " return true") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") +} + +func (msg *MsgName) iterNext(w io.Writer) { + var BASE string = msg.Name + + fmt.Fprintln(w, "// Next() returns the next thing in the array") + fmt.Fprintln(w, "func (it *"+BASE+"Iterator) Next() *"+BASE+" {") + fmt.Fprintln(w, " if it.things[it.index-1] == nil {") + fmt.Fprintln(w, " for i, d := range it.things {") + fmt.Fprintln(w, " fmt.Println(\"i =\", i, d)") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, " return it.things[it.index-1]") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") +} + +func (pf *File) selectAllFunc(w io.Writer) { + var BASES string = pf.Bases.Name + var BASE string = pf.Base.Name + var LOCK string = pf.Bases.Lockname + + fmt.Fprintln(w, "func (x *"+BASES+") All() *"+BASE+"Iterator {") + fmt.Fprintln(w, " "+BASE+"Pointers := x.selectAll"+BASE+"()") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " iterator := New"+BASE+"Iterator("+BASE+"Pointers)") + fmt.Fprintln(w, " return iterator") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "func (x *"+BASES+") Len() int {") + fmt.Fprintln(w, " "+LOCK+".RLock()") + fmt.Fprintln(w, " defer "+LOCK+".RUnlock()") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " return len(x."+BASES+")") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") +} + +func (pf *File) sortByFunc(w io.Writer) { + var BASES string = pf.Bases.Name + var BASE string = pf.Base.Name + + for _, SORT := range pf.Base.Sort { + fmt.Fprintln(w, "func (x *"+BASES+") SortBy"+SORT+"() *"+BASE+"Iterator {") + fmt.Fprintln(w, " things := x.selectAll"+BASE+"()") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " sort.Sort("+BASE+""+SORT+"(things))") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " iterator := New"+BASE+"Iterator(things)") + fmt.Fprintln(w, " return iterator") + fmt.Fprintln(w, "}") + fmt.Fprintln(w, "") + + fmt.Fprintln(w, "type "+BASE+""+SORT+" []*"+BASE+"") + fmt.Fprintln(w, "") + fmt.Fprintln(w, "func (a "+BASE+""+SORT+") Len() int { return len(a) }") + fmt.Fprintln(w, "func (a "+BASE+""+SORT+") Less(i, j int) bool { return a[i]."+SORT+" < a[j]."+SORT+" }") + fmt.Fprintln(w, "func (a "+BASE+""+SORT+") Swap(i, j int) { a[i], a[j] = a[j], a[i] }") + fmt.Fprintln(w, "") + } +} + +func (pf *File) iterSelect(w io.Writer) { + var BASES string = pf.Bases.Name + var BASE string = pf.Base.Name + var LOCK string = pf.Bases.Lockname + + fmt.Fprintln(w, "// safely returns a slice of pointers to the "+BASE+" protobufs") + fmt.Fprintln(w, "func (x *"+BASES+") selectAll"+BASE+"() []*"+BASE+" {") + fmt.Fprintln(w, " "+LOCK+".RLock()") + fmt.Fprintln(w, " defer "+LOCK+".RUnlock()") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " // Create a new slice to hold pointers to each "+BASE+"") + fmt.Fprintln(w, " var tmp []*"+BASE+"") + fmt.Fprintln(w, " tmp = make([]*"+BASE+", len(x."+BASES+"))") + fmt.Fprintln(w, " for i, p := range x."+BASES+" {") + fmt.Fprintln(w, " tmp[i] = p // Copy pointers for safe iteration") + fmt.Fprintln(w, " }") + fmt.Fprintln(w, "") + fmt.Fprintln(w, " return tmp") + fmt.Fprintln(w, "}") +} diff --git a/header.go b/header.go deleted file mode 100644 index 8d5fbfb..0000000 --- a/header.go +++ /dev/null @@ -1,45 +0,0 @@ -package main - -import ( - "fmt" - "io" -) - -func pbHeaderComment(w io.Writer) { - // technically this should be the first line and in this exact format: - fmt.Fprintln(w, "// Code modified by go.wit.com/apps/autogenpb DO NOT EDIT.") - fmt.Fprintln(w, "//") - fmt.Fprintln(w, "// user defined Mutex locks were auto added") - fmt.Fprintln(w, "//") - fmt.Fprintln(w, "// autogenpb version & build time:", VERSION, BUILDTIME) - fmt.Fprintln(w, "// autogenpb auto generates Sort(), Unique() and Marshal() functions") - fmt.Fprintln(w, "// go install go.wit.com/apps/autogenpb@latest") - fmt.Fprintln(w, "") -} - -func headerComment(w io.Writer) { - // technically this should be the first line and in this exact format: - fmt.Fprintln(w, "// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT.") - fmt.Fprintln(w, "// This file was autogenerated with autogenpb", VERSION, BUILDTIME) - fmt.Fprintln(w, "// go install go.wit.com/apps/autogenpb@latest") - fmt.Fprintln(w, "//") - fmt.Fprintln(w, "// define which structs (messages) you want to use in the .proto file") - fmt.Fprintln(w, "// Then sort.pb.go and marshal.pb.go files are autogenerated") - fmt.Fprintln(w, "//") - fmt.Fprintln(w, "// autogenpb uses it and has an example .proto file with instructions") - fmt.Fprintln(w, "//") - fmt.Fprintln(w, "") -} - -func header(w io.Writer, pf *File) { - // header must come first - headerComment(w) - fmt.Fprintf(w, "package %s\n", pf.Package) - fmt.Fprintln(w, "") - fmt.Fprintln(w, "import (") - fmt.Fprintln(w, " \"fmt\"") - fmt.Fprintln(w, " \"sort\"") - fmt.Fprintln(w, " \"sync\"") - fmt.Fprintln(w, ")") - fmt.Fprintln(w, "") -} diff --git a/marshal.go b/marshal.go deleted file mode 100644 index 9cb1a4e..0000000 --- a/marshal.go +++ /dev/null @@ -1,83 +0,0 @@ -package main - -import ( - "fmt" - "io" - "os" - - "go.wit.com/log" -) - -// makes Marshal and Unmarshal functions for protoWIRE protoTEXT and protoJSON -func (pb *Files) marshal(f *File) { - if argv.DryRun { - return - } - - w, _ := os.OpenFile(f.Filebase+".marshal.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) - - headerComment(w) - fmt.Fprintf(w, "package %s\n", f.Package) - fmt.Fprintln(w, "import (") - fmt.Fprintln(w, " \"google.golang.org/protobuf/encoding/protojson\"") - fmt.Fprintln(w, " \"google.golang.org/protobuf/encoding/prototext\"") - fmt.Fprintln(w, " \"google.golang.org/protobuf/proto\"") - fmt.Fprintln(w, ")") - fmt.Fprintln(w, "") - - if f.Bases.DoMarshal { - marshalThing(w, f.Bases.Name) - } - - if f.Base.DoMarshal { - marshalThing(w, f.Base.Name) - } - - for _, msg := range f.MsgNames { - if msg.DoMarshal { - marshalThing(w, msg.Name) - } else { - log.Info("Skipping. DoMarshal = false for", msg.Name) - } - } -} - -func marshalThing(w io.Writer, thing string) { - fmt.Fprintln(w, "// human readable JSON") - fmt.Fprintln(w, "func (v *"+thing+") FormatJSON() string {") - fmt.Fprintln(w, " return protojson.Format(v)") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "// marshal json") - fmt.Fprintln(w, "func (v *"+thing+") MarshalJSON() ([]byte, error) {") - fmt.Fprintln(w, " return protojson.Marshal(v)") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "// unmarshal json") - fmt.Fprintln(w, "func (v *"+thing+") UnmarshalJSON(data []byte) error {") - fmt.Fprintln(w, " return protojson.Unmarshal(data, v)") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "// apparently this isn't stable, but it's awesomely better") - fmt.Fprintln(w, "// https://protobuf.dev/reference/go/faq/#unstable-text") - fmt.Fprintln(w, "// it's brilliant for config files!") - fmt.Fprintln(w, "func (v *"+thing+") FormatTEXT() string {") - fmt.Fprintln(w, " return prototext.Format(v)") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "// unmarshalTEXT. This reads the .text config file back in after the user edits it") - fmt.Fprintln(w, "func (v *"+thing+") UnmarshalTEXT(data []byte) error {") - fmt.Fprintln(w, " return prototext.Unmarshal(data, v)") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "// marshal to wire. This is called winning.") - fmt.Fprintln(w, "func (v *"+thing+") Marshal() ([]byte, error) {") - fmt.Fprintln(w, " return proto.Marshal(v)") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "// unmarshal from wire. You have won.") - fmt.Fprintln(w, "func (v *"+thing+") Unmarshal(data []byte) error {") - fmt.Fprintln(w, " return proto.Unmarshal(data, v)") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") -} diff --git a/sort.go b/sort.go deleted file mode 100644 index 90e7f5a..0000000 --- a/sort.go +++ /dev/null @@ -1,166 +0,0 @@ -package main - -import ( - "fmt" - "io" - "os" - - "go.wit.com/log" - "golang.org/x/text/cases" - "golang.org/x/text/language" -) - -// this file is named poorly. It has more than Sort() - -func (pb *Files) makeNewSortfile(pf *File) error { - wSort, _ := os.OpenFile(pf.Filebase+".sort.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) - defer wSort.Close() - wFind, _ := os.OpenFile(pf.Filebase+".find.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) - defer wFind.Close() - - header(wSort, pf) - - pf.Base.iterTop(wSort) - pf.Base.iterNext(wSort) - pf.selectAllFunc(wSort) - pf.iterSelect(wSort) - - pf.sortByFunc(wSort) - - /* - pf.appendUnique(wFind) // Append() enforce no unique keys - if argv.Delete { - pf.deleteWithCopyFunc(wFind) - } else { - pf.deleteFunc(wFind) - } - pf.findFunc(wFind) - */ - - header(wFind, pf) - pf.syncLock(wFind) - pf.specialBases(wFind) - - // attempt to add sort functions for pf.Base - if err := pf.processMessage(pf.Bases, wSort, wFind); err != nil { - return err - } - if err := pf.processMessage(pf.Base, wSort, wFind); err != nil { - return err - } - return nil -} - -func (pf *File) specialBases(wFind io.Writer) { - var FRUIT string = cases.Title(language.English, cases.NoLower).String(pf.Bases.Name) - var APPLES string = cases.Title(language.English, cases.NoLower).String(pf.Bases.Name) - var APPLE string = cases.Title(language.English, cases.NoLower).String(pf.Base.Name) - - pf.Bases.simpleAppend(wFind, FRUIT, APPLES, APPLE) - -} - -// to simplify being able to read the code, FRUIT, APPLES and APPLE are used -// FRUIT == the string name of the message in the protobuf file -// APPLE == the type of the repeated variable -// APPLES == the variable name of the repeated struct -func (pf *File) processMessage(msg *MsgName, wSort, wFind io.Writer) error { - var FRUIT string = cases.Title(language.English, cases.NoLower).String(msg.Name) - - log.Printf("Generating functions for %s\n", FRUIT) - - for _, v := range msg.Vars { - if !v.IsRepeated { - log.Printf("\tSKIP %s %s\n", v.VarName, v.VarType) - continue - } - log.Printf("\tFOUND REPEATED %s %s\n", v.VarName, v.VarType) - // use easier to read variable names APPLE and APPLES in the code - var APPLE string = v.VarType - var APPLES string = cases.Title(language.English, cases.NoLower).String(v.VarName) - - // try and find the message struct for APPLE - var found *MsgName - if pf.Base.Name == APPLE { - found = pf.Base - } - for _, m := range pf.MsgNames { - if m.Name == APPLE { - found = m - break - } - } - if found == nil { - return fmt.Errorf("failed to find struct %s", APPLE) - } - - log.Printf("FOUND: %s %s for %s\n", APPLES, APPLE, FRUIT) - - found.addAppendByMsg(wFind, FRUIT, APPLES, APPLE) - found.addDeleteByMsg(wFind, FRUIT, APPLES, APPLE) - found.addInsertByMsg(wFind, FRUIT, APPLES, APPLE) // new idea - - found.addSortByMsg(wSort, FRUIT, APPLES, APPLE) - } - return nil -} - -func (parent *MsgName) addDeleteByMsg(w io.Writer, FRUIT, APPLES, APPLE string) { - log.Printf("\tDELETE: %s %s for %s\n", APPLES, APPLE, FRUIT) - var COLORS []string - for _, v := range parent.Vars { - if !v.HasUnique { - continue - } - var COLOR string = cases.Title(language.English, cases.NoLower).String(v.VarName) - COLORS = append(COLORS, COLOR) - - log.Printf("\t\t(x %s) DeleteBy%s(string) *%s\n", FRUIT, COLOR, APPLE) - if argv.Delete { - parent.deleteByWithCopy(w, FRUIT, APPLES, APPLE, COLOR) - } else { - parent.deleteBy(w, FRUIT, APPLES, APPLE, COLOR) - } - } -} - -func (parent *MsgName) addInsertByMsg(w io.Writer, FRUIT, APPLES, APPLE string) { - log.Printf("\tINSERT: %s %s for %s\n", APPLES, APPLE, FRUIT) - for _, v := range parent.Vars { - if v.HasUnique { - var COLOR string = cases.Title(language.English, cases.NoLower).String(v.VarName) - log.Printf("\t\t(x %s) InsertBy%s(string) *%s\n", FRUIT, COLOR, APPLE) - parent.insertByColor(w, FRUIT, APPLES, APPLE, COLOR) - } - } -} - -func (parent *MsgName) addAppendByMsg(w io.Writer, FRUIT, APPLES, APPLE string) { - log.Printf("\tAPPEND!: %s %s for %s\n", APPLES, APPLE, FRUIT) - var COLORS []string - - for _, v := range parent.Vars { - if v.HasUnique { - var COLOR string = cases.Title(language.English, cases.NoLower).String(v.VarName) - COLORS = append(COLORS, COLOR) - - log.Printf("\t\t(x %s) AppendUniqueBy%s(%s)\n", FRUIT, COLOR, APPLE) - parent.appendUniqueBy(w, FRUIT, APPLES, APPLE, COLOR) - } - } - if len(COLORS) > 0 { - parent.appendUnique(w, FRUIT, APPLES, APPLE, COLORS) - } -} - -func (parent *MsgName) addSortByMsg(w io.Writer, FRUIT, APPLES, APPLE string) { - log.Printf("\tSORT!: %s %s for %s\n", APPLES, APPLE, FRUIT) - - for _, v := range parent.Vars { - if v.HasSort { - // log.Printf("\tSort!: %s %s for %s\n", APPLES, APPLE, v.VarName) - newS := cases.Title(language.English, cases.NoLower).String(v.VarName) - log.Printf("\t\t(x %s) SortdBy%s() *%sIter\n", FRUIT, newS, APPLE) - } - } -} diff --git a/sortFunc.go b/sortFunc.go deleted file mode 100644 index e5cfa20..0000000 --- a/sortFunc.go +++ /dev/null @@ -1,119 +0,0 @@ -package main - -import ( - "fmt" - "io" -) - -func (msg *MsgName) iterTop(w io.Writer) { - var BASE string = msg.Name - - fmt.Fprintln(w, "type "+BASE+"Iterator struct {") - fmt.Fprintln(w, " sync.RWMutex") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " things []*"+BASE) - fmt.Fprintln(w, " index int") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "// New"+BASE+"Iterator initializes a new iterator.") - fmt.Fprintln(w, "func New"+BASE+"Iterator(things []*"+BASE+") *"+BASE+"Iterator {") - fmt.Fprintln(w, " return &"+BASE+"Iterator{things: things}") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "// Scan moves to the next element and returns false if there are no more things.") - fmt.Fprintln(w, "// Use Scan() in a loop, similar to a while loop") - fmt.Fprintln(w, "//") - fmt.Fprintln(w, "// for iterator.Scan() ") - fmt.Fprintln(w, "// d := iterator.Next(") - fmt.Fprintln(w, "// fmt.Println(\"found UUID:\", d.Uuid") - fmt.Fprintln(w, "// }") - fmt.Fprintln(w, "func (it *"+BASE+"Iterator) Scan() bool {") - fmt.Fprintln(w, " if it.index >= len(it.things) {") - fmt.Fprintln(w, " return false") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, " it.index++") - fmt.Fprintln(w, " return true") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") -} - -func (msg *MsgName) iterNext(w io.Writer) { - var BASE string = msg.Name - - fmt.Fprintln(w, "// Next() returns the next thing in the array") - fmt.Fprintln(w, "func (it *"+BASE+"Iterator) Next() *"+BASE+" {") - fmt.Fprintln(w, " if it.things[it.index-1] == nil {") - fmt.Fprintln(w, " for i, d := range it.things {") - fmt.Fprintln(w, " fmt.Println(\"i =\", i, d)") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, " return it.things[it.index-1]") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") -} - -func (pf *File) selectAllFunc(w io.Writer) { - var BASES string = pf.Bases.Name - var BASE string = pf.Base.Name - var LOCK string = pf.Bases.Lockname - - fmt.Fprintln(w, "func (x *"+BASES+") All() *"+BASE+"Iterator {") - fmt.Fprintln(w, " "+BASE+"Pointers := x.selectAll"+BASE+"()") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " iterator := New"+BASE+"Iterator("+BASE+"Pointers)") - fmt.Fprintln(w, " return iterator") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "func (x *"+BASES+") Len() int {") - fmt.Fprintln(w, " "+LOCK+".RLock()") - fmt.Fprintln(w, " defer "+LOCK+".RUnlock()") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " return len(x."+BASES+")") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") -} - -func (pf *File) sortByFunc(w io.Writer) { - var BASES string = pf.Bases.Name - var BASE string = pf.Base.Name - - for _, SORT := range pf.Base.Sort { - fmt.Fprintln(w, "func (x *"+BASES+") SortBy"+SORT+"() *"+BASE+"Iterator {") - fmt.Fprintln(w, " things := x.selectAll"+BASE+"()") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " sort.Sort("+BASE+""+SORT+"(things))") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " iterator := New"+BASE+"Iterator(things)") - fmt.Fprintln(w, " return iterator") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") - - fmt.Fprintln(w, "type "+BASE+""+SORT+" []*"+BASE+"") - fmt.Fprintln(w, "") - fmt.Fprintln(w, "func (a "+BASE+""+SORT+") Len() int { return len(a) }") - fmt.Fprintln(w, "func (a "+BASE+""+SORT+") Less(i, j int) bool { return a[i]."+SORT+" < a[j]."+SORT+" }") - fmt.Fprintln(w, "func (a "+BASE+""+SORT+") Swap(i, j int) { a[i], a[j] = a[j], a[i] }") - fmt.Fprintln(w, "") - } -} - -func (pf *File) iterSelect(w io.Writer) { - var BASES string = pf.Bases.Name - var BASE string = pf.Base.Name - var LOCK string = pf.Bases.Lockname - - fmt.Fprintln(w, "// safely returns a slice of pointers to the "+BASE+" protobufs") - fmt.Fprintln(w, "func (x *"+BASES+") selectAll"+BASE+"() []*"+BASE+" {") - fmt.Fprintln(w, " "+LOCK+".RLock()") - fmt.Fprintln(w, " defer "+LOCK+".RUnlock()") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " // Create a new slice to hold pointers to each "+BASE+"") - fmt.Fprintln(w, " var tmp []*"+BASE+"") - fmt.Fprintln(w, " tmp = make([]*"+BASE+", len(x."+BASES+"))") - fmt.Fprintln(w, " for i, p := range x."+BASES+" {") - fmt.Fprintln(w, " tmp[i] = p // Copy pointers for safe iteration") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " return tmp") - fmt.Fprintln(w, "}") -} diff --git a/sortNew.go b/sortNew.go deleted file mode 100644 index 72370ba..0000000 --- a/sortNew.go +++ /dev/null @@ -1,169 +0,0 @@ -package main - -import ( - "fmt" - "io" - - "go.wit.com/log" -) - -func (msg *MsgName) getLockname(s string) string { - // 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 -} - -// I like these functions the best. -func (msg *MsgName) simpleAppend(w io.Writer, FRUIT, APPLES, APPLE string) { - LOCK := msg.getLockname("x") - - log.Printf("\t\t(x %s) APPEND(%s)\n", FRUIT, APPLE) - // append -- no check at all - fmt.Fprintln(w, "// TESTING 2") - fmt.Fprintln(w, "// just a simple Append() shortcut (but still uses the mutex lock)") - fmt.Fprintln(w, "func (x *"+FRUIT+") Append(y *"+APPLE+") {") - fmt.Fprintln(w, " "+LOCK+".Lock()") - fmt.Fprintln(w, " defer "+LOCK+".Unlock()") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " x."+APPLES+" = append(x."+APPLES+", y)") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") -} - -func (msg *MsgName) insertByColor(w io.Writer, FRUIT, APPLES, APPLE string, COLOR string) { - LOCK := msg.getLockname("x") - - fmt.Fprintln(w, "// TESTING") - fmt.Fprintln(w, "// returns an "+APPLE+" if "+COLOR+" matches, otherwise create") - fmt.Fprintln(w, "func (x *"+FRUIT+") InsertBy"+COLOR+" (y string) *"+APPLE+" {") - fmt.Fprintln(w, " "+LOCK+".Lock()") - fmt.Fprintln(w, " defer "+LOCK+".Unlock()") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " for _, p := range x."+APPLES+" {") - fmt.Fprintln(w, " if p."+COLOR+" == y {") - fmt.Fprintln(w, " return p") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " z := new("+APPLE+")") - fmt.Fprintln(w, " z."+COLOR+" = y") - fmt.Fprintln(w, " x."+APPLES+" = append(x."+APPLES+", z)") - fmt.Fprintln(w, " return z") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") -} - -func (msg *MsgName) appendUnique(w io.Writer, FRUIT, APPLES, APPLE string, COLORS []string) { - LOCK := msg.getLockname("x") - - fmt.Fprintln(w, "// TESTING") - fmt.Fprintln(w, "// enforces "+APPLE+" is unique in "+FRUIT+"."+APPLES) - fmt.Fprintln(w, "func (x *"+FRUIT+") AppendUnique(newP *"+APPLE+") bool {") - fmt.Fprintln(w, " "+LOCK+".Lock()") - fmt.Fprintln(w, " defer "+LOCK+".Unlock()") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " for _, p := range x."+APPLES+" {") - for _, COLOR := range COLORS { - fmt.Fprintln(w, " if p."+COLOR+" == newP."+COLOR+" {") - fmt.Fprintln(w, " return false") - fmt.Fprintln(w, " }") - } - fmt.Fprintln(w, " }") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " x."+APPLES+" = append(x."+APPLES+", newP)") - fmt.Fprintln(w, " return true") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") -} - -func (msg *MsgName) appendUniqueBy(w io.Writer, FRUIT, APPLES, APPLE, COLOR string) { - LOCK := msg.getLockname("x") - - fmt.Fprintln(w, "// TESTING") - fmt.Fprintln(w, "// enforces "+APPLE+"."+COLOR+" is unique in "+FRUIT+"."+APPLES) - fmt.Fprintln(w, "func (x *"+FRUIT+") AppendUniqueBy"+COLOR+"(newP *"+APPLE+") bool {") - fmt.Fprintln(w, " "+LOCK+".Lock()") - fmt.Fprintln(w, " defer "+LOCK+".Unlock()") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " for _, p := range x."+APPLES+" {") - fmt.Fprintln(w, " if p."+COLOR+" == newP."+COLOR+" {") - fmt.Fprintln(w, " return false") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " x."+APPLES+" = append(x."+APPLES+", newP)") - fmt.Fprintln(w, " return true") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") -} - -func (msg *MsgName) findBy(w io.Writer, FRUIT, APPLES, APPLE, COLOR string) { - LOCK := msg.getLockname("x") - - fmt.Fprintln(w, "// TESTING") - fmt.Fprintln(w, "// find a dependancy by the go path") - fmt.Fprintln(w, "func (x *"+FRUIT+") FindBy"+COLOR+"(s string) *"+APPLE+" {") - fmt.Fprintln(w, " if x == nil {") - fmt.Fprintln(w, " return nil") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " "+LOCK+".RLock()") - fmt.Fprintln(w, " defer "+LOCK+".RUnlock()") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " for i, _ := range x."+APPLES+" {") - fmt.Fprintln(w, " if x."+APPLES+"[i]."+COLOR+" == s {") - fmt.Fprintln(w, " return x."+APPLES+"[i]") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, " return nil") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") -} - -func (msg *MsgName) deleteBy(w io.Writer, FRUIT, APPLES, APPLE, COLOR string) { - LOCK := msg.getLockname("x") - - fmt.Fprintln(w, "// TESTING") - fmt.Fprintln(w, "func (x *"+FRUIT+") DeleteBy"+COLOR+"(s string) bool {") - fmt.Fprintln(w, " "+LOCK+".Lock()") - fmt.Fprintln(w, " defer "+LOCK+".Unlock()") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " for i, _ := range x."+APPLES+" {") - fmt.Fprintln(w, " if x."+APPLES+"[i]."+COLOR+" == s {") - fmt.Fprintln(w, " x."+APPLES+"[i] = x."+APPLES+"[len(x."+APPLES+")-1]") - fmt.Fprintln(w, " x."+APPLES+" = x."+APPLES+"[:len(x."+APPLES+")-1]") - fmt.Fprintln(w, " return true") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, " return false") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") -} - -// this tries to return the deleted one but is wrong/gives warning if mutex lock is in struct -func (msg *MsgName) deleteByWithCopy(w io.Writer, FRUIT, APPLES, APPLE, COLOR string) { - LOCK := msg.getLockname("x") - - fmt.Fprintln(w, "// TESTING") - fmt.Fprintln(w, "func (x *"+FRUIT+") DeleteBy"+COLOR+"(s string) *"+APPLE+" {") - fmt.Fprintln(w, " "+LOCK+".Lock()") - fmt.Fprintln(w, " defer "+LOCK+".Unlock()") - fmt.Fprintln(w, "") - fmt.Fprintln(w, " var newr "+APPLE) - fmt.Fprintln(w, "") - fmt.Fprintln(w, " for i, _ := range x."+APPLES+" {") - fmt.Fprintln(w, " if x."+APPLES+"[i]."+COLOR+" == s {") - fmt.Fprintln(w, " newr = *x."+APPLES+"[i]") - fmt.Fprintln(w, " x."+APPLES+"[i] = x."+APPLES+"[len(x."+APPLES+")-1]") - fmt.Fprintln(w, " x."+APPLES+" = x."+APPLES+"[:len(x."+APPLES+")-1]") - fmt.Fprintln(w, " return &newr") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, " }") - fmt.Fprintln(w, " return nil") - fmt.Fprintln(w, "}") - fmt.Fprintln(w, "") -} -- cgit v1.2.3