From 78a9e4389a36cc28d382891e32ee0148d81a18a4 Mon Sep 17 00:00:00 2001 From: Stefan Junker Date: Thu, 26 May 2016 11:41:18 +0200 Subject: [PATCH] deps: k8s.io/kubernetes: use v1.3.0-alpha.4 --- Godeps/Godeps.json | 12 +- .../kubernetes/pkg/api/resource/amount.go | 298 --------- .../pkg/api/resource/deep_copy_generated.go | 32 +- .../pkg/api/resource/generated.pb.go | 325 ++++++++++ .../pkg/api/resource/generated.proto | 20 +- .../kubernetes/pkg/api/resource/math.go | 327 ---------- .../kubernetes/pkg/api/resource/quantity.go | 607 ++++++------------ .../pkg/api/resource/quantity_proto.go | 292 ++------- .../kubernetes/pkg/api/resource/suffix.go | 84 +-- 9 files changed, 617 insertions(+), 1380 deletions(-) delete mode 100644 Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/amount.go delete mode 100644 Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/math.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 42c70fac..fff562d8 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -37,18 +37,18 @@ }, { "ImportPath": "k8s.io/kubernetes/pkg/api/resource", - "Comment": "v1.3.0-alpha.3-1204-g9625926", - "Rev": "9625926852e215caa35e278c2cd7926744532291" + "Comment": "v1.3.0-alpha.4", + "Rev": "9990f843cd62caa90445cf76b07d63ba7b5c86fd" }, { "ImportPath": "k8s.io/kubernetes/pkg/conversion", - "Comment": "v1.3.0-alpha.3-1204-g9625926", - "Rev": "9625926852e215caa35e278c2cd7926744532291" + "Comment": "v1.3.0-alpha.4", + "Rev": "9990f843cd62caa90445cf76b07d63ba7b5c86fd" }, { "ImportPath": "k8s.io/kubernetes/third_party/forked/reflect", - "Comment": "v1.3.0-alpha.3-1204-g9625926", - "Rev": "9625926852e215caa35e278c2cd7926744532291" + "Comment": "v1.3.0-alpha.4", + "Rev": "9990f843cd62caa90445cf76b07d63ba7b5c86fd" } ] } diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/amount.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/amount.go deleted file mode 100644 index 49caf3c1..00000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/amount.go +++ /dev/null @@ -1,298 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package resource - -import ( - "math/big" - "strconv" - - inf "gopkg.in/inf.v0" -) - -// Scale is used for getting and setting the base-10 scaled value. -// Base-2 scales are omitted for mathematical simplicity. -// See Quantity.ScaledValue for more details. -type Scale int32 - -// infScale adapts a Scale value to an inf.Scale value. -func (s Scale) infScale() inf.Scale { - return inf.Scale(-s) // inf.Scale is upside-down -} - -const ( - Nano Scale = -9 - Micro Scale = -6 - Milli Scale = -3 - Kilo Scale = 3 - Mega Scale = 6 - Giga Scale = 9 - Tera Scale = 12 - Peta Scale = 15 - Exa Scale = 18 -) - -var ( - Zero = int64Amount{} - - // Used by quantity strings - treat as read only - zeroBytes = []byte("0") -) - -// int64Amount represents a fixed precision numerator and arbitary scale exponent. It is faster -// than operations on inf.Dec for values that can be represented as int64. -type int64Amount struct { - value int64 - scale Scale -} - -// Sign returns 0 if the value is zero, -1 if it is less than 0, or 1 if it is greater than 0. -func (a int64Amount) Sign() int { - switch { - case a.value == 0: - return 0 - case a.value > 0: - return 1 - default: - return -1 - } -} - -// AsInt64 returns the current amount as an int64 at scale 0, or false if the value cannot be -// represented in an int64 OR would result in a loss of precision. This method is intended as -// an optimization to avoid calling AsDec. -func (a int64Amount) AsInt64() (int64, bool) { - if a.scale == 0 { - return a.value, true - } - if a.scale < 0 { - // TODO: attempt to reduce factors, although it is assumed that factors are reduced prior - // to the int64Amount being created. - return 0, false - } - return positiveScaleInt64(a.value, a.scale) -} - -// AsScaledInt64 returns an int64 representing the value of this amount at the specified scale, -// rounding up, or false if that would result in overflow. (1e20).AsScaledInt64(1) would result -// in overflow because 1e19 is not representable as an int64. Note that setting a scale larger -// than the current value may result in loss of precision - i.e. (1e-6).AsScaledInt64(0) would -// return 1, because 0.000001 is rounded up to 1. -func (a int64Amount) AsScaledInt64(scale Scale) (result int64, ok bool) { - if a.scale < scale { - result, _ = negativeScaleInt64(a.value, scale-a.scale) - return result, true - } - return positiveScaleInt64(a.value, a.scale-scale) -} - -// AsDec returns an inf.Dec representation of this value. -func (a int64Amount) AsDec() *inf.Dec { - var base inf.Dec - base.SetUnscaled(a.value) - base.SetScale(inf.Scale(-a.scale)) - return &base -} - -// Cmp returns 0 if a and b are equal, 1 if a is greater than b, or -1 if a is less than b. -func (a int64Amount) Cmp(b int64Amount) int { - switch { - case a.scale == b.scale: - // compare only the unscaled portion - case a.scale > b.scale: - result, remainder, exact := divideByScaleInt64(b.value, a.scale-b.scale) - if !exact { - return a.AsDec().Cmp(b.AsDec()) - } - if result == a.value { - switch { - case remainder == 0: - return 0 - case remainder > 0: - return -1 - default: - return 1 - } - } - b.value = result - default: - result, remainder, exact := divideByScaleInt64(a.value, b.scale-a.scale) - if !exact { - return a.AsDec().Cmp(b.AsDec()) - } - if result == b.value { - switch { - case remainder == 0: - return 0 - case remainder > 0: - return 1 - default: - return -1 - } - } - a.value = result - } - - switch { - case a.value == b.value: - return 0 - case a.value < b.value: - return -1 - default: - return 1 - } -} - -// Add adds two int64Amounts together, matching scales. It will return false and not mutate -// a if overflow or underflow would result. -func (a *int64Amount) Add(b int64Amount) bool { - switch { - case b.value == 0: - return true - case a.value == 0: - a.value = b.value - a.scale = b.scale - return true - case a.scale == b.scale: - c, ok := int64Add(a.value, b.value) - if !ok { - return false - } - a.value = c - case a.scale > b.scale: - c, ok := positiveScaleInt64(a.value, a.scale-b.scale) - if !ok { - return false - } - c, ok = int64Add(c, b.value) - if !ok { - return false - } - a.scale = b.scale - a.value = c - default: - c, ok := positiveScaleInt64(b.value, b.scale-a.scale) - if !ok { - return false - } - c, ok = int64Add(a.value, c) - if !ok { - return false - } - a.value = c - } - return true -} - -// Sub removes the value of b from the current amount, or returns false if underflow would result. -func (a *int64Amount) Sub(b int64Amount) bool { - return a.Add(int64Amount{value: -b.value, scale: b.scale}) -} - -// AsScale adjusts this amount to set a minimum scale, rounding up, and returns true iff no precision -// was lost. (1.1e5).AsScale(5) would return 1.1e5, but (1.1e5).AsScale(6) would return 1e6. -func (a int64Amount) AsScale(scale Scale) (int64Amount, bool) { - if a.scale >= scale { - return a, true - } - result, exact := negativeScaleInt64(a.value, scale-a.scale) - return int64Amount{value: result, scale: scale}, exact -} - -// AsCanonicalBytes accepts a buffer to write the base-10 string value of this field to, and returns -// either that buffer or a larger buffer and the current exponent of the value. The value is adjusted -// until the exponent is a multiple of 3 - i.e. 1.1e5 would return "110", 3. -func (a int64Amount) AsCanonicalBytes(out []byte) (result []byte, exponent int32) { - mantissa := a.value - exponent = int32(a.scale) - - amount, times := removeInt64Factors(mantissa, 10) - exponent += int32(times) - - // make sure exponent is a multiple of 3 - var ok bool - switch exponent % 3 { - case 1, -2: - amount, ok = int64MultiplyScale10(amount) - if !ok { - return infDecAmount{a.AsDec()}.AsCanonicalBytes(out) - } - exponent = exponent - 1 - case 2, -1: - amount, ok = int64MultiplyScale100(amount) - if !ok { - return infDecAmount{a.AsDec()}.AsCanonicalBytes(out) - } - exponent = exponent - 2 - } - return strconv.AppendInt(out, amount, 10), exponent -} - -// AsCanonicalBase1024Bytes accepts a buffer to write the base-1024 string value of this field to, and returns -// either that buffer or a larger buffer and the current exponent of the value. 2048 is 2 * 1024 ^ 1 and would -// return []byte("2048"), 1. -func (a int64Amount) AsCanonicalBase1024Bytes(out []byte) (result []byte, exponent int32) { - value, ok := a.AsScaledInt64(0) - if !ok { - return infDecAmount{a.AsDec()}.AsCanonicalBase1024Bytes(out) - } - amount, exponent := removeInt64Factors(value, 1024) - return strconv.AppendInt(out, amount, 10), exponent -} - -// infDecAmount implements common operations over an inf.Dec that are specific to the quantity -// representation. -type infDecAmount struct { - *inf.Dec -} - -// AsScale adjusts this amount to set a minimum scale, rounding up, and returns true iff no precision -// was lost. (1.1e5).AsScale(5) would return 1.1e5, but (1.1e5).AsScale(6) would return 1e6. -func (a infDecAmount) AsScale(scale Scale) (infDecAmount, bool) { - tmp := &inf.Dec{} - tmp.Round(a.Dec, scale.infScale(), inf.RoundUp) - return infDecAmount{tmp}, tmp.Cmp(a.Dec) == 0 -} - -// AsCanonicalBytes accepts a buffer to write the base-10 string value of this field to, and returns -// either that buffer or a larger buffer and the current exponent of the value. The value is adjusted -// until the exponent is a multiple of 3 - i.e. 1.1e5 would return "110", 3. -func (a infDecAmount) AsCanonicalBytes(out []byte) (result []byte, exponent int32) { - mantissa := a.Dec.UnscaledBig() - exponent = int32(-a.Dec.Scale()) - amount := big.NewInt(0).Set(mantissa) - // move all factors of 10 into the exponent for easy reasoning - amount, times := removeBigIntFactors(amount, bigTen) - exponent += times - - // make sure exponent is a multiple of 3 - for exponent%3 != 0 { - amount.Mul(amount, bigTen) - exponent-- - } - - return append(out, amount.String()...), exponent -} - -// AsCanonicalBase1024Bytes accepts a buffer to write the base-1024 string value of this field to, and returns -// either that buffer or a larger buffer and the current exponent of the value. 2048 is 2 * 1024 ^ 1 and would -// return []byte("2048"), 1. -func (a infDecAmount) AsCanonicalBase1024Bytes(out []byte) (result []byte, exponent int32) { - tmp := &inf.Dec{} - tmp.Round(a.Dec, 0, inf.RoundUp) - amount, exponent := removeBigIntFactors(tmp.UnscaledBig(), big1024) - return append(out, amount.String()...), exponent -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/deep_copy_generated.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/deep_copy_generated.go index 3f721410..6a34e2d4 100644 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/deep_copy_generated.go +++ b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/deep_copy_generated.go @@ -21,27 +21,35 @@ limitations under the License. package resource import ( + inf_v0 "gopkg.in/inf.v0" conversion "k8s.io/kubernetes/pkg/conversion" ) func DeepCopy_resource_Quantity(in Quantity, out *Quantity, c *conversion.Cloner) error { - if newVal, err := c.DeepCopy(in.i); err != nil { - return err + if in.Amount != nil { + in, out := in.Amount, &out.Amount + *out = new(inf_v0.Dec) + if newVal, err := c.DeepCopy(*in); err != nil { + return err + } else { + **out = newVal.(inf_v0.Dec) + } } else { - out.i = newVal.(int64Amount) + out.Amount = nil } - if newVal, err := c.DeepCopy(in.d); err != nil { - return err - } else { - out.d = newVal.(infDecAmount) - } - if in.s != nil { - in, out := in.s, &out.s + out.Format = in.Format + return nil +} + +func DeepCopy_resource_QuantityProto(in QuantityProto, out *QuantityProto, c *conversion.Cloner) error { + out.Format = in.Format + out.Scale = in.Scale + if in.Bigint != nil { + in, out := in.Bigint, &out.Bigint *out = make([]byte, len(in)) copy(*out, in) } else { - out.s = nil + out.Bigint = nil } - out.Format = in.Format return nil } diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/generated.pb.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/generated.pb.go index cf9447a3..7484f927 100644 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/generated.pb.go +++ b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/generated.pb.go @@ -26,6 +26,7 @@ limitations under the License. It has these top-level messages: Quantity + QuantityProto */ package resource @@ -33,6 +34,8 @@ import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" +import io "io" + // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf @@ -41,6 +44,328 @@ var _ = math.Inf func (m *Quantity) Reset() { *m = Quantity{} } func (*Quantity) ProtoMessage() {} +func (m *QuantityProto) Reset() { *m = QuantityProto{} } +func (m *QuantityProto) String() string { return proto.CompactTextString(m) } +func (*QuantityProto) ProtoMessage() {} + func init() { proto.RegisterType((*Quantity)(nil), "k8s.io.kubernetes.pkg.api.resource.Quantity") + proto.RegisterType((*QuantityProto)(nil), "k8s.io.kubernetes.pkg.api.resource.QuantityProto") +} +func (m *QuantityProto) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *QuantityProto) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + data[i] = 0xa + i++ + i = encodeVarintGenerated(data, i, uint64(len(m.Format))) + i += copy(data[i:], m.Format) + data[i] = 0x10 + i++ + i = encodeVarintGenerated(data, i, uint64(m.Scale)) + if m.Bigint != nil { + data[i] = 0x1a + i++ + i = encodeVarintGenerated(data, i, uint64(len(m.Bigint))) + i += copy(data[i:], m.Bigint) + } + return i, nil +} + +func encodeFixed64Generated(data []byte, offset int, v uint64) int { + data[offset] = uint8(v) + data[offset+1] = uint8(v >> 8) + data[offset+2] = uint8(v >> 16) + data[offset+3] = uint8(v >> 24) + data[offset+4] = uint8(v >> 32) + data[offset+5] = uint8(v >> 40) + data[offset+6] = uint8(v >> 48) + data[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Generated(data []byte, offset int, v uint32) int { + data[offset] = uint8(v) + data[offset+1] = uint8(v >> 8) + data[offset+2] = uint8(v >> 16) + data[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintGenerated(data []byte, offset int, v uint64) int { + for v >= 1<<7 { + data[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + data[offset] = uint8(v) + return offset + 1 } +func (m *QuantityProto) Size() (n int) { + var l int + _ = l + l = len(m.Format) + n += 1 + l + sovGenerated(uint64(l)) + n += 1 + sovGenerated(uint64(m.Scale)) + if m.Bigint != nil { + l = len(m.Bigint) + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + +func sovGenerated(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozGenerated(x uint64) (n int) { + return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QuantityProto) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QuantityProto: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QuantityProto: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Format", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Format = Format(data[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Scale", wireType) + } + m.Scale = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.Scale |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Bigint", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Bigint = append(m.Bigint[:0], data[iNdEx:postIndex]...) + if m.Bigint == nil { + m.Bigint = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenerated(data []byte) (n int, err error) { + l := len(data) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if data[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthGenerated + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipGenerated(data[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow") +) diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/generated.proto b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/generated.proto index 8a1376c3..34ede458 100644 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/generated.proto +++ b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/generated.proto @@ -84,10 +84,26 @@ option go_package = "resource"; // cause implementors to also use a fixed point implementation. // // +protobuf=true -// +protobuf.embed=string +// +protobuf.embed=QuantityProto // +protobuf.options.marshal=false // +protobuf.options.(gogoproto.goproto_stringer)=false message Quantity { - optional string string = 1; + optional QuantityProto QuantityProto = 1; +} + +// QuantityProto is a struct that is equivalent to Quantity, but intended for +// protobuf marshalling/unmarshalling. It is generated into a serialization +// that matches Quantity. Do not use in Go structs. +// +// +protobuf=true +message QuantityProto { + // The format of the quantity + optional string format = 1; + + // The scale dimension of the value + optional int32 scale = 2; + + // Bigint is serialized as a raw bytes array + optional bytes bigint = 3; } diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/math.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/math.go deleted file mode 100644 index 163aafa5..00000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/math.go +++ /dev/null @@ -1,327 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package resource - -import ( - "math/big" - - inf "gopkg.in/inf.v0" -) - -const ( - // maxInt64Factors is the highest value that will be checked when removing factors of 10 from an int64. - // It is also the maximum decimal digits that can be represented with an int64. - maxInt64Factors = 18 -) - -var ( - // Commonly needed big.Int values-- treat as read only! - bigTen = big.NewInt(10) - bigZero = big.NewInt(0) - bigOne = big.NewInt(1) - bigThousand = big.NewInt(1000) - big1024 = big.NewInt(1024) - - // Commonly needed inf.Dec values-- treat as read only! - decZero = inf.NewDec(0, 0) - decOne = inf.NewDec(1, 0) - decMinusOne = inf.NewDec(-1, 0) - decThousand = inf.NewDec(1000, 0) - dec1024 = inf.NewDec(1024, 0) - decMinus1024 = inf.NewDec(-1024, 0) - - // Largest (in magnitude) number allowed. - maxAllowed = infDecAmount{inf.NewDec((1<<63)-1, 0)} // == max int64 - - // The maximum value we can represent milli-units for. - // Compare with the return value of Quantity.Value() to - // see if it's safe to use Quantity.MilliValue(). - MaxMilliValue = int64(((1 << 63) - 1) / 1000) -) - -const mostNegative = -(mostPositive + 1) -const mostPositive = 1<<63 - 1 - -// int64Add returns a+b, or false if that would overflow int64. -func int64Add(a, b int64) (int64, bool) { - c := a + b - switch { - case a > 0 && b > 0: - if c < 0 { - return 0, false - } - case a < 0 && b < 0: - if c > 0 { - return 0, false - } - if a == mostNegative && b == mostNegative { - return 0, false - } - } - return c, true -} - -// int64Multiply returns a*b, or false if that would overflow or underflow int64. -func int64Multiply(a, b int64) (int64, bool) { - if a == 0 || b == 0 || a == 1 || b == 1 { - return a * b, true - } - if a == mostNegative || b == mostNegative { - return 0, false - } - c := a * b - return c, c/b == a -} - -// int64MultiplyScale returns a*b, assuming b is greater than one, or false if that would overflow or underflow int64. -// Use when b is known to be greater than one. -func int64MultiplyScale(a int64, b int64) (int64, bool) { - if a == 0 || a == 1 { - return a * b, true - } - if a == mostNegative && b != 1 { - return 0, false - } - c := a * b - return c, c/b == a -} - -// int64MultiplyScale10 multiplies a by 10, or returns false if that would overflow. This method is faster than -// int64Multiply(a, 10) because the compiler can optimize constant factor multiplication. -func int64MultiplyScale10(a int64) (int64, bool) { - if a == 0 || a == 1 { - return a * 10, true - } - if a == mostNegative { - return 0, false - } - c := a * 10 - return c, c/10 == a -} - -// int64MultiplyScale100 multiplies a by 100, or returns false if that would overflow. This method is faster than -// int64Multiply(a, 100) because the compiler can optimize constant factor multiplication. -func int64MultiplyScale100(a int64) (int64, bool) { - if a == 0 || a == 1 { - return a * 100, true - } - if a == mostNegative { - return 0, false - } - c := a * 100 - return c, c/100 == a -} - -// int64MultiplyScale1000 multiplies a by 1000, or returns false if that would overflow. This method is faster than -// int64Multiply(a, 1000) because the compiler can optimize constant factor multiplication. -func int64MultiplyScale1000(a int64) (int64, bool) { - if a == 0 || a == 1 { - return a * 1000, true - } - if a == mostNegative { - return 0, false - } - c := a * 1000 - return c, c/1000 == a -} - -// positiveScaleInt64 multiplies base by 10^scale, returning false if the -// value overflows. Passing a negative scale is undefined. -func positiveScaleInt64(base int64, scale Scale) (int64, bool) { - switch scale { - case 0: - return base, true - case 1: - return int64MultiplyScale10(base) - case 2: - return int64MultiplyScale100(base) - case 3: - return int64MultiplyScale1000(base) - case 6: - return int64MultiplyScale(base, 1000000) - case 9: - return int64MultiplyScale(base, 1000000000) - default: - value := base - var ok bool - for i := Scale(0); i < scale; i++ { - if value, ok = int64MultiplyScale(value, 10); !ok { - return 0, false - } - } - return value, true - } -} - -// negativeScaleInt64 reduces base by the provided scale, rounding up, until the -// value is zero or the scale is reached. Passing a negative scale is undefined. -// The value returned, if not exact, is rounded away from zero. -func negativeScaleInt64(base int64, scale Scale) (result int64, exact bool) { - if scale == 0 { - return base, true - } - - value := base - var fraction bool - for i := Scale(0); i < scale; i++ { - if !fraction && value%10 != 0 { - fraction = true - } - value = value / 10 - if value == 0 { - if fraction { - if base > 0 { - return 1, false - } - return -1, false - } - return 0, true - } - } - if fraction { - if base > 0 { - value += 1 - } else { - value += -1 - } - } - return value, !fraction -} - -func pow10Int64(b int64) int64 { - switch b { - case 0: - return 1 - case 1: - return 10 - case 2: - return 100 - case 3: - return 1000 - case 4: - return 10000 - case 5: - return 100000 - case 6: - return 1000000 - case 7: - return 10000000 - case 8: - return 100000000 - case 9: - return 1000000000 - case 10: - return 10000000000 - case 11: - return 100000000000 - case 12: - return 1000000000000 - case 13: - return 10000000000000 - case 14: - return 100000000000000 - case 15: - return 1000000000000000 - case 16: - return 10000000000000000 - case 17: - return 100000000000000000 - case 18: - return 1000000000000000000 - default: - return 0 - } -} - -// powInt64 raises a to the bth power. Is not overflow aware. -func powInt64(a, b int64) int64 { - p := int64(1) - for b > 0 { - if b&1 != 0 { - p *= a - } - b >>= 1 - a *= a - } - return p -} - -// negativeScaleInt64 returns the result of dividing base by scale * 10 and the remainder, or -// false if no such division is possible. Dividing by negative scales is undefined. -func divideByScaleInt64(base int64, scale Scale) (result, remainder int64, exact bool) { - if scale == 0 { - return base, 0, true - } - // the max scale representable in base 10 in an int64 is 18 decimal places - if scale >= 18 { - return 0, base, false - } - divisor := pow10Int64(int64(scale)) - return base / divisor, base % divisor, true -} - -// removeInt64Factors divides in a loop; the return values have the property that -// value == result * base ^ scale -func removeInt64Factors(value int64, base int64) (result int64, times int32) { - times = 0 - result = value - negative := result < 0 - if negative { - result = -result - } - switch base { - // allow the compiler to optimize the common cases - case 10: - for result >= 10 && result%10 == 0 { - times++ - result = result / 10 - } - // allow the compiler to optimize the common cases - case 1024: - for result >= 1024 && result%1024 == 0 { - times++ - result = result / 1024 - } - default: - for result >= base && result%base == 0 { - times++ - result = result / base - } - } - if negative { - result = -result - } - return result, times -} - -// removeBigIntFactors divides in a loop; the return values have the property that -// d == result * factor ^ times -// d may be modified in place. -// If d == 0, then the return values will be (0, 0) -func removeBigIntFactors(d, factor *big.Int) (result *big.Int, times int32) { - q := big.NewInt(0) - m := big.NewInt(0) - for d.Cmp(bigZero) != 0 { - q.DivMod(d, factor, m) - if m.Cmp(bigZero) != 0 { - break - } - times++ - d, q = q, d - } - return d, times -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity.go index 47c0ac08..e61c8800 100644 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity.go +++ b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity.go @@ -17,12 +17,10 @@ limitations under the License. package resource import ( - "bytes" "errors" "fmt" "math/big" "regexp" - "strconv" "strings" flag "github.com/spf13/pflag" @@ -88,34 +86,19 @@ import ( // cause implementors to also use a fixed point implementation. // // +protobuf=true -// +protobuf.embed=string +// +protobuf.embed=QuantityProto // +protobuf.options.marshal=false // +protobuf.options.(gogoproto.goproto_stringer)=false type Quantity struct { - // i is the quantity in int64 scaled form, if d.Dec == nil - i int64Amount - // d is the quantity in inf.Dec form if d.Dec != nil - d infDecAmount - // s is the generated value of this quantity to avoid recalculation - s []byte + // Amount is public, so you can manipulate it if the accessor + // functions are not sufficient. + Amount *inf.Dec // Change Format at will. See the comment for Canonicalize for // more details. Format } -// CanonicalValue allows a quantity amount to be converted to a string. -type CanonicalValue interface { - // AsCanonicalBytes returns a byte array representing the string representation - // of the value mantissa and an int32 representing its exponent in base-10. Callers may - // pass a byte slice to the method to avoid allocations. - AsCanonicalBytes(out []byte) ([]byte, int32) - // AsCanonicalBase1024Bytes returns a byte array representing the string representation - // of the value mantissa and an int32 representing its exponent in base-1024. Callers - // may pass a byte slice to the method to avoid allocations. - AsCanonicalBase1024Bytes(out []byte) ([]byte, int32) -} - // Format lists the three possible formattings of a quantity. type Format string @@ -132,9 +115,26 @@ func MustParse(str string) Quantity { if err != nil { panic(fmt.Errorf("cannot parse '%v': %v", str, err)) } - return q + return *q } +// Scale is used for getting and setting the base-10 scaled value. +// Base-2 scales are omitted for mathematical simplicity. +// See Quantity.ScaledValue for more details. +type Scale int + +const ( + Nano Scale = -9 + Micro Scale = -6 + Milli Scale = -3 + Kilo Scale = 3 + Mega Scale = 6 + Giga Scale = 9 + Tera Scale = 12 + Peta Scale = 15 + Exa Scale = 18 +) + const ( // splitREString is used to separate a number from its suffix; as such, // this is overly permissive, but that's OK-- it will be checked later. @@ -149,189 +149,47 @@ var ( ErrFormatWrong = errors.New("quantities must match the regular expression '" + splitREString + "'") ErrNumeric = errors.New("unable to parse numeric part of quantity") ErrSuffix = errors.New("unable to parse quantity's suffix") -) - -// parseQuantityString is a fast scanner for quantity values. -func parseQuantityString(str string) (positive bool, value, num, denom, suffix string, err error) { - positive = true - pos := 0 - end := len(str) - - // handle leading sign - if pos < end { - switch str[0] { - case '-': - positive = false - pos++ - case '+': - pos++ - } - } - - // strip leading zeros -Zeroes: - for i := pos; ; i++ { - if i >= end { - num = "0" - value = num - return - } - switch str[i] { - case '0': - pos++ - default: - break Zeroes - } - } - // extract the numerator -Num: - for i := pos; ; i++ { - if i >= end { - num = str[pos:end] - value = str[0:end] - return - } - switch str[i] { - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - default: - num = str[pos:i] - pos = i - break Num - } - } - - // if we stripped all numerator positions, always return 0 - if len(num) == 0 { - num = "0" - } - - // handle a denominator - if pos < end && str[pos] == '.' { - pos++ - Denom: - for i := pos; ; i++ { - if i >= end { - denom = str[pos:end] - value = str[0:end] - return - } - switch str[i] { - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - default: - denom = str[pos:i] - pos = i - break Denom - } - } - // TODO: we currently allow 1.G, but we may not want to in the future. - // if len(denom) == 0 { - // err = ErrFormatWrong - // return - // } - } - value = str[0:pos] - - // grab the elements of the suffix - suffixStart := pos - for i := pos; ; i++ { - if i >= end { - suffix = str[suffixStart:end] - return - } - if !strings.ContainsAny(str[i:i+1], "eEinumkKMGTP") { - pos = i - break - } - } - if pos < end { - switch str[pos] { - case '-', '+': - pos++ - } - } -Suffix: - for i := pos; ; i++ { - if i >= end { - suffix = str[suffixStart:end] - return - } - switch str[i] { - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - default: - pos = i - break Suffix - } - } - // we encountered a non decimal in the Suffix loop, but the last character - // was not a valid exponent - err = ErrFormatWrong - return -} + // Commonly needed big.Int values-- treat as read only! + bigTen = big.NewInt(10) + bigZero = big.NewInt(0) + bigOne = big.NewInt(1) + bigThousand = big.NewInt(1000) + big1024 = big.NewInt(1024) + + // Commonly needed inf.Dec values-- treat as read only! + decZero = inf.NewDec(0, 0) + decOne = inf.NewDec(1, 0) + decMinusOne = inf.NewDec(-1, 0) + decThousand = inf.NewDec(1000, 0) + dec1024 = inf.NewDec(1024, 0) + decMinus1024 = inf.NewDec(-1024, 0) + + // Largest (in magnitude) number allowed. + maxAllowed = inf.NewDec((1<<63)-1, 0) // == max int64 + + // The maximum value we can represent milli-units for. + // Compare with the return value of Quantity.Value() to + // see if it's safe to use Quantity.MilliValue(). + MaxMilliValue = int64(((1 << 63) - 1) / 1000) +) // ParseQuantity turns str into a Quantity, or returns an error. -func ParseQuantity(str string) (Quantity, error) { - if len(str) == 0 { - return Quantity{}, ErrFormatWrong - } - if str == "0" { - return Quantity{Format: DecimalSI}, nil +func ParseQuantity(str string) (*Quantity, error) { + parts := splitRE.FindStringSubmatch(strings.TrimSpace(str)) + // regexp returns are entire match, followed by an entry for each () section. + if len(parts) != 3 { + return nil, ErrFormatWrong } - positive, value, num, denom, suf, err := parseQuantityString(str) - if err != nil { - return Quantity{}, err + amount := new(inf.Dec) + if _, ok := amount.SetString(parts[1]); !ok { + return nil, ErrNumeric } - base, exponent, format, ok := quantitySuffixer.interpret(suffix(suf)) + base, exponent, format, ok := quantitySuffixer.interpret(suffix(parts[2])) if !ok { - return Quantity{}, ErrSuffix - } - - precision := int32(0) - scale := int32(0) - mantissa := int64(1) - switch format { - case DecimalExponent, DecimalSI: - scale = exponent - precision = maxInt64Factors - int32(len(num)+len(denom)) - case BinarySI: - scale = 0 - switch { - case exponent >= 0 && len(denom) == 0: - // only handle positive binary numbers with the fast path - mantissa = int64(int64(mantissa) << uint64(exponent)) - // 1Mi (2^20) has ~6 digits of decimal precision, so exponent*3/10 -1 is roughly the precision - precision = 15 - int32(len(num)) - int32(float32(exponent)*3/10) - 1 - default: - precision = -1 - } - } - - if precision >= 0 { - // if we have a denominator, shift the entire value to the left by the number of places in the - // denominator - scale -= int32(len(denom)) - if scale >= int32(Nano) { - shifted := num + denom - - var value int64 - value, err := strconv.ParseInt(shifted, 10, 64) - if err != nil { - return Quantity{}, ErrNumeric - } - if result, ok := int64Multiply(value, int64(mantissa)); ok { - if !positive { - result = -result - } - return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format}, nil - } - } - } - - amount := new(inf.Dec) - if _, ok := amount.SetString(value); !ok { - return Quantity{}, ErrNumeric + return nil, ErrSuffix } // So that no one but us has to think about suffixes, remove it. @@ -359,11 +217,9 @@ func ParseQuantity(str string) (Quantity, error) { } // The max is just a simple cap. - // TODO: this prevents accumulating quantities greater than int64, for instance quota across a cluster - if format == BinarySI && amount.Cmp(maxAllowed.Dec) > 0 { - amount.Set(maxAllowed.Dec) + if amount.Cmp(maxAllowed) > 0 { + amount.Set(maxAllowed) } - if format == BinarySI && amount.Cmp(decOne) < 0 && amount.Cmp(decZero) > 0 { // This avoids rounding and hopefully confusion, too. format = DecimalSI @@ -372,7 +228,25 @@ func ParseQuantity(str string) (Quantity, error) { amount.Neg(amount) } - return Quantity{d: infDecAmount{amount}, Format: format}, nil + return &Quantity{amount, format}, nil +} + +// removeFactors divides in a loop; the return values have the property that +// d == result * factor ^ times +// d may be modified in place. +// If d == 0, then the return values will be (0, 0) +func removeFactors(d, factor *big.Int) (result *big.Int, times int) { + q := big.NewInt(0) + m := big.NewInt(0) + for d.Cmp(bigZero) != 0 { + q.DivMod(d, factor, m) + if m.Cmp(bigZero) != 0 { + break + } + times++ + d, q = q, d + } + return d, times } // Canonicalize returns the canonical form of q and its suffix (see comment on Quantity). @@ -382,22 +256,27 @@ func ParseQuantity(str string) (Quantity, error) { // -1 and +1, it will be emitted as if q.Format were DecimalSI. // * Otherwise, if q.Format is set to BinarySI, frational parts of q.Amount will be // rounded up. (1.1i becomes 2i.) -func (q *Quantity) CanonicalizeBytes(out []byte) (result, suffix []byte) { - if q.IsZero() { - return zeroBytes, nil +func (q *Quantity) Canonicalize() (string, suffix) { + if q.Amount == nil { + return "0", "" + } + + // zero is zero always + if q.Amount.Cmp(&inf.Dec{}) == 0 { + return "0", "" } - var rounded CanonicalValue format := q.Format switch format { case DecimalExponent, DecimalSI: case BinarySI: - if q.CmpInt64(-1024) > 0 && q.CmpInt64(1024) < 0 { + if q.Amount.Cmp(decMinus1024) > 0 && q.Amount.Cmp(dec1024) < 0 { // This avoids rounding and hopefully confusion, too. format = DecimalSI } else { - var exact bool - if rounded, exact = q.AsScale(0); !exact { + tmp := &inf.Dec{} + tmp.Round(q.Amount, 0, inf.RoundUp) + if tmp.Cmp(q.Amount) != 0 { // Don't lose precision-- show as DecimalSI format = DecimalSI } @@ -410,223 +289,125 @@ func (q *Quantity) CanonicalizeBytes(out []byte) (result, suffix []byte) { // one of the other formats. switch format { case DecimalExponent, DecimalSI: - number, exponent := q.AsCanonicalBytes(out) - suffix, _ := quantitySuffixer.constructBytes(10, exponent, format) - return number, suffix - default: - // format must be BinarySI - number, exponent := rounded.AsCanonicalBase1024Bytes(out) - suffix, _ := quantitySuffixer.constructBytes(2, exponent*10, format) - return number, suffix - } -} - -// AsInt64 returns a representation of the current value as an int64 if a fast conversion -// is possible. If false is returned, callers must use the inf.Dec form of this quantity. -func (q *Quantity) AsInt64() (int64, bool) { - if q.d.Dec != nil { - return 0, false - } - return q.i.AsInt64() -} - -// ToDec promotes the quantity in place to use an inf.Dec representation and returns itself. -func (q *Quantity) ToDec() *Quantity { - if q.d.Dec == nil { - q.d.Dec = q.i.AsDec() - q.i = int64Amount{} - } - return q -} + mantissa := q.Amount.UnscaledBig() + exponent := int(-q.Amount.Scale()) + amount := big.NewInt(0).Set(mantissa) + // move all factors of 10 into the exponent for easy reasoning + amount, times := removeFactors(amount, bigTen) + exponent += times + + // make sure exponent is a multiple of 3 + for exponent%3 != 0 { + amount.Mul(amount, bigTen) + exponent-- + } -// AsDec returns the quantity as represented by a scaled inf.Dec. -func (q *Quantity) AsDec() *inf.Dec { - if q.d.Dec != nil { - return q.d.Dec - } - q.d.Dec = q.i.AsDec() - q.i = int64Amount{} - return q.d.Dec -} + suffix, _ := quantitySuffixer.construct(10, exponent, format) + number := amount.String() + return number, suffix + case BinarySI: + tmp := &inf.Dec{} + tmp.Round(q.Amount, 0, inf.RoundUp) -// AsCanonicalBytes returns the canonical byte representation of this quantity as a mantissa -// and base 10 exponent. The out byte slice may be passed to the method to avoid an extra -// allocation. -func (q *Quantity) AsCanonicalBytes(out []byte) (result []byte, exponent int32) { - if q.d.Dec != nil { - return q.d.AsCanonicalBytes(out) + amount, exponent := removeFactors(tmp.UnscaledBig(), big1024) + suffix, _ := quantitySuffixer.construct(2, exponent*10, format) + number := amount.String() + return number, suffix } - return q.i.AsCanonicalBytes(out) + return "0", "" } -// IsZero returns true if the quantity is equal to zero. -func (q *Quantity) IsZero() bool { - if q.d.Dec != nil { - return q.d.Dec.Sign() == 0 - } - return q.i.value == 0 +// String formats the Quantity as a string. +func (q *Quantity) String() string { + number, suffix := q.Canonicalize() + return number + string(suffix) } -// Sign returns 0 if the quantity is zero, -1 if the quantity is less than zero, or 1 if the -// quantity is greater than zero. -func (q *Quantity) Sign() int { - if q.d.Dec != nil { - return q.d.Dec.Sign() +// Cmp compares q and y and returns: +// +// -1 if q < y +// 0 if q == y +// +1 if q > y +// +func (q *Quantity) Cmp(y Quantity) int { + if q.Amount == nil { + if y.Amount == nil { + return 0 + } + return -y.Amount.Sign() } - return q.i.Sign() -} - -// AsScaled returns the current value, rounded up to the provided scale, and returns -// false if the scale resulted in a loss of precision. -func (q *Quantity) AsScale(scale Scale) (CanonicalValue, bool) { - if q.d.Dec != nil { - return q.d.AsScale(scale) + if y.Amount == nil { + return q.Amount.Sign() } - return q.i.AsScale(scale) + return q.Amount.Cmp(y.Amount) } -// RoundUp updates the quantity to the provided scale, ensuring that the value is at -// least 1. False is returned if the rounding operation resulted in a loss of precision. -// Negative numbers are rounded away from zero (-9 scale 1 rounds to -10). -func (q *Quantity) RoundUp(scale Scale) bool { - if q.d.Dec != nil { - d, exact := q.d.AsScale(scale) - q.d = d - return exact +func (q *Quantity) Add(y Quantity) error { + switch { + case y.Amount == nil: + // Adding 0: do nothing. + case q.Amount == nil: + q.Amount = &inf.Dec{} + return q.Add(y) + default: + // we want to preserve the format of the non-zero value + zero := &inf.Dec{} + if q.Amount.Cmp(zero) == 0 && y.Amount.Cmp(zero) != 0 { + q.Format = y.Format + } + q.Amount.Add(q.Amount, y.Amount) } - i, exact := q.i.AsScale(scale) - q.i = i - return exact + return nil } -// Add adds the provide y quantity to the current value. If the current value is zero, -// the format of the quantity will be updated to the format of y. -func (q *Quantity) Add(y Quantity) { - q.s = nil - if q.d.Dec == nil && y.d.Dec == nil { - if q.i.value == 0 { +func (q *Quantity) Sub(y Quantity) error { + switch { + case y.Amount == nil: + // Subtracting 0: do nothing. + case q.Amount == nil: + q.Amount = &inf.Dec{} + return q.Sub(y) + default: + // we want to preserve the format of the non-zero value + zero := &inf.Dec{} + if q.Amount.Cmp(zero) == 0 && y.Amount.Cmp(zero) != 0 { q.Format = y.Format } - if q.i.Add(y.i) { - return - } - } else if q.IsZero() { - q.Format = y.Format + q.Amount.Sub(q.Amount, y.Amount) } - q.ToDec().d.Dec.Add(q.d.Dec, y.AsDec()) + return nil } -// Sub subtracts the provided quantity from the current value in place. If the current -// value is zero, the format of the quantity will be updated to the format of y. -func (q *Quantity) Sub(y Quantity) { - q.s = nil - if q.IsZero() { +// Neg sets q to the negative value of y. +// It updates the format of q to match y. +func (q *Quantity) Neg(y Quantity) error { + switch { + case y.Amount == nil: + *q = y + case q.Amount == nil: + q.Amount = &inf.Dec{} + fallthrough + default: + q.Amount.Neg(y.Amount) q.Format = y.Format } - if q.d.Dec == nil && y.d.Dec == nil && q.i.Sub(y.i) { - return - } - q.ToDec().d.Dec.Sub(q.d.Dec, y.AsDec()) -} - -// Cmp returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the -// quantity is greater than y. -func (q *Quantity) Cmp(y Quantity) int { - if q.d.Dec == nil && y.d.Dec == nil { - return q.i.Cmp(y.i) - } - return q.AsDec().Cmp(y.AsDec()) -} - -// CmpInt64 returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the -// quantity is greater than y. -func (q *Quantity) CmpInt64(y int64) int { - if q.d.Dec != nil { - return q.d.Dec.Cmp(inf.NewDec(y, inf.Scale(0))) - } - return q.i.Cmp(int64Amount{value: y}) -} - -// Neg sets quantity to be the negative value of itself. -func (q *Quantity) Neg() { - q.s = nil - if q.d.Dec == nil { - q.i.value = -q.i.value - return - } - q.d.Dec.Neg(q.d.Dec) -} - -// toBytes ensures q.s is set to a byte slice representing the canonical string form of this -// quantity and then returns the value. CanonicalizeBytes is an expensive operation, and caching -// this result significantly reduces the cost of normal parse / marshal operations on Quantity. -func (q *Quantity) toBytes() []byte { - if q.s == nil { - result := make([]byte, 0, int64QuantityExpectedBytes) - number, suffix := q.CanonicalizeBytes(result) - number = append(number, suffix...) - q.s = number - } - return q.s -} - -// int64QuantityExpectedBytes is the expected width in bytes of the canonical string representation -// of most Quantity values. -const int64QuantityExpectedBytes = 18 - -// String formats the Quantity as a string. -func (q *Quantity) String() string { - return string(q.toBytes()) + return nil } // MarshalJSON implements the json.Marshaller interface. func (q Quantity) MarshalJSON() ([]byte, error) { - if q.s != nil { - out := make([]byte, len(q.s)+2) - out[0], out[len(out)-1] = '"', '"' - copy(out[1:], q.s) - return out, nil - } - result := make([]byte, int64QuantityExpectedBytes, int64QuantityExpectedBytes) - result[0] = '"' - number, suffix := q.CanonicalizeBytes(result[1:1]) - // if the same slice was returned to us that we passed in, avoid another allocation by copying number into - // the source slice and returning that - if len(number) > 0 && &number[0] == &result[1] && (len(number)+len(suffix)+2) <= int64QuantityExpectedBytes { - number = append(number, suffix...) - number = append(number, '"') - return result[:1+len(number)], nil - } - // if CanonicalizeBytes needed more space than our slice provided, we may need to allocate again so use - // append - result = result[:1] - result = append(result, number...) - result = append(result, suffix...) - result = append(result, '"') - return result, nil + return []byte(`"` + q.String() + `"`), nil } // UnmarshalJSON implements the json.Unmarshaller interface. func (q *Quantity) UnmarshalJSON(value []byte) error { - l := len(value) - if l == 4 && bytes.Equal(value, []byte("null")) { - q.d.Dec = nil - q.i = int64Amount{} - return nil - } - if l < 2 { - return ErrFormatWrong - } - if value[0] == '"' && value[l-1] == '"' { - value = value[1 : l-1] - } - parsed, err := ParseQuantity(string(value)) + str := string(value) + parsed, err := ParseQuantity(strings.Trim(str, `"`)) if err != nil { return err } - parsed.s = value // This copy is safe because parsed will not be referred to again. - *q = parsed + *q = *parsed return nil } @@ -634,7 +415,7 @@ func (q *Quantity) UnmarshalJSON(value []byte) error { // value in the given format. func NewQuantity(value int64, format Format) *Quantity { return &Quantity{ - i: int64Amount{value: value}, + Amount: inf.NewDec(value, 0), Format: format, } } @@ -645,7 +426,7 @@ func NewQuantity(value int64, format Format) *Quantity { // values x where (-1 < x < 1) && (x != 0). func NewMilliQuantity(value int64, format Format) *Quantity { return &Quantity{ - i: int64Amount{value: value, scale: -3}, + Amount: inf.NewDec(value, 3), Format: format, } } @@ -654,7 +435,7 @@ func NewMilliQuantity(value int64, format Format) *Quantity { // value * 10^scale in DecimalSI format. func NewScaledQuantity(value int64, scale Scale) *Quantity { return &Quantity{ - i: int64Amount{value: value, scale: scale}, + Amount: inf.NewDec(value, scale.infScale()), Format: DecimalSI, } } @@ -673,12 +454,10 @@ func (q *Quantity) MilliValue() int64 { // ScaledValue returns the value of ceil(q * 10^scale); this could overflow an int64. // To detect overflow, call Value() first and verify the expected magnitude. func (q *Quantity) ScaledValue(scale Scale) int64 { - if q.d.Dec == nil { - i, _ := q.i.AsScaledInt64(scale) - return i + if q.Amount == nil { + return 0 } - dec := q.d.Dec - return scaledValue(dec.UnscaledBig(), int(dec.Scale()), int(scale.infScale())) + return scaledValue(q.Amount.UnscaledBig(), int(q.Amount.Scale()), int(scale.infScale())) } // Set sets q's value to be value. @@ -693,25 +472,22 @@ func (q *Quantity) SetMilli(value int64) { // SetScaled sets q's value to be value * 10^scale func (q *Quantity) SetScaled(value int64, scale Scale) { - q.s = nil - q.d.Dec = nil - q.i = int64Amount{value: value, scale: scale} + if q.Amount == nil { + q.Amount = &inf.Dec{} + } + q.Amount.SetUnscaled(value) + q.Amount.SetScale(scale.infScale()) } // Copy is a convenience function that makes a deep copy for you. Non-deep // copies of quantities share pointers and you will regret that. func (q *Quantity) Copy() *Quantity { - if q.d.Dec == nil { - return &Quantity{ - s: q.s, - i: q.i, - Format: q.Format, - } + if q.Amount == nil { + return NewQuantity(0, q.Format) } tmp := &inf.Dec{} return &Quantity{ - s: q.s, - d: infDecAmount{tmp.Set(q.d.Dec)}, + Amount: tmp.Set(q.Amount), Format: q.Format, } } @@ -728,7 +504,7 @@ func (qf qFlag) Set(val string) error { return err } // This copy is OK because q will not be referenced again. - *qf.dest = q + *qf.dest = *q return nil } @@ -755,3 +531,8 @@ func QuantityFlag(flagName, defaultValue, description string) *Quantity { func NewQuantityFlagValue(q *Quantity) flag.Value { return qFlag{q} } + +// infScale adapts a Scale value to an inf.Scale value. +func (s Scale) infScale() inf.Scale { + return inf.Scale(-s) // inf.Scale is upside-down +} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity_proto.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity_proto.go index 0159a411..01d5c299 100644 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity_proto.go +++ b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity_proto.go @@ -17,268 +17,62 @@ limitations under the License. package resource import ( - "fmt" - "io" + "math/big" - "github.com/gogo/protobuf/proto" + inf "gopkg.in/inf.v0" ) -var _ proto.Sizer = &Quantity{} - -func (m *Quantity) Marshal() (data []byte, err error) { - size := m.Size() - data = make([]byte, size) - n, err := m.MarshalTo(data) - if err != nil { - return nil, err - } - return data[:n], nil -} - -// MarshalTo is a customized version of the generated Protobuf unmarshaler for a struct -// with a single string field. -func (m *Quantity) MarshalTo(data []byte) (int, error) { - var i int - _ = i - var l int - _ = l - - data[i] = 0xa - i++ - // BEGIN CUSTOM MARSHAL - out := m.toBytes() - i = encodeVarintGenerated(data, i, uint64(len(out))) - i += copy(data[i:], out) - // END CUSTOM MARSHAL - - return i, nil +// QuantityProto is a struct that is equivalent to Quantity, but intended for +// protobuf marshalling/unmarshalling. It is generated into a serialization +// that matches Quantity. Do not use in Go structs. +// +// +protobuf=true +type QuantityProto struct { + // The format of the quantity + Format Format `protobuf:"bytes,1,opt,name=format,casttype=Format"` + // The scale dimension of the value + Scale int32 `protobuf:"varint,2,opt,name=scale"` + // Bigint is serialized as a raw bytes array + Bigint []byte `protobuf:"bytes,3,opt,name=bigint"` } -func encodeVarintGenerated(data []byte, offset int, v uint64) int { - for v >= 1<<7 { - data[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ +// ProtoTime returns the Time as a new ProtoTime value. +func (q *Quantity) QuantityProto() *QuantityProto { + if q == nil { + return &QuantityProto{} } - data[offset] = uint8(v) - return offset + 1 -} - -func (m *Quantity) Size() (n int) { - var l int - _ = l - - // BEGIN CUSTOM SIZE - l = len(m.toBytes()) - // END CUSTOM SIZE - - n += 1 + l + sovGenerated(uint64(l)) - return n -} - -func sovGenerated(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } + p := &QuantityProto{ + Format: q.Format, + } + if q.Amount != nil { + p.Scale = int32(q.Amount.Scale()) + p.Bigint = q.Amount.UnscaledBig().Bytes() } - return n + return p } -// Unmarshal is a customized version of the generated Protobuf unmarshaler for a struct -// with a single string field. -func (m *Quantity) Unmarshal(data []byte) error { - l := len(data) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Quantity: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Quantity: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field String_", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - s := string(data[iNdEx:postIndex]) +// Size implements the protobuf marshalling interface. +func (q *Quantity) Size() (n int) { return q.QuantityProto().Size() } - // BEGIN CUSTOM DECODE - p, err := ParseQuantity(s) - if err != nil { - return err - } - *m = p - // END CUSTOM DECODE - - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenerated(data[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF +// Reset implements the protobuf marshalling interface. +func (q *Quantity) Unmarshal(data []byte) error { + p := QuantityProto{} + if err := p.Unmarshal(data); err != nil { + return err } + q.Format = p.Format + b := big.NewInt(0) + b.SetBytes(p.Bigint) + q.Amount = inf.NewDecBig(b, inf.Scale(p.Scale)) return nil } -func skipGenerated(data []byte) (n int, err error) { - l := len(data) - iNdEx := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowGenerated - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowGenerated - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if data[iNdEx-1] < 0x80 { - break - } - } - return iNdEx, nil - case 1: - iNdEx += 8 - return iNdEx, nil - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowGenerated - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - iNdEx += length - if length < 0 { - return 0, ErrInvalidLengthGenerated - } - return iNdEx, nil - case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowGenerated - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipGenerated(data[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil - case 4: - return iNdEx, nil - case 5: - iNdEx += 4 - return iNdEx, nil - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - } - panic("unreachable") +// Marshal implements the protobuf marshalling interface. +func (q *Quantity) Marshal() (data []byte, err error) { + return q.QuantityProto().Marshal() } -var ( - ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow") -) +// MarshalTo implements the protobuf marshalling interface. +func (q *Quantity) MarshalTo(data []byte) (int, error) { + return q.QuantityProto().MarshalTo(data) +} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/suffix.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/suffix.go index 0aa2ce2b..52971236 100644 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/suffix.go +++ b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/suffix.go @@ -24,9 +24,8 @@ type suffix string // suffixer can interpret and construct suffixes. type suffixer interface { - interpret(suffix) (base, exponent int32, fmt Format, ok bool) - construct(base, exponent int32, fmt Format) (s suffix, ok bool) - constructBytes(base, exponent int32, fmt Format) (s []byte, ok bool) + interpret(suffix) (base, exponent int, fmt Format, ok bool) + construct(base, exponent int, fmt Format) (s suffix, ok bool) } // quantitySuffixer handles suffixes for all three formats that quantity @@ -34,13 +33,12 @@ type suffixer interface { var quantitySuffixer = newSuffixer() type bePair struct { - base, exponent int32 + base, exponent int } type listSuffixer struct { - suffixToBE map[suffix]bePair - beToSuffix map[bePair]suffix - beToSuffixBytes map[bePair][]byte + suffixToBE map[suffix]bePair + beToSuffix map[bePair]suffix } func (ls *listSuffixer) addSuffix(s suffix, pair bePair) { @@ -50,15 +48,11 @@ func (ls *listSuffixer) addSuffix(s suffix, pair bePair) { if ls.beToSuffix == nil { ls.beToSuffix = map[bePair]suffix{} } - if ls.beToSuffixBytes == nil { - ls.beToSuffixBytes = map[bePair][]byte{} - } ls.suffixToBE[s] = pair ls.beToSuffix[pair] = s - ls.beToSuffixBytes[pair] = []byte(s) } -func (ls *listSuffixer) lookup(s suffix) (base, exponent int32, ok bool) { +func (ls *listSuffixer) lookup(s suffix) (base, exponent int, ok bool) { pair, ok := ls.suffixToBE[s] if !ok { return 0, 0, false @@ -66,50 +60,19 @@ func (ls *listSuffixer) lookup(s suffix) (base, exponent int32, ok bool) { return pair.base, pair.exponent, true } -func (ls *listSuffixer) construct(base, exponent int32) (s suffix, ok bool) { +func (ls *listSuffixer) construct(base, exponent int) (s suffix, ok bool) { s, ok = ls.beToSuffix[bePair{base, exponent}] return } -func (ls *listSuffixer) constructBytes(base, exponent int32) (s []byte, ok bool) { - s, ok = ls.beToSuffixBytes[bePair{base, exponent}] - return -} - type suffixHandler struct { decSuffixes listSuffixer binSuffixes listSuffixer } -type fastLookup struct { - *suffixHandler -} - -func (l fastLookup) interpret(s suffix) (base, exponent int32, format Format, ok bool) { - switch s { - case "": - return 10, 0, DecimalSI, true - case "n": - return 10, -9, DecimalSI, true - case "u": - return 10, -6, DecimalSI, true - case "m": - return 10, -3, DecimalSI, true - case "k": - return 10, 3, DecimalSI, true - case "M": - return 10, 6, DecimalSI, true - case "G": - return 10, 9, DecimalSI, true - } - return l.suffixHandler.interpret(s) -} - func newSuffixer() suffixer { sh := &suffixHandler{} - // IMPORTANT: if you change this section you must change fastLookup - sh.binSuffixes.addSuffix("Ki", bePair{2, 10}) sh.binSuffixes.addSuffix("Mi", bePair{2, 20}) sh.binSuffixes.addSuffix("Gi", bePair{2, 30}) @@ -131,10 +94,10 @@ func newSuffixer() suffixer { sh.decSuffixes.addSuffix("P", bePair{10, 15}) sh.decSuffixes.addSuffix("E", bePair{10, 18}) - return fastLookup{sh} + return sh } -func (sh *suffixHandler) construct(base, exponent int32, fmt Format) (s suffix, ok bool) { +func (sh *suffixHandler) construct(base, exponent int, fmt Format) (s suffix, ok bool) { switch fmt { case DecimalSI: return sh.decSuffixes.construct(base, exponent) @@ -152,32 +115,7 @@ func (sh *suffixHandler) construct(base, exponent int32, fmt Format) (s suffix, return "", false } -func (sh *suffixHandler) constructBytes(base, exponent int32, format Format) (s []byte, ok bool) { - switch format { - case DecimalSI: - return sh.decSuffixes.constructBytes(base, exponent) - case BinarySI: - return sh.binSuffixes.constructBytes(base, exponent) - case DecimalExponent: - if base != 10 { - return nil, false - } - if exponent == 0 { - return nil, true - } - result := make([]byte, 8, 8) - result[0] = 'e' - number := strconv.AppendInt(result[1:1], int64(exponent), 10) - if &result[1] == &number[0] { - return result[:1+len(number)], true - } - result = append(result[:1], number...) - return result, true - } - return nil, false -} - -func (sh *suffixHandler) interpret(suffix suffix) (base, exponent int32, fmt Format, ok bool) { +func (sh *suffixHandler) interpret(suffix suffix) (base, exponent int, fmt Format, ok bool) { // Try lookup tables first if b, e, ok := sh.decSuffixes.lookup(suffix); ok { return b, e, DecimalSI, true @@ -191,7 +129,7 @@ func (sh *suffixHandler) interpret(suffix suffix) (base, exponent int32, fmt For if err != nil { return 0, 0, DecimalExponent, false } - return 10, int32(parsed), DecimalExponent, true + return 10, int(parsed), DecimalExponent, true } return 0, 0, DecimalExponent, false