1// Package models implements basic objects used throughout the TICK stack.
2package models // import "github.com/influxdata/influxdb/models"
3
4import (
5	"bytes"
6	"encoding/binary"
7	"errors"
8	"fmt"
9	"io"
10	"math"
11	"sort"
12	"strconv"
13	"strings"
14	"time"
15	"unicode"
16	"unicode/utf8"
17
18	"github.com/influxdata/influxdb/pkg/escape"
19)
20
21// Values used to store the field key and measurement name as special internal
22// tags.
23const (
24	FieldKeyTagKey    = "\xff"
25	MeasurementTagKey = "\x00"
26)
27
28// Predefined byte representations of special tag keys.
29var (
30	FieldKeyTagKeyBytes    = []byte(FieldKeyTagKey)
31	MeasurementTagKeyBytes = []byte(MeasurementTagKey)
32)
33
34type escapeSet struct {
35	k   [1]byte
36	esc [2]byte
37}
38
39var (
40	measurementEscapeCodes = [...]escapeSet{
41		{k: [1]byte{','}, esc: [2]byte{'\\', ','}},
42		{k: [1]byte{' '}, esc: [2]byte{'\\', ' '}},
43	}
44
45	tagEscapeCodes = [...]escapeSet{
46		{k: [1]byte{','}, esc: [2]byte{'\\', ','}},
47		{k: [1]byte{' '}, esc: [2]byte{'\\', ' '}},
48		{k: [1]byte{'='}, esc: [2]byte{'\\', '='}},
49	}
50
51	// ErrPointMustHaveAField is returned when operating on a point that does not have any fields.
52	ErrPointMustHaveAField = errors.New("point without fields is unsupported")
53
54	// ErrInvalidNumber is returned when a number is expected but not provided.
55	ErrInvalidNumber = errors.New("invalid number")
56
57	// ErrInvalidPoint is returned when a point cannot be parsed correctly.
58	ErrInvalidPoint = errors.New("point is invalid")
59)
60
61const (
62	// MaxKeyLength is the largest allowed size of the combined measurement and tag keys.
63	MaxKeyLength = 65535
64)
65
66// enableUint64Support will enable uint64 support if set to true.
67var enableUint64Support = false
68
69// EnableUintSupport manually enables uint support for the point parser.
70// This function will be removed in the future and only exists for unit tests during the
71// transition.
72func EnableUintSupport() {
73	enableUint64Support = true
74}
75
76// Point defines the values that will be written to the database.
77type Point interface {
78	// Name return the measurement name for the point.
79	Name() []byte
80
81	// SetName updates the measurement name for the point.
82	SetName(string)
83
84	// Tags returns the tag set for the point.
85	Tags() Tags
86
87	// ForEachTag iterates over each tag invoking fn.  If fn return false, iteration stops.
88	ForEachTag(fn func(k, v []byte) bool)
89
90	// AddTag adds or replaces a tag value for a point.
91	AddTag(key, value string)
92
93	// SetTags replaces the tags for the point.
94	SetTags(tags Tags)
95
96	// HasTag returns true if the tag exists for the point.
97	HasTag(tag []byte) bool
98
99	// Fields returns the fields for the point.
100	Fields() (Fields, error)
101
102	// Time return the timestamp for the point.
103	Time() time.Time
104
105	// SetTime updates the timestamp for the point.
106	SetTime(t time.Time)
107
108	// UnixNano returns the timestamp of the point as nanoseconds since Unix epoch.
109	UnixNano() int64
110
111	// HashID returns a non-cryptographic checksum of the point's key.
112	HashID() uint64
113
114	// Key returns the key (measurement joined with tags) of the point.
115	Key() []byte
116
117	// String returns a string representation of the point. If there is a
118	// timestamp associated with the point then it will be specified with the default
119	// precision of nanoseconds.
120	String() string
121
122	// MarshalBinary returns a binary representation of the point.
123	MarshalBinary() ([]byte, error)
124
125	// PrecisionString returns a string representation of the point. If there
126	// is a timestamp associated with the point then it will be specified in the
127	// given unit.
128	PrecisionString(precision string) string
129
130	// RoundedString returns a string representation of the point. If there
131	// is a timestamp associated with the point, then it will be rounded to the
132	// given duration.
133	RoundedString(d time.Duration) string
134
135	// Split will attempt to return multiple points with the same timestamp whose
136	// string representations are no longer than size. Points with a single field or
137	// a point without a timestamp may exceed the requested size.
138	Split(size int) []Point
139
140	// Round will round the timestamp of the point to the given duration.
141	Round(d time.Duration)
142
143	// StringSize returns the length of the string that would be returned by String().
144	StringSize() int
145
146	// AppendString appends the result of String() to the provided buffer and returns
147	// the result, potentially reducing string allocations.
148	AppendString(buf []byte) []byte
149
150	// FieldIterator returns a FieldIterator that can be used to traverse the
151	// fields of a point without constructing the in-memory map.
152	FieldIterator() FieldIterator
153}
154
155// FieldType represents the type of a field.
156type FieldType int
157
158const (
159	// Integer indicates the field's type is integer.
160	Integer FieldType = iota
161
162	// Float indicates the field's type is float.
163	Float
164
165	// Boolean indicates the field's type is boolean.
166	Boolean
167
168	// String indicates the field's type is string.
169	String
170
171	// Empty is used to indicate that there is no field.
172	Empty
173
174	// Unsigned indicates the field's type is an unsigned integer.
175	Unsigned
176)
177
178// FieldIterator provides a low-allocation interface to iterate through a point's fields.
179type FieldIterator interface {
180	// Next indicates whether there any fields remaining.
181	Next() bool
182
183	// FieldKey returns the key of the current field.
184	FieldKey() []byte
185
186	// Type returns the FieldType of the current field.
187	Type() FieldType
188
189	// StringValue returns the string value of the current field.
190	StringValue() string
191
192	// IntegerValue returns the integer value of the current field.
193	IntegerValue() (int64, error)
194
195	// UnsignedValue returns the unsigned value of the current field.
196	UnsignedValue() (uint64, error)
197
198	// BooleanValue returns the boolean value of the current field.
199	BooleanValue() (bool, error)
200
201	// FloatValue returns the float value of the current field.
202	FloatValue() (float64, error)
203
204	// Reset resets the iterator to its initial state.
205	Reset()
206}
207
208// Points represents a sortable list of points by timestamp.
209type Points []Point
210
211// Len implements sort.Interface.
212func (a Points) Len() int { return len(a) }
213
214// Less implements sort.Interface.
215func (a Points) Less(i, j int) bool { return a[i].Time().Before(a[j].Time()) }
216
217// Swap implements sort.Interface.
218func (a Points) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
219
220// point is the default implementation of Point.
221type point struct {
222	time time.Time
223
224	// text encoding of measurement and tags
225	// key must always be stored sorted by tags, if the original line was not sorted,
226	// we need to resort it
227	key []byte
228
229	// text encoding of field data
230	fields []byte
231
232	// text encoding of timestamp
233	ts []byte
234
235	// cached version of parsed fields from data
236	cachedFields map[string]interface{}
237
238	// cached version of parsed name from key
239	cachedName string
240
241	// cached version of parsed tags
242	cachedTags Tags
243
244	it fieldIterator
245}
246
247// type assertions
248var (
249	_ Point         = (*point)(nil)
250	_ FieldIterator = (*point)(nil)
251)
252
253const (
254	// the number of characters for the largest possible int64 (9223372036854775807)
255	maxInt64Digits = 19
256
257	// the number of characters for the smallest possible int64 (-9223372036854775808)
258	minInt64Digits = 20
259
260	// the number of characters for the largest possible uint64 (18446744073709551615)
261	maxUint64Digits = 20
262
263	// the number of characters required for the largest float64 before a range check
264	// would occur during parsing
265	maxFloat64Digits = 25
266
267	// the number of characters required for smallest float64 before a range check occur
268	// would occur during parsing
269	minFloat64Digits = 27
270)
271
272// ParsePoints returns a slice of Points from a text representation of a point
273// with each point separated by newlines.  If any points fail to parse, a non-nil error
274// will be returned in addition to the points that parsed successfully.
275func ParsePoints(buf []byte) ([]Point, error) {
276	return ParsePointsWithPrecision(buf, time.Now().UTC(), "n")
277}
278
279// ParsePointsString is identical to ParsePoints but accepts a string.
280func ParsePointsString(buf string) ([]Point, error) {
281	return ParsePoints([]byte(buf))
282}
283
284// ParseKey returns the measurement name and tags from a point.
285//
286// NOTE: to minimize heap allocations, the returned Tags will refer to subslices of buf.
287// This can have the unintended effect preventing buf from being garbage collected.
288func ParseKey(buf []byte) (string, Tags) {
289	name, tags := ParseKeyBytes(buf)
290	return string(name), tags
291}
292
293func ParseKeyBytes(buf []byte) ([]byte, Tags) {
294	return ParseKeyBytesWithTags(buf, nil)
295}
296
297func ParseKeyBytesWithTags(buf []byte, tags Tags) ([]byte, Tags) {
298	// Ignore the error because scanMeasurement returns "missing fields" which we ignore
299	// when just parsing a key
300	state, i, _ := scanMeasurement(buf, 0)
301
302	var name []byte
303	if state == tagKeyState {
304		tags = parseTags(buf, tags)
305		// scanMeasurement returns the location of the comma if there are tags, strip that off
306		name = buf[:i-1]
307	} else {
308		name = buf[:i]
309	}
310	return unescapeMeasurement(name), tags
311}
312
313func ParseTags(buf []byte) Tags {
314	return parseTags(buf, nil)
315}
316
317func ParseName(buf []byte) []byte {
318	// Ignore the error because scanMeasurement returns "missing fields" which we ignore
319	// when just parsing a key
320	state, i, _ := scanMeasurement(buf, 0)
321	var name []byte
322	if state == tagKeyState {
323		name = buf[:i-1]
324	} else {
325		name = buf[:i]
326	}
327
328	return unescapeMeasurement(name)
329}
330
331// ParsePointsWithPrecision is similar to ParsePoints, but allows the
332// caller to provide a precision for time.
333//
334// NOTE: to minimize heap allocations, the returned Points will refer to subslices of buf.
335// This can have the unintended effect preventing buf from being garbage collected.
336func ParsePointsWithPrecision(buf []byte, defaultTime time.Time, precision string) ([]Point, error) {
337	points := make([]Point, 0, bytes.Count(buf, []byte{'\n'})+1)
338	var (
339		pos    int
340		block  []byte
341		failed []string
342	)
343	for pos < len(buf) {
344		pos, block = scanLine(buf, pos)
345		pos++
346
347		if len(block) == 0 {
348			continue
349		}
350
351		start := skipWhitespace(block, 0)
352
353		// If line is all whitespace, just skip it
354		if start >= len(block) {
355			continue
356		}
357
358		// lines which start with '#' are comments
359		if block[start] == '#' {
360			continue
361		}
362
363		// strip the newline if one is present
364		if block[len(block)-1] == '\n' {
365			block = block[:len(block)-1]
366		}
367
368		pt, err := parsePoint(block[start:], defaultTime, precision)
369		if err != nil {
370			failed = append(failed, fmt.Sprintf("unable to parse '%s': %v", string(block[start:]), err))
371		} else {
372			points = append(points, pt)
373		}
374
375	}
376	if len(failed) > 0 {
377		return points, fmt.Errorf("%s", strings.Join(failed, "\n"))
378	}
379	return points, nil
380
381}
382
383func parsePoint(buf []byte, defaultTime time.Time, precision string) (Point, error) {
384	// scan the first block which is measurement[,tag1=value1,tag2=value2...]
385	pos, key, err := scanKey(buf, 0)
386	if err != nil {
387		return nil, err
388	}
389
390	// measurement name is required
391	if len(key) == 0 {
392		return nil, fmt.Errorf("missing measurement")
393	}
394
395	if len(key) > MaxKeyLength {
396		return nil, fmt.Errorf("max key length exceeded: %v > %v", len(key), MaxKeyLength)
397	}
398
399	// scan the second block is which is field1=value1[,field2=value2,...]
400	pos, fields, err := scanFields(buf, pos)
401	if err != nil {
402		return nil, err
403	}
404
405	// at least one field is required
406	if len(fields) == 0 {
407		return nil, fmt.Errorf("missing fields")
408	}
409
410	var maxKeyErr error
411	err = walkFields(fields, func(k, v []byte) bool {
412		if sz := seriesKeySize(key, k); sz > MaxKeyLength {
413			maxKeyErr = fmt.Errorf("max key length exceeded: %v > %v", sz, MaxKeyLength)
414			return false
415		}
416		return true
417	})
418
419	if err != nil {
420		return nil, err
421	}
422
423	if maxKeyErr != nil {
424		return nil, maxKeyErr
425	}
426
427	// scan the last block which is an optional integer timestamp
428	pos, ts, err := scanTime(buf, pos)
429	if err != nil {
430		return nil, err
431	}
432
433	pt := &point{
434		key:    key,
435		fields: fields,
436		ts:     ts,
437	}
438
439	if len(ts) == 0 {
440		pt.time = defaultTime
441		pt.SetPrecision(precision)
442	} else {
443		ts, err := parseIntBytes(ts, 10, 64)
444		if err != nil {
445			return nil, err
446		}
447		pt.time, err = SafeCalcTime(ts, precision)
448		if err != nil {
449			return nil, err
450		}
451
452		// Determine if there are illegal non-whitespace characters after the
453		// timestamp block.
454		for pos < len(buf) {
455			if buf[pos] != ' ' {
456				return nil, ErrInvalidPoint
457			}
458			pos++
459		}
460	}
461	return pt, nil
462}
463
464// GetPrecisionMultiplier will return a multiplier for the precision specified.
465func GetPrecisionMultiplier(precision string) int64 {
466	d := time.Nanosecond
467	switch precision {
468	case "u":
469		d = time.Microsecond
470	case "ms":
471		d = time.Millisecond
472	case "s":
473		d = time.Second
474	case "m":
475		d = time.Minute
476	case "h":
477		d = time.Hour
478	}
479	return int64(d)
480}
481
482// scanKey scans buf starting at i for the measurement and tag portion of the point.
483// It returns the ending position and the byte slice of key within buf.  If there
484// are tags, they will be sorted if they are not already.
485func scanKey(buf []byte, i int) (int, []byte, error) {
486	start := skipWhitespace(buf, i)
487
488	i = start
489
490	// Determines whether the tags are sort, assume they are
491	sorted := true
492
493	// indices holds the indexes within buf of the start of each tag.  For example,
494	// a buf of 'cpu,host=a,region=b,zone=c' would have indices slice of [4,11,20]
495	// which indicates that the first tag starts at buf[4], seconds at buf[11], and
496	// last at buf[20]
497	indices := make([]int, 100)
498
499	// tracks how many commas we've seen so we know how many values are indices.
500	// Since indices is an arbitrarily large slice,
501	// we need to know how many values in the buffer are in use.
502	commas := 0
503
504	// First scan the Point's measurement.
505	state, i, err := scanMeasurement(buf, i)
506	if err != nil {
507		return i, buf[start:i], err
508	}
509
510	// Optionally scan tags if needed.
511	if state == tagKeyState {
512		i, commas, indices, err = scanTags(buf, i, indices)
513		if err != nil {
514			return i, buf[start:i], err
515		}
516	}
517
518	// Now we know where the key region is within buf, and the location of tags, we
519	// need to determine if duplicate tags exist and if the tags are sorted. This iterates
520	// over the list comparing each tag in the sequence with each other.
521	for j := 0; j < commas-1; j++ {
522		// get the left and right tags
523		_, left := scanTo(buf[indices[j]:indices[j+1]-1], 0, '=')
524		_, right := scanTo(buf[indices[j+1]:indices[j+2]-1], 0, '=')
525
526		// If left is greater than right, the tags are not sorted. We do not have to
527		// continue because the short path no longer works.
528		// If the tags are equal, then there are duplicate tags, and we should abort.
529		// If the tags are not sorted, this pass may not find duplicate tags and we
530		// need to do a more exhaustive search later.
531		if cmp := bytes.Compare(left, right); cmp > 0 {
532			sorted = false
533			break
534		} else if cmp == 0 {
535			return i, buf[start:i], fmt.Errorf("duplicate tags")
536		}
537	}
538
539	// If the tags are not sorted, then sort them.  This sort is inline and
540	// uses the tag indices we created earlier.  The actual buffer is not sorted, the
541	// indices are using the buffer for value comparison.  After the indices are sorted,
542	// the buffer is reconstructed from the sorted indices.
543	if !sorted && commas > 0 {
544		// Get the measurement name for later
545		measurement := buf[start : indices[0]-1]
546
547		// Sort the indices
548		indices := indices[:commas]
549		insertionSort(0, commas, buf, indices)
550
551		// Create a new key using the measurement and sorted indices
552		b := make([]byte, len(buf[start:i]))
553		pos := copy(b, measurement)
554		for _, i := range indices {
555			b[pos] = ','
556			pos++
557			_, v := scanToSpaceOr(buf, i, ',')
558			pos += copy(b[pos:], v)
559		}
560
561		// Check again for duplicate tags now that the tags are sorted.
562		for j := 0; j < commas-1; j++ {
563			// get the left and right tags
564			_, left := scanTo(buf[indices[j]:], 0, '=')
565			_, right := scanTo(buf[indices[j+1]:], 0, '=')
566
567			// If the tags are equal, then there are duplicate tags, and we should abort.
568			// If the tags are not sorted, this pass may not find duplicate tags and we
569			// need to do a more exhaustive search later.
570			if bytes.Equal(left, right) {
571				return i, b, fmt.Errorf("duplicate tags")
572			}
573		}
574
575		return i, b, nil
576	}
577
578	return i, buf[start:i], nil
579}
580
581// The following constants allow us to specify which state to move to
582// next, when scanning sections of a Point.
583const (
584	tagKeyState = iota
585	tagValueState
586	fieldsState
587)
588
589// scanMeasurement examines the measurement part of a Point, returning
590// the next state to move to, and the current location in the buffer.
591func scanMeasurement(buf []byte, i int) (int, int, error) {
592	// Check first byte of measurement, anything except a comma is fine.
593	// It can't be a space, since whitespace is stripped prior to this
594	// function call.
595	if i >= len(buf) || buf[i] == ',' {
596		return -1, i, fmt.Errorf("missing measurement")
597	}
598
599	for {
600		i++
601		if i >= len(buf) {
602			// cpu
603			return -1, i, fmt.Errorf("missing fields")
604		}
605
606		if buf[i-1] == '\\' {
607			// Skip character (it's escaped).
608			continue
609		}
610
611		// Unescaped comma; move onto scanning the tags.
612		if buf[i] == ',' {
613			return tagKeyState, i + 1, nil
614		}
615
616		// Unescaped space; move onto scanning the fields.
617		if buf[i] == ' ' {
618			// cpu value=1.0
619			return fieldsState, i, nil
620		}
621	}
622}
623
624// scanTags examines all the tags in a Point, keeping track of and
625// returning the updated indices slice, number of commas and location
626// in buf where to start examining the Point fields.
627func scanTags(buf []byte, i int, indices []int) (int, int, []int, error) {
628	var (
629		err    error
630		commas int
631		state  = tagKeyState
632	)
633
634	for {
635		switch state {
636		case tagKeyState:
637			// Grow our indices slice if we have too many tags.
638			if commas >= len(indices) {
639				newIndics := make([]int, cap(indices)*2)
640				copy(newIndics, indices)
641				indices = newIndics
642			}
643			indices[commas] = i
644			commas++
645
646			i, err = scanTagsKey(buf, i)
647			state = tagValueState // tag value always follows a tag key
648		case tagValueState:
649			state, i, err = scanTagsValue(buf, i)
650		case fieldsState:
651			indices[commas] = i + 1
652			return i, commas, indices, nil
653		}
654
655		if err != nil {
656			return i, commas, indices, err
657		}
658	}
659}
660
661// scanTagsKey scans each character in a tag key.
662func scanTagsKey(buf []byte, i int) (int, error) {
663	// First character of the key.
664	if i >= len(buf) || buf[i] == ' ' || buf[i] == ',' || buf[i] == '=' {
665		// cpu,{'', ' ', ',', '='}
666		return i, fmt.Errorf("missing tag key")
667	}
668
669	// Examine each character in the tag key until we hit an unescaped
670	// equals (the tag value), or we hit an error (i.e., unescaped
671	// space or comma).
672	for {
673		i++
674
675		// Either we reached the end of the buffer or we hit an
676		// unescaped comma or space.
677		if i >= len(buf) ||
678			((buf[i] == ' ' || buf[i] == ',') && buf[i-1] != '\\') {
679			// cpu,tag{'', ' ', ','}
680			return i, fmt.Errorf("missing tag value")
681		}
682
683		if buf[i] == '=' && buf[i-1] != '\\' {
684			// cpu,tag=
685			return i + 1, nil
686		}
687	}
688}
689
690// scanTagsValue scans each character in a tag value.
691func scanTagsValue(buf []byte, i int) (int, int, error) {
692	// Tag value cannot be empty.
693	if i >= len(buf) || buf[i] == ',' || buf[i] == ' ' {
694		// cpu,tag={',', ' '}
695		return -1, i, fmt.Errorf("missing tag value")
696	}
697
698	// Examine each character in the tag value until we hit an unescaped
699	// comma (move onto next tag key), an unescaped space (move onto
700	// fields), or we error out.
701	for {
702		i++
703		if i >= len(buf) {
704			// cpu,tag=value
705			return -1, i, fmt.Errorf("missing fields")
706		}
707
708		// An unescaped equals sign is an invalid tag value.
709		if buf[i] == '=' && buf[i-1] != '\\' {
710			// cpu,tag={'=', 'fo=o'}
711			return -1, i, fmt.Errorf("invalid tag format")
712		}
713
714		if buf[i] == ',' && buf[i-1] != '\\' {
715			// cpu,tag=foo,
716			return tagKeyState, i + 1, nil
717		}
718
719		// cpu,tag=foo value=1.0
720		// cpu, tag=foo\= value=1.0
721		if buf[i] == ' ' && buf[i-1] != '\\' {
722			return fieldsState, i, nil
723		}
724	}
725}
726
727func insertionSort(l, r int, buf []byte, indices []int) {
728	for i := l + 1; i < r; i++ {
729		for j := i; j > l && less(buf, indices, j, j-1); j-- {
730			indices[j], indices[j-1] = indices[j-1], indices[j]
731		}
732	}
733}
734
735func less(buf []byte, indices []int, i, j int) bool {
736	// This grabs the tag names for i & j, it ignores the values
737	_, a := scanTo(buf, indices[i], '=')
738	_, b := scanTo(buf, indices[j], '=')
739	return bytes.Compare(a, b) < 0
740}
741
742// scanFields scans buf, starting at i for the fields section of a point.  It returns
743// the ending position and the byte slice of the fields within buf.
744func scanFields(buf []byte, i int) (int, []byte, error) {
745	start := skipWhitespace(buf, i)
746	i = start
747	quoted := false
748
749	// tracks how many '=' we've seen
750	equals := 0
751
752	// tracks how many commas we've seen
753	commas := 0
754
755	for {
756		// reached the end of buf?
757		if i >= len(buf) {
758			break
759		}
760
761		// escaped characters?
762		if buf[i] == '\\' && i+1 < len(buf) {
763			i += 2
764			continue
765		}
766
767		// If the value is quoted, scan until we get to the end quote
768		// Only quote values in the field value since quotes are not significant
769		// in the field key
770		if buf[i] == '"' && equals > commas {
771			quoted = !quoted
772			i++
773			continue
774		}
775
776		// If we see an =, ensure that there is at least on char before and after it
777		if buf[i] == '=' && !quoted {
778			equals++
779
780			// check for "... =123" but allow "a\ =123"
781			if buf[i-1] == ' ' && buf[i-2] != '\\' {
782				return i, buf[start:i], fmt.Errorf("missing field key")
783			}
784
785			// check for "...a=123,=456" but allow "a=123,a\,=456"
786			if buf[i-1] == ',' && buf[i-2] != '\\' {
787				return i, buf[start:i], fmt.Errorf("missing field key")
788			}
789
790			// check for "... value="
791			if i+1 >= len(buf) {
792				return i, buf[start:i], fmt.Errorf("missing field value")
793			}
794
795			// check for "... value=,value2=..."
796			if buf[i+1] == ',' || buf[i+1] == ' ' {
797				return i, buf[start:i], fmt.Errorf("missing field value")
798			}
799
800			if isNumeric(buf[i+1]) || buf[i+1] == '-' || buf[i+1] == 'N' || buf[i+1] == 'n' {
801				var err error
802				i, err = scanNumber(buf, i+1)
803				if err != nil {
804					return i, buf[start:i], err
805				}
806				continue
807			}
808			// If next byte is not a double-quote, the value must be a boolean
809			if buf[i+1] != '"' {
810				var err error
811				i, _, err = scanBoolean(buf, i+1)
812				if err != nil {
813					return i, buf[start:i], err
814				}
815				continue
816			}
817		}
818
819		if buf[i] == ',' && !quoted {
820			commas++
821		}
822
823		// reached end of block?
824		if buf[i] == ' ' && !quoted {
825			break
826		}
827		i++
828	}
829
830	if quoted {
831		return i, buf[start:i], fmt.Errorf("unbalanced quotes")
832	}
833
834	// check that all field sections had key and values (e.g. prevent "a=1,b"
835	if equals == 0 || commas != equals-1 {
836		return i, buf[start:i], fmt.Errorf("invalid field format")
837	}
838
839	return i, buf[start:i], nil
840}
841
842// scanTime scans buf, starting at i for the time section of a point. It
843// returns the ending position and the byte slice of the timestamp within buf
844// and and error if the timestamp is not in the correct numeric format.
845func scanTime(buf []byte, i int) (int, []byte, error) {
846	start := skipWhitespace(buf, i)
847	i = start
848
849	for {
850		// reached the end of buf?
851		if i >= len(buf) {
852			break
853		}
854
855		// Reached end of block or trailing whitespace?
856		if buf[i] == '\n' || buf[i] == ' ' {
857			break
858		}
859
860		// Handle negative timestamps
861		if i == start && buf[i] == '-' {
862			i++
863			continue
864		}
865
866		// Timestamps should be integers, make sure they are so we don't need
867		// to actually  parse the timestamp until needed.
868		if buf[i] < '0' || buf[i] > '9' {
869			return i, buf[start:i], fmt.Errorf("bad timestamp")
870		}
871		i++
872	}
873	return i, buf[start:i], nil
874}
875
876func isNumeric(b byte) bool {
877	return (b >= '0' && b <= '9') || b == '.'
878}
879
880// scanNumber returns the end position within buf, start at i after
881// scanning over buf for an integer, or float.  It returns an
882// error if a invalid number is scanned.
883func scanNumber(buf []byte, i int) (int, error) {
884	start := i
885	var isInt, isUnsigned bool
886
887	// Is negative number?
888	if i < len(buf) && buf[i] == '-' {
889		i++
890		// There must be more characters now, as just '-' is illegal.
891		if i == len(buf) {
892			return i, ErrInvalidNumber
893		}
894	}
895
896	// how many decimal points we've see
897	decimal := false
898
899	// indicates the number is float in scientific notation
900	scientific := false
901
902	for {
903		if i >= len(buf) {
904			break
905		}
906
907		if buf[i] == ',' || buf[i] == ' ' {
908			break
909		}
910
911		if buf[i] == 'i' && i > start && !(isInt || isUnsigned) {
912			isInt = true
913			i++
914			continue
915		} else if buf[i] == 'u' && i > start && !(isInt || isUnsigned) {
916			isUnsigned = true
917			i++
918			continue
919		}
920
921		if buf[i] == '.' {
922			// Can't have more than 1 decimal (e.g. 1.1.1 should fail)
923			if decimal {
924				return i, ErrInvalidNumber
925			}
926			decimal = true
927		}
928
929		// `e` is valid for floats but not as the first char
930		if i > start && (buf[i] == 'e' || buf[i] == 'E') {
931			scientific = true
932			i++
933			continue
934		}
935
936		// + and - are only valid at this point if they follow an e (scientific notation)
937		if (buf[i] == '+' || buf[i] == '-') && (buf[i-1] == 'e' || buf[i-1] == 'E') {
938			i++
939			continue
940		}
941
942		// NaN is an unsupported value
943		if i+2 < len(buf) && (buf[i] == 'N' || buf[i] == 'n') {
944			return i, ErrInvalidNumber
945		}
946
947		if !isNumeric(buf[i]) {
948			return i, ErrInvalidNumber
949		}
950		i++
951	}
952
953	if (isInt || isUnsigned) && (decimal || scientific) {
954		return i, ErrInvalidNumber
955	}
956
957	numericDigits := i - start
958	if isInt {
959		numericDigits--
960	}
961	if decimal {
962		numericDigits--
963	}
964	if buf[start] == '-' {
965		numericDigits--
966	}
967
968	if numericDigits == 0 {
969		return i, ErrInvalidNumber
970	}
971
972	// It's more common that numbers will be within min/max range for their type but we need to prevent
973	// out or range numbers from being parsed successfully.  This uses some simple heuristics to decide
974	// if we should parse the number to the actual type.  It does not do it all the time because it incurs
975	// extra allocations and we end up converting the type again when writing points to disk.
976	if isInt {
977		// Make sure the last char is an 'i' for integers (e.g. 9i10 is not valid)
978		if buf[i-1] != 'i' {
979			return i, ErrInvalidNumber
980		}
981		// Parse the int to check bounds the number of digits could be larger than the max range
982		// We subtract 1 from the index to remove the `i` from our tests
983		if len(buf[start:i-1]) >= maxInt64Digits || len(buf[start:i-1]) >= minInt64Digits {
984			if _, err := parseIntBytes(buf[start:i-1], 10, 64); err != nil {
985				return i, fmt.Errorf("unable to parse integer %s: %s", buf[start:i-1], err)
986			}
987		}
988	} else if isUnsigned {
989		// Return an error if uint64 support has not been enabled.
990		if !enableUint64Support {
991			return i, ErrInvalidNumber
992		}
993		// Make sure the last char is a 'u' for unsigned
994		if buf[i-1] != 'u' {
995			return i, ErrInvalidNumber
996		}
997		// Make sure the first char is not a '-' for unsigned
998		if buf[start] == '-' {
999			return i, ErrInvalidNumber
1000		}
1001		// Parse the uint to check bounds the number of digits could be larger than the max range
1002		// We subtract 1 from the index to remove the `u` from our tests
1003		if len(buf[start:i-1]) >= maxUint64Digits {
1004			if _, err := parseUintBytes(buf[start:i-1], 10, 64); err != nil {
1005				return i, fmt.Errorf("unable to parse unsigned %s: %s", buf[start:i-1], err)
1006			}
1007		}
1008	} else {
1009		// Parse the float to check bounds if it's scientific or the number of digits could be larger than the max range
1010		if scientific || len(buf[start:i]) >= maxFloat64Digits || len(buf[start:i]) >= minFloat64Digits {
1011			if _, err := parseFloatBytes(buf[start:i], 10); err != nil {
1012				return i, fmt.Errorf("invalid float")
1013			}
1014		}
1015	}
1016
1017	return i, nil
1018}
1019
1020// scanBoolean returns the end position within buf, start at i after
1021// scanning over buf for boolean. Valid values for a boolean are
1022// t, T, true, TRUE, f, F, false, FALSE.  It returns an error if a invalid boolean
1023// is scanned.
1024func scanBoolean(buf []byte, i int) (int, []byte, error) {
1025	start := i
1026
1027	if i < len(buf) && (buf[i] != 't' && buf[i] != 'f' && buf[i] != 'T' && buf[i] != 'F') {
1028		return i, buf[start:i], fmt.Errorf("invalid boolean")
1029	}
1030
1031	i++
1032	for {
1033		if i >= len(buf) {
1034			break
1035		}
1036
1037		if buf[i] == ',' || buf[i] == ' ' {
1038			break
1039		}
1040		i++
1041	}
1042
1043	// Single char bool (t, T, f, F) is ok
1044	if i-start == 1 {
1045		return i, buf[start:i], nil
1046	}
1047
1048	// length must be 4 for true or TRUE
1049	if (buf[start] == 't' || buf[start] == 'T') && i-start != 4 {
1050		return i, buf[start:i], fmt.Errorf("invalid boolean")
1051	}
1052
1053	// length must be 5 for false or FALSE
1054	if (buf[start] == 'f' || buf[start] == 'F') && i-start != 5 {
1055		return i, buf[start:i], fmt.Errorf("invalid boolean")
1056	}
1057
1058	// Otherwise
1059	valid := false
1060	switch buf[start] {
1061	case 't':
1062		valid = bytes.Equal(buf[start:i], []byte("true"))
1063	case 'f':
1064		valid = bytes.Equal(buf[start:i], []byte("false"))
1065	case 'T':
1066		valid = bytes.Equal(buf[start:i], []byte("TRUE")) || bytes.Equal(buf[start:i], []byte("True"))
1067	case 'F':
1068		valid = bytes.Equal(buf[start:i], []byte("FALSE")) || bytes.Equal(buf[start:i], []byte("False"))
1069	}
1070
1071	if !valid {
1072		return i, buf[start:i], fmt.Errorf("invalid boolean")
1073	}
1074
1075	return i, buf[start:i], nil
1076
1077}
1078
1079// skipWhitespace returns the end position within buf, starting at i after
1080// scanning over spaces in tags.
1081func skipWhitespace(buf []byte, i int) int {
1082	for i < len(buf) {
1083		if buf[i] != ' ' && buf[i] != '\t' && buf[i] != 0 {
1084			break
1085		}
1086		i++
1087	}
1088	return i
1089}
1090
1091// scanLine returns the end position in buf and the next line found within
1092// buf.
1093func scanLine(buf []byte, i int) (int, []byte) {
1094	start := i
1095	quoted := false
1096	fields := false
1097
1098	// tracks how many '=' and commas we've seen
1099	// this duplicates some of the functionality in scanFields
1100	equals := 0
1101	commas := 0
1102	for {
1103		// reached the end of buf?
1104		if i >= len(buf) {
1105			break
1106		}
1107
1108		// skip past escaped characters
1109		if buf[i] == '\\' && i+2 < len(buf) {
1110			i += 2
1111			continue
1112		}
1113
1114		if buf[i] == ' ' {
1115			fields = true
1116		}
1117
1118		// If we see a double quote, makes sure it is not escaped
1119		if fields {
1120			if !quoted && buf[i] == '=' {
1121				i++
1122				equals++
1123				continue
1124			} else if !quoted && buf[i] == ',' {
1125				i++
1126				commas++
1127				continue
1128			} else if buf[i] == '"' && equals > commas {
1129				i++
1130				quoted = !quoted
1131				continue
1132			}
1133		}
1134
1135		if buf[i] == '\n' && !quoted {
1136			break
1137		}
1138
1139		i++
1140	}
1141
1142	return i, buf[start:i]
1143}
1144
1145// scanTo returns the end position in buf and the next consecutive block
1146// of bytes, starting from i and ending with stop byte, where stop byte
1147// has not been escaped.
1148//
1149// If there are leading spaces, they are skipped.
1150func scanTo(buf []byte, i int, stop byte) (int, []byte) {
1151	start := i
1152	for {
1153		// reached the end of buf?
1154		if i >= len(buf) {
1155			break
1156		}
1157
1158		// Reached unescaped stop value?
1159		if buf[i] == stop && (i == 0 || buf[i-1] != '\\') {
1160			break
1161		}
1162		i++
1163	}
1164
1165	return i, buf[start:i]
1166}
1167
1168// scanTo returns the end position in buf and the next consecutive block
1169// of bytes, starting from i and ending with stop byte.  If there are leading
1170// spaces, they are skipped.
1171func scanToSpaceOr(buf []byte, i int, stop byte) (int, []byte) {
1172	start := i
1173	if buf[i] == stop || buf[i] == ' ' {
1174		return i, buf[start:i]
1175	}
1176
1177	for {
1178		i++
1179		if buf[i-1] == '\\' {
1180			continue
1181		}
1182
1183		// reached the end of buf?
1184		if i >= len(buf) {
1185			return i, buf[start:i]
1186		}
1187
1188		// reached end of block?
1189		if buf[i] == stop || buf[i] == ' ' {
1190			return i, buf[start:i]
1191		}
1192	}
1193}
1194
1195func scanTagValue(buf []byte, i int) (int, []byte) {
1196	start := i
1197	for {
1198		if i >= len(buf) {
1199			break
1200		}
1201
1202		if buf[i] == ',' && buf[i-1] != '\\' {
1203			break
1204		}
1205		i++
1206	}
1207	if i > len(buf) {
1208		return i, nil
1209	}
1210	return i, buf[start:i]
1211}
1212
1213func scanFieldValue(buf []byte, i int) (int, []byte) {
1214	start := i
1215	quoted := false
1216	for i < len(buf) {
1217		// Only escape char for a field value is a double-quote and backslash
1218		if buf[i] == '\\' && i+1 < len(buf) && (buf[i+1] == '"' || buf[i+1] == '\\') {
1219			i += 2
1220			continue
1221		}
1222
1223		// Quoted value? (e.g. string)
1224		if buf[i] == '"' {
1225			i++
1226			quoted = !quoted
1227			continue
1228		}
1229
1230		if buf[i] == ',' && !quoted {
1231			break
1232		}
1233		i++
1234	}
1235	return i, buf[start:i]
1236}
1237
1238func EscapeMeasurement(in []byte) []byte {
1239	for _, c := range measurementEscapeCodes {
1240		if bytes.IndexByte(in, c.k[0]) != -1 {
1241			in = bytes.Replace(in, c.k[:], c.esc[:], -1)
1242		}
1243	}
1244	return in
1245}
1246
1247func unescapeMeasurement(in []byte) []byte {
1248	if bytes.IndexByte(in, '\\') == -1 {
1249		return in
1250	}
1251
1252	for i := range measurementEscapeCodes {
1253		c := &measurementEscapeCodes[i]
1254		if bytes.IndexByte(in, c.k[0]) != -1 {
1255			in = bytes.Replace(in, c.esc[:], c.k[:], -1)
1256		}
1257	}
1258	return in
1259}
1260
1261func escapeTag(in []byte) []byte {
1262	for i := range tagEscapeCodes {
1263		c := &tagEscapeCodes[i]
1264		if bytes.IndexByte(in, c.k[0]) != -1 {
1265			in = bytes.Replace(in, c.k[:], c.esc[:], -1)
1266		}
1267	}
1268	return in
1269}
1270
1271func unescapeTag(in []byte) []byte {
1272	if bytes.IndexByte(in, '\\') == -1 {
1273		return in
1274	}
1275
1276	for i := range tagEscapeCodes {
1277		c := &tagEscapeCodes[i]
1278		if bytes.IndexByte(in, c.k[0]) != -1 {
1279			in = bytes.Replace(in, c.esc[:], c.k[:], -1)
1280		}
1281	}
1282	return in
1283}
1284
1285// escapeStringFieldReplacer replaces double quotes and backslashes
1286// with the same character preceded by a backslash.
1287// As of Go 1.7 this benchmarked better in allocations and CPU time
1288// compared to iterating through a string byte-by-byte and appending to a new byte slice,
1289// calling strings.Replace twice, and better than (*Regex).ReplaceAllString.
1290var escapeStringFieldReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`)
1291
1292// EscapeStringField returns a copy of in with any double quotes or
1293// backslashes with escaped values.
1294func EscapeStringField(in string) string {
1295	return escapeStringFieldReplacer.Replace(in)
1296}
1297
1298// unescapeStringField returns a copy of in with any escaped double-quotes
1299// or backslashes unescaped.
1300func unescapeStringField(in string) string {
1301	if strings.IndexByte(in, '\\') == -1 {
1302		return in
1303	}
1304
1305	var out []byte
1306	i := 0
1307	for {
1308		if i >= len(in) {
1309			break
1310		}
1311		// unescape backslashes
1312		if in[i] == '\\' && i+1 < len(in) && in[i+1] == '\\' {
1313			out = append(out, '\\')
1314			i += 2
1315			continue
1316		}
1317		// unescape double-quotes
1318		if in[i] == '\\' && i+1 < len(in) && in[i+1] == '"' {
1319			out = append(out, '"')
1320			i += 2
1321			continue
1322		}
1323		out = append(out, in[i])
1324		i++
1325
1326	}
1327	return string(out)
1328}
1329
1330// NewPoint returns a new point with the given measurement name, tags, fields and timestamp.  If
1331// an unsupported field value (NaN, or +/-Inf) or out of range time is passed, this function
1332// returns an error.
1333func NewPoint(name string, tags Tags, fields Fields, t time.Time) (Point, error) {
1334	key, err := pointKey(name, tags, fields, t)
1335	if err != nil {
1336		return nil, err
1337	}
1338
1339	return &point{
1340		key:    key,
1341		time:   t,
1342		fields: fields.MarshalBinary(),
1343	}, nil
1344}
1345
1346// pointKey checks some basic requirements for valid points, and returns the
1347// key, along with an possible error.
1348func pointKey(measurement string, tags Tags, fields Fields, t time.Time) ([]byte, error) {
1349	if len(fields) == 0 {
1350		return nil, ErrPointMustHaveAField
1351	}
1352
1353	if !t.IsZero() {
1354		if err := CheckTime(t); err != nil {
1355			return nil, err
1356		}
1357	}
1358
1359	for key, value := range fields {
1360		switch value := value.(type) {
1361		case float64:
1362			// Ensure the caller validates and handles invalid field values
1363			if math.IsInf(value, 0) {
1364				return nil, fmt.Errorf("+/-Inf is an unsupported value for field %s", key)
1365			}
1366			if math.IsNaN(value) {
1367				return nil, fmt.Errorf("NaN is an unsupported value for field %s", key)
1368			}
1369		case float32:
1370			// Ensure the caller validates and handles invalid field values
1371			if math.IsInf(float64(value), 0) {
1372				return nil, fmt.Errorf("+/-Inf is an unsupported value for field %s", key)
1373			}
1374			if math.IsNaN(float64(value)) {
1375				return nil, fmt.Errorf("NaN is an unsupported value for field %s", key)
1376			}
1377		}
1378		if len(key) == 0 {
1379			return nil, fmt.Errorf("all fields must have non-empty names")
1380		}
1381	}
1382
1383	key := MakeKey([]byte(measurement), tags)
1384	for field := range fields {
1385		sz := seriesKeySize(key, []byte(field))
1386		if sz > MaxKeyLength {
1387			return nil, fmt.Errorf("max key length exceeded: %v > %v", sz, MaxKeyLength)
1388		}
1389	}
1390
1391	return key, nil
1392}
1393
1394func seriesKeySize(key, field []byte) int {
1395	// 4 is the length of the tsm1.fieldKeySeparator constant.  It's inlined here to avoid a circular
1396	// dependency.
1397	return len(key) + 4 + len(field)
1398}
1399
1400// NewPointFromBytes returns a new Point from a marshalled Point.
1401func NewPointFromBytes(b []byte) (Point, error) {
1402	p := &point{}
1403	if err := p.UnmarshalBinary(b); err != nil {
1404		return nil, err
1405	}
1406
1407	// This does some basic validation to ensure there are fields and they
1408	// can be unmarshalled as well.
1409	iter := p.FieldIterator()
1410	var hasField bool
1411	for iter.Next() {
1412		if len(iter.FieldKey()) == 0 {
1413			continue
1414		}
1415		hasField = true
1416		switch iter.Type() {
1417		case Float:
1418			_, err := iter.FloatValue()
1419			if err != nil {
1420				return nil, fmt.Errorf("unable to unmarshal field %s: %s", string(iter.FieldKey()), err)
1421			}
1422		case Integer:
1423			_, err := iter.IntegerValue()
1424			if err != nil {
1425				return nil, fmt.Errorf("unable to unmarshal field %s: %s", string(iter.FieldKey()), err)
1426			}
1427		case Unsigned:
1428			_, err := iter.UnsignedValue()
1429			if err != nil {
1430				return nil, fmt.Errorf("unable to unmarshal field %s: %s", string(iter.FieldKey()), err)
1431			}
1432		case String:
1433			// Skip since this won't return an error
1434		case Boolean:
1435			_, err := iter.BooleanValue()
1436			if err != nil {
1437				return nil, fmt.Errorf("unable to unmarshal field %s: %s", string(iter.FieldKey()), err)
1438			}
1439		}
1440	}
1441
1442	if !hasField {
1443		return nil, ErrPointMustHaveAField
1444	}
1445
1446	return p, nil
1447}
1448
1449// MustNewPoint returns a new point with the given measurement name, tags, fields and timestamp.  If
1450// an unsupported field value (NaN) is passed, this function panics.
1451func MustNewPoint(name string, tags Tags, fields Fields, time time.Time) Point {
1452	pt, err := NewPoint(name, tags, fields, time)
1453	if err != nil {
1454		panic(err.Error())
1455	}
1456	return pt
1457}
1458
1459// Key returns the key (measurement joined with tags) of the point.
1460func (p *point) Key() []byte {
1461	return p.key
1462}
1463
1464func (p *point) name() []byte {
1465	_, name := scanTo(p.key, 0, ',')
1466	return name
1467}
1468
1469func (p *point) Name() []byte {
1470	return escape.Unescape(p.name())
1471}
1472
1473// SetName updates the measurement name for the point.
1474func (p *point) SetName(name string) {
1475	p.cachedName = ""
1476	p.key = MakeKey([]byte(name), p.Tags())
1477}
1478
1479// Time return the timestamp for the point.
1480func (p *point) Time() time.Time {
1481	return p.time
1482}
1483
1484// SetTime updates the timestamp for the point.
1485func (p *point) SetTime(t time.Time) {
1486	p.time = t
1487}
1488
1489// Round will round the timestamp of the point to the given duration.
1490func (p *point) Round(d time.Duration) {
1491	p.time = p.time.Round(d)
1492}
1493
1494// Tags returns the tag set for the point.
1495func (p *point) Tags() Tags {
1496	if p.cachedTags != nil {
1497		return p.cachedTags
1498	}
1499	p.cachedTags = parseTags(p.key, nil)
1500	return p.cachedTags
1501}
1502
1503func (p *point) ForEachTag(fn func(k, v []byte) bool) {
1504	walkTags(p.key, fn)
1505}
1506
1507func (p *point) HasTag(tag []byte) bool {
1508	if len(p.key) == 0 {
1509		return false
1510	}
1511
1512	var exists bool
1513	walkTags(p.key, func(key, value []byte) bool {
1514		if bytes.Equal(tag, key) {
1515			exists = true
1516			return false
1517		}
1518		return true
1519	})
1520
1521	return exists
1522}
1523
1524func walkTags(buf []byte, fn func(key, value []byte) bool) {
1525	if len(buf) == 0 {
1526		return
1527	}
1528
1529	pos, name := scanTo(buf, 0, ',')
1530
1531	// it's an empty key, so there are no tags
1532	if len(name) == 0 {
1533		return
1534	}
1535
1536	hasEscape := bytes.IndexByte(buf, '\\') != -1
1537	i := pos + 1
1538	var key, value []byte
1539	for {
1540		if i >= len(buf) {
1541			break
1542		}
1543		i, key = scanTo(buf, i, '=')
1544		i, value = scanTagValue(buf, i+1)
1545
1546		if len(value) == 0 {
1547			continue
1548		}
1549
1550		if hasEscape {
1551			if !fn(unescapeTag(key), unescapeTag(value)) {
1552				return
1553			}
1554		} else {
1555			if !fn(key, value) {
1556				return
1557			}
1558		}
1559
1560		i++
1561	}
1562}
1563
1564// walkFields walks each field key and value via fn.  If fn returns false, the iteration
1565// is stopped.  The values are the raw byte slices and not the converted types.
1566func walkFields(buf []byte, fn func(key, value []byte) bool) error {
1567	var i int
1568	var key, val []byte
1569	for len(buf) > 0 {
1570		i, key = scanTo(buf, 0, '=')
1571		if i > len(buf)-2 {
1572			return fmt.Errorf("invalid value: field-key=%s", key)
1573		}
1574		buf = buf[i+1:]
1575		i, val = scanFieldValue(buf, 0)
1576		buf = buf[i:]
1577		if !fn(key, val) {
1578			break
1579		}
1580
1581		// slice off comma
1582		if len(buf) > 0 {
1583			buf = buf[1:]
1584		}
1585	}
1586	return nil
1587}
1588
1589// parseTags parses buf into the provided destination tags, returning destination
1590// Tags, which may have a different length and capacity.
1591func parseTags(buf []byte, dst Tags) Tags {
1592	if len(buf) == 0 {
1593		return nil
1594	}
1595
1596	n := bytes.Count(buf, []byte(","))
1597	if cap(dst) < n {
1598		dst = make(Tags, n)
1599	} else {
1600		dst = dst[:n]
1601	}
1602
1603	// Ensure existing behaviour when point has no tags and nil slice passed in.
1604	if dst == nil {
1605		dst = Tags{}
1606	}
1607
1608	// Series keys can contain escaped commas, therefore the number of commas
1609	// in a series key only gives an estimation of the upper bound on the number
1610	// of tags.
1611	var i int
1612	walkTags(buf, func(key, value []byte) bool {
1613		dst[i].Key, dst[i].Value = key, value
1614		i++
1615		return true
1616	})
1617	return dst[:i]
1618}
1619
1620// MakeKey creates a key for a set of tags.
1621func MakeKey(name []byte, tags Tags) []byte {
1622	return AppendMakeKey(nil, name, tags)
1623}
1624
1625// AppendMakeKey appends the key derived from name and tags to dst and returns the extended buffer.
1626func AppendMakeKey(dst []byte, name []byte, tags Tags) []byte {
1627	// unescape the name and then re-escape it to avoid double escaping.
1628	// The key should always be stored in escaped form.
1629	dst = append(dst, EscapeMeasurement(unescapeMeasurement(name))...)
1630	dst = tags.AppendHashKey(dst)
1631	return dst
1632}
1633
1634// SetTags replaces the tags for the point.
1635func (p *point) SetTags(tags Tags) {
1636	p.key = MakeKey(p.Name(), tags)
1637	p.cachedTags = tags
1638}
1639
1640// AddTag adds or replaces a tag value for a point.
1641func (p *point) AddTag(key, value string) {
1642	tags := p.Tags()
1643	tags = append(tags, Tag{Key: []byte(key), Value: []byte(value)})
1644	sort.Sort(tags)
1645	p.cachedTags = tags
1646	p.key = MakeKey(p.Name(), tags)
1647}
1648
1649// Fields returns the fields for the point.
1650func (p *point) Fields() (Fields, error) {
1651	if p.cachedFields != nil {
1652		return p.cachedFields, nil
1653	}
1654	cf, err := p.unmarshalBinary()
1655	if err != nil {
1656		return nil, err
1657	}
1658	p.cachedFields = cf
1659	return p.cachedFields, nil
1660}
1661
1662// SetPrecision will round a time to the specified precision.
1663func (p *point) SetPrecision(precision string) {
1664	switch precision {
1665	case "n":
1666	case "u":
1667		p.SetTime(p.Time().Truncate(time.Microsecond))
1668	case "ms":
1669		p.SetTime(p.Time().Truncate(time.Millisecond))
1670	case "s":
1671		p.SetTime(p.Time().Truncate(time.Second))
1672	case "m":
1673		p.SetTime(p.Time().Truncate(time.Minute))
1674	case "h":
1675		p.SetTime(p.Time().Truncate(time.Hour))
1676	}
1677}
1678
1679// String returns the string representation of the point.
1680func (p *point) String() string {
1681	if p.Time().IsZero() {
1682		return string(p.Key()) + " " + string(p.fields)
1683	}
1684	return string(p.Key()) + " " + string(p.fields) + " " + strconv.FormatInt(p.UnixNano(), 10)
1685}
1686
1687// AppendString appends the string representation of the point to buf.
1688func (p *point) AppendString(buf []byte) []byte {
1689	buf = append(buf, p.key...)
1690	buf = append(buf, ' ')
1691	buf = append(buf, p.fields...)
1692
1693	if !p.time.IsZero() {
1694		buf = append(buf, ' ')
1695		buf = strconv.AppendInt(buf, p.UnixNano(), 10)
1696	}
1697
1698	return buf
1699}
1700
1701// StringSize returns the length of the string that would be returned by String().
1702func (p *point) StringSize() int {
1703	size := len(p.key) + len(p.fields) + 1
1704
1705	if !p.time.IsZero() {
1706		digits := 1 // even "0" has one digit
1707		t := p.UnixNano()
1708		if t < 0 {
1709			// account for negative sign, then negate
1710			digits++
1711			t = -t
1712		}
1713		for t > 9 { // already accounted for one digit
1714			digits++
1715			t /= 10
1716		}
1717		size += digits + 1 // digits and a space
1718	}
1719
1720	return size
1721}
1722
1723// MarshalBinary returns a binary representation of the point.
1724func (p *point) MarshalBinary() ([]byte, error) {
1725	if len(p.fields) == 0 {
1726		return nil, ErrPointMustHaveAField
1727	}
1728
1729	tb, err := p.time.MarshalBinary()
1730	if err != nil {
1731		return nil, err
1732	}
1733
1734	b := make([]byte, 8+len(p.key)+len(p.fields)+len(tb))
1735	i := 0
1736
1737	binary.BigEndian.PutUint32(b[i:], uint32(len(p.key)))
1738	i += 4
1739
1740	i += copy(b[i:], p.key)
1741
1742	binary.BigEndian.PutUint32(b[i:i+4], uint32(len(p.fields)))
1743	i += 4
1744
1745	i += copy(b[i:], p.fields)
1746
1747	copy(b[i:], tb)
1748	return b, nil
1749}
1750
1751// UnmarshalBinary decodes a binary representation of the point into a point struct.
1752func (p *point) UnmarshalBinary(b []byte) error {
1753	var n int
1754
1755	// Read key length.
1756	if len(b) < 4 {
1757		return io.ErrShortBuffer
1758	}
1759	n, b = int(binary.BigEndian.Uint32(b[:4])), b[4:]
1760
1761	// Read key.
1762	if len(b) < n {
1763		return io.ErrShortBuffer
1764	}
1765	p.key, b = b[:n], b[n:]
1766
1767	// Read fields length.
1768	if len(b) < 4 {
1769		return io.ErrShortBuffer
1770	}
1771	n, b = int(binary.BigEndian.Uint32(b[:4])), b[4:]
1772
1773	// Read fields.
1774	if len(b) < n {
1775		return io.ErrShortBuffer
1776	}
1777	p.fields, b = b[:n], b[n:]
1778
1779	// Read timestamp.
1780	return p.time.UnmarshalBinary(b)
1781}
1782
1783// PrecisionString returns a string representation of the point. If there
1784// is a timestamp associated with the point then it will be specified in the
1785// given unit.
1786func (p *point) PrecisionString(precision string) string {
1787	if p.Time().IsZero() {
1788		return fmt.Sprintf("%s %s", p.Key(), string(p.fields))
1789	}
1790	return fmt.Sprintf("%s %s %d", p.Key(), string(p.fields),
1791		p.UnixNano()/GetPrecisionMultiplier(precision))
1792}
1793
1794// RoundedString returns a string representation of the point. If there
1795// is a timestamp associated with the point, then it will be rounded to the
1796// given duration.
1797func (p *point) RoundedString(d time.Duration) string {
1798	if p.Time().IsZero() {
1799		return fmt.Sprintf("%s %s", p.Key(), string(p.fields))
1800	}
1801	return fmt.Sprintf("%s %s %d", p.Key(), string(p.fields),
1802		p.time.Round(d).UnixNano())
1803}
1804
1805func (p *point) unmarshalBinary() (Fields, error) {
1806	iter := p.FieldIterator()
1807	fields := make(Fields, 8)
1808	for iter.Next() {
1809		if len(iter.FieldKey()) == 0 {
1810			continue
1811		}
1812		switch iter.Type() {
1813		case Float:
1814			v, err := iter.FloatValue()
1815			if err != nil {
1816				return nil, fmt.Errorf("unable to unmarshal field %s: %s", string(iter.FieldKey()), err)
1817			}
1818			fields[string(iter.FieldKey())] = v
1819		case Integer:
1820			v, err := iter.IntegerValue()
1821			if err != nil {
1822				return nil, fmt.Errorf("unable to unmarshal field %s: %s", string(iter.FieldKey()), err)
1823			}
1824			fields[string(iter.FieldKey())] = v
1825		case Unsigned:
1826			v, err := iter.UnsignedValue()
1827			if err != nil {
1828				return nil, fmt.Errorf("unable to unmarshal field %s: %s", string(iter.FieldKey()), err)
1829			}
1830			fields[string(iter.FieldKey())] = v
1831		case String:
1832			fields[string(iter.FieldKey())] = iter.StringValue()
1833		case Boolean:
1834			v, err := iter.BooleanValue()
1835			if err != nil {
1836				return nil, fmt.Errorf("unable to unmarshal field %s: %s", string(iter.FieldKey()), err)
1837			}
1838			fields[string(iter.FieldKey())] = v
1839		}
1840	}
1841	return fields, nil
1842}
1843
1844// HashID returns a non-cryptographic checksum of the point's key.
1845func (p *point) HashID() uint64 {
1846	h := NewInlineFNV64a()
1847	h.Write(p.key)
1848	sum := h.Sum64()
1849	return sum
1850}
1851
1852// UnixNano returns the timestamp of the point as nanoseconds since Unix epoch.
1853func (p *point) UnixNano() int64 {
1854	return p.Time().UnixNano()
1855}
1856
1857// Split will attempt to return multiple points with the same timestamp whose
1858// string representations are no longer than size. Points with a single field or
1859// a point without a timestamp may exceed the requested size.
1860func (p *point) Split(size int) []Point {
1861	if p.time.IsZero() || p.StringSize() <= size {
1862		return []Point{p}
1863	}
1864
1865	// key string, timestamp string, spaces
1866	size -= len(p.key) + len(strconv.FormatInt(p.time.UnixNano(), 10)) + 2
1867
1868	var points []Point
1869	var start, cur int
1870
1871	for cur < len(p.fields) {
1872		end, _ := scanTo(p.fields, cur, '=')
1873		end, _ = scanFieldValue(p.fields, end+1)
1874
1875		if cur > start && end-start > size {
1876			points = append(points, &point{
1877				key:    p.key,
1878				time:   p.time,
1879				fields: p.fields[start : cur-1],
1880			})
1881			start = cur
1882		}
1883
1884		cur = end + 1
1885	}
1886
1887	points = append(points, &point{
1888		key:    p.key,
1889		time:   p.time,
1890		fields: p.fields[start:],
1891	})
1892
1893	return points
1894}
1895
1896// Tag represents a single key/value tag pair.
1897type Tag struct {
1898	Key   []byte
1899	Value []byte
1900}
1901
1902// NewTag returns a new Tag.
1903func NewTag(key, value []byte) Tag {
1904	return Tag{
1905		Key:   key,
1906		Value: value,
1907	}
1908}
1909
1910// Size returns the size of the key and value.
1911func (t Tag) Size() int { return len(t.Key) + len(t.Value) }
1912
1913// Clone returns a shallow copy of Tag.
1914//
1915// Tags associated with a Point created by ParsePointsWithPrecision will hold references to the byte slice that was parsed.
1916// Use Clone to create a Tag with new byte slices that do not refer to the argument to ParsePointsWithPrecision.
1917func (t Tag) Clone() Tag {
1918	other := Tag{
1919		Key:   make([]byte, len(t.Key)),
1920		Value: make([]byte, len(t.Value)),
1921	}
1922
1923	copy(other.Key, t.Key)
1924	copy(other.Value, t.Value)
1925
1926	return other
1927}
1928
1929// String returns the string reprsentation of the tag.
1930func (t *Tag) String() string {
1931	var buf bytes.Buffer
1932	buf.WriteByte('{')
1933	buf.WriteString(string(t.Key))
1934	buf.WriteByte(' ')
1935	buf.WriteString(string(t.Value))
1936	buf.WriteByte('}')
1937	return buf.String()
1938}
1939
1940// Tags represents a sorted list of tags.
1941type Tags []Tag
1942
1943// NewTags returns a new Tags from a map.
1944func NewTags(m map[string]string) Tags {
1945	if len(m) == 0 {
1946		return nil
1947	}
1948	a := make(Tags, 0, len(m))
1949	for k, v := range m {
1950		a = append(a, NewTag([]byte(k), []byte(v)))
1951	}
1952	sort.Sort(a)
1953	return a
1954}
1955
1956// Keys returns the list of keys for a tag set.
1957func (a Tags) Keys() []string {
1958	if len(a) == 0 {
1959		return nil
1960	}
1961	keys := make([]string, len(a))
1962	for i, tag := range a {
1963		keys[i] = string(tag.Key)
1964	}
1965	return keys
1966}
1967
1968// Values returns the list of values for a tag set.
1969func (a Tags) Values() []string {
1970	if len(a) == 0 {
1971		return nil
1972	}
1973	values := make([]string, len(a))
1974	for i, tag := range a {
1975		values[i] = string(tag.Value)
1976	}
1977	return values
1978}
1979
1980// String returns the string representation of the tags.
1981func (a Tags) String() string {
1982	var buf bytes.Buffer
1983	buf.WriteByte('[')
1984	for i := range a {
1985		buf.WriteString(a[i].String())
1986		if i < len(a)-1 {
1987			buf.WriteByte(' ')
1988		}
1989	}
1990	buf.WriteByte(']')
1991	return buf.String()
1992}
1993
1994// Size returns the number of bytes needed to store all tags. Note, this is
1995// the number of bytes needed to store all keys and values and does not account
1996// for data structures or delimiters for example.
1997func (a Tags) Size() int {
1998	var total int
1999	for i := range a {
2000		total += a[i].Size()
2001	}
2002	return total
2003}
2004
2005// Clone returns a copy of the slice where the elements are a result of calling `Clone` on the original elements
2006//
2007// Tags associated with a Point created by ParsePointsWithPrecision will hold references to the byte slice that was parsed.
2008// Use Clone to create Tags with new byte slices that do not refer to the argument to ParsePointsWithPrecision.
2009func (a Tags) Clone() Tags {
2010	if len(a) == 0 {
2011		return nil
2012	}
2013
2014	others := make(Tags, len(a))
2015	for i := range a {
2016		others[i] = a[i].Clone()
2017	}
2018
2019	return others
2020}
2021
2022func (a Tags) Len() int           { return len(a) }
2023func (a Tags) Less(i, j int) bool { return bytes.Compare(a[i].Key, a[j].Key) == -1 }
2024func (a Tags) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
2025
2026// Equal returns true if a equals other.
2027func (a Tags) Equal(other Tags) bool {
2028	if len(a) != len(other) {
2029		return false
2030	}
2031	for i := range a {
2032		if !bytes.Equal(a[i].Key, other[i].Key) || !bytes.Equal(a[i].Value, other[i].Value) {
2033			return false
2034		}
2035	}
2036	return true
2037}
2038
2039// CompareTags returns -1 if a < b, 1 if a > b, and 0 if a == b.
2040func CompareTags(a, b Tags) int {
2041	// Compare each key & value until a mismatch.
2042	for i := 0; i < len(a) && i < len(b); i++ {
2043		if cmp := bytes.Compare(a[i].Key, b[i].Key); cmp != 0 {
2044			return cmp
2045		}
2046		if cmp := bytes.Compare(a[i].Value, b[i].Value); cmp != 0 {
2047			return cmp
2048		}
2049	}
2050
2051	// If all tags are equal up to this point then return shorter tagset.
2052	if len(a) < len(b) {
2053		return -1
2054	} else if len(a) > len(b) {
2055		return 1
2056	}
2057
2058	// All tags are equal.
2059	return 0
2060}
2061
2062// Get returns the value for a key.
2063func (a Tags) Get(key []byte) []byte {
2064	// OPTIMIZE: Use sort.Search if tagset is large.
2065
2066	for _, t := range a {
2067		if bytes.Equal(t.Key, key) {
2068			return t.Value
2069		}
2070	}
2071	return nil
2072}
2073
2074// GetString returns the string value for a string key.
2075func (a Tags) GetString(key string) string {
2076	return string(a.Get([]byte(key)))
2077}
2078
2079// Set sets the value for a key.
2080func (a *Tags) Set(key, value []byte) {
2081	for i, t := range *a {
2082		if bytes.Equal(t.Key, key) {
2083			(*a)[i].Value = value
2084			return
2085		}
2086	}
2087	*a = append(*a, Tag{Key: key, Value: value})
2088	sort.Sort(*a)
2089}
2090
2091// SetString sets the string value for a string key.
2092func (a *Tags) SetString(key, value string) {
2093	a.Set([]byte(key), []byte(value))
2094}
2095
2096// Delete removes a tag by key.
2097func (a *Tags) Delete(key []byte) {
2098	for i, t := range *a {
2099		if bytes.Equal(t.Key, key) {
2100			copy((*a)[i:], (*a)[i+1:])
2101			(*a)[len(*a)-1] = Tag{}
2102			*a = (*a)[:len(*a)-1]
2103			return
2104		}
2105	}
2106}
2107
2108// Map returns a map representation of the tags.
2109func (a Tags) Map() map[string]string {
2110	m := make(map[string]string, len(a))
2111	for _, t := range a {
2112		m[string(t.Key)] = string(t.Value)
2113	}
2114	return m
2115}
2116
2117// Merge merges the tags combining the two. If both define a tag with the
2118// same key, the merged value overwrites the old value.
2119// A new map is returned.
2120func (a Tags) Merge(other map[string]string) Tags {
2121	merged := make(map[string]string, len(a)+len(other))
2122	for _, t := range a {
2123		merged[string(t.Key)] = string(t.Value)
2124	}
2125	for k, v := range other {
2126		merged[k] = v
2127	}
2128	return NewTags(merged)
2129}
2130
2131// HashKey hashes all of a tag's keys.
2132func (a Tags) HashKey() []byte {
2133	return a.AppendHashKey(nil)
2134}
2135
2136func (a Tags) needsEscape() bool {
2137	for i := range a {
2138		t := &a[i]
2139		for j := range tagEscapeCodes {
2140			c := &tagEscapeCodes[j]
2141			if bytes.IndexByte(t.Key, c.k[0]) != -1 || bytes.IndexByte(t.Value, c.k[0]) != -1 {
2142				return true
2143			}
2144		}
2145	}
2146	return false
2147}
2148
2149// AppendHashKey appends the result of hashing all of a tag's keys and values to dst and returns the extended buffer.
2150func (a Tags) AppendHashKey(dst []byte) []byte {
2151	// Empty maps marshal to empty bytes.
2152	if len(a) == 0 {
2153		return dst
2154	}
2155
2156	// Type invariant: Tags are sorted
2157
2158	sz := 0
2159	var escaped Tags
2160	if a.needsEscape() {
2161		var tmp [20]Tag
2162		if len(a) < len(tmp) {
2163			escaped = tmp[:len(a)]
2164		} else {
2165			escaped = make(Tags, len(a))
2166		}
2167
2168		for i := range a {
2169			t := &a[i]
2170			nt := &escaped[i]
2171			nt.Key = escapeTag(t.Key)
2172			nt.Value = escapeTag(t.Value)
2173			sz += len(nt.Key) + len(nt.Value)
2174		}
2175	} else {
2176		sz = a.Size()
2177		escaped = a
2178	}
2179
2180	sz += len(escaped) + (len(escaped) * 2) // separators
2181
2182	// Generate marshaled bytes.
2183	if cap(dst)-len(dst) < sz {
2184		nd := make([]byte, len(dst), len(dst)+sz)
2185		copy(nd, dst)
2186		dst = nd
2187	}
2188	buf := dst[len(dst) : len(dst)+sz]
2189	idx := 0
2190	for i := range escaped {
2191		k := &escaped[i]
2192		if len(k.Value) == 0 {
2193			continue
2194		}
2195		buf[idx] = ','
2196		idx++
2197		copy(buf[idx:], k.Key)
2198		idx += len(k.Key)
2199		buf[idx] = '='
2200		idx++
2201		copy(buf[idx:], k.Value)
2202		idx += len(k.Value)
2203	}
2204	return dst[:len(dst)+idx]
2205}
2206
2207// CopyTags returns a shallow copy of tags.
2208func CopyTags(a Tags) Tags {
2209	other := make(Tags, len(a))
2210	copy(other, a)
2211	return other
2212}
2213
2214// DeepCopyTags returns a deep copy of tags.
2215func DeepCopyTags(a Tags) Tags {
2216	// Calculate size of keys/values in bytes.
2217	var n int
2218	for _, t := range a {
2219		n += len(t.Key) + len(t.Value)
2220	}
2221
2222	// Build single allocation for all key/values.
2223	buf := make([]byte, n)
2224
2225	// Copy tags to new set.
2226	other := make(Tags, len(a))
2227	for i, t := range a {
2228		copy(buf, t.Key)
2229		other[i].Key, buf = buf[:len(t.Key)], buf[len(t.Key):]
2230
2231		copy(buf, t.Value)
2232		other[i].Value, buf = buf[:len(t.Value)], buf[len(t.Value):]
2233	}
2234
2235	return other
2236}
2237
2238// Fields represents a mapping between a Point's field names and their
2239// values.
2240type Fields map[string]interface{}
2241
2242// FieldIterator returns a FieldIterator that can be used to traverse the
2243// fields of a point without constructing the in-memory map.
2244func (p *point) FieldIterator() FieldIterator {
2245	p.Reset()
2246	return p
2247}
2248
2249type fieldIterator struct {
2250	start, end  int
2251	key, keybuf []byte
2252	valueBuf    []byte
2253	fieldType   FieldType
2254}
2255
2256// Next indicates whether there any fields remaining.
2257func (p *point) Next() bool {
2258	p.it.start = p.it.end
2259	if p.it.start >= len(p.fields) {
2260		return false
2261	}
2262
2263	p.it.end, p.it.key = scanTo(p.fields, p.it.start, '=')
2264	if escape.IsEscaped(p.it.key) {
2265		p.it.keybuf = escape.AppendUnescaped(p.it.keybuf[:0], p.it.key)
2266		p.it.key = p.it.keybuf
2267	}
2268
2269	p.it.end, p.it.valueBuf = scanFieldValue(p.fields, p.it.end+1)
2270	p.it.end++
2271
2272	if len(p.it.valueBuf) == 0 {
2273		p.it.fieldType = Empty
2274		return true
2275	}
2276
2277	c := p.it.valueBuf[0]
2278
2279	if c == '"' {
2280		p.it.fieldType = String
2281		return true
2282	}
2283
2284	if strings.IndexByte(`0123456789-.nNiIu`, c) >= 0 {
2285		if p.it.valueBuf[len(p.it.valueBuf)-1] == 'i' {
2286			p.it.fieldType = Integer
2287			p.it.valueBuf = p.it.valueBuf[:len(p.it.valueBuf)-1]
2288		} else if p.it.valueBuf[len(p.it.valueBuf)-1] == 'u' {
2289			p.it.fieldType = Unsigned
2290			p.it.valueBuf = p.it.valueBuf[:len(p.it.valueBuf)-1]
2291		} else {
2292			p.it.fieldType = Float
2293		}
2294		return true
2295	}
2296
2297	// to keep the same behavior that currently exists, default to boolean
2298	p.it.fieldType = Boolean
2299	return true
2300}
2301
2302// FieldKey returns the key of the current field.
2303func (p *point) FieldKey() []byte {
2304	return p.it.key
2305}
2306
2307// Type returns the FieldType of the current field.
2308func (p *point) Type() FieldType {
2309	return p.it.fieldType
2310}
2311
2312// StringValue returns the string value of the current field.
2313func (p *point) StringValue() string {
2314	return unescapeStringField(string(p.it.valueBuf[1 : len(p.it.valueBuf)-1]))
2315}
2316
2317// IntegerValue returns the integer value of the current field.
2318func (p *point) IntegerValue() (int64, error) {
2319	n, err := parseIntBytes(p.it.valueBuf, 10, 64)
2320	if err != nil {
2321		return 0, fmt.Errorf("unable to parse integer value %q: %v", p.it.valueBuf, err)
2322	}
2323	return n, nil
2324}
2325
2326// UnsignedValue returns the unsigned value of the current field.
2327func (p *point) UnsignedValue() (uint64, error) {
2328	n, err := parseUintBytes(p.it.valueBuf, 10, 64)
2329	if err != nil {
2330		return 0, fmt.Errorf("unable to parse unsigned value %q: %v", p.it.valueBuf, err)
2331	}
2332	return n, nil
2333}
2334
2335// BooleanValue returns the boolean value of the current field.
2336func (p *point) BooleanValue() (bool, error) {
2337	b, err := parseBoolBytes(p.it.valueBuf)
2338	if err != nil {
2339		return false, fmt.Errorf("unable to parse bool value %q: %v", p.it.valueBuf, err)
2340	}
2341	return b, nil
2342}
2343
2344// FloatValue returns the float value of the current field.
2345func (p *point) FloatValue() (float64, error) {
2346	f, err := parseFloatBytes(p.it.valueBuf, 64)
2347	if err != nil {
2348		return 0, fmt.Errorf("unable to parse floating point value %q: %v", p.it.valueBuf, err)
2349	}
2350	return f, nil
2351}
2352
2353// Reset resets the iterator to its initial state.
2354func (p *point) Reset() {
2355	p.it.fieldType = Empty
2356	p.it.key = nil
2357	p.it.valueBuf = nil
2358	p.it.start = 0
2359	p.it.end = 0
2360}
2361
2362// MarshalBinary encodes all the fields to their proper type and returns the binary
2363// representation
2364// NOTE: uint64 is specifically not supported due to potential overflow when we decode
2365// again later to an int64
2366// NOTE2: uint is accepted, and may be 64 bits, and is for some reason accepted...
2367func (p Fields) MarshalBinary() []byte {
2368	var b []byte
2369	keys := make([]string, 0, len(p))
2370
2371	for k := range p {
2372		keys = append(keys, k)
2373	}
2374
2375	// Not really necessary, can probably be removed.
2376	sort.Strings(keys)
2377
2378	for i, k := range keys {
2379		if i > 0 {
2380			b = append(b, ',')
2381		}
2382		b = appendField(b, k, p[k])
2383	}
2384
2385	return b
2386}
2387
2388func appendField(b []byte, k string, v interface{}) []byte {
2389	b = append(b, []byte(escape.String(k))...)
2390	b = append(b, '=')
2391
2392	// check popular types first
2393	switch v := v.(type) {
2394	case float64:
2395		b = strconv.AppendFloat(b, v, 'f', -1, 64)
2396	case int64:
2397		b = strconv.AppendInt(b, v, 10)
2398		b = append(b, 'i')
2399	case string:
2400		b = append(b, '"')
2401		b = append(b, []byte(EscapeStringField(v))...)
2402		b = append(b, '"')
2403	case bool:
2404		b = strconv.AppendBool(b, v)
2405	case int32:
2406		b = strconv.AppendInt(b, int64(v), 10)
2407		b = append(b, 'i')
2408	case int16:
2409		b = strconv.AppendInt(b, int64(v), 10)
2410		b = append(b, 'i')
2411	case int8:
2412		b = strconv.AppendInt(b, int64(v), 10)
2413		b = append(b, 'i')
2414	case int:
2415		b = strconv.AppendInt(b, int64(v), 10)
2416		b = append(b, 'i')
2417	case uint64:
2418		b = strconv.AppendUint(b, v, 10)
2419		b = append(b, 'u')
2420	case uint32:
2421		b = strconv.AppendInt(b, int64(v), 10)
2422		b = append(b, 'i')
2423	case uint16:
2424		b = strconv.AppendInt(b, int64(v), 10)
2425		b = append(b, 'i')
2426	case uint8:
2427		b = strconv.AppendInt(b, int64(v), 10)
2428		b = append(b, 'i')
2429	case uint:
2430		// TODO: 'uint' should be converted to writing as an unsigned integer,
2431		// but we cannot since that would break backwards compatibility.
2432		b = strconv.AppendInt(b, int64(v), 10)
2433		b = append(b, 'i')
2434	case float32:
2435		b = strconv.AppendFloat(b, float64(v), 'f', -1, 32)
2436	case []byte:
2437		b = append(b, v...)
2438	case nil:
2439		// skip
2440	default:
2441		// Can't determine the type, so convert to string
2442		b = append(b, '"')
2443		b = append(b, []byte(EscapeStringField(fmt.Sprintf("%v", v)))...)
2444		b = append(b, '"')
2445
2446	}
2447
2448	return b
2449}
2450
2451// ValidKeyToken returns true if the token used for measurement, tag key, or tag
2452// value is a valid unicode string and only contains printable, non-replacement characters.
2453func ValidKeyToken(s string) bool {
2454	if !utf8.ValidString(s) {
2455		return false
2456	}
2457	for _, r := range s {
2458		if !unicode.IsPrint(r) || r == unicode.ReplacementChar {
2459			return false
2460		}
2461	}
2462	return true
2463}
2464
2465// ValidKeyTokens returns true if the measurement name and all tags are valid.
2466func ValidKeyTokens(name string, tags Tags) bool {
2467	if !ValidKeyToken(name) {
2468		return false
2469	}
2470	for _, tag := range tags {
2471		if !ValidKeyToken(string(tag.Key)) || !ValidKeyToken(string(tag.Value)) {
2472			return false
2473		}
2474	}
2475	return true
2476}
2477