diff options
| author | Stefan Majewsky <majewsky@gmx.net> | 2018-02-16 16:41:18 +0100 |
|---|---|---|
| committer | Stefan Majewsky <majewsky@gmx.net> | 2018-02-16 16:41:18 +0100 |
| commit | 6be5f143bf7abd39129145d310980c8ab3c47203 (patch) | |
| tree | 88c76325cfcf045bf4a48231d0e419c9b90b8f42 /iterator.go | |
| parent | 403359114bf971f037e2737b43e2734a89df9f0a (diff) | |
| download | go-schwift-6be5f143bf7abd39129145d310980c8ab3c47203.tar.gz | |
prepare ContainerIterator for sharing code with ObjectIterator
Diffstat (limited to 'iterator.go')
| -rw-r--r-- | iterator.go | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/iterator.go b/iterator.go new file mode 100644 index 0000000..af01bbe --- /dev/null +++ b/iterator.go @@ -0,0 +1,136 @@ +/****************************************************************************** +* +* Copyright 2018 Stefan Majewsky <majewsky@gmx.net> +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +******************************************************************************/ + +package schwift + +import ( + "encoding/json" + "strconv" + "strings" +) + +//iteratorInterface allows iteratorBase to access public attributes of +//ContainerIterator/ObjectIterator. +type iteratorInterface interface { + getAccount() *Account + getContainerName() string + getPrefix() string + getHeaders() map[string]string + getOptions() *RequestOptions +} + +func (i ContainerIterator) getAccount() *Account { return i.Account } +func (i ContainerIterator) getContainerName() string { return "" } +func (i ContainerIterator) getPrefix() string { return i.Prefix } +func (i ContainerIterator) getHeaders() map[string]string { return i.Headers } +func (i ContainerIterator) getOptions() *RequestOptions { return i.Options } + +//iteratorBase provides shared behavior for ContainerIterator and ObjectIterator. +type iteratorBase struct { + i iteratorInterface + marker string + eof bool +} + +func (b *iteratorBase) request(limit int, detailed bool) Request { + r := Request{ + Method: "GET", + ContainerName: b.i.getContainerName(), + Headers: headersToHTTP(b.i.getHeaders()), + Options: cloneRequestOptions(b.i.getOptions()), + } + + if prefix := b.i.getPrefix(); prefix != "" { + r.Options.Values.Set("prefix", prefix) + } + + if b.marker == "" { + r.Options.Values.Del("marker") + } else { + r.Options.Values.Set("marker", b.marker) + } + + if limit < 0 { + r.Options.Values.Del("limit") + } else { + r.Options.Values.Set("limit", strconv.FormatUint(uint64(limit), 10)) + } + + if detailed { + r.Headers.Set("Accept", "application/json") + r.Options.Values.Set("format", "json") + r.ExpectStatusCodes = []int{200} + } else { + r.Headers.Set("Accept", "text/plain") + r.Options.Values.Set("format", "plain") + r.ExpectStatusCodes = []int{200, 204} + } + + return r +} + +func (b *iteratorBase) nextPage(limit int) ([]string, error) { + if b.eof { + return nil, nil + } + resp, err := b.request(limit, false).Do(b.i.getAccount().client) + if err != nil { + return nil, err + } + + buf, err := collectResponseBody(resp) + if err != nil { + return nil, err + } + bufStr := strings.TrimSuffix(string(buf), "\n") + var result []string + if bufStr != "" { + result = strings.Split(bufStr, "\n") + } + + if len(result) == 0 { + b.eof = true + b.marker = "" + } else { + b.eof = false + b.marker = result[len(result)-1] + } + return result, nil +} + +func (b *iteratorBase) nextPageDetailed(limit int, data interface{}) error { + if b.eof { + return nil + } + resp, err := b.request(limit, true).Do(b.i.getAccount().client) + if err != nil { + return err + } + + err = json.NewDecoder(resp.Body).Decode(&data) + closeErr := resp.Body.Close() + if err == nil { + err = closeErr + } + return err +} + +func (b *iteratorBase) setMarker(marker string) { + b.marker = marker + b.eof = marker == "" +} |
