github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/core/arraytools/2darray.go (about) 1 package arraytools 2 3 import ( 4 "errors" 5 "fmt" 6 "sync" 7 "sync/atomic" 8 9 "github.com/lmorg/murex/lang" 10 "github.com/lmorg/murex/lang/types" 11 "github.com/lmorg/murex/utils/json" 12 ) 13 14 func init() { 15 lang.DefineFunction("2darray", twoDArray, types.Json) 16 } 17 18 type mdarray struct { 19 mutex sync.Mutex 20 array [][]string 21 len int 22 } 23 24 func newMultiArray(len int) mdarray { 25 array := [][]string{make([]string, len)} 26 return mdarray{array: array, len: len} 27 } 28 29 func (a *mdarray) Append(index int, count int, value string) { 30 a.mutex.Lock() 31 32 if len(a.array) <= count { 33 a.array = append(a.array, make([]string, a.len)) 34 } 35 36 a.array[count][index] = value 37 a.mutex.Unlock() 38 } 39 40 func twoDArray(p *lang.Process) (err error) { 41 p.Stdout.SetDataType(types.Json) 42 43 if p.Parameters.Len() == 0 { 44 return errors.New("missing parameters. Expecting code blocks to populate array") 45 } 46 47 block := make(map[int][]rune) 48 49 for i := 0; i < p.Parameters.Len(); i++ { 50 block[i], err = p.Parameters.Block(i) 51 if err != nil { 52 return err 53 } 54 } 55 56 var ( 57 wg sync.WaitGroup 58 array = newMultiArray(p.Parameters.Len()) 59 errCount int32 60 i int 61 ) 62 63 for i = 0; i < p.Parameters.Len(); i++ { 64 wg.Add(1) 65 66 index := i 67 count := 0 68 69 go func() { 70 fork := p.Fork(lang.F_NO_STDIN | lang.F_CREATE_STDOUT) 71 _, err := fork.Execute(block[index]) 72 73 if err != nil { 74 fork.Stderr.Write([]byte(fmt.Sprintf("error executing fork (block %d): %s", index, err.Error()))) 75 } 76 77 err = fork.Stdout.ReadArray(p.Context, func(b []byte) { 78 count++ 79 array.Append(index, count, string(b)) 80 }) 81 82 if err != nil { 83 p.Stderr.Writeln([]byte(fmt.Sprintf("error in ReadArray() (block %d): %s: ", index, err.Error()))) 84 atomic.AddInt32(&errCount, 1) 85 } 86 87 wg.Done() 88 }() 89 } 90 91 wg.Wait() 92 93 if errCount > 0 { 94 return fmt.Errorf("%d/%d blocks contained errors. Please read STDERR for details", errCount, i+1) 95 } 96 97 b, err := json.Marshal(array.array, p.Stdout.IsTTY()) 98 if err != nil { 99 return err 100 } 101 102 _, err = p.Stdout.Write(b) 103 return err 104 }