github.com/ontio/ontology@v1.14.4/vm/neovm/params_builder.go (about)

     1  /*
     2   * Copyright (C) 2018 The ontology Authors
     3   * This file is part of The ontology library.
     4   *
     5   * The ontology is free software: you can redistribute it and/or modify
     6   * it under the terms of the GNU Lesser General Public License as published by
     7   * the Free Software Foundation, either version 3 of the License, or
     8   * (at your option) any later version.
     9   *
    10   * The ontology is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU Lesser General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU Lesser General Public License
    16   * along with The ontology.  If not, see <http://www.gnu.org/licenses/>.
    17   */
    18  
    19  package neovm
    20  
    21  import (
    22  	"bytes"
    23  	"encoding/binary"
    24  	"math/big"
    25  
    26  	"github.com/ontio/ontology/common"
    27  )
    28  
    29  type ParamsBuilder struct {
    30  	buffer *bytes.Buffer
    31  }
    32  
    33  func NewParamsBuilder(buffer *bytes.Buffer) *ParamsBuilder {
    34  	return &ParamsBuilder{buffer}
    35  }
    36  
    37  func (p *ParamsBuilder) Emit(op OpCode) {
    38  	p.buffer.WriteByte(byte(op))
    39  }
    40  
    41  func (p *ParamsBuilder) EmitPushBool(data bool) {
    42  	if data {
    43  		p.Emit(PUSHT)
    44  		return
    45  	}
    46  	p.Emit(PUSHF)
    47  }
    48  
    49  func (p *ParamsBuilder) EmitPushInteger(data *big.Int) {
    50  	if data.Cmp(big.NewInt(int64(-1))) == 0 {
    51  		p.Emit(PUSHM1)
    52  		return
    53  	}
    54  	if data.Sign() == 0 {
    55  		p.Emit(PUSH0)
    56  		return
    57  	}
    58  
    59  	if data.Cmp(big.NewInt(int64(0))) == 1 && data.Cmp(big.NewInt(int64(16))) == -1 {
    60  		p.Emit(OpCode(int(PUSH1) - 1 + int(data.Int64())))
    61  		return
    62  	}
    63  
    64  	bytes := common.BigIntToNeoBytes(data)
    65  	p.EmitPushByteArray(bytes)
    66  }
    67  
    68  func (p *ParamsBuilder) EmitPushByteArray(data []byte) {
    69  	l := len(data)
    70  	if l < int(PUSHBYTES75) {
    71  		p.buffer.WriteByte(byte(l))
    72  	} else if l < 0x100 {
    73  		p.Emit(PUSHDATA1)
    74  		p.buffer.WriteByte(byte(l))
    75  	} else if l < 0x10000 {
    76  		p.Emit(PUSHDATA2)
    77  		b := make([]byte, 2)
    78  		binary.LittleEndian.PutUint16(b, uint16(l))
    79  		p.buffer.Write(b)
    80  	} else {
    81  		p.Emit(PUSHDATA4)
    82  		b := make([]byte, 4)
    83  		binary.LittleEndian.PutUint32(b, uint32(l))
    84  		p.buffer.Write(b)
    85  	}
    86  	p.buffer.Write(data)
    87  }
    88  
    89  func (p *ParamsBuilder) EmitPushCall(address []byte) {
    90  	p.Emit(APPCALL)
    91  	p.buffer.Write(address)
    92  }
    93  
    94  func (p *ParamsBuilder) ToArray() []byte {
    95  	return p.buffer.Bytes()
    96  }