github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/core/lists/push_pop.go (about) 1 package lists 2 3 import ( 4 "github.com/lmorg/murex/lang" 5 "github.com/lmorg/murex/lang/types" 6 ) 7 8 func init() { 9 lang.DefineMethod("left", cmdLeft, types.ReadArray, types.WriteArray) 10 lang.DefineMethod("right", cmdRight, types.ReadArray, types.WriteArray) 11 lang.DefineMethod("prefix", cmdPrefix, types.ReadArray, types.WriteArray) 12 lang.DefineMethod("suffix", cmdSuffix, types.ReadArray, types.WriteArray) 13 } 14 15 func cmdLeft(p *lang.Process) error { 16 dt := p.Stdin.GetDataType() 17 p.Stdout.SetDataType(dt) 18 19 if err := p.ErrIfNotAMethod(); err != nil { 20 return err 21 } 22 23 left, err := p.Parameters.Int(0) 24 if err != nil { 25 return err 26 } 27 28 aw, err := p.Stdout.WriteArray(dt) 29 if err != nil { 30 return err 31 } 32 33 switch { 34 case left > 0: 35 p.Stdin.ReadArray(p.Context, func(b []byte) { 36 if len(b) < left { 37 err = aw.Write(b) 38 } else { 39 err = aw.Write(b[:left]) 40 } 41 42 if err != nil { 43 p.Stdin.ForceClose() 44 p.Done() 45 } 46 }) 47 48 case left < 0: 49 left = left * -1 50 p.Stdin.ReadArray(p.Context, func(b []byte) { 51 if len(b) < left { 52 err = aw.WriteString("") 53 } else { 54 err = aw.Write(b[:len(b)-left]) 55 } 56 57 if err != nil { 58 p.Stdin.ForceClose() 59 p.Done() 60 } 61 }) 62 63 default: 64 p.Stdin.ReadArray(p.Context, func([]byte) { 65 err = aw.WriteString("") 66 if err != nil { 67 p.Stdin.ForceClose() 68 p.Done() 69 } 70 }) 71 } 72 73 if p.HasCancelled() { 74 return err 75 } 76 77 return aw.Close() 78 } 79 80 func cmdRight(p *lang.Process) error { 81 dt := p.Stdin.GetDataType() 82 p.Stdout.SetDataType(dt) 83 84 if err := p.ErrIfNotAMethod(); err != nil { 85 return err 86 } 87 88 right, err := p.Parameters.Int(0) 89 if err != nil { 90 return err 91 } 92 93 aw, err := p.Stdout.WriteArray(dt) 94 if err != nil { 95 return err 96 } 97 98 switch { 99 case right > 0: 100 p.Stdin.ReadArray(p.Context, func(b []byte) { 101 if len(b) < right { 102 err = aw.Write(b) 103 } else { 104 err = aw.Write(b[len(b)-right:]) 105 } 106 107 if err != nil { 108 p.Stdin.ForceClose() 109 p.Done() 110 } 111 }) 112 113 case right < 0: 114 right = right * -1 115 p.Stdin.ReadArray(p.Context, func(b []byte) { 116 if len(b) < right { 117 err = aw.WriteString("") 118 } else { 119 err = aw.Write(b[right:]) 120 } 121 122 if err != nil { 123 p.Stdin.ForceClose() 124 p.Done() 125 } 126 }) 127 128 default: 129 p.Stdin.ReadArray(p.Context, func([]byte) { 130 err = aw.WriteString("") 131 132 if err != nil { 133 p.Stdin.ForceClose() 134 p.Done() 135 } 136 }) 137 } 138 139 if p.HasCancelled() { 140 return err 141 } 142 143 return aw.Close() 144 } 145 146 func cmdPrefix(p *lang.Process) error { return cmdFix(p, true) } 147 func cmdSuffix(p *lang.Process) error { return cmdFix(p, false) } 148 149 func cmdFix(p *lang.Process, pre bool) (err error) { 150 dt := p.Stdin.GetDataType() 151 p.Stdout.SetDataType(dt) 152 153 if err := p.ErrIfNotAMethod(); err != nil { 154 return err 155 } 156 157 fix := p.Parameters.ByteAll() 158 159 aw, err := p.Stdout.WriteArray(dt) 160 if err != nil { 161 return err 162 } 163 164 p.Stdin.ReadArray(p.Context, func(b []byte) { 165 write := make([]byte, len(b)+len(fix)) 166 if pre { 167 copy(write, fix, b) 168 } else { 169 copy(write, b, fix) 170 } 171 172 err = aw.Write(write) 173 if err != nil { 174 p.Stdin.ForceClose() 175 p.Done() 176 } 177 }) 178 179 if p.HasCancelled() { 180 return err 181 } 182 183 return aw.Close() 184 } 185 186 func copy(write, pre, post []byte) { 187 l := len(pre) 188 for i := 0; i < l; i++ { 189 write[i] = pre[i] 190 } 191 for i := 0; i < len(post); i++ { 192 write[l+i] = post[i] 193 } 194 }