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  }