func (s *testFlusherSink) appendNumber(v interface{}) { switch n := v.(type) { case int: s.buf = strconv.AppendInt(s.buf, int64(n), 10) case uint: s.buf = strconv.AppendUint(s.buf, uint64(n), 10) case int64: s.buf = strconv.AppendInt(s.buf, n, 10) case uint64: s.buf = strconv.AppendUint(s.buf, n, 10) case int32: s.buf = strconv.AppendInt(s.buf, int64(n), 10) case uint32: s.buf = strconv.AppendUint(s.buf, uint64(n), 10) case int16: s.buf = strconv.AppendInt(s.buf, int64(n), 10) case uint16: s.buf = strconv.AppendUint(s.buf, uint64(n), 10) case int8: s.buf = strconv.AppendInt(s.buf, int64(n), 10) case uint8: s.buf = strconv.AppendUint(s.buf, uint64(n), 10) case float64: s.buf = strconv.AppendFloat(s.buf, n, 'f', -1, 64) case float32: s.buf = strconv.AppendFloat(s.buf, float64(n), 'f', -1, 32) } }
func formatTextValue(value interface{}) ([]byte, error) { switch v := value.(type) { case int8: return strconv.AppendInt(nil, int64(v), 10), nil case int16: return strconv.AppendInt(nil, int64(v), 10), nil case int32: return strconv.AppendInt(nil, int64(v), 10), nil case int64: return strconv.AppendInt(nil, int64(v), 10), nil case int: return strconv.AppendInt(nil, int64(v), 10), nil case uint8: return strconv.AppendUint(nil, uint64(v), 10), nil case uint16: return strconv.AppendUint(nil, uint64(v), 10), nil case uint32: return strconv.AppendUint(nil, uint64(v), 10), nil case uint64: return strconv.AppendUint(nil, uint64(v), 10), nil case uint: return strconv.AppendUint(nil, uint64(v), 10), nil case float32: return strconv.AppendFloat(nil, float64(v), 'f', -1, 64), nil case float64: return strconv.AppendFloat(nil, float64(v), 'f', -1, 64), nil case []byte: return v, nil case string: return hack.Slice(v), nil default: return nil, errors.Errorf("invalid type %T", value) } }
func (c *conn) appendNumber(v interface{}) { switch n := v.(type) { case int: c.buf = strconv.AppendInt(c.buf, int64(n), 10) case uint: c.buf = strconv.AppendUint(c.buf, uint64(n), 10) case int64: c.buf = strconv.AppendInt(c.buf, n, 10) case uint64: c.buf = strconv.AppendUint(c.buf, n, 10) case int32: c.buf = strconv.AppendInt(c.buf, int64(n), 10) case uint32: c.buf = strconv.AppendUint(c.buf, uint64(n), 10) case int16: c.buf = strconv.AppendInt(c.buf, int64(n), 10) case uint16: c.buf = strconv.AppendUint(c.buf, uint64(n), 10) case int8: c.buf = strconv.AppendInt(c.buf, int64(n), 10) case uint8: c.buf = strconv.AppendUint(c.buf, uint64(n), 10) case float64: c.buf = strconv.AppendFloat(c.buf, n, 'f', -1, 64) case float32: c.buf = strconv.AppendFloat(c.buf, float64(n), 'f', -1, 32) } }
// appendEncodedText encodes item in text format as required by COPY // and appends to buf func appendEncodedText(parameterStatus *parameterStatus, buf []byte, x interface{}) []byte { switch v := x.(type) { case int64: return strconv.AppendInt(buf, v, 10) case float32: return strconv.AppendFloat(buf, float64(v), 'f', -1, 32) case float64: return strconv.AppendFloat(buf, v, 'f', -1, 64) case []byte: encodedBytea := encodeBytea(parameterStatus.serverVersion, v) return appendEscapedText(buf, string(encodedBytea)) case string: return appendEscapedText(buf, v) case bool: return strconv.AppendBool(buf, v) case time.Time: return append(buf, v.Format(time.RFC3339Nano)...) case nil: return append(buf, "\\N"...) default: errorf("encode: unknown type for %T", v) } panic("not reached") }
func dumpTextValue(mysqlType uint8, value types.Datum) ([]byte, error) { switch value.Kind() { case types.KindInt64: return strconv.AppendInt(nil, value.GetInt64(), 10), nil case types.KindUint64: return strconv.AppendUint(nil, value.GetUint64(), 10), nil case types.KindFloat32: return strconv.AppendFloat(nil, value.GetFloat64(), 'f', -1, 32), nil case types.KindFloat64: return strconv.AppendFloat(nil, value.GetFloat64(), 'f', -1, 64), nil case types.KindString, types.KindBytes: return value.GetBytes(), nil case types.KindMysqlTime: return hack.Slice(value.GetMysqlTime().String()), nil case types.KindMysqlDuration: return hack.Slice(value.GetMysqlDuration().String()), nil case types.KindMysqlDecimal: return hack.Slice(value.GetMysqlDecimal().String()), nil case types.KindMysqlEnum: return hack.Slice(value.GetMysqlEnum().String()), nil case types.KindMysqlSet: return hack.Slice(value.GetMysqlSet().String()), nil case types.KindMysqlBit: return hack.Slice(value.GetMysqlBit().ToString()), nil case types.KindMysqlHex: return hack.Slice(value.GetMysqlHex().ToString()), nil default: return nil, errInvalidType.Gen("invalid type %T", value) } }
func appendField(b []byte, k string, v interface{}) []byte { b = append(b, []byte(escape.String(k))...) b = append(b, '=') // check popular types first switch v := v.(type) { case float64: b = strconv.AppendFloat(b, v, 'f', -1, 64) case int64: b = strconv.AppendInt(b, v, 10) b = append(b, 'i') case string: b = append(b, '"') b = append(b, []byte(EscapeStringField(v))...) b = append(b, '"') case bool: b = strconv.AppendBool(b, v) case int32: b = strconv.AppendInt(b, int64(v), 10) b = append(b, 'i') case int16: b = strconv.AppendInt(b, int64(v), 10) b = append(b, 'i') case int8: b = strconv.AppendInt(b, int64(v), 10) b = append(b, 'i') case int: b = strconv.AppendInt(b, int64(v), 10) b = append(b, 'i') case uint32: b = strconv.AppendInt(b, int64(v), 10) b = append(b, 'i') case uint16: b = strconv.AppendInt(b, int64(v), 10) b = append(b, 'i') case uint8: b = strconv.AppendInt(b, int64(v), 10) b = append(b, 'i') // TODO: 'uint' should be considered just as "dangerous" as a uint64, // perhaps the value should be checked and capped at MaxInt64? We could // then include uint64 as an accepted value case uint: b = strconv.AppendInt(b, int64(v), 10) b = append(b, 'i') case float32: b = strconv.AppendFloat(b, float64(v), 'f', -1, 32) case []byte: b = append(b, v...) case nil: // skip default: // Can't determine the type, so convert to string b = append(b, '"') b = append(b, []byte(EscapeStringField(fmt.Sprintf("%v", v)))...) b = append(b, '"') } return b }
func ExampleAppendFloat() { b32 := []byte("float32:") b32 = strconv.AppendFloat(b32, 3.1415926535, 'E', -1, 32) fmt.Println(string(b32)) b64 := []byte("float64:") b64 = strconv.AppendFloat(b64, 3.1415926535, 'E', -1, 64) fmt.Println(string(b64)) // Output: // float32:3.1415927E+00 // float64:3.1415926535E+00 }
/* func AppendFloat(dst []byte, f float64, fmt byte, prec int, bitSize int) []byte 参数列表 dst 原列表 f 需要append到列表的浮点数 fmt 转换格式 'b' 'e' 'E' 'f' 'g'或'G' prec 浮点数精度 bitSize 32或64,32对应float32,64对应float64 返回值: []byte 返回列表 功能说明: 将浮点数f转换为字符串值,并将转换结果追加到dst的尾部,返回追加后的[]byte。 浮点数格式有'b' (-ddddp±ddd, 二进制指数), 'e' (-d.dddde±dd, 十进制指数), 'E' (-d.ddddE±dd, 十进制指数), 'f' (-ddd.dddd, 无指数), 'g' (大指数时相当于'e', 其他情况时相当于'f'), 'G' (大指数时相当于'E', 其他情况相当于'f'). 精度用于控制当格式为'e' 'E' 'f' 'g' 'G'时除指数外的数字的个数;对于'e' 'E' 'f'指小数点后位数;对于'g' 'G'则表示总共的位数;如果使用-1,表示不改变数值的最小位数 */ func main() { f := 100.123456789 fmt.Println(f) c := strconv.AppendFloat(make([]byte, 0), f, 'f', 10, 32) fmt.Println(string(c)) c = strconv.AppendFloat(make([]byte, 0), f, 'e', 10, 32) fmt.Println(string(c)) c = strconv.AppendFloat(make([]byte, 0), f, 'f', 10, 64) fmt.Println(string(c)) c = strconv.AppendFloat(make([]byte, 0), f, 'e', 10, 64) fmt.Println(string(c)) }
// submit an already sampled raw stat func (s *Client) submit(stat, vprefix string, value interface{}, suffix string, rate float32) error { data := bufPool.Get() defer bufPool.Put(data) if s.prefix != "" { data.WriteString(s.prefix) data.WriteString(".") } data.WriteString(stat) data.WriteString(":") if vprefix != "" { data.WriteString(vprefix) } // sadly, no way to jam this back into the bytes.Buffer without // doing a few allocations... avoiding those is the whole point here... // so from here on out just use it as a raw []byte b := data.Bytes() switch v := value.(type) { case string: b = append(b, v...) case int64: b = strconv.AppendInt(b, v, 10) case float64: b = strconv.AppendFloat(b, v, 'f', -1, 64) default: return fmt.Errorf("No matching type format") } if suffix != "" { b = append(b, suffix...) } if s.rate != 0 && s.rate != 1 { rate *= s.rate } if rate < 1 { b = append(b, "|@"...) b = strconv.AppendFloat(b, float64(rate), 'f', 6, 32) } _, err := s.sender.Send(b) return err }
func encode(parameterStatus *parameterStatus, x interface{}, pgtypOid oid.Oid) []byte { switch v := x.(type) { case int64: return strconv.AppendInt(nil, v, 10) case float64: return strconv.AppendFloat(nil, v, 'f', -1, 64) case []byte: if pgtypOid == oid.T_bytea { return encodeBytea(parameterStatus.serverVersion, v) } return v case string: if pgtypOid == oid.T_bytea { return encodeBytea(parameterStatus.serverVersion, []byte(v)) } return []byte(v) case bool: return strconv.AppendBool(nil, v) case time.Time: return formatTs(v) default: errorf("encode: unknown type for %T", v) } panic("not reached") }
func maxCellWidth(m Matrix, c rune, printed, prec int) ([]byte, int) { var ( buf = make([]byte, 0, 64) rows, cols = m.Dims() max int ) for i := 0; i < rows; i++ { if i >= printed-1 && i < rows-printed && 2*printed < rows { i = rows - printed - 1 continue } for j := 0; j < cols; j++ { if j >= printed && j < cols-printed { continue } buf = strconv.AppendFloat(buf, m.At(i, j), byte(c), prec, 64) if len(buf) > max { max = len(buf) } buf = buf[:0] } } return buf, max }
// EncodeSQLValue ... func EncodeSQLValue(buf []byte, arg interface{}) ([]byte, error) { // Use sql.driver to convert the arg to a sql.Value which is simply // an interface{} with a restricted set of types. This also takes // care of using the sql.Valuer interface to convert arbitrary types // into sql.Values. dv, err := driver.DefaultParameterConverter.ConvertValue(arg) if err != nil { return nil, fmt.Errorf("converting query argument type: %v", err) } switch v := dv.(type) { case nil: return append(buf, nullstr...), nil case bool: if v { return append(buf, '1'), nil } return append(buf, '0'), nil case int64: return strconv.AppendInt(buf, v, 10), nil case float64: return strconv.AppendFloat(buf, v, 'f', -1, 64), nil case string: return encodeSQLString(buf, []byte(v)), nil case []byte: return encodeSQLBytes(buf, v), nil case time.Time: return encodeSQLString(buf, []byte(v.Format("2006-01-02 15:04:05"))), nil default: return nil, fmt.Errorf("unsupported bind variable type %T: %v", arg, arg) } }
// formatFloat formats a float64; it is an efficient equivalent to f.pad(strconv.FormatFloat()...). func (f *fmt) formatFloat(v float64, verb byte, prec, n int) { // Format number, reserving space for leading + sign if needed. num := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n) if num[1] == '-' || num[1] == '+' { num = num[1:] } else { num[0] = '+' } // num is now a signed version of the number. // If we're zero padding, want the sign before the leading zeros. // Achieve this by writing the sign out and then padding the unsigned number. if f.zero && f.widPresent && f.wid > len(num) { f.buf.WriteByte(num[0]) f.wid-- f.pad(num[1:]) f.wid++ // Restore width; complex numbers will reuse this value for imaginary part. return } // f.space says to replace a leading + with a space. if f.space && num[0] == '+' { num[0] = ' ' f.pad(num) return } // Now we know the sign is attached directly to the number, if present at all. // We want a sign if asked for, if it's negative, or if it's infinity (+Inf vs. -Inf). if f.plus || num[0] == '-' || math.IsInf(v, 0) { f.pad(num) return } // No sign to show and the number is positive; just print the unsigned number. f.pad(num[1:]) }
// formatFloat formats a float64; it is an efficient equivalent to f.pad(strconv.FormatFloat()...). func (f *fmt) formatFloat(v float64, verb byte, prec, n int) { // We leave one byte at the beginning of f.intbuf for a sign if needed, // and make it a space, which we might be able to use. f.intbuf[0] = ' ' slice := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n) // Add a plus sign or space to the floating-point string representation if missing and required. // The formatted number starts at slice[1]. switch slice[1] { case '-', '+': // If we're zero padding, want the sign before the leading zeros. // Achieve this by writing the sign out and padding the postive number. if f.zero && f.widPresent && f.wid > len(slice) { f.buf.WriteByte(slice[1]) f.wid-- f.pad(slice[2:]) return } // We're set; drop the leading space. slice = slice[1:] default: // There's no sign, but we might need one. if f.plus { slice[0] = '+' } else if f.space { // space is already there } else { slice = slice[1:] } } f.pad(slice) }
func BenchmarkFloatToBytes1(b *testing.B) { r := []byte{} //make([]byte, 10) f := 123.456 for i := 0; i < b.N; i++ { r = strconv.AppendFloat(r[:0], f, 'g', 6, 64) } }
func (e *jsonEncDriver) EncodeFloat64(f float64) { if c := e.s.sc.sep(); c != 0 { e.w.writen1(c) } // e.w.writestr(strconv.FormatFloat(f, 'E', -1, 64)) e.w.writeb(strconv.AppendFloat(e.b[:0], f, 'E', -1, 64)) }
func (p *PathData) shortenAltPosInstruction(cmd byte, coordFloats []float64, x, y float64) PathDataState { state := p.state p.altBuffer = p.altBuffer[:0] if cmd != state.cmd && !(state.cmd == 'M' && cmd == 'L' || state.cmd == 'm' && cmd == 'l') { p.altBuffer = append(p.altBuffer, cmd) state.cmd = cmd state.prevDigit = false state.prevDigitIsInt = false } for i, f := range coordFloats { if cmd == 'L' || cmd == 'l' || cmd == 'C' || cmd == 'c' || cmd == 'S' || cmd == 's' || cmd == 'Q' || cmd == 'q' || cmd == 'T' || cmd == 't' || cmd == 'M' || cmd == 'm' { if i%2 == 0 { f += x } else { f += y } } else if cmd == 'H' || cmd == 'h' { f += x } else if cmd == 'V' || cmd == 'v' { f += y } else if cmd == 'A' || cmd == 'a' { if i%7 == 5 { f += x } else if i%7 == 6 { f += y } } p.coordBuffer = strconvStdlib.AppendFloat(p.coordBuffer[:0], f, 'g', -1, 64) coord := minify.Number(p.coordBuffer, p.o.Decimals) state.copyNumber(&p.altBuffer, coord) } return state }
func (ps *Sample) AppendToPhout(dst []byte) []byte { dst = strconv.AppendFloat(dst, ps.TS, 'f', 3, 64) dst = append(dst, phoutDelimiter) dst = append(dst, ps.Tag...) dst = append(dst, phoutDelimiter) dst = strconv.AppendInt(dst, int64(ps.RT), 10) dst = append(dst, phoutDelimiter) dst = strconv.AppendInt(dst, int64(ps.Connect), 10) dst = append(dst, phoutDelimiter) dst = strconv.AppendInt(dst, int64(ps.Send), 10) dst = append(dst, phoutDelimiter) dst = strconv.AppendInt(dst, int64(ps.Latency), 10) dst = append(dst, phoutDelimiter) dst = strconv.AppendInt(dst, int64(ps.Receive), 10) dst = append(dst, phoutDelimiter) dst = strconv.AppendInt(dst, int64(ps.IntervalEvent), 10) dst = append(dst, phoutDelimiter) dst = strconv.AppendInt(dst, int64(ps.Egress), 10) dst = append(dst, phoutDelimiter) dst = strconv.AppendInt(dst, int64(ps.Igress), 10) dst = append(dst, phoutDelimiter) dst = strconv.AppendInt(dst, int64(ps.NetCode), 10) dst = append(dst, phoutDelimiter) dst = strconv.AppendInt(dst, int64(ps.ProtoCode), 10) dst = append(dst, phoutNewLine) return dst }
func Hincrbyfloat(args [][]byte, wb *levigo.WriteBatch) interface{} { mk := metaKey(args[0]) length, err := hlen(mk, nil) if err != nil { return err } key := NewKeyBufferWithSuffix(HashKey, args[0], args[1]).Key() res, err := DB.Get(DefaultReadOptions, key) if err != nil { return err } var current float64 if res != nil { current, err = bconv.ParseFloat(res, 64) if err != nil { return fmt.Errorf("hash value is not a valid float") } } increment, err := bconv.ParseFloat(args[2], 64) if err != nil { return fmt.Errorf("value is not a valid float") } result := strconv.AppendFloat(nil, current+increment, 'f', -1, 64) wb.Put(key, result) // if is a new key, increment the hash length if res == nil { setHlen(mk, length+1, wb) } return result }
// This function exists to manually encode floats. func (ts Timeseries) MarshalJSON() ([]byte, error) { var buffer bytes.Buffer var scratch [64]byte buffer.WriteByte('{') buffer.WriteString("\"tagset\":") tagset, err := json.Marshal(ts.TagSet) if err != nil { return []byte{}, err } buffer.Write(tagset) buffer.WriteByte(',') buffer.WriteString("\"values\":") buffer.WriteByte('[') n := len(ts.Values) for i := 0; i < n; i++ { if i > 0 { buffer.WriteByte(',') } f := ts.Values[i] if math.IsInf(f, 1) { buffer.WriteString("null") // TODO - positive infinity } else if math.IsInf(f, -1) { buffer.WriteString("null") // TODO - negative infinity } else if math.IsNaN(f) { buffer.WriteString("null") } else { b := strconv.AppendFloat(scratch[:0], f, 'g', -1, 64) buffer.Write(b) } } buffer.WriteByte(']') buffer.WriteByte('}') return buffer.Bytes(), err }
func BuildValue(goval interface{}) (v Value, err error) { switch bindVal := goval.(type) { case nil: // no op case int: v = Value{Numeric(strconv.AppendInt(nil, int64(bindVal), 10))} case int32: v = Value{Numeric(strconv.AppendInt(nil, int64(bindVal), 10))} case int64: v = Value{Numeric(strconv.AppendInt(nil, int64(bindVal), 10))} case uint: v = Value{Numeric(strconv.AppendUint(nil, uint64(bindVal), 10))} case uint32: v = Value{Numeric(strconv.AppendUint(nil, uint64(bindVal), 10))} case uint64: v = Value{Numeric(strconv.AppendUint(nil, uint64(bindVal), 10))} case float64: v = Value{Fractional(strconv.AppendFloat(nil, bindVal, 'f', -1, 64))} case string: v = Value{String([]byte(bindVal))} case []byte: v = Value{String(bindVal)} case time.Time: v = Value{String([]byte(bindVal.Format("'2006-01-02 15:04:05'")))} case Numeric, Fractional, String: v = Value{bindVal.(InnerValue)} case Value: v = bindVal default: return Value{}, fmt.Errorf("Unsupported bind variable type %T: %v", goval, goval) } return v, nil }
func (e *jsonEncDriver) encodeFloat(f float64, numbits int) { x := strconv.AppendFloat(e.b[:0], f, 'G', -1, numbits) e.w.writeb(x) if bytes.IndexByte(x, 'E') == -1 && bytes.IndexByte(x, '.') == -1 { e.w.writen2('.', '0') } }
func MarshalRaw(results []*MetricData) []byte { var b []byte for _, r := range results { b = append(b, r.GetName()...) b = append(b, ',') b = strconv.AppendInt(b, int64(r.GetStartTime()), 10) b = append(b, ',') b = strconv.AppendInt(b, int64(r.GetStopTime()), 10) b = append(b, ',') b = strconv.AppendInt(b, int64(r.GetStepTime()), 10) b = append(b, '|') var comma bool for i, v := range r.Values { if comma { b = append(b, ',') } comma = true if r.IsAbsent[i] { b = append(b, "None"...) } else { b = strconv.AppendFloat(b, v, 'f', -1, 64) } } b = append(b, '\n') } return b }
func (c *conn) wBulkFloat64(f float64) (err error) { b := strconv.AppendFloat([]byte{}, f, 'g', -1, 64) l := len(b) c.wLen('$', l) c.bw.Write(b) err = c.wCRLF() return }
func rwFloat64(dst jsWriter, src *Reader) (int, error) { f, err := src.ReadFloat64() if err != nil { return 0, err } src.scratch = strconv.AppendFloat(src.scratch[:0], f, 'f', -1, 32) return dst.Write(src.scratch) }
func (bits floatEncoder) encode(e *encodeState, v reflect.Value) { f := v.Float() if math.IsInf(f, 0) || math.IsNaN(f) { e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))}) } b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, int(bits)) e.Write(b) }
// SampledDeltaFloat64 emits a 'sampled' float64 delta with the given rate. func (c *Client) SampledDeltaFloat64(stat string, val float64, rate float32) error { b := c.getbuf(stat) if val > 0 { b = append(b, '+') } b = strconv.AppendFloat(b, val, 'f', 10, 64) return c.finishbuf(b, "|g", rate) }
func dumpTextValue(mysqlType uint8, value interface{}) ([]byte, error) { switch v := value.(type) { case int8: return strconv.AppendInt(nil, int64(v), 10), nil case int16: return strconv.AppendInt(nil, int64(v), 10), nil case int32: return strconv.AppendInt(nil, int64(v), 10), nil case int64: return strconv.AppendInt(nil, int64(v), 10), nil case int: return strconv.AppendInt(nil, int64(v), 10), nil case uint8: return strconv.AppendUint(nil, uint64(v), 10), nil case uint16: return strconv.AppendUint(nil, uint64(v), 10), nil case uint32: return strconv.AppendUint(nil, uint64(v), 10), nil case uint64: return strconv.AppendUint(nil, uint64(v), 10), nil case uint: return strconv.AppendUint(nil, uint64(v), 10), nil case float32: return strconv.AppendFloat(nil, float64(v), 'f', -1, 32), nil case float64: return strconv.AppendFloat(nil, float64(v), 'f', -1, 64), nil case []byte: return v, nil case string: return hack.Slice(v), nil case mysql.Time: return hack.Slice(v.String()), nil case mysql.Duration: return hack.Slice(v.String()), nil case mysql.Decimal: return hack.Slice(v.String()), nil case mysql.Enum: return hack.Slice(v.String()), nil case mysql.Set: return hack.Slice(v.String()), nil case mysql.Bit: return hack.Slice(v.ToString()), nil default: return nil, errors.Errorf("invalid type %T", value) } }
// GaugeSmpl is a statsd gauge, after sampling by Sample(). func (t *T) GaugeSmpl(k string, v float64) { b := make([]byte, 0, len(k)+20) b = append(b, []byte(k)...) b = append(b, ':') b = strconv.AppendFloat(b, v, 'f', 6, 64) b = append(b, '|', 'g') t.p <- b }
// WriteFloat64 encodes and writes a 64-bit float. func (e *encoder) WriteFloat64(v float64) error { if err := e.check(); err != nil { return err } buf := strconv.AppendFloat(e.buf[e.pos:e.pos], v, 'g', -1, 64) e.pos += len(buf) return nil }