github.com/waldiirawan/apm-agent-go/v2@v2.2.2/internal/configutil/size.go (about)

     1  // Licensed to Elasticsearch B.V. under one or more contributor
     2  // license agreements. See the NOTICE file distributed with
     3  // this work for additional information regarding copyright
     4  // ownership. Elasticsearch B.V. licenses this file to you under
     5  // the Apache License, Version 2.0 (the "License"); you may
     6  // not use this file except in compliance with the License.
     7  // 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,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package configutil
    19  
    20  import (
    21  	"fmt"
    22  	"strconv"
    23  	"strings"
    24  	"unicode"
    25  )
    26  
    27  // Size represents a size in bytes.
    28  type Size int64
    29  
    30  // Common power-of-two sizes.
    31  const (
    32  	Byte  Size = 1
    33  	KByte Size = 1024
    34  	MByte Size = 1024 * 1024
    35  	GByte Size = 1024 * 1024 * 1024
    36  )
    37  
    38  // Bytes returns s as a number of bytes.
    39  func (s Size) Bytes() int64 {
    40  	return int64(s)
    41  }
    42  
    43  // String returns s in its most compact string representation.
    44  func (s Size) String() string {
    45  	if s == 0 {
    46  		return "0B"
    47  	}
    48  	switch {
    49  	case s%GByte == 0:
    50  		return fmt.Sprintf("%dGB", s/GByte)
    51  	case s%MByte == 0:
    52  		return fmt.Sprintf("%dMB", s/MByte)
    53  	case s%KByte == 0:
    54  		return fmt.Sprintf("%dKB", s/KByte)
    55  	default:
    56  		return fmt.Sprintf("%dB", s)
    57  	}
    58  }
    59  
    60  // ParseSize parses s as a size, in bytes.
    61  //
    62  // Valid size units are "b", "kb", "mb", "gb".
    63  func ParseSize(s string) (Size, error) {
    64  	orig := s
    65  	var mul Size = 1
    66  	if strings.HasPrefix(s, "-") {
    67  		mul = -1
    68  		s = s[1:]
    69  	}
    70  
    71  	sep := -1
    72  	for i, c := range s {
    73  		if sep == -1 {
    74  			if c < '0' || c > '9' {
    75  				sep = i
    76  				break
    77  			}
    78  		}
    79  	}
    80  	if sep == -1 {
    81  		return 0, fmt.Errorf("missing unit in size %s (allowed units: B, KB, MB, GB)", orig)
    82  	}
    83  
    84  	n, err := strconv.ParseInt(s[:sep], 10, 32)
    85  	if err != nil {
    86  		return 0, fmt.Errorf("invalid size %s", orig)
    87  	}
    88  	switch strings.ToLower(s[sep:]) {
    89  	case "gb":
    90  		mul = GByte
    91  	case "mb":
    92  		mul = MByte
    93  	case "kb":
    94  		mul = KByte
    95  	case "b":
    96  	default:
    97  		for _, c := range s[sep:] {
    98  			if unicode.IsSpace(c) {
    99  				return 0, fmt.Errorf("invalid character %q in size %s", c, orig)
   100  			}
   101  		}
   102  		return 0, fmt.Errorf("invalid unit in size %s (allowed units: B, KB, MB, GB)", orig)
   103  	}
   104  	return mul * Size(n), nil
   105  }