From 72489042d6eb71461513d7e1ed39209264173409 Mon Sep 17 00:00:00 2001 From: Ciprian Dorin Craciun Date: Tue, 13 Nov 2018 17:38:03 +0200 Subject: [PATCH] [common] Add support for iterating over decoded metadata thus eliminating allocations --- sources/lib/common/metadata.go | 48 ++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/sources/lib/common/metadata.go b/sources/lib/common/metadata.go index 783e1a6..877b432 100644 --- a/sources/lib/common/metadata.go +++ b/sources/lib/common/metadata.go @@ -39,18 +39,44 @@ func MetadataEncode (_metadata map[string]string) ([]byte, error) { func MetadataDecode (_data []byte) ([][2]string, error) { _metadata := make ([][2]string, 0, 16) - for _, _data := range bytes.Split (_data, []byte ("\n")) { - if len (_data) == 0 { - continue - } - _data := bytes.SplitN (_data, []byte (" : "), 2) - if len (_data) == 2 { - _metadata = append (_metadata, [2]string { string (_data[0]), string (_data[1]) }) - } else { - return nil, fmt.Errorf ("[7cb30bf7] invalid metadata encoding") - } + _metadataAppend := func (_key []byte, _value []byte) () { + _metadata = append (_metadata, [2]string { string (_key), string (_value) }) + } + if _error := MetadataDecodeIterate (_data, _metadataAppend); _error != nil { + return nil, _error + } else { + return _metadata, nil + } +} + +func MetadataDecodeIterate (_data []byte, _callback func ([]byte, []byte) ()) (error) { + + _dataSize := len (_data) + _headerOffset := 0 + + for { + + if _headerOffset == _dataSize { + return nil + } + + _data := _data[_headerOffset :] + _headerLimit := bytes.IndexByte (_data, '\n') + if (_headerLimit == -1) { + return fmt.Errorf ("[2d0d442a] invalid metadata encoding") + } + _headerOffset += _headerLimit + 1 + + _data = _data[: _headerLimit] + _separator := bytes.Index (_data, []byte (" : ")) + if _separator == -1 { + return fmt.Errorf ("[41f3756c] invalid metadata encoding") + } + _key := _data[: _separator] + _value := _data[_separator + 3 :] + + _callback (_key, _value) } - return _metadata, nil }