aboutsummaryrefslogtreecommitdiff
path: root/iterator.go
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2018-02-16 16:41:18 +0100
committerStefan Majewsky <majewsky@gmx.net>2018-02-16 16:41:18 +0100
commit6be5f143bf7abd39129145d310980c8ab3c47203 (patch)
tree88c76325cfcf045bf4a48231d0e419c9b90b8f42 /iterator.go
parent403359114bf971f037e2737b43e2734a89df9f0a (diff)
downloadgo-schwift-6be5f143bf7abd39129145d310980c8ab3c47203.tar.gz
prepare ContainerIterator for sharing code with ObjectIterator
Diffstat (limited to 'iterator.go')
-rw-r--r--iterator.go136
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 == ""
+}