github.com/apache/arrow/go/v16@v16.1.0/arrow/array/booleanbuilder.go (about)

     1  // Licensed to the Apache Software Foundation (ASF) under one
     2  // or more contributor license agreements.  See the NOTICE file
     3  // distributed with this work for additional information
     4  // regarding copyright ownership.  The ASF licenses this file
     5  // to you under the Apache License, Version 2.0 (the
     6  // "License"); you may not use this file except in compliance
     7  // with the License.  You may obtain a copy of the License at
     8  //
     9  // http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package array
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"reflect"
    23  	"strconv"
    24  	"sync/atomic"
    25  
    26  	"github.com/apache/arrow/go/v16/arrow"
    27  	"github.com/apache/arrow/go/v16/arrow/bitutil"
    28  	"github.com/apache/arrow/go/v16/arrow/internal/debug"
    29  	"github.com/apache/arrow/go/v16/arrow/memory"
    30  	"github.com/apache/arrow/go/v16/internal/json"
    31  )
    32  
    33  type BooleanBuilder struct {
    34  	builder
    35  
    36  	data    *memory.Buffer
    37  	rawData []byte
    38  }
    39  
    40  func NewBooleanBuilder(mem memory.Allocator) *BooleanBuilder {
    41  	return &BooleanBuilder{builder: builder{refCount: 1, mem: mem}}
    42  }
    43  
    44  func (b *BooleanBuilder) Type() arrow.DataType { return arrow.FixedWidthTypes.Boolean }
    45  
    46  // Release decreases the reference count by 1.
    47  // When the reference count goes to zero, the memory is freed.
    48  // Release may be called simultaneously from multiple goroutines.
    49  func (b *BooleanBuilder) Release() {
    50  	debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
    51  
    52  	if atomic.AddInt64(&b.refCount, -1) == 0 {
    53  		if b.nullBitmap != nil {
    54  			b.nullBitmap.Release()
    55  			b.nullBitmap = nil
    56  		}
    57  		if b.data != nil {
    58  			b.data.Release()
    59  			b.data = nil
    60  			b.rawData = nil
    61  		}
    62  	}
    63  }
    64  
    65  func (b *BooleanBuilder) Append(v bool) {
    66  	b.Reserve(1)
    67  	b.UnsafeAppend(v)
    68  }
    69  
    70  func (b *BooleanBuilder) AppendByte(v byte) {
    71  	b.Reserve(1)
    72  	b.UnsafeAppend(v != 0)
    73  }
    74  
    75  func (b *BooleanBuilder) AppendNull() {
    76  	b.Reserve(1)
    77  	b.UnsafeAppendBoolToBitmap(false)
    78  }
    79  
    80  func (b *BooleanBuilder) AppendNulls(n int) {
    81  	for i := 0; i < n; i++ {
    82  		b.AppendNull()
    83  	}
    84  }
    85  
    86  func (b *BooleanBuilder) AppendEmptyValue() {
    87  	b.Reserve(1)
    88  	b.UnsafeAppend(false)
    89  }
    90  
    91  func (b *BooleanBuilder) AppendEmptyValues(n int) {
    92  	for i := 0; i < n; i++ {
    93  		b.AppendEmptyValue()
    94  	}
    95  }
    96  
    97  func (b *BooleanBuilder) AppendValueFromString(s string) error {
    98  	if s == NullValueStr {
    99  		b.AppendNull()
   100  		return nil
   101  	}
   102  	val, err := strconv.ParseBool(s)
   103  	if err != nil {
   104  		return err
   105  	}
   106  	b.Append(val)
   107  	return nil
   108  }
   109  
   110  func (b *BooleanBuilder) UnsafeAppend(v bool) {
   111  	bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
   112  	if v {
   113  		bitutil.SetBit(b.rawData, b.length)
   114  	} else {
   115  		bitutil.ClearBit(b.rawData, b.length)
   116  	}
   117  	b.length++
   118  }
   119  
   120  func (b *BooleanBuilder) AppendValues(v []bool, valid []bool) {
   121  	if len(v) != len(valid) && len(valid) != 0 {
   122  		panic("len(v) != len(valid) && len(valid) != 0")
   123  	}
   124  
   125  	if len(v) == 0 {
   126  		return
   127  	}
   128  
   129  	b.Reserve(len(v))
   130  	for i, vv := range v {
   131  		bitutil.SetBitTo(b.rawData, b.length+i, vv)
   132  	}
   133  	b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
   134  }
   135  
   136  func (b *BooleanBuilder) init(capacity int) {
   137  	b.builder.init(capacity)
   138  
   139  	b.data = memory.NewResizableBuffer(b.mem)
   140  	bytesN := arrow.BooleanTraits.BytesRequired(capacity)
   141  	b.data.Resize(bytesN)
   142  	b.rawData = b.data.Bytes()
   143  }
   144  
   145  // Reserve ensures there is enough space for appending n elements
   146  // by checking the capacity and calling Resize if necessary.
   147  func (b *BooleanBuilder) Reserve(n int) {
   148  	b.builder.reserve(n, b.Resize)
   149  }
   150  
   151  // Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
   152  // additional memory will be allocated. If n is smaller, the allocated memory may reduced.
   153  func (b *BooleanBuilder) Resize(n int) {
   154  	if n < minBuilderCapacity {
   155  		n = minBuilderCapacity
   156  	}
   157  
   158  	if b.capacity == 0 {
   159  		b.init(n)
   160  	} else {
   161  		b.builder.resize(n, b.init)
   162  		b.data.Resize(arrow.BooleanTraits.BytesRequired(n))
   163  		b.rawData = b.data.Bytes()
   164  	}
   165  }
   166  
   167  // NewArray creates a Boolean array from the memory buffers used by the builder and resets the BooleanBuilder
   168  // so it can be used to build a new array.
   169  func (b *BooleanBuilder) NewArray() arrow.Array {
   170  	return b.NewBooleanArray()
   171  }
   172  
   173  // NewBooleanArray creates a Boolean array from the memory buffers used by the builder and resets the BooleanBuilder
   174  // so it can be used to build a new array.
   175  func (b *BooleanBuilder) NewBooleanArray() (a *Boolean) {
   176  	data := b.newData()
   177  	a = NewBooleanData(data)
   178  	data.Release()
   179  	return
   180  }
   181  
   182  func (b *BooleanBuilder) newData() *Data {
   183  	bytesRequired := arrow.BooleanTraits.BytesRequired(b.length)
   184  	if bytesRequired > 0 && bytesRequired < b.data.Len() {
   185  		// trim buffers
   186  		b.data.Resize(bytesRequired)
   187  	}
   188  	res := NewData(arrow.FixedWidthTypes.Boolean, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0)
   189  	b.reset()
   190  
   191  	if b.data != nil {
   192  		b.data.Release()
   193  		b.data = nil
   194  		b.rawData = nil
   195  	}
   196  
   197  	return res
   198  }
   199  
   200  func (b *BooleanBuilder) UnmarshalOne(dec *json.Decoder) error {
   201  	t, err := dec.Token()
   202  	if err != nil {
   203  		return err
   204  	}
   205  
   206  	switch v := t.(type) {
   207  	case bool:
   208  		b.Append(v)
   209  	case string:
   210  		val, err := strconv.ParseBool(v)
   211  		if err != nil {
   212  			return err
   213  		}
   214  		b.Append(val)
   215  	case json.Number:
   216  		val, err := strconv.ParseBool(v.String())
   217  		if err != nil {
   218  			return err
   219  		}
   220  		b.Append(val)
   221  	case nil:
   222  		b.AppendNull()
   223  	default:
   224  		return &json.UnmarshalTypeError{
   225  			Value:  fmt.Sprint(t),
   226  			Type:   reflect.TypeOf(true),
   227  			Offset: dec.InputOffset(),
   228  		}
   229  	}
   230  	return nil
   231  }
   232  
   233  func (b *BooleanBuilder) Unmarshal(dec *json.Decoder) error {
   234  	for dec.More() {
   235  		if err := b.UnmarshalOne(dec); err != nil {
   236  			return err
   237  		}
   238  	}
   239  	return nil
   240  }
   241  
   242  func (b *BooleanBuilder) UnmarshalJSON(data []byte) error {
   243  	dec := json.NewDecoder(bytes.NewReader(data))
   244  	dec.UseNumber()
   245  	t, err := dec.Token()
   246  	if err != nil {
   247  		return err
   248  	}
   249  
   250  	if delim, ok := t.(json.Delim); !ok || delim != '[' {
   251  		return fmt.Errorf("boolean builder must unpack from json array, found %s", delim)
   252  	}
   253  
   254  	return b.Unmarshal(dec)
   255  }
   256  
   257  func (b *BooleanBuilder) Value(i int) bool {
   258  	return bitutil.BitIsSet(b.rawData, i)
   259  }
   260  
   261  var (
   262  	_ Builder = (*BooleanBuilder)(nil)
   263  )