Remove vendor/ tree, and dep files

This commit is contained in:
Andrey Smirnov
2019-09-27 00:49:30 +03:00
committed by Andrey Smirnov
parent b731e17850
commit 0146411483
4779 changed files with 0 additions and 3135142 deletions

405
Gopkg.lock generated
View File

@@ -1,405 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:e8777c437e157121465a08c05304d5847ae70b5683ef4afeb723b3c9e5e3bc67"
name = "github.com/AlekSi/pointer"
packages = ["."]
pruneopts = ""
revision = "08a25bac605b3fcb6cc27f3917b2c2c87451963d"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:218a66570875d243938fff08f17ec03e79b18c138d0845b2428bcb4929ffa4fe"
name = "github.com/DisposaBoy/JsonConfigReader"
packages = ["."]
pruneopts = ""
revision = "33a99fdf1d5ee1f79b5077e9c06f955ad356d5f4"
[[projects]]
digest = "1:658ab137074ef3d1216e01cbe166eb171a1bd77daeae0b686ab1ae184a9a5ec9"
name = "github.com/awalterschulze/gographviz"
packages = [
".",
"ast",
"parser",
"scanner",
"token"
]
pruneopts = ""
revision = "761fd5fbb34e4c2c138c280395b65b48e4ff5a53"
version = "v1.0"
[[projects]]
digest = "1:06a3d6c930263524e16e4c0b4b6cf461f83ffcb468864a18f537ce19a44e5de4"
name = "github.com/aws/aws-sdk-go"
packages = [
"aws",
"aws/awserr",
"aws/awsutil",
"aws/client",
"aws/client/metadata",
"aws/corehandlers",
"aws/credentials",
"aws/credentials/ec2rolecreds",
"aws/credentials/endpointcreds",
"aws/credentials/processcreds",
"aws/credentials/stscreds",
"aws/csm",
"aws/defaults",
"aws/ec2metadata",
"aws/endpoints",
"aws/request",
"aws/session",
"aws/signer/v4",
"internal/ini",
"internal/s3err",
"internal/sdkio",
"internal/sdkrand",
"internal/sdkuri",
"internal/shareddefaults",
"private/protocol",
"private/protocol/eventstream",
"private/protocol/eventstream/eventstreamapi",
"private/protocol/json/jsonutil",
"private/protocol/query",
"private/protocol/query/queryutil",
"private/protocol/rest",
"private/protocol/restxml",
"private/protocol/xml/xmlutil",
"service/s3",
"service/sts"
]
pruneopts = ""
revision = "420cda5d6383f94f7d9c231aa44bad3325181950"
version = "v1.20.20"
[[projects]]
digest = "1:b9922c7da8a89c973758c03bde497017567f785b49bd253402a3587abec1e53d"
name = "github.com/cheggaaa/pb"
packages = ["."]
pruneopts = ""
revision = "cdf719fac0dd208251aa828e687c2d5802053b51"
version = "v1.0.10"
[[projects]]
branch = "master"
digest = "1:1120f960f5c334f0f94bad29eefaf73d52d226893369693686148f66c1993f15"
name = "github.com/gin-contrib/sse"
packages = ["."]
pruneopts = ""
revision = "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae"
[[projects]]
digest = "1:348ceb76f2ac958e541e4ba3190484b68df28c38ac9720ed4ef8d36af69ce52e"
name = "github.com/gin-gonic/gin"
packages = [
".",
"binding",
"render"
]
pruneopts = ""
revision = "d459835d2b077e44f7c9b453505ee29881d5d12d"
version = "v1.2"
[[projects]]
branch = "master"
digest = "1:27854310d59099f8dcc61dd8af4a69f0a3597f001154b2fb4d1c41baf2e31ec1"
name = "github.com/golang/protobuf"
packages = ["proto"]
pruneopts = ""
revision = "130e6b02ab059e7b717a096f397c5b60111cae74"
[[projects]]
branch = "master"
digest = "1:09307dfb1aa3f49a2bf869dcfa4c6c06ecd3c207221bd1c1a1141f0e51f209eb"
name = "github.com/golang/snappy"
packages = ["."]
pruneopts = ""
revision = "553a641470496b2327abcac10b36396bd98e45c9"
[[projects]]
digest = "1:6ee50e0ace655f26787c120dbce51b3185c470f475c9e57d0dcada8ebb115004"
name = "github.com/h2non/filetype"
packages = ["matchers"]
pruneopts = ""
revision = "cc14fdc9ca0e4c2bafad7458f6ff79fd3947cfbb"
version = "v1.0.5"
[[projects]]
branch = "master"
digest = "1:64b78d98b8956492576911baf6a1e3499816d4575e485d12792e4abe7d8b6c46"
name = "github.com/jlaffaye/ftp"
packages = ["."]
pruneopts = ""
revision = "2403248fa8cc9f7909862627aa7337f13f8e0bf1"
[[projects]]
digest = "1:13fe471d0ed891e8544eddfeeb0471fd3c9f2015609a1c000aefdedf52a19d40"
name = "github.com/jmespath/go-jmespath"
packages = ["."]
pruneopts = ""
revision = "c2b33e84"
[[projects]]
branch = "master"
digest = "1:c728183dd470c8bb2d1775edc641a81ec25f5e3804b8b0536e99f71df17a13a6"
name = "github.com/kjk/lzma"
packages = ["."]
pruneopts = ""
revision = "3fd93898850d5252457e48c1b3d5e1510597280b"
[[projects]]
digest = "1:78229b46ddb7434f881390029bd1af7661294af31f6802e0e1bedaad4ab0af3c"
name = "github.com/mattn/go-isatty"
packages = ["."]
pruneopts = ""
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
version = "v0.0.3"
[[projects]]
digest = "1:81e673df85e765593a863f67cba4544cf40e8919590f04d67664940786c2b61a"
name = "github.com/mattn/go-runewidth"
packages = ["."]
pruneopts = ""
revision = "9e777a8366cce605130a531d2cd6363d07ad7317"
version = "v0.0.2"
[[projects]]
digest = "1:fb8502ed69803c4cd97b1def119db73869ec2f7e2b408eb9c1b8276df6f05b3e"
name = "github.com/mattn/go-shellwords"
packages = ["."]
pruneopts = ""
revision = "005a0944d84452842197c2108bd9168ced206f78"
version = "v1.0.2"
[[projects]]
branch = "master"
digest = "1:3ba28ef4fbbf8d099c6227b698a6ceae28f8a071e12f06839c12c4c0003b7554"
name = "github.com/mkrautz/goar"
packages = ["."]
pruneopts = ""
revision = "282caa8bd9daba480b51f1d5a988714913b97aad"
[[projects]]
branch = "master"
digest = "1:d33ce379780d7c43405b9251289493cabada82f6bf9ab35eea6915d04f6ac8e0"
name = "github.com/mxk/go-flowrate"
packages = ["flowrate"]
pruneopts = ""
revision = "cca7078d478f8520f85629ad7c68962d31ed7682"
[[projects]]
branch = "master"
digest = "1:428d8af27f534ed06d783b03d477124796de06aa86402777cd2b494c64278da5"
name = "github.com/ncw/swift"
packages = [
".",
"swifttest"
]
pruneopts = ""
revision = "8e9b10220613abdbc2896808ee6b43e411a4fa6c"
[[projects]]
branch = "master"
digest = "1:beeb9206cc21cfeb113066c3dcf4bbb0ba304d73dd441f3244721566f51f44e6"
name = "github.com/pborman/uuid"
packages = ["."]
pruneopts = ""
revision = "c65b2f87fee37d1c7854c9164a450713c28d50cd"
[[projects]]
digest = "1:1d7e1867c49a6dd9856598ef7c3123604ea3daabf5b83f303ff457bcbc410b1d"
name = "github.com/pkg/errors"
packages = ["."]
pruneopts = ""
revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4"
version = "v0.8.1"
[[projects]]
branch = "master"
digest = "1:c6e71685a14409c3a1fdbecef044ee6447c3887de7c2bb025ee12f9a8a368960"
name = "github.com/smira/commander"
packages = ["."]
pruneopts = ""
revision = "f408b00e68d5d6e21b9f18bd310978dafc604e47"
[[projects]]
branch = "master"
digest = "1:a75eb2e6e718988505f704d651eeb4734f0f0b580f761aa58b4a5b0afe585091"
name = "github.com/smira/flag"
packages = ["."]
pruneopts = ""
revision = "695ea5e84e76dea7c8656e43c384e54b32aa1b2a"
[[projects]]
branch = "master"
digest = "1:cd3b8057abbb453404cbef569951a7359986eedfc0a887f9bc5efff8d02e1760"
name = "github.com/smira/go-aws-auth"
packages = ["."]
pruneopts = ""
revision = "8b73995fd8d1d82519c7037ee243a497552cd54d"
[[projects]]
branch = "master"
digest = "1:7dd59b3536a07651baf394466da3b8a20bd3ed9ce1984c7583fdf2412fdcfea9"
name = "github.com/smira/go-ftp-protocol"
packages = ["protocol"]
pruneopts = ""
revision = "066b75c2b70dca7ae10b1b88b47534a3c31ccfaa"
[[projects]]
branch = "master"
digest = "1:55fe1086100b305a5562e9f1e6825ef97c49e82331cb0f055b2069f7c7ebd469"
name = "github.com/smira/go-xz"
packages = ["."]
pruneopts = ""
revision = "0c531f070014e218b21f3cfca801cc992d52726d"
[[projects]]
digest = "1:0a9834d471916f392c608d4f13225444d47b6b7a0378dce1aef683d83711179f"
name = "github.com/syndtr/goleveldb"
packages = [
"leveldb",
"leveldb/cache",
"leveldb/comparer",
"leveldb/errors",
"leveldb/filter",
"leveldb/iterator",
"leveldb/journal",
"leveldb/memdb",
"leveldb/opt",
"leveldb/storage",
"leveldb/table",
"leveldb/util"
]
pruneopts = ""
revision = "9d007e481048296f09f59bd19bb7ae584563cd95"
version = "v1.0.0"
[[projects]]
digest = "1:a1ca17cff1abec6d4ecdeb03c52338c559affd7f0b2474e928c162986da2d348"
name = "github.com/ugorji/go"
packages = ["codec"]
pruneopts = ""
revision = "2adff0894ba3bc2eeb9f9aea45fefd49802e1a13"
version = "v1.1.4"
[[projects]]
branch = "master"
digest = "1:2d8078b329a80bf4b71537dcd30853ff89fcafb611c94b2dfdb3d43ef1f23a1a"
name = "github.com/wsxiaoys/terminal"
packages = ["color"]
pruneopts = ""
revision = "0940f3fc43a0ed42d04916b1c04578462c650b09"
[[projects]]
branch = "master"
digest = "1:51aff2b69272cb95713b74675c0817e0a0caadc20337a8d9115bc68bf1105280"
name = "golang.org/x/crypto"
packages = [
"cast5",
"openpgp",
"openpgp/armor",
"openpgp/clearsign",
"openpgp/elgamal",
"openpgp/errors",
"openpgp/packet",
"openpgp/s2k",
"ssh/terminal"
]
pruneopts = ""
revision = "b2aa35443fbc700ab74c586ae79b81c171851023"
[[projects]]
branch = "master"
digest = "1:267aa6124260d0e48d1ebf8bb84dce97caa133406b3caabc076cfc7a9e85ffe4"
name = "golang.org/x/sys"
packages = [
"unix",
"windows"
]
pruneopts = ""
revision = "1d206c9fa8975fb4cf00df1dc8bf3283dc24ba0e"
[[projects]]
branch = "v1"
digest = "1:e75566abfb876e81f00290ec153ff994c33bf8886134c1a38a9a9df5c15a2045"
name = "gopkg.in/check.v1"
packages = ["."]
pruneopts = ""
revision = "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec"
[[projects]]
digest = "1:dd549e360e5a8f982a28c2bcbe667307ceffe538ed9afc7c965524f1ac285b3f"
name = "gopkg.in/go-playground/validator.v8"
packages = ["."]
pruneopts = ""
revision = "5f1438d3fca68893a817e4a66806cea46a9e4ebf"
version = "v8.18.2"
[[projects]]
digest = "1:0e886d5a5845f58255fb57bcb4a6aae7e1f9dd7c53defe7b87d57dd4cd127545"
name = "gopkg.in/h2non/filetype.v1"
packages = ["types"]
pruneopts = ""
revision = "3093b8ebec6efb56ac813238b8beab4ed4eaac6a"
version = "v1.0.1"
[[projects]]
branch = "v2"
digest = "1:81314a486195626940617e43740b4fa073f265b0715c9f54ce2027fee1cb5f61"
name = "gopkg.in/yaml.v2"
packages = ["."]
pruneopts = ""
revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"github.com/AlekSi/pointer",
"github.com/DisposaBoy/JsonConfigReader",
"github.com/awalterschulze/gographviz",
"github.com/aws/aws-sdk-go/aws",
"github.com/aws/aws-sdk-go/aws/awserr",
"github.com/aws/aws-sdk-go/aws/corehandlers",
"github.com/aws/aws-sdk-go/aws/credentials",
"github.com/aws/aws-sdk-go/aws/request",
"github.com/aws/aws-sdk-go/aws/session",
"github.com/aws/aws-sdk-go/service/s3",
"github.com/cheggaaa/pb",
"github.com/gin-gonic/gin",
"github.com/h2non/filetype/matchers",
"github.com/kjk/lzma",
"github.com/mattn/go-shellwords",
"github.com/mkrautz/goar",
"github.com/mxk/go-flowrate/flowrate",
"github.com/ncw/swift",
"github.com/ncw/swift/swifttest",
"github.com/pborman/uuid",
"github.com/pkg/errors",
"github.com/smira/commander",
"github.com/smira/flag",
"github.com/smira/go-aws-auth",
"github.com/smira/go-ftp-protocol/protocol",
"github.com/smira/go-xz",
"github.com/syndtr/goleveldb/leveldb",
"github.com/syndtr/goleveldb/leveldb/filter",
"github.com/syndtr/goleveldb/leveldb/opt",
"github.com/syndtr/goleveldb/leveldb/storage",
"github.com/syndtr/goleveldb/leveldb/util",
"github.com/ugorji/go/codec",
"github.com/wsxiaoys/terminal/color",
"golang.org/x/crypto/openpgp",
"golang.org/x/crypto/openpgp/armor",
"golang.org/x/crypto/openpgp/clearsign",
"golang.org/x/crypto/openpgp/errors",
"golang.org/x/crypto/openpgp/packet",
"golang.org/x/crypto/ssh/terminal",
"golang.org/x/sys/unix",
"gopkg.in/check.v1"
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -1,28 +0,0 @@
[[override]]
branch = "master"
name = "github.com/mkrautz/goar"
[[override]]
branch = "master"
name = "github.com/smira/go-uuid"
[[override]]
branch = "master"
name = "github.com/smira/go-xz"
[[override]]
name = "github.com/ugorji/go"
version = "=1.1.4"
[[override]]
branch = "master"
name = "golang.org/x/crypto"
[[override]]
branch = "master"
name = "golang.org/x/sys"
[[override]]
branch = "v1"
name = "gopkg.in/check.v1"

View File

@@ -1,9 +0,0 @@
language: go
sudo: false
go:
- 1.6.4
- 1.7.4
- tip
script: go test -v

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015 Alexey Palazhchenko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,42 +0,0 @@
# pointer [![GoDoc](https://godoc.org/github.com/AlekSi/pointer?status.svg)](https://godoc.org/github.com/AlekSi/pointer) [![Build Status](https://travis-ci.org/AlekSi/pointer.svg)](https://travis-ci.org/AlekSi/pointer)
Go package pointer provides helpers to get pointers to values of build-in types.
```
go get github.com/AlekSi/pointer
```
API is stable. [Documentation](http://godoc.org/github.com/AlekSi/pointer).
```go
package motivationalexample
import (
"encoding/json"
"github.com/AlekSi/pointer"
)
const (
defaultName = "some name"
)
// Stuff contains optional fields.
type Stuff struct {
Name *string
Comment *string
Value *int64
Time *time.Time
}
// SomeStuff makes some JSON-encoded stuff.
func SomeStuff() (data []byte, err error) {
return json.Marshal(&Stuff{
Name: pointer.ToString(defaultName), // can't say &defaultName
Comment: pointer.ToString("not yet"), // can't say &"not yet"
Value: pointer.ToInt64(42), // can't say &42 or &int64(42)
Time: pointer.ToTime(time.Date(2014, 6, 25, 12, 24, 40, 0, time.UTC)), // can't say &time.Date(…)
})
}
```

View File

@@ -1,28 +0,0 @@
// Package pointer provides helpers to get pointers to values of build-in types.
package pointer // import "github.com/AlekSi/pointer"
import (
"time"
)
func ToBool(b bool) *bool { return &b }
func ToByte(b byte) *byte { return &b }
func ToComplex128(c complex128) *complex128 { return &c }
func ToComplex64(c complex64) *complex64 { return &c }
func ToError(e error) *error { return &e }
func ToFloat32(f float32) *float32 { return &f }
func ToFloat64(f float64) *float64 { return &f }
func ToInt(i int) *int { return &i }
func ToInt16(i int16) *int16 { return &i }
func ToInt32(i int32) *int32 { return &i }
func ToInt64(i int64) *int64 { return &i }
func ToInt8(i int8) *int8 { return &i }
func ToRune(r rune) *rune { return &r }
func ToString(s string) *string { return &s }
func ToTime(t time.Time) *time.Time { return &t }
func ToUint(u uint) *uint { return &u }
func ToUint16(u uint16) *uint16 { return &u }
func ToUint32(u uint32) *uint32 { return &u }
func ToUint64(u uint64) *uint64 { return &u }
func ToUint8(u uint8) *uint8 { return &u }
func ToUintptr(u uintptr) *uintptr { return &u }

View File

@@ -1,180 +0,0 @@
package pointer
import (
"encoding/json"
"fmt"
"testing"
"time"
)
func TestBool(t *testing.T) {
var x bool
if *ToBool(x) != x {
t.Fail()
}
}
func TestByte(t *testing.T) {
var x byte
if *ToByte(x) != x {
t.Fail()
}
}
func TestComplex128(t *testing.T) {
var x complex128
if *ToComplex128(x) != x {
t.Fail()
}
}
func TestComplex64(t *testing.T) {
var x complex64
if *ToComplex64(x) != x {
t.Fail()
}
}
func TestError(t *testing.T) {
var x error
if *ToError(x) != x {
t.Fail()
}
}
func TestFloat32(t *testing.T) {
var x float32
if *ToFloat32(x) != x {
t.Fail()
}
}
func TestFloat64(t *testing.T) {
var x float64
if *ToFloat64(x) != x {
t.Fail()
}
}
func TestInt(t *testing.T) {
var x int
if *ToInt(x) != x {
t.Fail()
}
}
func TestInt16(t *testing.T) {
var x int16
if *ToInt16(x) != x {
t.Fail()
}
}
func TestInt32(t *testing.T) {
var x int32
if *ToInt32(x) != x {
t.Fail()
}
}
func TestInt64(t *testing.T) {
var x int64
if *ToInt64(x) != x {
t.Fail()
}
}
func TestInt8(t *testing.T) {
var x int8
if *ToInt8(x) != x {
t.Fail()
}
}
func TestRune(t *testing.T) {
var x rune
if *ToRune(x) != x {
t.Fail()
}
}
func TestString(t *testing.T) {
var x string
if *ToString(x) != x {
t.Fail()
}
}
func TestTime(t *testing.T) {
var x time.Time
if *ToTime(x) != x {
t.Fail()
}
}
func TestUint(t *testing.T) {
var x uint
if *ToUint(x) != x {
t.Fail()
}
}
func TestUint16(t *testing.T) {
var x uint16
if *ToUint16(x) != x {
t.Fail()
}
}
func TestUint32(t *testing.T) {
var x uint32
if *ToUint32(x) != x {
t.Fail()
}
}
func TestUint64(t *testing.T) {
var x uint64
if *ToUint64(x) != x {
t.Fail()
}
}
func TestUint8(t *testing.T) {
var x uint8
if *ToUint8(x) != x {
t.Fail()
}
}
func TestUintptr(t *testing.T) {
var x uintptr
if *ToUintptr(x) != x {
t.Fail()
}
}
func Example() {
const (
defaultName = "some name"
)
// Stuff contains optional fields.
type Stuff struct {
Name *string
Comment *string
Value *int64
Time *time.Time
}
b, _ := json.Marshal(&Stuff{
Name: ToString(defaultName), // can't say &defaultName
Comment: ToString("not yet"), // can't say &"not yet"
Value: ToInt64(42), // can't say &42 or &int64(42)
Time: ToTime(time.Date(2014, 6, 25, 12, 24, 40, 0, time.UTC)), // can't say &time.Date(…)
})
fmt.Printf("%s", b)
// Output: {"Name":"some name","Comment":"not yet","Value":42,"Time":"2014-06-25T12:24:40Z"}
}

View File

@@ -1,4 +0,0 @@
This is the official list of JsonConfigReader authors for copyright purposes.
* DisposaBoy `https://github.com/DisposaBoy`
* Steven Osborn `https://github.com/steve918`

View File

@@ -1,7 +0,0 @@
Copyright (c) 2012 The JsonConfigReader Authors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,36 +0,0 @@
JsonConfigReader is a proxy for [golang's io.Reader](http://golang.org/pkg/io/#Reader) that strips line comments and trailing commas, allowing you to use json as a *reasonable* config format.
Comments start with `//` and continue to the end of the line.
If a trailing comma is in front of `]` or `}` it will be stripped as well.
Given `settings.json`
{
"key": "value", // k:v
// a list of numbers
"list": [1, 2, 3],
}
You can read it in as a *normal* json file:
package main
import (
"encoding/json"
"fmt"
"github.com/DisposaBoy/JsonConfigReader"
"os"
)
func main() {
var v interface{}
f, _ := os.Open("settings.json")
// wrap our reader before passing it to the json decoder
r := JsonConfigReader.New(f)
json.NewDecoder(r).Decode(&v)
fmt.Println(v)
}

View File

@@ -1,94 +0,0 @@
package JsonConfigReader
import (
"bytes"
"io"
)
type state struct {
r io.Reader
br *bytes.Reader
}
func isNL(c byte) bool {
return c == '\n' || c == '\r'
}
func isWS(c byte) bool {
return c == ' ' || c == '\t' || isNL(c)
}
func consumeComment(s []byte, i int) int {
if i < len(s) && s[i] == '/' {
s[i-1] = ' '
for ; i < len(s) && !isNL(s[i]); i += 1 {
s[i] = ' '
}
}
return i
}
func prep(r io.Reader) (s []byte, err error) {
buf := &bytes.Buffer{}
_, err = io.Copy(buf, r)
s = buf.Bytes()
if err != nil {
return
}
i := 0
for i < len(s) {
switch s[i] {
case '"':
i += 1
for i < len(s) {
if s[i] == '"' {
i += 1
break
} else if s[i] == '\\' {
i += 1
}
i += 1
}
case '/':
i = consumeComment(s, i+1)
case ',':
j := i
for {
i += 1
if i >= len(s) {
break
} else if s[i] == '}' || s[i] == ']' {
s[j] = ' '
break
} else if s[i] == '/' {
i = consumeComment(s, i+1)
} else if !isWS(s[i]) {
break
}
}
default:
i += 1
}
}
return
}
// Read acts as a proxy for the underlying reader and cleans p
// of comments and trailing commas preceeding ] and }
// comments are delimitted by // up until the end the line
func (st *state) Read(p []byte) (n int, err error) {
if st.br == nil {
var s []byte
if s, err = prep(st.r); err != nil {
return
}
st.br = bytes.NewReader(s)
}
return st.br.Read(p)
}
// New returns an io.Reader acting as proxy to r
func New(r io.Reader) io.Reader {
return &state{r: r}
}

View File

@@ -1,66 +0,0 @@
package JsonConfigReader
import (
"bytes"
"io"
"strings"
"testing"
)
var tests = map[string]string{
`{
// a
"x": "y", // b
"x": "y", // c
}`: `{
"x": "y",
"x": "y"
}`,
`// serve a directory
"l/test": [
{
"handler": "fs",
"dir": "../",
// "strip_prefix": "",
},
],`: `
"l/test": [
{
"handler": "fs",
"dir": "../"
}
],`,
`[1, 2, 3]`: `[1, 2, 3]`,
`[1, 2, 3, 4,]`: `[1, 2, 3, 4 ]`,
`{"x":1}//[1, 2, 3, 4,]`: `{"x":1} `,
`//////`: ` `,
`{}/ /..`: `{}/ /..`,
`{,}/ /..`: `{ }/ /..`,
`{,}//..`: `{ } `,
`{[],}`: `{[] }`,
`{[,}`: `{[ }`,
`[[",",],]`: `[["," ] ]`,
`[",\"",]`: `[",\"" ]`,
`[",\"\\\",]`: `[",\"\\\",]`,
`[",//"]`: `[",//"]`,
`[",//\"
"],`: `[",//\"
"],`,
}
func TestMain(t *testing.T) {
for a, b := range tests {
buf := &bytes.Buffer{}
io.Copy(buf, New(strings.NewReader(a)))
a = buf.String()
if a != b {
a = strings.Replace(a, " ", ".", -1)
b = strings.Replace(b, " ", ".", -1)
t.Errorf("reader failed to clean json: expected: `%s`, got `%s`", b, a)
}
}
}

View File

@@ -1,10 +0,0 @@
script:
- go build ./...
- go test ./...
- gofmt -l -s -w .
- git diff --exit-code
language: go
go:
- 1.7.1

View File

@@ -1,14 +0,0 @@
# This is the official list of GoGraphviz authors for copyright purposes.
# This file is distinct from the CONTRIBUTORS file, which
# lists people. For example, employees are listed in CONTRIBUTORS,
# but not in AUTHORS, because the employer holds the copyright.
# Names should be added to this file as one of
# Organization's name
# Individual's name <submission email address>
# Individual's name <submission email address> <email2> <emailN>
# Please keep the list sorted.
Vastech SA (PTY) LTD
Xavier Chassin <xavier.chassin@live.fr>

View File

@@ -1 +0,0 @@
Walter Schulze <awalterschulze@gmail.com>

View File

@@ -1,46 +0,0 @@
Copyright 2013 GoGraphviz Authors
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.
-------------------------------------------------------------------------------
Portions of gocc's source code has been derived from Go, and are covered by the
following license:
-------------------------------------------------------------------------------
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,34 +0,0 @@
Parses the Graphviz DOT language and creates an interface, in golang, with which to easily create new and manipulate existing graphs which can be written back to the DOT format.
This parser has been created using [gocc](http://code.google.com/p/gocc).
### Example (Parse and Edit) ###
```
graphAst, _ := parser.ParseString(`digraph G {}`)
graph := NewGraph()
Analyse(graphAst, graph)
graph.AddNode("G", "a", nil)
graph.AddNode("G", "b", nil)
graph.AddEdge("a", "b", true, nil)
output := graph.String()
```
### Documentation ###
The [godoc](https://godoc.org/github.com/awalterschulze/gographviz) includes some more examples.
### Installation ###
go get github.com/awalterschulze/gographviz
### Tests ###
[![Build Status](https://travis-ci.org/awalterschulze/gographviz.svg?branch=master)](https://travis-ci.org/awalterschulze/gographviz)
### Users ###
[aptly](https://github.com/smira/aptly) - Debian repository management tool
### Mentions ###
[Using Golang and GraphViz to Visualize Complex Grails Applications](http://ilikeorangutans.github.io/2014/05/03/using-golang-and-graphviz-to-visualize-complex-grails-applications/)

View File

@@ -1,168 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"github.com/awalterschulze/gographviz/ast"
)
//Creates a Graph structure by analysing an Abstract Syntax Tree representing a parsed graph.
func NewAnalysedGraph(graph *ast.Graph) Interface {
g := NewGraph()
Analyse(graph, g)
return g
}
//Analyses an Abstract Syntax Tree representing a parsed graph into a newly created graph structure Interface.
func Analyse(graph *ast.Graph, g Interface) {
graph.Walk(&graphVisitor{g})
}
type nilVisitor struct {
}
func (this *nilVisitor) Visit(v ast.Elem) ast.Visitor {
return this
}
type graphVisitor struct {
g Interface
}
func (this *graphVisitor) Visit(v ast.Elem) ast.Visitor {
graph, ok := v.(*ast.Graph)
if !ok {
return this
}
this.g.SetStrict(graph.Strict)
this.g.SetDir(graph.Type == ast.DIGRAPH)
graphName := graph.Id.String()
this.g.SetName(graphName)
return newStmtVisitor(this.g, graphName)
}
func newStmtVisitor(g Interface, graphName string) *stmtVisitor {
return &stmtVisitor{g, graphName, make(Attrs), make(Attrs), make(Attrs)}
}
type stmtVisitor struct {
g Interface
graphName string
currentNodeAttrs Attrs
currentEdgeAttrs Attrs
currentGraphAttrs Attrs
}
func (this *stmtVisitor) Visit(v ast.Elem) ast.Visitor {
switch s := v.(type) {
case ast.NodeStmt:
return this.nodeStmt(s)
case ast.EdgeStmt:
return this.edgeStmt(s)
case ast.NodeAttrs:
return this.nodeAttrs(s)
case ast.EdgeAttrs:
return this.edgeAttrs(s)
case ast.GraphAttrs:
return this.graphAttrs(s)
case *ast.SubGraph:
return this.subGraph(s)
case *ast.Attr:
return this.attr(s)
case ast.AttrList:
return &nilVisitor{}
default:
//fmt.Fprintf(os.Stderr, "unknown stmt %T\n", v)
}
return this
}
func ammend(attrs Attrs, add Attrs) Attrs {
for key, value := range add {
if _, ok := attrs[key]; !ok {
attrs[key] = value
}
}
return attrs
}
func overwrite(attrs Attrs, overwrite Attrs) Attrs {
for key, value := range overwrite {
attrs[key] = value
}
return attrs
}
func (this *stmtVisitor) nodeStmt(stmt ast.NodeStmt) ast.Visitor {
attrs := Attrs(stmt.Attrs.GetMap())
attrs = ammend(attrs, this.currentNodeAttrs)
this.g.AddNode(this.graphName, stmt.NodeId.String(), attrs)
return &nilVisitor{}
}
func (this *stmtVisitor) edgeStmt(stmt ast.EdgeStmt) ast.Visitor {
attrs := stmt.Attrs.GetMap()
attrs = ammend(attrs, this.currentEdgeAttrs)
src := stmt.Source.GetId()
srcName := src.String()
if stmt.Source.IsNode() {
this.g.AddNode(this.graphName, srcName, this.currentNodeAttrs.Copy())
}
srcPort := stmt.Source.GetPort()
for i := range stmt.EdgeRHS {
directed := bool(stmt.EdgeRHS[i].Op)
dst := stmt.EdgeRHS[i].Destination.GetId()
dstName := dst.String()
if stmt.EdgeRHS[i].Destination.IsNode() {
this.g.AddNode(this.graphName, dstName, this.currentNodeAttrs.Copy())
}
dstPort := stmt.EdgeRHS[i].Destination.GetPort()
this.g.AddPortEdge(srcName, srcPort.String(), dstName, dstPort.String(), directed, attrs)
src = dst
srcPort = dstPort
srcName = dstName
}
return this
}
func (this *stmtVisitor) nodeAttrs(stmt ast.NodeAttrs) ast.Visitor {
this.currentNodeAttrs = overwrite(this.currentNodeAttrs, ast.AttrList(stmt).GetMap())
return &nilVisitor{}
}
func (this *stmtVisitor) edgeAttrs(stmt ast.EdgeAttrs) ast.Visitor {
this.currentEdgeAttrs = overwrite(this.currentEdgeAttrs, ast.AttrList(stmt).GetMap())
return &nilVisitor{}
}
func (this *stmtVisitor) graphAttrs(stmt ast.GraphAttrs) ast.Visitor {
attrs := ast.AttrList(stmt).GetMap()
for key, value := range attrs {
this.g.AddAttr(this.graphName, key, value)
}
this.currentGraphAttrs = overwrite(this.currentGraphAttrs, attrs)
return &nilVisitor{}
}
func (this *stmtVisitor) subGraph(stmt *ast.SubGraph) ast.Visitor {
subGraphName := stmt.Id.String()
this.g.AddSubGraph(this.graphName, subGraphName, this.currentGraphAttrs)
return newStmtVisitor(this.g, subGraphName)
}
func (this *stmtVisitor) attr(stmt *ast.Attr) ast.Visitor {
this.g.AddAttr(this.graphName, stmt.Field.String(), stmt.Value.String())
return this
}

View File

@@ -1,318 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"fmt"
"github.com/awalterschulze/gographviz/parser"
"io/ioutil"
"os"
"testing"
)
func (this *Nodes) String() string {
s := "Nodes:"
for i := range this.Nodes {
s += fmt.Sprintf("Node{%v}", this.Nodes[i])
}
return s + "\n"
}
func (this *Edges) String() string {
s := "Edges:"
for i := range this.Edges {
s += fmt.Sprintf("Edge{%v}", this.Edges[i])
}
return s + "\n"
}
func check(t *testing.T, err error) {
if err != nil {
t.Fatalf("%v", err)
}
}
func assert(t *testing.T, msg string, v1 interface{}, v2 interface{}) {
if v1 != v2 {
t.Fatalf("%v %v != %v", msg, v1, v2)
}
}
func anal(t *testing.T, input string) Interface {
t.Logf("Input: %v\n", input)
g, err := parser.ParseString(input)
check(t, err)
t.Logf("Parsed: %v\n", g)
ag := NewGraph()
Analyse(g, ag)
t.Logf("Analysed: %v\n", ag)
agstr := ag.String()
t.Logf("Written: %v\n", agstr)
g2, err := parser.ParseString(agstr)
check(t, err)
t.Logf("Parsed %v\n", g2)
ag2 := NewEscape()
Analyse(g2, ag2)
t.Logf("Analysed %v\n", ag2)
ag2str := ag2.String()
t.Logf("Written: %v\n", ag2str)
assert(t, "analysed", agstr, ag2str)
return ag2
}
func analfile(t *testing.T, filename string) Interface {
f, err := os.Open(filename)
check(t, err)
all, err := ioutil.ReadAll(f)
check(t, err)
return anal(t, string(all))
}
func analtest(t *testing.T, testname string) Interface {
return analfile(t, "./testdata/"+testname)
}
func TestHelloWorldString(t *testing.T) {
input := `digraph G {Hello->World}`
anal(t, input)
}
func TestHelloWorldFile(t *testing.T) {
analfile(t, "./testdata/helloworld.gv.txt")
}
func TestAttr(t *testing.T) {
anal(t,
"digraph finite_state { rankdir = LR }")
}
func TestString(t *testing.T) {
anal(t,
`digraph finite_state { rankdir = "LR" }`)
}
func TestAttrList(t *testing.T) {
anal(t, `
digraph { node [ shape = doublecircle ] }`)
}
func TestStringLit(t *testing.T) {
anal(t, `digraph finite_state_machine {
size= "8" ; }`)
}
func TestHashComments(t *testing.T) {
anal(t, `## bla \n
digraph G {Hello->World}`)
}
func TestIntLit(t *testing.T) {
anal(t, `graph G {
1 -- 30 [f=1];}`)
}
func TestFloat1(t *testing.T) {
anal(t, `digraph { bla = 2.0 }`)
}
func TestFloat2(t *testing.T) {
anal(t, `digraph { bla = .1 }`)
}
func TestNegative(t *testing.T) {
anal(t, `digraph { -2 -> -1 }`)
}
func TestUnderscore(t *testing.T) {
anal(t, `digraph { a_b = 1 }`)
}
func TestNonAscii(t *testing.T) {
anal(t, `digraph { label=T<>th }`)
}
func TestPorts(t *testing.T) {
anal(t, `digraph { "node6":f0 -> "node9":f1 }`)
}
func TestHtml(t *testing.T) {
anal(t, `digraph { a = <<table></table>> }`)
}
func TestIdWithKeyword(t *testing.T) {
anal(t, `digraph { edgeURL = "a" }`)
}
func TestSubGraph(t *testing.T) {
anal(t, `digraph { subgraph { a -> b } }`)
}
func TestImplicitSubGraph(t *testing.T) {
anal(t, `digraph { { a -> b } }`)
}
func TestEdges(t *testing.T) {
anal(t, `digraph { a0 -> a1 -> a2 -> a3 }`)
}
func TestEasyFsm1(t *testing.T) {
anal(t, `digraph finite_state_machine {
rankdir=LR;
size="8,5";
node [shape = circle];
LR_0 -> LR_2 [ label = "SS(B)" ];
LR_0 -> LR_1 [ label = "SS(S)" ];
LR_1 -> LR_3 [ label = "S($end)" ];
LR_2 -> LR_6 [ label = "SS(b)" ];
LR_2 -> LR_5 [ label = "SS(a)" ];
LR_2 -> LR_4 [ label = "S(A)" ];
LR_5 -> LR_7 [ label = "S(b)" ];
LR_5 -> LR_5 [ label = "S(a)" ];
LR_6 -> LR_6 [ label = "S(b)" ];
LR_6 -> LR_5 [ label = "S(a)" ];
LR_7 -> LR_8 [ label = "S(b)" ];
LR_7 -> LR_5 [ label = "S(a)" ];
LR_8 -> LR_6 [ label = "S(b)" ];
LR_8 -> LR_5 [ label = "S(a)" ];
}`)
}
//node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8; should be applied to the nodes
func TestEasyFsm2(t *testing.T) {
anal(t, `digraph finite_state_machine {
rankdir=LR;
size="8,5";
node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8;
node [shape = circle];
LR_0 -> LR_2 [ label = "SS(B)" ];
LR_0 -> LR_1 [ label = "SS(S)" ];
LR_1 -> LR_3 [ label = "S($end)" ];
LR_2 -> LR_6 [ label = "SS(b)" ];
LR_2 -> LR_5 [ label = "SS(a)" ];
LR_2 -> LR_4 [ label = "S(A)" ];
LR_5 -> LR_7 [ label = "S(b)" ];
LR_5 -> LR_5 [ label = "S(a)" ];
LR_6 -> LR_6 [ label = "S(b)" ];
LR_6 -> LR_5 [ label = "S(a)" ];
LR_7 -> LR_8 [ label = "S(b)" ];
LR_7 -> LR_5 [ label = "S(a)" ];
LR_8 -> LR_6 [ label = "S(b)" ];
LR_8 -> LR_5 [ label = "S(a)" ];
}`)
}
func TestEmptyAttrList(t *testing.T) {
anal(t, `digraph g { edge [ ] }`)
}
func TestHelloWorld(t *testing.T) {
analtest(t, "helloworld.gv.txt")
}
func TestCluster(t *testing.T) {
analtest(t, "cluster.gv.txt")
}
func TestPsg(t *testing.T) {
analtest(t, "psg.gv.txt")
}
func TestTransparency(t *testing.T) {
analtest(t, "transparency.gv.txt")
}
func TestCrazy(t *testing.T) {
analtest(t, "crazy.gv.txt")
}
func TestKennedyanc(t *testing.T) {
analtest(t, "kennedyanc.gv.txt")
}
func TestRoot(t *testing.T) {
analtest(t, "root.gv.txt")
}
func TestTwpoi(t *testing.T) {
analtest(t, "twopi.gv.txt")
}
func TestDataStruct(t *testing.T) {
analtest(t, "datastruct.gv.txt")
}
func TestLionShare(t *testing.T) {
analtest(t, "lion_share.gv.txt")
}
func TestSdh(t *testing.T) {
analtest(t, "sdh.gv.txt")
}
func TestUnix(t *testing.T) {
analtest(t, "unix.gv.txt")
}
func TestEr(t *testing.T) {
analtest(t, "er.gv.txt")
}
func TestNerworkMapTwopi(t *testing.T) {
analtest(t, "networkmap_twopi.gv.txt")
}
func TestSibling(t *testing.T) {
analtest(t, "siblings.gv.txt")
}
func TestWorld(t *testing.T) {
analtest(t, "world.gv.txt")
}
func TestFdpclust(t *testing.T) {
analtest(t, "fdpclust.gv.txt")
}
func TestPhilo(t *testing.T) {
analtest(t, "philo.gv.txt")
}
func TestSoftmaint(t *testing.T) {
analtest(t, "softmaint.gv.txt")
}
func TestFsm(t *testing.T) {
analtest(t, "fsm.gv.txt")
}
func TestProcess(t *testing.T) {
analtest(t, "process.gv.txt")
}
func TestSwitchGv(t *testing.T) {
analtest(t, "switch.gv.txt")
}
func TestGd19942007(t *testing.T) {
analtest(t, "gd_1994_2007.gv.txt")
}
func TestProfile(t *testing.T) {
analtest(t, "profile.gv.txt")
}
func TestTrafficLights(t *testing.T) {
analtest(t, "traffic_lights.gv.txt")
}

View File

@@ -1,690 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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.
//Abstract Syntax Tree representing the DOT grammar
package ast
import (
"errors"
"fmt"
"github.com/awalterschulze/gographviz/token"
"math/rand"
"sort"
"strings"
)
var (
r = rand.New(rand.NewSource(1234))
)
type Visitor interface {
Visit(e Elem) Visitor
}
type Elem interface {
String() string
}
type Walkable interface {
Walk(v Visitor)
}
type Bool bool
const (
FALSE = Bool(false)
TRUE = Bool(true)
)
func (this Bool) String() string {
switch this {
case false:
return "false"
case true:
return "true"
}
panic("unreachable")
}
func (this Bool) Walk(v Visitor) {
if v == nil {
return
}
v.Visit(this)
}
type GraphType bool
const (
GRAPH = GraphType(false)
DIGRAPH = GraphType(true)
)
func (this GraphType) String() string {
switch this {
case false:
return "graph"
case true:
return "digraph"
}
panic("unreachable")
}
func (this GraphType) Walk(v Visitor) {
if v == nil {
return
}
v.Visit(this)
}
type Graph struct {
Type GraphType
Strict bool
Id Id
StmtList StmtList
}
func NewGraph(t, strict, id, l Elem) (*Graph, error) {
g := &Graph{Type: t.(GraphType), Strict: bool(strict.(Bool)), Id: Id("")}
if id != nil {
g.Id = id.(Id)
}
if l != nil {
g.StmtList = l.(StmtList)
}
return g, nil
}
func (this *Graph) String() string {
s := this.Type.String() + " " + this.Id.String() + " {\n"
if this.StmtList != nil {
s += this.StmtList.String()
}
s += "\n}\n"
return s
}
func (this *Graph) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
this.Type.Walk(v)
this.Id.Walk(v)
this.StmtList.Walk(v)
}
type StmtList []Stmt
func NewStmtList(s Elem) (StmtList, error) {
ss := make(StmtList, 1)
ss[0] = s.(Stmt)
return ss, nil
}
func AppendStmtList(ss, s Elem) (StmtList, error) {
this := ss.(StmtList)
this = append(this, s.(Stmt))
return this, nil
}
func (this StmtList) String() string {
if len(this) == 0 {
return ""
}
s := ""
for i := 0; i < len(this); i++ {
ss := this[i].String()
if len(ss) > 0 {
s += "\t" + ss + ";\n"
}
}
return s
}
func (this StmtList) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
for i := range this {
this[i].Walk(v)
}
}
type Stmt interface {
Elem
Walkable
isStmt()
}
func (this NodeStmt) isStmt() {}
func (this EdgeStmt) isStmt() {}
func (this EdgeAttrs) isStmt() {}
func (this NodeAttrs) isStmt() {}
func (this GraphAttrs) isStmt() {}
func (this *SubGraph) isStmt() {}
func (this *Attr) isStmt() {}
type SubGraph struct {
Id Id
StmtList StmtList
}
func NewSubGraph(id, l Elem) (*SubGraph, error) {
g := &SubGraph{Id: Id(fmt.Sprintf("anon%d", r.Int63()))}
if id != nil {
if len(id.(Id)) > 0 {
g.Id = id.(Id)
}
}
if l != nil {
g.StmtList = l.(StmtList)
}
return g, nil
}
func (this *SubGraph) GetId() Id {
return this.Id
}
func (this *SubGraph) GetPort() Port {
port, err := NewPort(nil, nil)
if err != nil {
panic(err)
}
return port
}
func (this *SubGraph) String() string {
gName := this.Id.String()
if strings.HasPrefix(gName, "anon") {
gName = ""
}
s := "subgraph " + this.Id.String() + " {\n"
if this.StmtList != nil {
s += this.StmtList.String()
}
s += "\n}\n"
return s
}
func (this *SubGraph) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
this.Id.Walk(v)
this.StmtList.Walk(v)
}
type EdgeAttrs AttrList
func NewEdgeAttrs(a Elem) (EdgeAttrs, error) {
return EdgeAttrs(a.(AttrList)), nil
}
func (this EdgeAttrs) String() string {
s := AttrList(this).String()
if len(s) == 0 {
return ""
}
return `edge ` + s
}
func (this EdgeAttrs) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
for i := range this {
this[i].Walk(v)
}
}
type NodeAttrs AttrList
func NewNodeAttrs(a Elem) (NodeAttrs, error) {
return NodeAttrs(a.(AttrList)), nil
}
func (this NodeAttrs) String() string {
s := AttrList(this).String()
if len(s) == 0 {
return ""
}
return `node ` + s
}
func (this NodeAttrs) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
for i := range this {
this[i].Walk(v)
}
}
type GraphAttrs AttrList
func NewGraphAttrs(a Elem) (GraphAttrs, error) {
return GraphAttrs(a.(AttrList)), nil
}
func (this GraphAttrs) String() string {
s := AttrList(this).String()
if len(s) == 0 {
return ""
}
return `graph ` + s
}
func (this GraphAttrs) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
for i := range this {
this[i].Walk(v)
}
}
type AttrList []AList
func NewAttrList(a Elem) (AttrList, error) {
as := make(AttrList, 0)
if a != nil {
as = append(as, a.(AList))
}
return as, nil
}
func AppendAttrList(as, a Elem) (AttrList, error) {
this := as.(AttrList)
if a == nil {
return this, nil
}
this = append(this, a.(AList))
return this, nil
}
func (this AttrList) String() string {
s := ""
for _, alist := range this {
ss := alist.String()
if len(ss) > 0 {
s += "[ " + ss + " ] "
}
}
if len(s) == 0 {
return ""
}
return s
}
func (this AttrList) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
for i := range this {
this[i].Walk(v)
}
}
func PutMap(attrmap map[string]string) AttrList {
attrlist := make(AttrList, 1)
attrlist[0] = make(AList, 0)
keys := make([]string, 0, len(attrmap))
for key := range attrmap {
keys = append(keys, key)
}
sort.Strings(keys)
for _, name := range keys {
value := attrmap[name]
attrlist[0] = append(attrlist[0], &Attr{Id(name), Id(value)})
}
return attrlist
}
func (this AttrList) GetMap() map[string]string {
attrs := make(map[string]string)
for _, alist := range this {
for _, attr := range alist {
attrs[attr.Field.String()] = attr.Value.String()
}
}
return attrs
}
type AList []*Attr
func NewAList(a Elem) (AList, error) {
as := make(AList, 1)
as[0] = a.(*Attr)
return as, nil
}
func AppendAList(as, a Elem) (AList, error) {
this := as.(AList)
attr := a.(*Attr)
this = append(this, attr)
return this, nil
}
func (this AList) String() string {
if len(this) == 0 {
return ""
}
str := this[0].String()
for i := 1; i < len(this); i++ {
str += `, ` + this[i].String()
}
return str
}
func (this AList) Walk(v Visitor) {
v = v.Visit(this)
for i := range this {
this[i].Walk(v)
}
}
type Attr struct {
Field Id
Value Id
}
func NewAttr(f, v Elem) (*Attr, error) {
a := &Attr{Field: f.(Id)}
a.Value = Id("true")
if v != nil {
ok := false
a.Value, ok = v.(Id)
if !ok {
return nil, errors.New(fmt.Sprintf("value = %v", v))
}
}
return a, nil
}
func (this *Attr) String() string {
return this.Field.String() + `=` + this.Value.String()
}
func (this *Attr) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
this.Field.Walk(v)
this.Value.Walk(v)
}
type Location interface {
Elem
Walkable
isLocation()
GetId() Id
GetPort() Port
IsNode() bool
}
func (this *NodeId) isLocation() {}
func (this *NodeId) IsNode() bool { return true }
func (this *SubGraph) isLocation() {}
func (this *SubGraph) IsNode() bool { return false }
type EdgeStmt struct {
Source Location
EdgeRHS EdgeRHS
Attrs AttrList
}
func NewEdgeStmt(id, e, attrs Elem) (*EdgeStmt, error) {
var a AttrList = nil
var err error = nil
if attrs == nil {
a, err = NewAttrList(nil)
if err != nil {
return nil, err
}
} else {
a = attrs.(AttrList)
}
return &EdgeStmt{id.(Location), e.(EdgeRHS), a}, nil
}
func (this EdgeStmt) String() string {
return strings.TrimSpace(this.Source.String() + this.EdgeRHS.String() + this.Attrs.String())
}
func (this EdgeStmt) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
this.Source.Walk(v)
this.EdgeRHS.Walk(v)
this.Attrs.Walk(v)
}
type EdgeRHS []*EdgeRH
func NewEdgeRHS(op, id Elem) (EdgeRHS, error) {
return EdgeRHS{&EdgeRH{op.(EdgeOp), id.(Location)}}, nil
}
func AppendEdgeRHS(e, op, id Elem) (EdgeRHS, error) {
erhs := e.(EdgeRHS)
erhs = append(erhs, &EdgeRH{op.(EdgeOp), id.(Location)})
return erhs, nil
}
func (this EdgeRHS) String() string {
s := ""
for i := range this {
s += this[i].String()
}
return strings.TrimSpace(s)
}
func (this EdgeRHS) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
for i := range this {
this[i].Walk(v)
}
}
type EdgeRH struct {
Op EdgeOp
Destination Location
}
func (this *EdgeRH) String() string {
return strings.TrimSpace(this.Op.String() + this.Destination.String())
}
func (this *EdgeRH) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
this.Op.Walk(v)
this.Destination.Walk(v)
}
type NodeStmt struct {
NodeId *NodeId
Attrs AttrList
}
func NewNodeStmt(id, attrs Elem) (*NodeStmt, error) {
nid := id.(*NodeId)
var a AttrList = nil
var err error = nil
if attrs == nil {
a, err = NewAttrList(nil)
if err != nil {
return nil, err
}
} else {
a = attrs.(AttrList)
}
return &NodeStmt{nid, a}, nil
}
func (this NodeStmt) String() string {
return strings.TrimSpace(this.NodeId.String() + ` ` + this.Attrs.String())
}
func (this NodeStmt) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
this.NodeId.Walk(v)
this.Attrs.Walk(v)
}
type EdgeOp bool
const (
DIRECTED EdgeOp = true
UNDIRECTED EdgeOp = false
)
func (this EdgeOp) String() string {
switch this {
case DIRECTED:
return "->"
case UNDIRECTED:
return "--"
}
panic("unreachable")
}
func (this EdgeOp) Walk(v Visitor) {
if v == nil {
return
}
v.Visit(this)
}
type NodeId struct {
Id Id
Port Port
}
func NewNodeId(id Elem, port Elem) (*NodeId, error) {
if port == nil {
return &NodeId{id.(Id), Port{"", ""}}, nil
}
return &NodeId{id.(Id), port.(Port)}, nil
}
func MakeNodeId(id string, port string) *NodeId {
p := Port{"", ""}
if len(port) > 0 {
ps := strings.Split(port, ":")
p.Id1 = Id(ps[1])
if len(ps) > 2 {
p.Id2 = Id(ps[2])
}
}
return &NodeId{Id(id), p}
}
func (this *NodeId) String() string {
return this.Id.String() + this.Port.String()
}
func (this *NodeId) GetId() Id {
return this.Id
}
func (this *NodeId) GetPort() Port {
return this.Port
}
func (this *NodeId) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
this.Id.Walk(v)
this.Port.Walk(v)
}
//TODO semantic analysis should decide which Id is an Id and which is a Compass Point
type Port struct {
Id1 Id
Id2 Id
}
func NewPort(id1, id2 Elem) (Port, error) {
port := Port{Id(""), Id("")}
if id1 != nil {
port.Id1 = id1.(Id)
}
if id2 != nil {
port.Id2 = id2.(Id)
}
return port, nil
}
func (this Port) String() string {
if len(this.Id1) == 0 {
return ""
}
s := ":" + this.Id1.String()
if len(this.Id2) > 0 {
s += ":" + this.Id2.String()
}
return s
}
func (this Port) Walk(v Visitor) {
if v == nil {
return
}
v = v.Visit(this)
this.Id1.Walk(v)
this.Id2.Walk(v)
}
type Id string
func NewId(id Elem) (Id, error) {
if id == nil {
return Id(""), nil
}
id_lit := string(id.(*token.Token).Lit)
return Id(id_lit), nil
}
func (this Id) String() string {
return string(this)
}
func (this Id) Walk(v Visitor) {
if v == nil {
return
}
v.Visit(this)
}

View File

@@ -1,71 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"fmt"
"os"
"sort"
)
//Represents attributes for an Edge, Node or Graph.
type Attrs map[string]string
//Creates an empty Attributes type.
func NewAttrs() Attrs {
return make(Attrs)
}
//Adds an attribute name and value.
func (this Attrs) Add(field string, value string) {
prev, ok := this[field]
if ok {
fmt.Fprintf(os.Stderr, "WARNING: overwriting field %v value %v, with value %v\n", field, prev, value)
}
this[field] = value
}
//Adds the attributes into this Attrs type overwriting duplicates.
func (this Attrs) Extend(more Attrs) {
for key, value := range more {
this.Add(key, value)
}
}
//Only adds the missing attributes to this Attrs type.
func (this Attrs) Ammend(more Attrs) {
for key, value := range more {
if _, ok := this[key]; !ok {
this.Add(key, value)
}
}
}
func (this Attrs) SortedNames() []string {
keys := make([]string, 0)
for key := range this {
keys = append(keys, key)
}
sort.Strings(keys)
return keys
}
func (this Attrs) Copy() Attrs {
attrs := make(Attrs)
for k, v := range this {
attrs[k] = v
}
return attrs
}

View File

@@ -1,42 +0,0 @@
package gographviz
import (
"github.com/awalterschulze/gographviz/ast"
"github.com/awalterschulze/gographviz/parser"
"testing"
)
type bugSubGraphWorldVisitor struct {
t *testing.T
found bool
}
func (this *bugSubGraphWorldVisitor) Visit(v ast.Elem) ast.Visitor {
edge, ok := v.(ast.EdgeStmt)
if !ok {
return this
}
if edge.Source.GetId().String() != "2" {
return this
}
dst := edge.EdgeRHS[0].Destination
if _, ok := dst.(*ast.SubGraph); !ok {
this.t.Fatalf("2 -> Not SubGraph")
} else {
this.found = true
}
return this
}
func TestBugSubGraphWorld(t *testing.T) {
g := analtest(t, "world.gv.txt")
st, err := parser.ParseString(g.String())
check(t, err)
s := &bugSubGraphWorldVisitor{
t: t,
}
st.Walk(s)
if !s.found {
t.Fatalf("2 -> SubGraph not found")
}
}

View File

@@ -1,209 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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.
//This bnf has been derived from http://www.graphviz.org/content/dot-language
//The rules have been copied and are shown in the comments, with their derived bnf rules below.
//graph : [ strict ] (graph | digraph) [ ID ] '{' stmt_list '}'
DotGraph
: Graph "{" "}" << ast.NewGraph(ast.GRAPH, ast.FALSE, nil, nil) >>
| Strict Graph "{" "}" << ast.NewGraph(ast.GRAPH, ast.TRUE, nil, nil) >>
| Graph Id "{" "}" << ast.NewGraph(ast.GRAPH, ast.FALSE, $1, nil) >>
| Strict Graph Id "{" "}" << ast.NewGraph(ast.GRAPH, ast.TRUE, $2, nil) >>
| Graph "{" StmtList "}" << ast.NewGraph(ast.GRAPH, ast.FALSE, nil, $2) >>
| Graph Id "{" StmtList "}" << ast.NewGraph(ast.GRAPH, ast.FALSE, $1, $3) >>
| Strict Graph "{" StmtList "}" << ast.NewGraph(ast.GRAPH, ast.TRUE, nil, $3) >>
| Strict Graph Id "{" StmtList "}" << ast.NewGraph(ast.GRAPH, ast.TRUE, $2, $4) >>
| Digraph "{" "}" << ast.NewGraph(ast.DIGRAPH, ast.FALSE, nil, nil) >>
| Strict Digraph "{" "}" << ast.NewGraph(ast.DIGRAPH, ast.TRUE, nil, nil) >>
| Digraph Id "{" "}" << ast.NewGraph(ast.DIGRAPH, ast.FALSE, $1, nil) >>
| Strict Digraph Id "{" "}" << ast.NewGraph(ast.DIGRAPH, ast.TRUE, $2, nil) >>
| Digraph "{" StmtList "}" << ast.NewGraph(ast.DIGRAPH, ast.FALSE, nil, $2) >>
| Digraph Id "{" StmtList "}" << ast.NewGraph(ast.DIGRAPH, ast.FALSE, $1, $3) >>
| Strict Digraph "{" StmtList "}" << ast.NewGraph(ast.DIGRAPH, ast.TRUE, nil, $3) >>
| Strict Digraph Id "{" StmtList "}" << ast.NewGraph(ast.DIGRAPH, ast.TRUE, $2, $4) >>
;
//stmt_list : [ stmt [ ';' ] [ stmt_list ] ]
StmtList
: Stmt1 << ast.NewStmtList($0) >>
| StmtList Stmt1 << ast.AppendStmtList($0, $1) >>
;
Stmt1
: Stmt << $0, nil >>
| Stmt ";" << $0, nil >>
;
//stmt : node_stmt | edge_stmt | attr_stmt | (ID '=' ID) | subgraph
Stmt
: Id "=" Id << ast.NewAttr($0, $2) >>
| NodeStmt << $0, nil >>
| EdgeStmt << $0, nil >>
| AttrStmt << $0, nil >>
| SubGraphStmt << $0, nil >>
;
//attr_stmt : (graph | node | edge) attr_list
AttrStmt
: Graph AttrList << ast.NewGraphAttrs($1) >>
| Node AttrList << ast.NewNodeAttrs($1) >>
| Edge AttrList << ast.NewEdgeAttrs($1) >>
;
//attr_list : '[' [ a_list ] ']' [ attr_list ]
AttrList
: "[" "]" << ast.NewAttrList(nil) >>
| "[" AList "]" << ast.NewAttrList($1) >>
| AttrList "[" "]" << ast.AppendAttrList($0, nil) >>
| AttrList "[" AList "]" << ast.AppendAttrList($0, $2) >>
;
//a_list : ID [ '=' ID ] [ ',' ] [ a_list ]
AList
: Attr << ast.NewAList($0) >>
| AList Attr << ast.AppendAList($0, $1) >>
| AList "," Attr << ast.AppendAList($0, $2) >>
;
//An a_list clause of the form ID is equivalent to ID=true.
Attr
: Id << ast.NewAttr($0, nil) >>
| Id "=" Id << ast.NewAttr($0, $2) >>
;
//edge_stmt : (node_id | subgraph) edgeRHS [ attr_list ]
EdgeStmt
: NodeId EdgeRHS << ast.NewEdgeStmt($0, $1, nil) >>
| NodeId EdgeRHS AttrList << ast.NewEdgeStmt($0, $1, $2) >>
| SubGraphStmt EdgeRHS << ast.NewEdgeStmt($0, $1, nil) >>
| SubGraphStmt EdgeRHS AttrList << ast.NewEdgeStmt($0, $1, $2) >>
;
//edgeRHS : edgeop (node_id | subgraph) [ edgeRHS ]
EdgeRHS
: EdgeOp NodeId << ast.NewEdgeRHS($0, $1) >>
| EdgeOp SubGraphStmt << ast.NewEdgeRHS($0, $1) >>
| EdgeRHS EdgeOp NodeId << ast.AppendEdgeRHS($0, $1, $2) >>
| EdgeRHS EdgeOp SubGraphStmt << ast.AppendEdgeRHS($0, $1, $2) >>
;
//node_stmt : node_id [ attr_list ]
NodeStmt
: NodeId << ast.NewNodeStmt($0, nil) >>
| NodeId AttrList << ast.NewNodeStmt($0, $1) >>
;
//node_id : ID [ port ]
NodeId
: Id << ast.NewNodeId($0, nil) >>
| Id Port << ast.NewNodeId($0, $1) >>
;
//compass_pt : (n | ne | e | se | s | sw | w | nw | c | _)
//Note also that the allowed compass point values are not keywords,
//so these strings can be used elsewhere as ordinary identifiers and,
//conversely, the parser will actually accept any identifier.
//port : ':' ID [ ':' compass_pt ]
// | ':' compass_pt
Port
: ":" Id << ast.NewPort($1, nil) >>
| ":" Id ":" Id << ast.NewPort($1, $3) >>
;
//subgraph : [ subgraph [ ID ] ] '{' stmt_list '}'
SubGraphStmt
: "{" StmtList "}" << ast.NewSubGraph(nil, $1) >>
| Subgraph "{" StmtList "}" << ast.NewSubGraph(nil, $2) >>
| Subgraph Id "{" StmtList "}" << ast.NewSubGraph($1, $3) >>
;
//An edgeop is -> in directed graphs and -- in undirected graphs.
EdgeOp
: "->" << ast.DIRECTED, nil >>
| "--" << ast.UNDIRECTED, nil >>
;
//The keywords node, edge, graph, digraph, subgraph, and strict are case-independent.
Graph
: "graph" << $0, nil >>
| "Graph" << $0, nil >>
| "GRAPH" << $0, nil >>
;
Strict
: "strict" << $0, nil >>
| "Strict" << $0, nil >>
| "STRICT" << $0, nil >>
;
Digraph
: "digraph" << $0, nil >>
| "Digraph" << $0, nil >>
| "DiGraph" << $0, nil >>
| "DIGRAPH" << $0, nil >>
;
Node
: "node" << $0, nil >>
| "Node" << $0, nil >>
| "NODE" << $0, nil >>
;
Edge
: "edge" << $0, nil >>
| "Edge" << $0, nil >>
| "EDGE" << $0, nil >>
;
Subgraph
: "subgraph" << $0, nil >>
| "Subgraph" << $0, nil >>
| "SubGraph" << $0, nil >>
| "SUBGRAPH" << $0, nil >>
;
// An ID is one of the following:
// Any string of alphabetic ([a-zA-Z'200-'377]) characters, underscores ('_') or digits ([0-9]), not beginning with a digit; //CHECK 200-377
// a numeral [-]?(.[0-9]+ | [0-9]+(.[0-9]*)? );
// any double-quoted string ("...") possibly containing escaped quotes ('")1; //TODO
// an HTML string (<...>).
// An ID is just a string; the lack of quote characters in the first two forms is just for simplicity.
// There is no semantic difference between abc_2 and "abc_2", or between 2.34 and "2.34".
// Obviously, to use a keyword as an ID, it must be quoted. Note that, in HTML strings, angle brackets must occur in matched pairs, and unescaped newlines are allowed.
// In addition, the content must be legal XML, so that the special XML escape sequences for ", &, <, and > may be necessary in order to embed these characters in attribute values or raw text.
// Both quoted strings and HTML strings are scanned as a unit, so any embedded comments will be treated as part of the strings.
Id
: id << ast.NewId($0) >>
| string_lit << ast.NewId($0) >>
| int_lit << ast.NewId($0) >>
| float_lit << ast.NewId($0) >>
| html_lit << ast.NewId($0) >>
;
//The language supports C++-style comments: /* */ and //.
//In addition, a line beginning with a '#' character is considered a line output from a C preprocessor (e.g., # 34 to indicate line 34 ) and discarded.
//TODO (if dot file is not parsable, it might be because of these points)
//Semicolons aid readability but are not required except in the rare case that a named subgraph with no body immediately preceeds an anonymous subgraph,
//since the precedence rules cause this sequence to be parsed as a subgraph with a heading and a body. Also, any amount of whitespace may be inserted between terminals.
//TODO
//As another aid for readability, dot allows single logical lines to span multiple physical lines using the standard C convention of a backslash immediately preceding a newline character.
//In addition, double-quoted strings can be concatenated using a '+' operator. As HTML strings can contain newline characters, they do not support the concatenation operator.
//TODO
//Note there are still 3 sections on the webpage which have not been included (Subgraphs and Clusters, Lexical and Semantic Notes, and Character Encodings)

View File

@@ -1,119 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"sort"
)
//Represents an Edge.
type Edge struct {
Src string
SrcPort string
Dst string
DstPort string
Dir bool
Attrs Attrs
}
//Represents a set of Edges.
type Edges struct {
SrcToDsts map[string]map[string][]*Edge
DstToSrcs map[string]map[string][]*Edge
Edges []*Edge
}
//Creates a blank set of Edges.
func NewEdges() *Edges {
return &Edges{make(map[string]map[string][]*Edge), make(map[string]map[string][]*Edge), make([]*Edge, 0)}
}
//Adds an Edge to the set of Edges.
func (this *Edges) Add(edge *Edge) {
if _, ok := this.SrcToDsts[edge.Src]; !ok {
this.SrcToDsts[edge.Src] = make(map[string][]*Edge)
}
if _, ok := this.SrcToDsts[edge.Src][edge.Dst]; !ok {
this.SrcToDsts[edge.Src][edge.Dst] = make([]*Edge, 0)
}
this.SrcToDsts[edge.Src][edge.Dst] = append(this.SrcToDsts[edge.Src][edge.Dst], edge)
if _, ok := this.DstToSrcs[edge.Dst]; !ok {
this.DstToSrcs[edge.Dst] = make(map[string][]*Edge)
}
if _, ok := this.DstToSrcs[edge.Dst][edge.Src]; !ok {
this.DstToSrcs[edge.Dst][edge.Src] = make([]*Edge, 0)
}
this.DstToSrcs[edge.Dst][edge.Src] = append(this.DstToSrcs[edge.Dst][edge.Src], edge)
this.Edges = append(this.Edges, edge)
}
//Returns a sorted list of Edges.
func (this Edges) Sorted() []*Edge {
es := make(edgeSorter, len(this.Edges))
copy(es, this.Edges)
sort.Sort(es)
return es
}
type edgeSorter []*Edge
func (es edgeSorter) Len() int { return len(es) }
func (es edgeSorter) Swap(i, j int) { es[i], es[j] = es[j], es[i] }
func (es edgeSorter) Less(i, j int) bool {
if es[i].Src < es[j].Src {
return true
} else if es[i].Src > es[j].Src {
return false
}
if es[i].Dst < es[j].Dst {
return true
} else if es[i].Dst > es[j].Dst {
return false
}
if es[i].SrcPort < es[j].SrcPort {
return true
} else if es[i].SrcPort > es[j].SrcPort {
return false
}
if es[i].DstPort < es[j].DstPort {
return true
} else if es[i].DstPort > es[j].DstPort {
return false
}
if es[i].Dir != es[j].Dir {
return es[i].Dir
}
attrs := es[i].Attrs.Copy()
for k, v := range es[j].Attrs {
attrs[k] = v
}
for _, k := range attrs.SortedNames() {
if es[i].Attrs[k] < es[j].Attrs[k] {
return true
} else if es[i].Attrs[k] > es[j].Attrs[k] {
return false
}
}
return false
}

View File

@@ -1,177 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"reflect"
"testing"
)
func TestEdges_Sorted(t *testing.T) {
var tts = map[string]struct {
edges []*Edge
expected []*Edge
}{
"empty": {
edges: []*Edge{},
expected: []*Edge{},
},
"one edge": {
edges: []*Edge{
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
},
expected: []*Edge{
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
},
},
"two non parallel edges": {
edges: []*Edge{
{Src: "0", Dst: "2", Attrs: map[string]string{"label": "hello"}},
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
},
expected: []*Edge{
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
{Src: "0", Dst: "2", Attrs: map[string]string{"label": "hello"}},
},
},
"two parallel edges": {
edges: []*Edge{
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "hello"}},
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
},
expected: []*Edge{
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "hello"}},
},
},
"two parallel edges - one without label": {
edges: []*Edge{
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
{Src: "0", Dst: "1"},
},
expected: []*Edge{
{Src: "0", Dst: "1"},
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
},
},
"several non parallel edges": {
edges: []*Edge{
{Src: "0", Dst: "2", Attrs: map[string]string{"label": "hello"}},
{Src: "1", Dst: "1", Attrs: map[string]string{"label": "world"}},
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
{Src: "1", Dst: "0", Attrs: map[string]string{"label": "golang"}},
},
expected: []*Edge{
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
{Src: "0", Dst: "2", Attrs: map[string]string{"label": "hello"}},
{Src: "1", Dst: "0", Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "1", Attrs: map[string]string{"label": "world"}},
},
},
"several with parallel edges": {
edges: []*Edge{
{Src: "0", Dst: "2", Attrs: map[string]string{"label": "hello"}},
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "cba"}},
{Src: "1", Dst: "1", Attrs: map[string]string{"label": "world"}},
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
{Src: "1", Dst: "0", Attrs: map[string]string{"label": "gopher"}},
{Src: "1", Dst: "0", Attrs: map[string]string{"label": "golang"}},
},
expected: []*Edge{
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "cba"}},
{Src: "0", Dst: "2", Attrs: map[string]string{"label": "hello"}},
{Src: "1", Dst: "0", Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "0", Attrs: map[string]string{"label": "gopher"}},
{Src: "1", Dst: "1", Attrs: map[string]string{"label": "world"}},
},
},
"edges with ports": {
edges: []*Edge{
{Src: "0", Dst: "1", SrcPort: "a", DstPort: "b"},
{Src: "0", Dst: "1", SrcPort: "a", DstPort: "a"},
{Src: "0", Dst: "1", SrcPort: "b", DstPort: "a"},
},
expected: []*Edge{
{Src: "0", Dst: "1", SrcPort: "a", DstPort: "a"},
{Src: "0", Dst: "1", SrcPort: "a", DstPort: "b"},
{Src: "0", Dst: "1", SrcPort: "b", DstPort: "a"},
},
},
"directed edges before non directed edges": {
edges: []*Edge{
{Src: "0", Dst: "1", Dir: false},
{Src: "0", Dst: "1", Dir: true},
},
expected: []*Edge{
{Src: "0", Dst: "1", Dir: true},
{Src: "0", Dst: "1", Dir: false},
},
},
"the theory of everything": {
edges: []*Edge{
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "cba"}},
{Src: "1", Dst: "0", SrcPort: "a", Dir: false, Attrs: map[string]string{"label": "gopher"}},
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
{Src: "0", Dst: "2", Attrs: map[string]string{"label": "hello"}},
{Src: "1", Dst: "0", Attrs: map[string]string{"label": "gopher"}},
{Src: "1", Dst: "0", Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "0", SrcPort: "b", Attrs: map[string]string{"label": "gopher"}},
{Src: "1", Dst: "0", SrcPort: "a", DstPort: "b", Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "1", Attrs: map[string]string{"comment": "test", "label": "world"}},
{Src: "1", Dst: "0", SrcPort: "a", DstPort: "a", Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "0", SrcPort: "a", Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "0", SrcPort: "b", Dir: false, Attrs: map[string]string{"label": "gopher"}},
{Src: "1", Dst: "1", Attrs: map[string]string{"label": "world"}},
{Src: "1", Dst: "0", SrcPort: "a", DstPort: "b", Dir: true, Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "1", Attrs: map[string]string{"comment": "test", "label": "hello"}},
{Src: "1", Dst: "0", SrcPort: "a", Dir: true, Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "0", SrcPort: "a", DstPort: "b", Dir: true, Attrs: map[string]string{"label": "graphviz"}},
},
expected: []*Edge{
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "abc"}},
{Src: "0", Dst: "1", Attrs: map[string]string{"label": "cba"}},
{Src: "0", Dst: "2", Attrs: map[string]string{"label": "hello"}},
{Src: "1", Dst: "0", Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "0", Attrs: map[string]string{"label": "gopher"}},
{Src: "1", Dst: "0", SrcPort: "a", Dir: true, Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "0", SrcPort: "a", Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "0", SrcPort: "a", Dir: false, Attrs: map[string]string{"label": "gopher"}},
{Src: "1", Dst: "0", SrcPort: "a", DstPort: "a", Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "0", SrcPort: "a", DstPort: "b", Dir: true, Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "0", SrcPort: "a", DstPort: "b", Dir: true, Attrs: map[string]string{"label": "graphviz"}},
{Src: "1", Dst: "0", SrcPort: "a", DstPort: "b", Attrs: map[string]string{"label": "golang"}},
{Src: "1", Dst: "0", SrcPort: "b", Dir: false, Attrs: map[string]string{"label": "gopher"}},
{Src: "1", Dst: "0", SrcPort: "b", Attrs: map[string]string{"label": "gopher"}},
{Src: "1", Dst: "1", Attrs: map[string]string{"label": "world"}},
{Src: "1", Dst: "1", Attrs: map[string]string{"comment": "test", "label": "hello"}},
{Src: "1", Dst: "1", Attrs: map[string]string{"comment": "test", "label": "world"}},
},
},
}
for name, tt := range tts {
edges := NewEdges()
for _, e := range tt.edges {
edges.Add(e)
}
s := edges.Sorted()
if !reflect.DeepEqual(tt.expected, s) {
t.Errorf("%s - Sorted invalid: expected %v got %v", name, tt.expected, s)
} else if !reflect.DeepEqual(edges.Edges, tt.edges) {
t.Errorf("%s - Sorted should not have changed original order: expected %v got %v", name, tt.edges, edges.Edges)
}
}
}

View File

@@ -1,185 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"fmt"
"github.com/awalterschulze/gographviz/scanner"
"github.com/awalterschulze/gographviz/token"
"strings"
"text/template"
"unicode"
)
type Escape struct {
*Graph
}
//Returns a graph which will try to escape some strings when required
func NewEscape() *Escape {
return &Escape{NewGraph()}
}
func isHtml(s string) bool {
if len(s) == 0 {
return false
}
ss := strings.TrimSpace(s)
if ss[0] != '<' {
return false
}
count := 0
for _, c := range ss {
if c == '<' {
count += 1
}
if c == '>' {
count -= 1
}
}
if count == 0 {
return true
}
return false
}
func isLetter(ch rune) bool {
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' ||
ch >= 0x80 && unicode.IsLetter(ch) && ch != 'ε'
}
func isId(s string) bool {
i := 0
pos := false
for _, c := range s {
if i == 0 {
if !isLetter(c) {
return false
}
pos = true
}
if unicode.IsSpace(c) {
return false
}
if c == '-' {
return false
}
i++
}
return pos
}
func isDigit(ch rune) bool {
return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
}
func isNumber(s string) bool {
state := 0
for _, c := range s {
if state == 0 {
if isDigit(c) || c == '.' {
state = 2
} else if c == '-' {
state = 1
} else {
return false
}
} else if state == 1 {
if isDigit(c) || c == '.' {
state = 2
}
} else if c != '.' && !isDigit(c) {
return false
}
}
return (state == 2)
}
func isStringLit(s string) bool {
lex := &scanner.Scanner{}
lex.Init([]byte(s), token.DOTTokens)
tok, _ := lex.Scan()
if tok.Type != token.DOTTokens.Type("string_lit") {
return false
}
tok, _ = lex.Scan()
if tok.Type != token.EOF {
return false
}
return true
}
func esc(s string) string {
if len(s) == 0 {
return s
}
if isHtml(s) {
return s
}
ss := strings.TrimSpace(s)
if ss[0] == '<' {
return fmt.Sprintf("\"%s\"", strings.Replace(s, "\"", "\\\"", -1))
}
if isId(s) {
return s
}
if isNumber(s) {
return s
}
if isStringLit(s) {
return s
}
return fmt.Sprintf("\"%s\"", template.HTMLEscapeString(s))
}
func escAttrs(attrs map[string]string) map[string]string {
newAttrs := make(map[string]string)
for k, v := range attrs {
newAttrs[esc(k)] = esc(v)
}
return newAttrs
}
func (this *Escape) SetName(name string) {
this.Graph.SetName(esc(name))
}
func (this *Escape) AddPortEdge(src, srcPort, dst, dstPort string, directed bool, attrs map[string]string) {
this.Graph.AddPortEdge(esc(src), srcPort, esc(dst), dstPort, directed, escAttrs(attrs))
}
func (this *Escape) AddEdge(src, dst string, directed bool, attrs map[string]string) {
this.AddPortEdge(src, "", dst, "", directed, attrs)
}
func (this *Escape) AddNode(parentGraph string, name string, attrs map[string]string) {
this.Graph.AddNode(esc(parentGraph), esc(name), escAttrs(attrs))
}
func (this *Escape) AddAttr(parentGraph string, field, value string) {
this.Graph.AddAttr(esc(parentGraph), esc(field), esc(value))
}
func (this *Escape) AddSubGraph(parentGraph string, name string, attrs map[string]string) {
this.Graph.AddSubGraph(esc(parentGraph), esc(name), escAttrs(attrs))
}
func (this *Escape) IsNode(name string) bool {
return this.Graph.IsNode(esc(name))
}
func (this *Escape) IsSubGraph(name string) bool {
return this.Graph.IsSubGraph(esc(name))
}

View File

@@ -1,47 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"strings"
"testing"
)
func TestEscape(t *testing.T) {
g := NewEscape()
g.SetName("asdf adsf")
g.SetDir(true)
g.AddNode("asdf asdf", "kasdf99 99", map[string]string{
"<asfd": "1",
})
g.AddNode("asdf asdf", "7", map[string]string{
"<asfd": "1",
})
g.AddNode("asdf asdf", "a << b", nil)
g.AddEdge("kasdf99 99", "7", true, nil)
s := g.String()
if !strings.HasPrefix(s, `digraph "asdf adsf" {
"kasdf99 99"->7;
"a &lt;&lt; b";
"kasdf99 99" [ "<asfd"=1 ];
7 [ "<asfd"=1 ];
}`) {
t.Fatalf("%s", s)
}
if !g.IsNode("a << b") {
t.Fatalf("should be a node")
}
}

View File

@@ -1,160 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"fmt"
"strconv"
)
func ExampleRead() {
g, err := Read([]byte(`digraph G {Hello->World}`))
if err != nil {
panic(err)
}
s := g.String()
fmt.Println(s)
// Output: digraph G {
// Hello->World;
// Hello;
// World;
//
//}
}
func ExampleNewGraph() {
g := NewGraph()
g.SetName("G")
g.SetDir(true)
g.AddNode("G", "Hello", nil)
g.AddNode("G", "World", nil)
g.AddEdge("Hello", "World", true, nil)
s := g.String()
fmt.Println(s)
// Output: digraph G {
// Hello->World;
// Hello;
// World;
//
//}
}
type MyOwnGraphStructure struct {
weights map[int]map[int]int
max int
}
func NewMyOwnGraphStructure() *MyOwnGraphStructure {
return &MyOwnGraphStructure{
make(map[int]map[int]int),
0,
}
}
func (this *MyOwnGraphStructure) SetStrict(strict bool) {}
func (this *MyOwnGraphStructure) SetDir(directed bool) {}
func (this *MyOwnGraphStructure) SetName(name string) {}
func (this *MyOwnGraphStructure) AddPortEdge(src, srcPort, dst, dstPort string, directed bool, attrs map[string]string) {
srci, err := strconv.Atoi(src)
if err != nil {
return
}
dsti, err := strconv.Atoi(dst)
if err != nil {
return
}
ai, err := strconv.Atoi(attrs["label"])
if err != nil {
return
}
if _, ok := this.weights[srci]; !ok {
this.weights[srci] = make(map[int]int)
}
this.weights[srci][dsti] = ai
if srci > this.max {
this.max = srci
}
if dsti > this.max {
this.max = dsti
}
}
func (this *MyOwnGraphStructure) AddEdge(src, dst string, directed bool, attrs map[string]string) {
this.AddPortEdge(src, "", dst, "", directed, attrs)
}
func (this *MyOwnGraphStructure) AddNode(parentGraph string, name string, attrs map[string]string) {}
func (this *MyOwnGraphStructure) AddAttr(parentGraph string, field, value string) {}
func (this *MyOwnGraphStructure) AddSubGraph(parentGraph string, name string, attrs map[string]string) {
}
func (this *MyOwnGraphStructure) String() string { return "" }
//An Example of how to parse into your own simpler graph structure and output it back to graphviz.
//This example reads in only numbers and outputs a matrix graph.
func ExampleMyOwnGraphStructure() {
name := "matrix"
parsed, err := Parse([]byte(`
digraph G {
1 -> 2 [ label = 5 ];
4 -> 2 [ label = 1 ];
4 -> 1 [ label = 2 ];
1 -> 1 [ label = 0 ];
}
`))
if err != nil {
panic(err)
}
mine := NewMyOwnGraphStructure()
Analyse(parsed, mine)
output := NewGraph()
output.SetName(name)
output.SetDir(true)
for i := 1; i <= mine.max; i++ {
output.AddNode(name, fmt.Sprintf("%v", i), nil)
if _, ok := mine.weights[i]; !ok {
mine.weights[i] = make(map[int]int)
}
}
for i := 1; i <= mine.max; i++ {
for j := 1; j <= mine.max; j++ {
output.AddEdge(fmt.Sprintf("%v", i), fmt.Sprintf("%v", j), true, map[string]string{"label": fmt.Sprintf("%v", mine.weights[i][j])})
}
}
s := output.String()
fmt.Println(s)
// Output: digraph matrix {
// 1->1[ label=0 ];
// 1->2[ label=5 ];
// 1->3[ label=0 ];
// 1->4[ label=0 ];
// 2->1[ label=0 ];
// 2->2[ label=0 ];
// 2->3[ label=0 ];
// 2->4[ label=0 ];
// 3->1[ label=0 ];
// 3->2[ label=0 ];
// 3->3[ label=0 ];
// 3->4[ label=0 ];
// 4->1[ label=2 ];
// 4->2[ label=1 ];
// 4->3[ label=0 ];
// 4->4[ label=0 ];
// 1;
// 2;
// 3;
// 4;
//
//}
}

View File

@@ -1,4 +0,0 @@
gocc -o ../ -p . dot.bnf
cp ./parser/parser.temp ./parser/parser.go
gofix parser/tables.go
gofix token/token.go

View File

@@ -1,53 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz provides parsing for the DOT grammar into
//an abstract syntax tree representing a graph,
//analysis of the abstract syntax tree into a more usable structure,
//and writing back of this structure into the DOT format.
package gographviz
import (
"github.com/awalterschulze/gographviz/ast"
"github.com/awalterschulze/gographviz/parser"
)
var _ Interface = NewGraph()
//Implementing this interface allows you to parse the graph into your own structure.
type Interface interface {
SetStrict(strict bool)
SetDir(directed bool)
SetName(name string)
AddPortEdge(src, srcPort, dst, dstPort string, directed bool, attrs map[string]string)
AddEdge(src, dst string, directed bool, attrs map[string]string)
AddNode(parentGraph string, name string, attrs map[string]string)
AddAttr(parentGraph string, field, value string)
AddSubGraph(parentGraph string, name string, attrs map[string]string)
String() string
}
//Parses the buffer into a abstract syntax tree representing the graph.
func Parse(buf []byte) (*ast.Graph, error) {
return parser.ParseBytes(buf)
}
//Parses and creates a new Graph from the data.
func Read(buf []byte) (Interface, error) {
st, err := Parse(buf)
if err != nil {
return nil, err
}
return NewAnalysedGraph(st), nil
}

View File

@@ -1,113 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
//The analysed representation of the Graph parsed from the DOT format.
type Graph struct {
Attrs Attrs
Name string
Directed bool
Strict bool
Nodes *Nodes
Edges *Edges
SubGraphs *SubGraphs
Relations *Relations
}
//Creates a new empty graph, ready to be populated.
func NewGraph() *Graph {
return &Graph{
Attrs: make(Attrs),
Name: "",
Directed: false,
Strict: false,
Nodes: NewNodes(),
Edges: NewEdges(),
SubGraphs: NewSubGraphs(),
Relations: NewRelations(),
}
}
//If the graph is strict then multiple edges are not allowed between the same pairs of nodes,
//see dot man page.
func (this *Graph) SetStrict(strict bool) {
this.Strict = strict
}
//Sets whether the graph is directed (true) or undirected (false).
func (this *Graph) SetDir(dir bool) {
this.Directed = dir
}
//Sets the graph name.
func (this *Graph) SetName(name string) {
this.Name = name
}
//Adds an edge to the graph from node src to node dst.
//srcPort and dstPort are the port the node ports, leave as empty strings if it is not required.
//This does not imply the adding of missing nodes.
func (this *Graph) AddPortEdge(src, srcPort, dst, dstPort string, directed bool, attrs map[string]string) {
this.Edges.Add(&Edge{src, srcPort, dst, dstPort, directed, attrs})
}
//Adds an edge to the graph from node src to node dst.
//This does not imply the adding of missing nodes.
//If directed is set to true then SetDir(true) must also be called or there will be a syntax error in the output.
func (this *Graph) AddEdge(src, dst string, directed bool, attrs map[string]string) {
this.AddPortEdge(src, "", dst, "", directed, attrs)
}
//Adds a node to a graph/subgraph.
//If not subgraph exists use the name of the main graph.
//This does not imply the adding of a missing subgraph.
func (this *Graph) AddNode(parentGraph string, name string, attrs map[string]string) {
this.Nodes.Add(&Node{name, attrs})
this.Relations.Add(parentGraph, name)
}
func (this *Graph) getAttrs(graphName string) Attrs {
if this.Name == graphName {
return this.Attrs
}
g, ok := this.SubGraphs.SubGraphs[graphName]
if !ok {
panic("graph or subgraph " + graphName + " does not exist")
}
return g.Attrs
}
//Adds an attribute to a graph/subgraph.
func (this *Graph) AddAttr(parentGraph string, field string, value string) {
this.getAttrs(parentGraph).Add(field, value)
}
//Adds a subgraph to a graph/subgraph.
func (this *Graph) AddSubGraph(parentGraph string, name string, attrs map[string]string) {
this.SubGraphs.Add(name)
for key, value := range attrs {
this.AddAttr(name, key, value)
}
}
func (this *Graph) IsNode(name string) bool {
_, ok := this.Nodes.Lookup[name]
return ok
}
func (this *Graph) IsSubGraph(name string) bool {
_, ok := this.SubGraphs.SubGraphs[name]
return ok
}

View File

@@ -1,61 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"sort"
)
//Represents a Node.
type Node struct {
Name string
Attrs Attrs
}
//Represents a set of Nodes.
type Nodes struct {
Lookup map[string]*Node
Nodes []*Node
}
//Creates a new set of Nodes.
func NewNodes() *Nodes {
return &Nodes{make(map[string]*Node), make([]*Node, 0)}
}
//Adds a Node to the set of Nodes, ammending the attributes of an already existing node.
func (this *Nodes) Add(node *Node) {
n, ok := this.Lookup[node.Name]
if ok {
n.Attrs.Ammend(node.Attrs)
return
}
this.Lookup[node.Name] = node
this.Nodes = append(this.Nodes, node)
}
//Returns a sorted list of nodes.
func (this Nodes) Sorted() []*Node {
keys := make([]string, 0, len(this.Lookup))
for key := range this.Lookup {
keys = append(keys, key)
}
sort.Strings(keys)
nodes := make([]*Node, len(keys))
for i := range keys {
nodes[i] = this.Lookup[keys[i]]
}
return nodes
}

View File

@@ -1,69 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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.
//A parser for the DOT grammar.
package parser
import (
"fmt"
"github.com/awalterschulze/gographviz/ast"
"github.com/awalterschulze/gographviz/scanner"
"github.com/awalterschulze/gographviz/token"
"io"
"io/ioutil"
"os"
)
//Parses a DOT string and outputs the
//abstract syntax tree representing the graph.
func ParseString(dotString string) (*ast.Graph, error) {
return ParseBytes([]byte(dotString))
}
//Parses the bytes representing a DOT string
//and outputs the abstract syntax tree representing the graph.
func ParseBytes(dotBytes []byte) (*ast.Graph, error) {
lex := &scanner.Scanner{}
lex.Init(dotBytes, token.DOTTokens)
parser := NewParser(ActionTable, GotoTable, ProductionsTable, token.DOTTokens)
st, err := parser.Parse(lex)
if err != nil {
return nil, err
}
g, ok := st.(*ast.Graph)
if !ok {
panic(fmt.Sprintf("Parser did not return an *ast.Graph, but rather a %T", st))
}
return g, err
}
//Parses a reader which contains a DOT string
//and outputs the abstract syntax tree representing the graph.
func Parse(r io.Reader) (*ast.Graph, error) {
bytes, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
return ParseBytes(bytes)
}
//Parses a file which contains a DOT string
//and outputs the abstract syntax tree representing the graph.
func ParseFile(filename string) (*ast.Graph, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
return Parse(f)
}

View File

@@ -1,200 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 parser
import (
"errors"
"strconv"
)
import "github.com/awalterschulze/gographviz/token"
type (
ActionTab []ActionRow
ActionRow map[token.Type]Action
)
func (R ActionRow) String() string {
s := ""
for t, a := range R {
s += strconv.Itoa(int(t)) + " : " + a.String() + "\n"
}
return s
}
type (
Accept int
Shift State
Reduce int
Action interface {
Act()
String() string
}
)
func (this Accept) Act() {}
func (this Shift) Act() {}
func (this Reduce) Act() {}
func (this Accept) String() string { return "Accept(0)" }
func (this Shift) String() string { return "Shift(" + strconv.Itoa(int(this)) + ")" }
func (this Reduce) String() string { return "Reduce(" + strconv.Itoa(int(this)) + ")" }
type (
GotoTab []GotoRow
GotoRow map[NT]State
State int
NT string
)
type (
ProdTab []ProdTabEntry
ProdTabEntry struct {
String string
Head NT
NumSymbols int
ReduceFunc func([]Attrib) (Attrib, error)
}
Attrib interface {
String() string
}
)
/*** Stack ***/
type stack struct {
state []State
attrib []Attrib
}
const INITIAL_STACK_SIZE = 100
func NewStack() *stack {
return &stack{state: make([]State, 0, INITIAL_STACK_SIZE),
attrib: make([]Attrib, 0, INITIAL_STACK_SIZE),
}
}
func (this *stack) Push(s State, a Attrib) {
this.state = append(this.state, s)
this.attrib = append(this.attrib, a)
}
func (this *stack) Top() State {
return this.state[len(this.state)-1]
}
func (this *stack) PopN(items int) []Attrib {
lo, hi := len(this.state)-items, len(this.state)
attrib := this.attrib[lo:hi]
this.state = this.state[:lo]
this.attrib = this.attrib[:lo]
return attrib
}
func (S *stack) String() string {
res := "stack:\n"
for i, st := range S.state {
res += "\t" + strconv.Itoa(i) + ": " + strconv.Itoa(int(st))
res += " , "
if S.attrib[i] == nil {
res += "nil"
} else {
res += S.attrib[i].String()
}
res += "\n"
}
return res
}
/*** Parser ***/
type Parser struct {
actTab ActionTab
gotoTab GotoTab
prodTab ProdTab
stack *stack
nextToken *token.Token
pos token.Position
tokenMap *token.TokenMap
}
type Scanner interface {
Scan() (*token.Token, token.Position)
}
func NewParser(act ActionTab, gto GotoTab, prod ProdTab, tm *token.TokenMap) *Parser {
p := &Parser{actTab: act, gotoTab: gto, prodTab: prod, stack: NewStack(), tokenMap: tm}
p.stack.Push(0, nil) //TODO: which attribute should be pushed here?
return p
}
func (P *Parser) Error(err error) error {
errmsg := "Error: " + P.TokString(P.nextToken) + " @ " + P.pos.String()
if err != nil {
errmsg += " " + err.Error()
} else {
errmsg += ", expected one of: "
actRow := P.actTab[P.stack.Top()]
i := 0
for t := range actRow {
errmsg += P.tokenMap.TokenString(t)
if i < len(actRow)-1 {
errmsg += " "
}
i++
}
}
return errors.New(errmsg)
}
func (P *Parser) TokString(tok *token.Token) string {
msg := P.tokenMap.TokenString(tok.Type) + "(" + strconv.Itoa(int(tok.Type)) + ")"
msg += " " + string(tok.Lit)
return msg
}
func (this *Parser) Parse(scanner Scanner) (res interface{}, err error) {
this.nextToken, this.pos = scanner.Scan()
for acc := false; !acc; {
action, ok := this.actTab[this.stack.Top()][this.nextToken.Type]
if !ok {
return nil, this.Error(nil)
}
switch act := action.(type) {
case Accept:
res = this.stack.PopN(1)[0]
acc = true
case Shift:
this.stack.Push(State(act), this.nextToken)
this.nextToken, this.pos = scanner.Scan()
case Reduce:
prod := this.prodTab[int(act)]
attrib, err := prod.ReduceFunc(this.stack.PopN(prod.NumSymbols))
if err != nil {
return nil, this.Error(err)
} else {
this.stack.Push(this.gotoTab[this.stack.Top()][prod.Head], attrib)
}
default:
panic("unknown action")
}
}
return res, nil
}

View File

@@ -1,200 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 parser
import (
"errors"
"strconv"
)
import "github.com/awalterschulze/gographviz/token"
type (
ActionTab []ActionRow
ActionRow map[token.Type]Action
)
func (R ActionRow) String() string {
s := ""
for t, a := range R {
s += strconv.Itoa(int(t)) + " : " + a.String() + "\n"
}
return s
}
type (
Accept int
Shift State
Reduce int
Action interface {
Act()
String() string
}
)
func (this Accept) Act() {}
func (this Shift) Act() {}
func (this Reduce) Act() {}
func (this Accept) String() string { return "Accept(0)" }
func (this Shift) String() string { return "Shift(" + strconv.Itoa(int(this)) + ")" }
func (this Reduce) String() string { return "Reduce(" + strconv.Itoa(int(this)) + ")" }
type (
GotoTab []GotoRow
GotoRow map[NT]State
State int
NT string
)
type (
ProdTab []ProdTabEntry
ProdTabEntry struct {
String string
Head NT
NumSymbols int
ReduceFunc func([]Attrib) (Attrib, error)
}
Attrib interface {
String() string
}
)
/*** Stack ***/
type stack struct {
state []State
attrib []Attrib
}
const INITIAL_STACK_SIZE = 100
func NewStack() *stack {
return &stack{state: make([]State, 0, INITIAL_STACK_SIZE),
attrib: make([]Attrib, 0, INITIAL_STACK_SIZE),
}
}
func (this *stack) Push(s State, a Attrib) {
this.state = append(this.state, s)
this.attrib = append(this.attrib, a)
}
func (this *stack) Top() State {
return this.state[len(this.state)-1]
}
func (this *stack) PopN(items int) []Attrib {
lo, hi := len(this.state)-items, len(this.state)
attrib := this.attrib[lo:hi]
this.state = this.state[:lo]
this.attrib = this.attrib[:lo]
return attrib
}
func (S *stack) String() string {
res := "stack:\n"
for i, st := range S.state {
res += "\t" + strconv.Itoa(i) + ": " + strconv.Itoa(int(st))
res += " , "
if S.attrib[i] == nil {
res += "nil"
} else {
res += S.attrib[i].String()
}
res += "\n"
}
return res
}
/*** Parser ***/
type Parser struct {
actTab ActionTab
gotoTab GotoTab
prodTab ProdTab
stack *stack
nextToken *token.Token
pos token.Position
tokenMap *token.TokenMap
}
type Scanner interface {
Scan() (*token.Token, token.Position)
}
func NewParser(act ActionTab, gto GotoTab, prod ProdTab, tm *token.TokenMap) *Parser {
p := &Parser{actTab: act, gotoTab: gto, prodTab: prod, stack: NewStack(), tokenMap: tm}
p.stack.Push(0, nil) //TODO: which attribute should be pushed here?
return p
}
func (P *Parser) Error(err error) error {
errmsg := "Error: " + P.TokString(P.nextToken) + " @ " + P.pos.String()
if err != nil {
errmsg += " " + err.Error()
} else {
errmsg += ", expected one of: "
actRow := P.actTab[P.stack.Top()]
i := 0
for t := range actRow {
errmsg += P.tokenMap.TokenString(t)
if i < len(actRow)-1 {
errmsg += " "
}
i++
}
}
return errors.New(errmsg)
}
func (P *Parser) TokString(tok *token.Token) string {
msg := P.tokenMap.TokenString(tok.Type) + "(" + strconv.Itoa(int(tok.Type)) + ")"
msg += " " + string(tok.Lit)
return msg
}
func (this *Parser) Parse(scanner Scanner) (res interface{}, err error) {
this.nextToken, this.pos = scanner.Scan()
for acc := false; !acc; {
action, ok := this.actTab[this.stack.Top()][this.nextToken.Type]
if !ok {
return nil, this.Error(nil)
}
switch act := action.(type) {
case Accept:
res = this.stack.PopN(1)[0]
acc = true
case Shift:
this.stack.Push(State(act), this.nextToken)
this.nextToken, this.pos = scanner.Scan()
case Reduce:
prod := this.prodTab[int(act)]
attrib, err := prod.ReduceFunc(this.stack.PopN(prod.NumSymbols))
if err != nil {
return nil, this.Error(err)
} else {
this.stack.Push(this.gotoTab[this.stack.Top()][prod.Head], attrib)
}
default:
panic("unknown action")
}
}
return res, nil
}

View File

@@ -1,293 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 parser
import (
"fmt"
"github.com/awalterschulze/gographviz/ast"
"io/ioutil"
"testing"
)
func check(t *testing.T, err error) {
if err != nil {
t.Fatalf("%v", err)
}
}
func assert(t *testing.T, msg string, v1 interface{}, v2 interface{}) {
if v1 != v2 {
t.Fatalf("%v\n%v\n!=\n%v", msg, v1, v2)
}
}
func parseTest(t *testing.T, filename string) {
localFilename := "../testdata/" + filename
s, err := ioutil.ReadFile(localFilename)
check(t, err)
t.Logf("Input String = %v", string(s))
g, err := ParseFile(localFilename)
t.Logf("First Parse = %v", g)
check(t, err)
gstr := g.String()
g2, err := ParseString(gstr)
t.Logf("Second Parse = %v", g2)
check(t, err)
gstr2 := g2.String()
assert(t, "output strings", gstr, gstr2)
}
func parseStringTest(t *testing.T, s string) {
t.Logf("Input String = %v", s)
g, err := ParseString(s)
t.Logf("First Parse = %v", g)
check(t, err)
gstr := g.String()
g2, err := ParseString(gstr)
t.Logf("Second Parse = %v", g2)
check(t, err)
gstr2 := g2.String()
assert(t, "output strings", gstr, gstr2)
}
func TestHelloWorldString(t *testing.T) {
input := `digraph G {Hello->World}`
g, err := ParseString(input)
check(t, err)
fmt.Printf("%#v", g)
}
func TestHelloWorldFile(t *testing.T) {
g, err := ParseFile("../testdata/helloworld.gv.txt")
check(t, err)
fmt.Printf("%#v", g)
}
func TestAttr(t *testing.T) {
parseStringTest(t,
"digraph finite_state { rankdir = LR }")
}
func TestString(t *testing.T) {
parseStringTest(t,
`digraph finite_state { rankdir = "LR" }`)
}
func TestAttrList(t *testing.T) {
parseStringTest(t, `
digraph { node [ shape = doublecircle ] }`)
}
func TestStringLit(t *testing.T) {
parseStringTest(t, `digraph finite_state_machine {
size= "8" ; }`)
}
func TestHashComments(t *testing.T) {
parseStringTest(t, `## bla \n
digraph G {Hello->World}`)
}
func TestIntLit(t *testing.T) {
parseStringTest(t, `graph G {
1 -- 30 [f=1];}`)
}
func TestFloat1(t *testing.T) {
parseStringTest(t, `digraph { bla = 2.0 }`)
}
func TestFloat2(t *testing.T) {
parseStringTest(t, `digraph { bla = .1 }`)
}
func TestNegative(t *testing.T) {
parseStringTest(t, `digraph { -2 -> -1 }`)
}
func TestUnderscore(t *testing.T) {
parseStringTest(t, `digraph { a_b = 1 }`)
}
func TestNonAscii(t *testing.T) {
parseStringTest(t, `digraph { label=T<>th }`)
}
func TestPorts(t *testing.T) {
parseStringTest(t, `digraph { "node6":f0 -> "node9":f1 }`)
}
func TestHtml(t *testing.T) {
parseStringTest(t, `digraph { a = <<table></table>> }`)
}
func TestIdWithKeyword(t *testing.T) {
parseStringTest(t, `digraph { edgeURL = "a" }`)
}
func TestSubGraph(t *testing.T) {
parseStringTest(t, `digraph { subgraph { a -> b } }`)
}
func TestImplicitSubGraph(t *testing.T) {
parseStringTest(t, `digraph { { a -> b } }`)
}
func TestEdges(t *testing.T) {
parseStringTest(t, `digraph { a0 -> a1 -> a2 -> a3 }`)
}
func TestNodes(t *testing.T) {
parseStringTest(t, `digraph { a0 a1 }`)
}
func TestTwoAttributes(t *testing.T) {
g, err := ParseString(`digraph { a0 [shape = circle bla = bla]}`)
check(t, err)
t.Logf("Parsed String = %v", g)
for _, stmt := range g.StmtList {
node := stmt.(*ast.NodeStmt)
if len(node.Attrs[0]) != 2 {
t.Fatalf("Not enough attributes, expected two, but found %v in %v", len(node.Attrs), node)
}
}
}
func TestEasyFsm(t *testing.T) {
parseStringTest(t, `digraph finite_state_machine {
rankdir=LR;
size="8,5";
node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8;
node [shape = circle];
LR_0 -> LR_2 [ label = "SS(B)" ];
LR_0 -> LR_1 [ label = "SS(S)" ];
LR_1 -> LR_3 [ label = "S($end)" ];
LR_2 -> LR_6 [ label = "SS(b)" ];
LR_2 -> LR_5 [ label = "SS(a)" ];
LR_2 -> LR_4 [ label = "S(A)" ];
LR_5 -> LR_7 [ label = "S(b)" ];
LR_5 -> LR_5 [ label = "S(a)" ];
LR_6 -> LR_6 [ label = "S(b)" ];
LR_6 -> LR_5 [ label = "S(a)" ];
LR_7 -> LR_8 [ label = "S(b)" ];
LR_7 -> LR_5 [ label = "S(a)" ];
LR_8 -> LR_6 [ label = "S(b)" ];
LR_8 -> LR_5 [ label = "S(a)" ];
}`)
}
func TestEmptyAttrList(t *testing.T) {
parseStringTest(t, `digraph g { edge [ ] }`)
}
func TestHelloWorld(t *testing.T) {
parseTest(t, "helloworld.gv.txt")
}
func TestCluster(t *testing.T) {
parseTest(t, "cluster.gv.txt")
}
func TestPsg(t *testing.T) {
parseTest(t, "psg.gv.txt")
}
func TestTransparency(t *testing.T) {
parseTest(t, "transparency.gv.txt")
}
func TestCrazy(t *testing.T) {
parseTest(t, "crazy.gv.txt")
}
func TestKennedyanc(t *testing.T) {
parseTest(t, "kennedyanc.gv.txt")
}
func TestRoot(t *testing.T) {
parseTest(t, "root.gv.txt")
}
func TestTwpoi(t *testing.T) {
parseTest(t, "twopi.gv.txt")
}
func TestDataStruct(t *testing.T) {
parseTest(t, "datastruct.gv.txt")
}
func TestLionShare(t *testing.T) {
parseTest(t, "lion_share.gv.txt")
}
func TestSdh(t *testing.T) {
parseTest(t, "sdh.gv.txt")
}
func TestUnix(t *testing.T) {
parseTest(t, "unix.gv.txt")
}
func TestEr(t *testing.T) {
parseTest(t, "er.gv.txt")
}
func TestNerworkMapTwopi(t *testing.T) {
parseTest(t, "networkmap_twopi.gv.txt")
}
func TestSibling(t *testing.T) {
parseTest(t, "siblings.gv.txt")
}
func TestWorld(t *testing.T) {
parseTest(t, "world.gv.txt")
}
func TestFdpclust(t *testing.T) {
parseTest(t, "fdpclust.gv.txt")
}
func TestPhilo(t *testing.T) {
parseTest(t, "philo.gv.txt")
}
func TestSoftmaint(t *testing.T) {
parseTest(t, "softmaint.gv.txt")
}
func TestFsm(t *testing.T) {
parseTest(t, "fsm.gv.txt")
}
func TestProcess(t *testing.T) {
parseTest(t, "process.gv.txt")
}
func TestSwitchGv(t *testing.T) {
parseTest(t, "switch.gv.txt")
}
func TestGd19942007(t *testing.T) {
parseTest(t, "gd_1994_2007.gv.txt")
}
func TestProfile(t *testing.T) {
parseTest(t, "profile.gv.txt")
}
func TestTrafficLights(t *testing.T) {
parseTest(t, "traffic_lights.gv.txt")
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"sort"
)
//Represents the relations between graphs and nodes.
//Each node belongs the main graph or a subgraph.
type Relations struct {
ParentToChildren map[string]map[string]bool
ChildToParents map[string]map[string]bool
}
//Creates an empty set of relations.
func NewRelations() *Relations {
return &Relations{make(map[string]map[string]bool), make(map[string]map[string]bool)}
}
//Adds a node to a parent graph.
func (this *Relations) Add(parent string, child string) {
if _, ok := this.ParentToChildren[parent]; !ok {
this.ParentToChildren[parent] = make(map[string]bool)
}
this.ParentToChildren[parent][child] = true
if _, ok := this.ChildToParents[child]; !ok {
this.ChildToParents[child] = make(map[string]bool)
}
this.ChildToParents[child][parent] = true
}
func (this *Relations) SortedChildren(parent string) []string {
keys := make([]string, 0)
for key := range this.ParentToChildren[parent] {
keys = append(keys, key)
}
sort.Strings(keys)
return keys
}

View File

@@ -1,570 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// A scanner for Go source text. Takes a []byte as source which can
// then be tokenized through repeated calls to the Scan function.
// For a sample use of a scanner, see the implementation of Tokenize.
//
//A scanner for the DOT grammar that has been derived from the standard
//golang scanner with extra added literals.
package scanner
import (
"bytes"
"strconv"
"unicode"
"unicode/utf8"
)
import "github.com/awalterschulze/gographviz/token"
// A Scanner holds the scanner's internal state while processing
// a given text. It can be allocated as part of another data
// structure but must be initialized via Init before use. For
// a sample use, see the implementation of Tokenize.
//
type Scanner struct {
// immutable state
src []byte // source
tokenMap *token.TokenMap
// scanning state
pos token.Position // previous reading position (position before ch)
offset int // current reading offset (position after ch)
ch rune // one char look-ahead
// public state - ok to modify
ErrorCount int // number of errors encountered
}
// Read the next Unicode char into S.ch.
// S.ch < 0 means end-of-file.
//
func (S *Scanner) next() {
if S.offset < len(S.src) {
S.pos.Offset = S.offset
S.pos.Column++
if S.ch == '\n' {
// next character starts a new line
S.pos.Line++
S.pos.Column = 1
}
r, w := rune(S.src[S.offset]), 1
switch {
case r == 0:
S.error(S.pos, "illegal character NUL")
case r >= 0x80:
// not ASCII
r, w = utf8.DecodeRune(S.src[S.offset:])
if r == utf8.RuneError && w == 1 {
S.error(S.pos, "illegal UTF-8 encoding")
}
}
S.offset += w
S.ch = r
} else {
S.pos.Offset = len(S.src)
S.ch = -1 // eof
}
}
// Init prepares the scanner S to tokenize the text src. Calls to Scan
// will use the error handler err if they encounter a syntax error and
// err is not nil. Also, for each error encountered, the Scanner field
// ErrorCount is incremented by one. The filename parameter is used as
// filename in the token.Position returned by Scan for each token. The
// mode parameter determines how comments and illegal characters are
// handled.
//
func (S *Scanner) Init(src []byte, tokenMap *token.TokenMap) {
// Explicitly initialize all fields since a scanner may be reused.
S.src = src
S.tokenMap = tokenMap
S.pos = token.Position{0, 1, 0}
S.offset = 0
S.ErrorCount = 0
S.next()
}
func charString(ch rune) string {
var s string
switch ch {
case -1:
return "EOF"
case '\a':
s = "\\a"
case '\b':
s = "\\b"
case '\f':
s = "\\f"
case '\n':
s = "\\n"
case '\r':
s = "\\r"
case '\t':
s = "\\t"
case '\v':
s = "\\v"
case '\\':
s = "\\\\"
case '\'':
s = "\\'"
default:
s = string(ch)
}
return "'" + s + "' (U+" + strconv.FormatInt(int64(ch), 16) + ")"
}
func (S *Scanner) error(pos token.Position, msg string) {
S.ErrorCount++
}
func (S *Scanner) expect(ch rune) {
if S.ch != ch {
S.error(S.pos, "expected "+charString(ch)+", found "+charString(S.ch))
}
S.next() // always make progress
}
var prefix = []byte("line ")
func (S *Scanner) scanComment(pos token.Position) {
// first '/' or '#' already consumed
if S.ch == '*' {
/*-style comment */
S.expect('*')
for S.ch >= 0 {
ch := S.ch
S.next()
if ch == '*' && S.ch == '/' {
S.next()
return
}
}
} else {
//-style comment or #-style comment
for S.ch >= 0 {
S.next()
if S.ch == '\n' {
// '\n' is not part of the comment for purposes of scanning
// (the comment ends on the same line where it started)
if pos.Column == 1 {
text := S.src[pos.Offset+2 : S.pos.Offset]
if bytes.HasPrefix(text, prefix) {
// comment starts at beginning of line with "//line ";
// get filename and line number, if any
i := bytes.Index(text, []byte{':'})
if i >= 0 {
if line, err := strconv.Atoi(string(text[i+1:])); err == nil && line > 0 {
// valid //line filename:line comment;
// update scanner position
S.pos.Line = line - 1 // -1 since the '\n' has not been consumed yet
}
}
}
}
return
}
}
}
S.error(pos, "comment not terminated")
}
func (S *Scanner) findNewline(pos token.Position) bool {
// first '/' already consumed; assume S.ch == '/' || S.ch == '*'
// read ahead until a newline or non-comment token is found
newline := false
for pos1 := pos; S.ch >= 0; {
if S.ch == '/' {
//-style comment always contains a newline
newline = true
break
}
S.scanComment(pos1)
if pos1.Line < S.pos.Line {
/*-style comment contained a newline */
newline = true
break
}
S.skipWhitespace() // S.insertSemi is set
if S.ch == '\n' {
newline = true
break
}
if S.ch != '/' {
// non-comment token
break
}
pos1 = S.pos
S.next()
if S.ch != '/' && S.ch != '*' {
// non-comment token
break
}
}
// reset position to where it was upon calling findNewline
S.pos = pos
S.offset = pos.Offset + 1
S.next()
return newline
}
func isLetter(ch rune) bool {
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' ||
ch >= 0x80 && unicode.IsLetter(ch) && ch != 'ε'
}
func isDigit(ch rune) bool {
return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
}
func digitVal(ch rune) int {
switch {
case '0' <= ch && ch <= '9':
return int(ch) - '0'
case 'a' <= ch && ch <= 'f':
return int(ch) - 'a' + 10
case 'A' <= ch && ch <= 'F':
return int(ch) - 'A' + 10
}
return 16 // larger than any legal digit val
}
func (S *Scanner) scanEscape(quote rune) {
pos := S.pos
var i, base, max uint32
switch S.ch {
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
S.next()
return
case '0', '1', '2', '3', '4', '5', '6', '7':
i, base, max = 3, 8, 255
case 'x':
S.next()
i, base, max = 2, 16, 255
case 'u':
S.next()
i, base, max = 4, 16, unicode.MaxRune
case 'U':
S.next()
i, base, max = 8, 16, unicode.MaxRune
default:
S.next() // always make progress
S.error(pos, "unknown escape sequence")
return
}
var x uint32
for ; i > 0; i-- {
d := uint32(digitVal(S.ch))
if d > base {
S.error(S.pos, "illegal character in escape sequence")
return
}
x = x*base + d
S.next()
}
if x > max || 0xd800 <= x && x < 0xe000 {
S.error(pos, "escape sequence is invalid Unicode code point")
}
}
func (S *Scanner) scanChar(pos token.Position) {
// '\'' already consumed
n := 0
for S.ch != '\'' {
ch := S.ch
n++
S.next()
if ch == '\n' || ch < 0 {
S.error(pos, "character literal not terminated")
n = 1
break
}
if ch == '\\' {
S.scanEscape('\'')
}
}
S.next()
if n != 1 {
S.error(pos, "illegal character literal")
}
}
func (S *Scanner) isToken(str string) bool {
return S.tokenMap.Type(str) != token.ILLEGAL
}
func (S *Scanner) scanIdentifier() token.Type {
pos := S.pos.Offset
for !S.isToken(string(S.ch)) && !unicode.IsSpace(S.ch) && S.ch != '-' {
S.next()
}
if tok := S.tokenMap.Type(string(S.src[pos:S.pos.Offset])); tok != token.ILLEGAL {
return tok
}
return S.tokenMap.Type("id")
}
func (S *Scanner) scanNumber() token.Type {
for isDigit(S.ch) {
S.next()
}
if S.ch == '.' {
S.next()
for isDigit(S.ch) {
S.next()
}
return S.tokenMap.Type("float_lit")
}
return S.tokenMap.Type("int_lit")
}
func (S *Scanner) scanHTML() token.Type {
count := 1
for count > 0 {
if S.ch == '<' {
count += 1
}
if S.ch == '>' {
count -= 1
}
S.next()
}
return S.tokenMap.Type("html_lit")
}
func (S *Scanner) scanSDTLit(pos token.Position) {
// '<' already consumed
S.next() // consume second <
for cmp := false; !cmp; {
if S.ch < 0 {
S.error(pos, "SDT not terminated")
break
}
if S.ch == '>' {
S.next()
if S.ch == '>' {
break
}
}
S.next()
}
S.next()
}
func (S *Scanner) scanString(pos token.Position) {
// '"' already consumed
for S.ch != '"' {
ch := S.ch
S.next()
if ch == '\n' || ch < 0 {
S.error(pos, "string not terminated")
break
}
if ch == '\\' {
S.scanEscape('"')
}
}
S.next()
}
func (S *Scanner) scanRawString(pos token.Position) {
// '\140' already consumed
for S.ch != '\140' {
ch := S.ch
S.next()
if ch < 0 {
S.error(pos, "string not terminated")
break
}
}
S.next()
}
func (S *Scanner) skipWhitespace() {
for S.ch == ' ' || S.ch == '\t' || S.ch == '\n' || S.ch == '\r' {
S.next()
}
}
// Helper functions for scanning multi-byte tokens such as >> += >>= .
// Different routines recognize different length tok_i based on matches
// of ch_i. If a token ends in '=', the result is tok1 or tok3
// respectively. Otherwise, the result is tok0 if there was no other
// matching character, or tok2 if the matching character was ch2.
func (S *Scanner) switch2(tok0, tok1 token.Type) token.Type {
if S.ch == '=' {
S.next()
return tok1
}
return tok0
}
func (S *Scanner) switch3(tok0, tok1 token.Type, ch2 rune, tok2 token.Type) token.Type {
if S.ch == '=' {
S.next()
return tok1
}
if S.ch == ch2 {
S.next()
return tok2
}
return tok0
}
func (S *Scanner) switch4(tok0, tok1 token.Type, ch2 rune, tok2, tok3 token.Type) token.Type {
if S.ch == '=' {
S.next()
return tok1
}
if S.ch == ch2 {
S.next()
if S.ch == '=' {
S.next()
return tok3
}
return tok2
}
return tok0
}
var semicolon = []byte{';'}
// Scan scans the next token and returns the token position pos,
// the token tok, and the literal text lit corresponding to the
// token. The source end is indicated by token.EOF.
//
// For more tolerant parsing, Scan will return a valid token if
// possible even if a syntax error was encountered. Thus, even
// if the resulting token sequence contains no illegal tokens,
// a client may not assume that no error occurred. Instead it
// must check the scanner's ErrorCount or the number of calls
// of the error handler, if there was one installed.
//
func (S *Scanner) Scan() (*token.Token, token.Position) {
scanAgain:
S.skipWhitespace()
// current token start
pos, tok := S.pos, token.ILLEGAL
// determine token value
switch ch := S.ch; {
case isLetter(ch):
tok = S.scanIdentifier()
case isDigit(ch), ch == '.':
tok = S.scanNumber()
default:
S.next() // always make progress
switch ch {
case -1:
tok = S.tokenMap.Type("$")
case '"':
tok = S.tokenMap.Type("string_lit")
S.scanString(pos)
case '\'':
tok = S.tokenMap.Type("char")
S.scanChar(pos)
case '\140':
tok = S.tokenMap.Type("string_lit")
S.scanRawString(pos)
case ',':
tok = S.tokenMap.Type(",")
case '{':
tok = S.tokenMap.Type("{")
case '}':
tok = S.tokenMap.Type("}")
case ':':
tok = S.tokenMap.Type(":")
case ';':
tok = S.tokenMap.Type(";")
case '+':
tok = S.tokenMap.Type("+")
case '-':
if S.ch == '-' {
tok = S.tokenMap.Type("--")
S.next()
} else if S.ch == '>' {
tok = S.tokenMap.Type("->")
S.next()
} else if isDigit(S.ch) {
tok = S.scanNumber()
} else {
tok = S.tokenMap.Type("-")
}
case '=':
tok = S.tokenMap.Type("=")
case '[':
tok = S.tokenMap.Type("[")
case ']':
tok = S.tokenMap.Type("]")
case '(':
tok = S.tokenMap.Type("(")
case ')':
tok = S.tokenMap.Type(")")
case 'ε':
tok = S.tokenMap.Type("ε")
case '#':
S.scanComment(pos)
goto scanAgain
case '/':
if S.ch == '/' || S.ch == '*' {
// comment
S.scanComment(pos)
goto scanAgain
} else {
tok = S.tokenMap.Type("/")
}
case '|':
tok = S.tokenMap.Type("|")
case '<':
tok = S.scanHTML()
default:
S.error(pos, "illegal character "+charString(ch))
}
}
//fmt.Fprintf(os.Stderr, "return tok %v, %v\n", token.NewToken(tok, S.src[pos.Offset:S.pos.Offset]), pos)
return token.NewToken(tok, S.src[pos.Offset:S.pos.Offset]), pos
}
// An implementation of an ErrorHandler may be provided to the Scanner.
// If a syntax error is encountered and a handler was installed, Error
// is called with a position and an error message. The position points
// to the beginning of the offending token.
//
type ErrorHandler interface {
Error(pos token.Position, msg string)
}
// Within ErrorVector, an error is represented by an Error node. The
// position Pos, if valid, points to the beginning of the offending
// token, and the error condition is described by Msg.
//
type Error struct {
Pos token.Position
Msg string
}
func (e *Error) String() string {
if e.Pos.IsValid() {
// don't print "<unknown position>"
// TODO(gri) reconsider the semantics of Position.IsValid
return e.Pos.String() + ": " + e.Msg
}
return e.Msg
}

View File

@@ -1,63 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"sort"
)
//Represents a Subgraph.
type SubGraph struct {
Attrs Attrs
Name string
}
//Creates a new Subgraph.
func NewSubGraph(name string) *SubGraph {
return &SubGraph{
Attrs: make(Attrs),
Name: name,
}
}
//Represents a set of SubGraphs.
type SubGraphs struct {
SubGraphs map[string]*SubGraph
}
//Creates a new blank set of SubGraphs.
func NewSubGraphs() *SubGraphs {
return &SubGraphs{make(map[string]*SubGraph)}
}
//Adds and creates a new Subgraph to the set of SubGraphs.
func (this *SubGraphs) Add(name string) {
if _, ok := this.SubGraphs[name]; !ok {
this.SubGraphs[name] = NewSubGraph(name)
}
}
func (this *SubGraphs) Sorted() []*SubGraph {
keys := make([]string, 0)
for key := range this.SubGraphs {
keys = append(keys, key)
}
sort.Strings(keys)
s := make([]*SubGraph, len(keys))
for i, key := range keys {
s[i] = this.SubGraphs[key]
}
return s
}

View File

@@ -1 +0,0 @@
These test graphs have been copied from the graphviz gallery found here http://www.graphviz.org/Gallery.php

View File

@@ -1,27 +0,0 @@
digraph G {
subgraph cluster_0 {
style=filled;
color=lightgrey;
node [style=filled,color=white];
a0 -> a1 -> a2 -> a3;
label = "process #1";
}
subgraph cluster_1 {
node [style=filled];
b0 -> b1 -> b2 -> b3;
label = "process #2";
color=blue
}
start -> a0;
start -> b0;
a1 -> b3;
b2 -> a3;
a3 -> a0;
a3 -> end;
b3 -> end;
start [shape=Mdiamond];
end [shape=Msquare];
}

View File

@@ -1,104 +0,0 @@
digraph "unix" {
graph [ fontname = "Helvetica-Oblique",
fontsize = 36,
label = "\n\n\n\nObject Oriented Graphs\nStephen North, 3/19/93",
size = "6,6" ];
node [ shape = polygon,
sides = 4,
distortion = "0.0",
orientation = "0.0",
skew = "0.0",
color = white,
style = filled,
fontname = "Helvetica-Outline" ];
"5th Edition" [sides=9, distortion="0.936354", orientation=28, skew="-0.126818", color=salmon2];
"6th Edition" [sides=5, distortion="0.238792", orientation=11, skew="0.995935", color=deepskyblue];
"PWB 1.0" [sides=8, distortion="0.019636", orientation=79, skew="-0.440424", color=goldenrod2];
LSX [sides=9, distortion="-0.698271", orientation=22, skew="-0.195492", color=burlywood2];
"1 BSD" [sides=7, distortion="0.265084", orientation=26, skew="0.403659", color=gold1];
"Mini Unix" [distortion="0.039386", orientation=2, skew="-0.461120", color=greenyellow];
Wollongong [sides=5, distortion="0.228564", orientation=63, skew="-0.062846", color=darkseagreen];
Interdata [distortion="0.624013", orientation=56, skew="0.101396", color=dodgerblue1];
"Unix/TS 3.0" [sides=8, distortion="0.731383", orientation=43, skew="-0.824612", color=thistle2];
"PWB 2.0" [sides=6, distortion="0.592100", orientation=34, skew="-0.719269", color=darkolivegreen3];
"7th Edition" [sides=10, distortion="0.298417", orientation=65, skew="0.310367", color=chocolate];
"8th Edition" [distortion="-0.997093", orientation=50, skew="-0.061117", color=turquoise3];
"32V" [sides=7, distortion="0.878516", orientation=19, skew="0.592905", color=steelblue3];
V7M [sides=10, distortion="-0.960249", orientation=32, skew="0.460424", color=navy];
"Ultrix-11" [sides=10, distortion="-0.633186", orientation=10, skew="0.333125", color=darkseagreen4];
Xenix [sides=8, distortion="-0.337997", orientation=52, skew="-0.760726", color=coral];
"UniPlus+" [sides=7, distortion="0.788483", orientation=39, skew="-0.526284", color=darkolivegreen3];
"9th Edition" [sides=7, distortion="0.138690", orientation=55, skew="0.554049", color=coral3];
"2 BSD" [sides=7, distortion="-0.010661", orientation=84, skew="0.179249", color=blanchedalmond];
"2.8 BSD" [distortion="-0.239422", orientation=44, skew="0.053841", color=lightskyblue1];
"2.9 BSD" [distortion="-0.843381", orientation=70, skew="-0.601395", color=aquamarine2];
"3 BSD" [sides=10, distortion="0.251820", orientation=18, skew="-0.530618", color=lemonchiffon];
"4 BSD" [sides=5, distortion="-0.772300", orientation=24, skew="-0.028475", color=darkorange1];
"4.1 BSD" [distortion="-0.226170", orientation=38, skew="0.504053", color=lightyellow1];
"4.2 BSD" [sides=10, distortion="-0.807349", orientation=50, skew="-0.908842", color=darkorchid4];
"4.3 BSD" [sides=10, distortion="-0.030619", orientation=76, skew="0.985021", color=lemonchiffon2];
"Ultrix-32" [distortion="-0.644209", orientation=21, skew="0.307836", color=goldenrod3];
"PWB 1.2" [sides=7, distortion="0.640971", orientation=84, skew="-0.768455", color=cyan];
"USG 1.0" [distortion="0.758942", orientation=42, skew="0.039886", color=blue];
"CB Unix 1" [sides=9, distortion="-0.348692", orientation=42, skew="0.767058", color=firebrick];
"USG 2.0" [distortion="0.748625", orientation=74, skew="-0.647656", color=chartreuse4];
"CB Unix 2" [sides=10, distortion="0.851818", orientation=32, skew="-0.020120", color=greenyellow];
"CB Unix 3" [sides=10, distortion="0.992237", orientation=29, skew="0.256102", color=bisque4];
"Unix/TS++" [sides=6, distortion="0.545461", orientation=16, skew="0.313589", color=mistyrose2];
"PDP-11 Sys V" [sides=9, distortion="-0.267769", orientation=40, skew="0.271226", color=cadetblue1];
"USG 3.0" [distortion="-0.848455", orientation=44, skew="0.267152", color=bisque2];
"Unix/TS 1.0" [distortion="0.305594", orientation=75, skew="0.070516", color=orangered];
"TS 4.0" [sides=10, distortion="-0.641701", orientation=50, skew="-0.952502", color=crimson];
"System V.0" [sides=9, distortion="0.021556", orientation=26, skew="-0.729938", color=darkorange1];
"System V.2" [sides=6, distortion="0.985153", orientation=33, skew="-0.399752", color=darkolivegreen4];
"System V.3" [sides=7, distortion="-0.687574", orientation=58, skew="-0.180116", color=lightsteelblue1];
"5th Edition" -> "6th Edition";
"5th Edition" -> "PWB 1.0";
"6th Edition" -> LSX;
"6th Edition" -> "1 BSD";
"6th Edition" -> "Mini Unix";
"6th Edition" -> Wollongong;
"6th Edition" -> Interdata;
Interdata -> "Unix/TS 3.0";
Interdata -> "PWB 2.0";
Interdata -> "7th Edition";
"7th Edition" -> "8th Edition";
"7th Edition" -> "32V";
"7th Edition" -> V7M;
"7th Edition" -> "Ultrix-11";
"7th Edition" -> Xenix;
"7th Edition" -> "UniPlus+";
V7M -> "Ultrix-11";
"8th Edition" -> "9th Edition";
"1 BSD" -> "2 BSD";
"2 BSD" -> "2.8 BSD";
"2.8 BSD" -> "Ultrix-11";
"2.8 BSD" -> "2.9 BSD";
"32V" -> "3 BSD";
"3 BSD" -> "4 BSD";
"4 BSD" -> "4.1 BSD";
"4.1 BSD" -> "4.2 BSD";
"4.1 BSD" -> "2.8 BSD";
"4.1 BSD" -> "8th Edition";
"4.2 BSD" -> "4.3 BSD";
"4.2 BSD" -> "Ultrix-32";
"PWB 1.0" -> "PWB 1.2";
"PWB 1.0" -> "USG 1.0";
"PWB 1.2" -> "PWB 2.0";
"USG 1.0" -> "CB Unix 1";
"USG 1.0" -> "USG 2.0";
"CB Unix 1" -> "CB Unix 2";
"CB Unix 2" -> "CB Unix 3";
"CB Unix 3" -> "Unix/TS++";
"CB Unix 3" -> "PDP-11 Sys V";
"USG 2.0" -> "USG 3.0";
"USG 3.0" -> "Unix/TS 3.0";
"PWB 2.0" -> "Unix/TS 3.0";
"Unix/TS 1.0" -> "Unix/TS 3.0";
"Unix/TS 3.0" -> "TS 4.0";
"Unix/TS++" -> "TS 4.0";
"CB Unix 3" -> "TS 4.0";
"TS 4.0" -> "System V.0";
"System V.0" -> "System V.2";
"System V.2" -> "System V.3";
}

View File

@@ -1,114 +0,0 @@
digraph g {
graph [
rankdir = "LR"
];
node [
fontsize = "16"
shape = "ellipse"
];
edge [
];
"node0" [
label = "<f0> 0x10ba8| <f1>"
shape = "record"
];
"node1" [
label = "<f0> 0xf7fc4380| <f1> | <f2> |-1"
shape = "record"
];
"node2" [
label = "<f0> 0xf7fc44b8| | |2"
shape = "record"
];
"node3" [
label = "<f0> 3.43322790286038071e-06|44.79998779296875|0"
shape = "record"
];
"node4" [
label = "<f0> 0xf7fc4380| <f1> | <f2> |2"
shape = "record"
];
"node5" [
label = "<f0> (nil)| | |-1"
shape = "record"
];
"node6" [
label = "<f0> 0xf7fc4380| <f1> | <f2> |1"
shape = "record"
];
"node7" [
label = "<f0> 0xf7fc4380| <f1> | <f2> |2"
shape = "record"
];
"node8" [
label = "<f0> (nil)| | |-1"
shape = "record"
];
"node9" [
label = "<f0> (nil)| | |-1"
shape = "record"
];
"node10" [
label = "<f0> (nil)| <f1> | <f2> |-1"
shape = "record"
];
"node11" [
label = "<f0> (nil)| <f1> | <f2> |-1"
shape = "record"
];
"node12" [
label = "<f0> 0xf7fc43e0| | |1"
shape = "record"
];
"node0":f0 -> "node1":f0 [
id = 0
];
"node0":f1 -> "node2":f0 [
id = 1
];
"node1":f0 -> "node3":f0 [
id = 2
];
"node1":f1 -> "node4":f0 [
id = 3
];
"node1":f2 -> "node5":f0 [
id = 4
];
"node4":f0 -> "node3":f0 [
id = 5
];
"node4":f1 -> "node6":f0 [
id = 6
];
"node4":f2 -> "node10":f0 [
id = 7
];
"node6":f0 -> "node3":f0 [
id = 8
];
"node6":f1 -> "node7":f0 [
id = 9
];
"node6":f2 -> "node9":f0 [
id = 10
];
"node7":f0 -> "node3":f0 [
id = 11
];
"node7":f1 -> "node1":f0 [
id = 12
];
"node7":f2 -> "node8":f0 [
id = 13
];
"node10":f1 -> "node11":f0 [
id = 14
];
"node10":f2 -> "node12":f0 [
id = 15
];
"node11":f2 -> "node1":f0 [
id = 16
];
}

View File

@@ -1,22 +0,0 @@
graph ER {
node [shape=box]; course; institute; student;
node [shape=ellipse]; {node [label="name"] name0; name1; name2;}
code; grade; number;
node [shape=diamond,style=filled,color=lightgrey]; "C-I"; "S-C"; "S-I";
name0 -- course;
code -- course;
course -- "C-I" [label="n",len=1.00];
"C-I" -- institute [label="1",len=1.00];
institute -- name1;
institute -- "S-I" [label="1",len=1.00];
"S-I" -- student [label="n",len=1.00];
student -- grade;
student -- name2;
student -- number;
student -- "S-C" [label="m",len=1.00];
"S-C" -- course [label="n",len=1.00];
label = "\n\nEntity Relation Diagram\ndrawn by NEATO";
fontsize=20;
}

View File

@@ -1,15 +0,0 @@
graph G {
e
subgraph clusterA {
a -- b;
subgraph clusterC {
C -- D;
}
}
subgraph clusterB {
d -- f
}
d -- D
e -- clusterB
clusterC -- clusterB
}

View File

@@ -1,20 +0,0 @@
digraph finite_state_machine {
rankdir=LR;
size="8,5"
node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8;
node [shape = circle];
LR_0 -> LR_2 [ label = "SS(B)" ];
LR_0 -> LR_1 [ label = "SS(S)" ];
LR_1 -> LR_3 [ label = "S($end)" ];
LR_2 -> LR_6 [ label = "SS(b)" ];
LR_2 -> LR_5 [ label = "SS(a)" ];
LR_2 -> LR_4 [ label = "S(A)" ];
LR_5 -> LR_7 [ label = "S(b)" ];
LR_5 -> LR_5 [ label = "S(a)" ];
LR_6 -> LR_6 [ label = "S(b)" ];
LR_6 -> LR_5 [ label = "S(a)" ];
LR_7 -> LR_8 [ label = "S(b)" ];
LR_7 -> LR_5 [ label = "S(a)" ];
LR_8 -> LR_6 [ label = "S(b)" ];
LR_8 -> LR_5 [ label = "S(a)" ];
}

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
digraph G {Hello->World}

View File

@@ -1,90 +0,0 @@
/*
Note: All images in the file is found at
http://www.graphviz.org/Gallery/directed/images/
-----------
from Kaarle Kaila:
I have implemented Genealogic descendant and ancestor graphs using Graphviz in FinFamily. I have made som description on how to use it with FinFamily at FinFamily wiki-pages at
http://www.finfamily.fi/index.php/Handbook
I attach a descendant graph from Joseph Patrick Kennedy and an ancestor graph from Caroline Bouvier Kennedy as samples from FinFamily. The file georg.jpg is a descendant graph w/o pictures from an imaginary person Georg af Charlow (who has some common attributes with my father) from my testdatabase like the person Charles Charlow has some resemblance to myself.
If you wish to display the attached pictures or wish me to create another ones then feel free to do so. I wish to thank you for Graphviz that let's me create such nice graphs with FinFamily.
regards
Kaarle Kaila
I have this little kennedy database as a sample gedcom file on the download webpage to give international users a few wellknown persons to play with if they wish to try out my software. I originally got it from Michael Kay who is among others Editor at http://www.w3.org/TR/xslt20/. I added the pictures and some data myself.
Attached are both the kennedyanc and kennedydesc files as you requested. I made them as zip-files so that tehy contain both source and destination files. As you email server does not accept zip-files I renamed them to anc.zip ->anc.files and desc.zip to desc.files. Hope these com through your filters.
Graphviz dot program is called from withing FinFamily with a command line such as:
dot -Tjpeg kennedyanc.txt -o kennedyanc.jpg
On page http://www.finfamily.fi/index.php/Graphviz is a description on the different colors together with instructions for finFamily users how to create Graphviz reports.
Kaarle Kaila
Colors and forms symbolize following
* Blue box - man
* Red ellipse - woman
* Blue line - Father/Child relation
* Red line - Mother/Child relation
* Green line - Spouse relation
* Orange line - Ancestors (other) children
* Violet line - Ancestors (other) spouse
*/
/* ancestor graph from Caroline Bouvier Kennedy */
graph G {
I5 [shape=ellipse,color=red,style=bold,label="Caroline Bouvier Kennedy\nb. 27.11.1957 New York",image="images/165px-Caroline_Kennedy.jpg",labelloc=b];
I1 [shape=box,color=blue,style=bold,label="John Fitzgerald Kennedy\nb. 29.5.1917 Brookline\nd. 22.11.1963 Dallas",image="images/kennedyface.jpg",labelloc=b];
I6 [shape=box,color=blue,style=bold,label="John Fitzgerald Kennedy\nb. 25.11.1960 Washington\nd. 16.7.1999 over the Atlantic Ocean, near Aquinnah, MA, USA",image="images/180px-JFKJr2.jpg",labelloc=b];
I7 [shape=box,color=blue,style=bold,label="Patrick Bouvier Kennedy\nb. 7.8.1963\nd. 9.8.1963"];
I2 [shape=ellipse,color=red,style=bold,label="Jaqueline Lee Bouvier\nb. 28.7.1929 Southampton\nd. 19.5.1994 New York City",image="images/jacqueline-kennedy-onassis.jpg",labelloc=b];
I8 [shape=box,color=blue,style=bold,label="Joseph Patrick Kennedy\nb. 6.9.1888 East Boston\nd. 16.11.1969 Hyannis Port",image="images/1025901671.jpg",labelloc=b];
I10 [shape=box,color=blue,style=bold,label="Joseph Patrick Kennedy Jr\nb. 1915\nd. 1944"];
I11 [shape=ellipse,color=red,style=bold,label="Rosemary Kennedy\nb. 13.9.1918\nd. 7.1.2005",image="images/rosemary.jpg",labelloc=b];
I12 [shape=ellipse,color=red,style=bold,label="Kathleen Kennedy\nb. 1920\nd. 1948"];
I13 [shape=ellipse,color=red,style=bold,label="Eunice Mary Kennedy\nb. 10.7.1921 Brookline"];
I9 [shape=ellipse,color=red,style=bold,label="Rose Elizabeth Fitzgerald\nb. 22.7.1890 Boston\nd. 22.1.1995 Hyannis Port",image="images/Rose_kennedy.JPG",labelloc=b];
I15 [shape=box,color=blue,style=bold,label="Aristotle Onassis"];
I3 [shape=box,color=blue,style=bold,label="John Vernou Bouvier III\nb. 1891\nd. 1957",image="images/BE037819.jpg",labelloc=b];
I4 [shape=ellipse,color=red,style=bold,label="Janet Norton Lee\nb. 2.10.1877\nd. 3.1.1968",image="images/n48862003257_1275276_1366.jpg",labelloc=b];
I1 -- I5 [style=bold,color=blue];
I1 -- I6 [style=bold,color=orange];
I2 -- I6 [style=bold,color=orange];
I1 -- I7 [style=bold,color=orange];
I2 -- I7 [style=bold,color=orange];
I1 -- I2 [style=bold,color=violet];
I8 -- I1 [style=bold,color=blue];
I8 -- I10 [style=bold,color=orange];
I9 -- I10 [style=bold,color=orange];
I8 -- I11 [style=bold,color=orange];
I9 -- I11 [style=bold,color=orange];
I8 -- I12 [style=bold,color=orange];
I9 -- I12 [style=bold,color=orange];
I8 -- I13 [style=bold,color=orange];
I9 -- I13 [style=bold,color=orange];
I8 -- I9 [style=bold,color=violet];
I9 -- I1 [style=bold,color=red];
I2 -- I5 [style=bold,color=red];
I2 -- I15 [style=bold,color=violet];
I3 -- I2 [style=bold,color=blue];
I3 -- I4 [style=bold,color=violet];
I4 -- I2 [style=bold,color=red];
}

View File

@@ -1,109 +0,0 @@
##"A few people in the field of genetics are using dot to draw "marriage node diagram" pedigree drawings. Here is one I have done of a test pedigree from the FTREE pedigree drawing package (Lion Share was a racehorse)." Contributed by David Duffy.
##Command to get the layout: "dot -Tpng thisfile > thisfile.png"
digraph Ped_Lion_Share {
# page = "8.2677165,11.692913" ;
ratio = "auto" ;
mincross = 2.0 ;
label = "Pedigree Lion_Share" ;
"001" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"002" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"003" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"004" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"005" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"006" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"007" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"009" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"014" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"015" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"016" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"ZZ01" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"ZZ02" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"017" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"012" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"008" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"011" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"013" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"010" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"023" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"020" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"021" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"018" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"025" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"019" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"022" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"024" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"027" [shape=circle , regular=1,style=filled,fillcolor=white ] ;
"026" [shape=box , regular=1,style=filled,fillcolor=white ] ;
"028" [shape=box , regular=1,style=filled,fillcolor=grey ] ;
"marr0001" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"001" -> "marr0001" [dir=none,weight=1] ;
"007" -> "marr0001" [dir=none,weight=1] ;
"marr0001" -> "017" [dir=none, weight=2] ;
"marr0002" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"001" -> "marr0002" [dir=none,weight=1] ;
"ZZ02" -> "marr0002" [dir=none,weight=1] ;
"marr0002" -> "012" [dir=none, weight=2] ;
"marr0003" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"002" -> "marr0003" [dir=none,weight=1] ;
"003" -> "marr0003" [dir=none,weight=1] ;
"marr0003" -> "008" [dir=none, weight=2] ;
"marr0004" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"002" -> "marr0004" [dir=none,weight=1] ;
"006" -> "marr0004" [dir=none,weight=1] ;
"marr0004" -> "011" [dir=none, weight=2] ;
"marr0005" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"002" -> "marr0005" [dir=none,weight=1] ;
"ZZ01" -> "marr0005" [dir=none,weight=1] ;
"marr0005" -> "013" [dir=none, weight=2] ;
"marr0006" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"004" -> "marr0006" [dir=none,weight=1] ;
"009" -> "marr0006" [dir=none,weight=1] ;
"marr0006" -> "010" [dir=none, weight=2] ;
"marr0007" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"005" -> "marr0007" [dir=none,weight=1] ;
"015" -> "marr0007" [dir=none,weight=1] ;
"marr0007" -> "023" [dir=none, weight=2] ;
"marr0008" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"005" -> "marr0008" [dir=none,weight=1] ;
"016" -> "marr0008" [dir=none,weight=1] ;
"marr0008" -> "020" [dir=none, weight=2] ;
"marr0009" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"005" -> "marr0009" [dir=none,weight=1] ;
"012" -> "marr0009" [dir=none,weight=1] ;
"marr0009" -> "021" [dir=none, weight=2] ;
"marr0010" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"008" -> "marr0010" [dir=none,weight=1] ;
"017" -> "marr0010" [dir=none,weight=1] ;
"marr0010" -> "018" [dir=none, weight=2] ;
"marr0011" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"011" -> "marr0011" [dir=none,weight=1] ;
"023" -> "marr0011" [dir=none,weight=1] ;
"marr0011" -> "025" [dir=none, weight=2] ;
"marr0012" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"013" -> "marr0012" [dir=none,weight=1] ;
"014" -> "marr0012" [dir=none,weight=1] ;
"marr0012" -> "019" [dir=none, weight=2] ;
"marr0013" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"010" -> "marr0013" [dir=none,weight=1] ;
"021" -> "marr0013" [dir=none,weight=1] ;
"marr0013" -> "022" [dir=none, weight=2] ;
"marr0014" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"019" -> "marr0014" [dir=none,weight=1] ;
"020" -> "marr0014" [dir=none,weight=1] ;
"marr0014" -> "024" [dir=none, weight=2] ;
"marr0015" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"022" -> "marr0015" [dir=none,weight=1] ;
"025" -> "marr0015" [dir=none,weight=1] ;
"marr0015" -> "027" [dir=none, weight=2] ;
"marr0016" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"024" -> "marr0016" [dir=none,weight=1] ;
"018" -> "marr0016" [dir=none,weight=1] ;
"marr0016" -> "026" [dir=none, weight=2] ;
"marr0017" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"026" -> "marr0017" [dir=none,weight=1] ;
"027" -> "marr0017" [dir=none,weight=1] ;
"marr0017" -> "028" [dir=none, weight=2] ;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,40 +0,0 @@
## "It encodes the so-called philosophers dilemma. Neato pretty much approximates the way how humans would layout the graph." Contributed by Manfred Jeusfield.
## Command to generate the layout: "neato -Tpng thisfile > thisfile.png"
digraph PhiloDilemma {
node [shape=box]; bec3; rel3; bec2; rel2; acq2; acq3; bec1; rel1; acq1;
node [shape=circle,fixedsize=true,width=0.9]; hu3; th3; ri3; ea3; hu2; th2; ri2; ea2; hu1; th1; ri1; ea1;
ri3->acq2;
ri3->acq3;
hu3->acq3;
bec3->hu3;
th3->bec3;
rel3->th3;
rel3->ri3;
ea3->rel3;
acq3->ea3;
ri2->acq1;
ri2->acq2;
hu2->acq2;
bec2->hu2;
th2->bec2;
rel2->th2;
rel2->ri2;
ea2->rel2;
acq2->ea2;
ri1->acq3;
ri1->acq1;
hu1->acq1;
bec1->hu1;
th1->bec1;
rel1->th1;
rel1->ri1;
ea1->rel1;
acq1->ea1;
overlap=false
label="PetriNet Model PhiloDilemma\nExtracted from ConceptBase and layed out by Graphviz "
fontsize=12;
}

View File

@@ -1,15 +0,0 @@
graph G {
run -- intr;
intr -- runbl;
runbl -- run;
run -- kernel;
kernel -- zombie;
kernel -- sleep;
kernel -- runmem;
sleep -- swap;
swap -- runswap;
runswap -- new;
runswap -- runmem;
new -- runmem;
sleep -- runmem;
}

View File

@@ -1,150 +0,0 @@
digraph prof {
size="6,4"; ratio = fill;
node [style=filled];
start -> main [color="0.002 0.999 0.999"];
start -> on_exit [color="0.649 0.701 0.701"];
main -> sort [color="0.348 0.839 0.839"];
main -> merge [color="0.515 0.762 0.762"];
main -> term [color="0.647 0.702 0.702"];
main -> signal [color="0.650 0.700 0.700"];
main -> sbrk [color="0.650 0.700 0.700"];
main -> unlink [color="0.650 0.700 0.700"];
main -> newfile [color="0.650 0.700 0.700"];
main -> fclose [color="0.650 0.700 0.700"];
main -> close [color="0.650 0.700 0.700"];
main -> brk [color="0.650 0.700 0.700"];
main -> setbuf [color="0.650 0.700 0.700"];
main -> copyproto [color="0.650 0.700 0.700"];
main -> initree [color="0.650 0.700 0.700"];
main -> safeoutfil [color="0.650 0.700 0.700"];
main -> getpid [color="0.650 0.700 0.700"];
main -> sprintf [color="0.650 0.700 0.700"];
main -> creat [color="0.650 0.700 0.700"];
main -> rem [color="0.650 0.700 0.700"];
main -> oldfile [color="0.650 0.700 0.700"];
sort -> msort [color="0.619 0.714 0.714"];
sort -> filbuf [color="0.650 0.700 0.700"];
sort -> newfile [color="0.650 0.700 0.700"];
sort -> fclose [color="0.650 0.700 0.700"];
sort -> setbuf [color="0.650 0.700 0.700"];
sort -> setfil [color="0.650 0.700 0.700"];
msort -> qsort [color="0.650 0.700 0.700"];
msort -> insert [color="0.650 0.700 0.700"];
msort -> wline [color="0.650 0.700 0.700"];
msort -> div [color="0.650 0.700 0.700"];
msort -> cmpsave [color="0.650 0.700 0.700"];
merge -> insert [color="0.650 0.700 0.700"];
merge -> rline [color="0.650 0.700 0.700"];
merge -> wline [color="0.650 0.700 0.700"];
merge -> unlink [color="0.650 0.700 0.700"];
merge -> fopen [color="0.650 0.700 0.700"];
merge -> fclose [color="0.650 0.700 0.700"];
merge -> setfil [color="0.650 0.700 0.700"];
merge -> mul [color="0.650 0.700 0.700"];
merge -> setbuf [color="0.650 0.700 0.700"];
merge -> cmpsave [color="0.650 0.700 0.700"];
insert -> cmpa [color="0.650 0.700 0.700"];
wline -> flsbuf [color="0.649 0.700 0.700"];
qsort -> cmpa [color="0.650 0.700 0.700"];
rline -> filbuf [color="0.649 0.700 0.700"];
xflsbuf -> write [color="0.650 0.700 0.700"];
flsbuf -> xflsbuf [color="0.649 0.700 0.700"];
filbuf -> read [color="0.650 0.700 0.700"];
term -> unlink [color="0.650 0.700 0.700"];
term -> signal [color="0.650 0.700 0.700"];
term -> setfil [color="0.650 0.700 0.700"];
term -> exit [color="0.650 0.700 0.700"];
endopen -> open [color="0.650 0.700 0.700"];
fopen -> endopen [color="0.639 0.705 0.705"];
fopen -> findiop [color="0.650 0.700 0.700"];
newfile -> fopen [color="0.634 0.707 0.707"];
newfile -> setfil [color="0.650 0.700 0.700"];
fclose -> fflush [color="0.642 0.704 0.704"];
fclose -> close [color="0.650 0.700 0.700"];
fflush -> xflsbuf [color="0.635 0.707 0.707"];
malloc -> morecore [color="0.325 0.850 0.850"];
malloc -> demote [color="0.650 0.700 0.700"];
morecore -> sbrk [color="0.650 0.700 0.700"];
morecore -> getfreehdr [color="0.650 0.700 0.700"];
morecore -> free [color="0.650 0.700 0.700"];
morecore -> getpagesize [color="0.650 0.700 0.700"];
morecore -> putfreehdr [color="0.650 0.700 0.700"];
morecore -> udiv [color="0.650 0.700 0.700"];
morecore -> umul [color="0.650 0.700 0.700"];
on_exit -> malloc [color="0.325 0.850 0.850"];
signal -> sigvec [color="0.650 0.700 0.700"];
moncontrol -> profil [color="0.650 0.700 0.700"];
getfreehdr -> sbrk [color="0.650 0.700 0.700"];
free -> insert [color="0.650 0.700 0.700"];
insert -> getfreehdr [color="0.650 0.700 0.700"];
setfil -> div [color="0.650 0.700 0.700"];
setfil -> rem [color="0.650 0.700 0.700"];
sigvec -> sigblock [color="0.650 0.700 0.700"];
sigvec -> sigsetmask [color="0.650 0.700 0.700"];
doprnt -> urem [color="0.650 0.700 0.700"];
doprnt -> udiv [color="0.650 0.700 0.700"];
doprnt -> strlen [color="0.650 0.700 0.700"];
doprnt -> localeconv [color="0.650 0.700 0.700"];
sprintf -> doprnt [color="0.650 0.700 0.700"];
cmpa [color="0.000 1.000 1.000"];
wline [color="0.201 0.753 1.000"];
insert [color="0.305 0.625 1.000"];
rline [color="0.355 0.563 1.000"];
sort [color="0.408 0.498 1.000"];
qsort [color="0.449 0.447 1.000"];
write [color="0.499 0.386 1.000"];
read [color="0.578 0.289 1.000"];
msort [color="0.590 0.273 1.000"];
merge [color="0.603 0.258 1.000"];
unlink [color="0.628 0.227 1.000"];
filbuf [color="0.641 0.212 1.000"];
open [color="0.641 0.212 1.000"];
sbrk [color="0.647 0.204 1.000"];
signal [color="0.647 0.204 1.000"];
moncontrol [color="0.647 0.204 1.000"];
xflsbuf [color="0.650 0.200 1.000"];
flsbuf [color="0.650 0.200 1.000"];
div [color="0.650 0.200 1.000"];
cmpsave [color="0.650 0.200 1.000"];
rem [color="0.650 0.200 1.000"];
setfil [color="0.650 0.200 1.000"];
close [color="0.650 0.200 1.000"];
fclose [color="0.650 0.200 1.000"];
fflush [color="0.650 0.200 1.000"];
setbuf [color="0.650 0.200 1.000"];
endopen [color="0.650 0.200 1.000"];
findiop [color="0.650 0.200 1.000"];
fopen [color="0.650 0.200 1.000"];
mul [color="0.650 0.200 1.000"];
newfile [color="0.650 0.200 1.000"];
sigblock [color="0.650 0.200 1.000"];
sigsetmask [color="0.650 0.200 1.000"];
sigvec [color="0.650 0.200 1.000"];
udiv [color="0.650 0.200 1.000"];
urem [color="0.650 0.200 1.000"];
brk [color="0.650 0.200 1.000"];
getfreehdr [color="0.650 0.200 1.000"];
strlen [color="0.650 0.200 1.000"];
umul [color="0.650 0.200 1.000"];
doprnt [color="0.650 0.200 1.000"];
copyproto [color="0.650 0.200 1.000"];
creat [color="0.650 0.200 1.000"];
demote [color="0.650 0.200 1.000"];
exit [color="0.650 0.200 1.000"];
free [color="0.650 0.200 1.000"];
getpagesize [color="0.650 0.200 1.000"];
getpid [color="0.650 0.200 1.000"];
initree [color="0.650 0.200 1.000"];
insert [color="0.650 0.200 1.000"];
localeconv [color="0.650 0.200 1.000"];
main [color="0.650 0.200 1.000"];
malloc [color="0.650 0.200 1.000"];
morecore [color="0.650 0.200 1.000"];
oldfile [color="0.650 0.200 1.000"];
on_exit [color="0.650 0.200 1.000"];
profil [color="0.650 0.200 1.000"];
putfreehdr [color="0.650 0.200 1.000"];
safeoutfil [color="0.650 0.200 1.000"];
sprintf [color="0.650 0.200 1.000"];
term [color="0.650 0.200 1.000"];
}

View File

@@ -1,32 +0,0 @@
##"I made a program to generate dot files representing the LR(0) state graph along with computed LALR(1) lookahead for an arbitrary context-free grammar, to make the diagrams I used in this article: http://blog.lab49.com/archives/2471. The program also highlights errant nodes in red if the grammar would produce a shift/reduce or reduce/reduce conflict -- you may be able to go to http://kthielen.dnsalias.com:8082/ to produce a graph more to your liking". Contributed by Kalani Thielen.
##Command to get the layout: "dot -Gsize=10,15 -Tpng thisfile > thisfile.png"
digraph g {
graph [fontsize=30 labelloc="t" label="" splines=true overlap=false rankdir = "LR"];
ratio = auto;
"state0" [ style = "filled, bold" penwidth = 5 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #0</font></td></tr><tr><td align="left" port="r0">&#40;0&#41; s -&gt; &bull;e $ </td></tr><tr><td align="left" port="r1">&#40;1&#41; e -&gt; &bull;l '=' r </td></tr><tr><td align="left" port="r2">&#40;2&#41; e -&gt; &bull;r </td></tr><tr><td align="left" port="r3">&#40;3&#41; l -&gt; &bull;'*' r </td></tr><tr><td align="left" port="r4">&#40;4&#41; l -&gt; &bull;'n' </td></tr><tr><td align="left" port="r5">&#40;5&#41; r -&gt; &bull;l </td></tr></table>> ];
"state1" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #1</font></td></tr><tr><td align="left" port="r3">&#40;3&#41; l -&gt; &bull;'*' r </td></tr><tr><td align="left" port="r3">&#40;3&#41; l -&gt; '*' &bull;r </td></tr><tr><td align="left" port="r4">&#40;4&#41; l -&gt; &bull;'n' </td></tr><tr><td align="left" port="r5">&#40;5&#41; r -&gt; &bull;l </td></tr></table>> ];
"state2" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #2</font></td></tr><tr><td align="left" port="r4">&#40;4&#41; l -&gt; 'n' &bull;</td><td bgcolor="grey" align="right">=$</td></tr></table>> ];
"state3" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #3</font></td></tr><tr><td align="left" port="r5">&#40;5&#41; r -&gt; l &bull;</td><td bgcolor="grey" align="right">=$</td></tr></table>> ];
"state4" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #4</font></td></tr><tr><td align="left" port="r3">&#40;3&#41; l -&gt; '*' r &bull;</td><td bgcolor="grey" align="right">=$</td></tr></table>> ];
"state5" [ style = "filled" penwidth = 1 fillcolor = "black" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="black"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #5</font></td></tr><tr><td align="left" port="r0"><font color="white">&#40;0&#41; s -&gt; e &bull;$ </font></td></tr></table>> ];
"state6" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #6</font></td></tr><tr><td align="left" port="r1">&#40;1&#41; e -&gt; l &bull;'=' r </td></tr><tr><td align="left" port="r5">&#40;5&#41; r -&gt; l &bull;</td><td bgcolor="grey" align="right">$</td></tr></table>> ];
"state7" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #7</font></td></tr><tr><td align="left" port="r1">&#40;1&#41; e -&gt; l '=' &bull;r </td></tr><tr><td align="left" port="r3">&#40;3&#41; l -&gt; &bull;'*' r </td></tr><tr><td align="left" port="r4">&#40;4&#41; l -&gt; &bull;'n' </td></tr><tr><td align="left" port="r5">&#40;5&#41; r -&gt; &bull;l </td></tr></table>> ];
"state8" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #8</font></td></tr><tr><td align="left" port="r1">&#40;1&#41; e -&gt; l '=' r &bull;</td><td bgcolor="grey" align="right">$</td></tr></table>> ];
"state9" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #9</font></td></tr><tr><td align="left" port="r2">&#40;2&#41; e -&gt; r &bull;</td><td bgcolor="grey" align="right">$</td></tr></table>> ];
state0 -> state5 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "e" ];
state0 -> state6 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "l" ];
state0 -> state9 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "r" ];
state0 -> state1 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'*'" ];
state0 -> state2 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'n'" ];
state1 -> state1 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'*'" ];
state1 -> state4 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "r" ];
state1 -> state2 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'n'" ];
state1 -> state3 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "l" ];
state6 -> state7 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'='" ];
state7 -> state8 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "r" ];
state7 -> state1 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'*'" ];
state7 -> state2 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'n'" ];
state7 -> state3 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "l" ];
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +0,0 @@
##"I made a program to generate dot files representing the LR(0) state graph along with computed LALR(1) lookahead for an arbitrary context-free grammar, to make the diagrams I used in this article: http://blog.lab49.com/archives/2471. The program also highlights errant nodes in red if the grammar would produce a shift/reduce or reduce/reduce conflict -- you may be able to go to http://kthielen.dnsalias.com:8082/ to produce a graph more to your liking". Contributed by Kalani Thielen.
##Command to get the layout: "dot -Gsize=10,15 -Tpng thisfile > thisfile.png"
digraph g {
graph [fontsize=30 labelloc="t" label="" splines=true overlap=false rankdir = "LR"];
ratio = auto;
"state0" [ style = "filled, bold" penwidth = 5 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #0</font></td></tr><tr><td align="left" port="r0">&#40;0&#41; s -&gt; &bull;e $ </td></tr><tr><td align="left" port="r1">&#40;1&#41; e -&gt; &bull;l '=' r </td></tr><tr><td align="left" port="r2">&#40;2&#41; e -&gt; &bull;r </td></tr><tr><td align="left" port="r3">&#40;3&#41; l -&gt; &bull;'*' r </td></tr><tr><td align="left" port="r4">&#40;4&#41; l -&gt; &bull;'n' </td></tr><tr><td align="left" port="r5">&#40;5&#41; r -&gt; &bull;l </td></tr></table>> ];
"state1" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #1</font></td></tr><tr><td align="left" port="r3">&#40;3&#41; l -&gt; &bull;'*' r </td></tr><tr><td align="left" port="r3">&#40;3&#41; l -&gt; '*' &bull;r </td></tr><tr><td align="left" port="r4">&#40;4&#41; l -&gt; &bull;'n' </td></tr><tr><td align="left" port="r5">&#40;5&#41; r -&gt; &bull;l </td></tr></table>> ];
"state2" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #2</font></td></tr><tr><td align="left" port="r4">&#40;4&#41; l -&gt; 'n' &bull;</td><td bgcolor="grey" align="right">=$</td></tr></table>> ];
"state3" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #3</font></td></tr><tr><td align="left" port="r5">&#40;5&#41; r -&gt; l &bull;</td><td bgcolor="grey" align="right">=$</td></tr></table>> ];
"state4" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #4</font></td></tr><tr><td align="left" port="r3">&#40;3&#41; l -&gt; '*' r &bull;</td><td bgcolor="grey" align="right">=$</td></tr></table>> ];
"state5" [ style = "filled" penwidth = 1 fillcolor = "black" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="black"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #5</font></td></tr><tr><td align="left" port="r0"><font color="white">&#40;0&#41; s -&gt; e &bull;$ </font></td></tr></table>> ];
"state6" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #6</font></td></tr><tr><td align="left" port="r1">&#40;1&#41; e -&gt; l &bull;'=' r </td></tr><tr><td align="left" port="r5">&#40;5&#41; r -&gt; l &bull;</td><td bgcolor="grey" align="right">$</td></tr></table>> ];
"state7" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #7</font></td></tr><tr><td align="left" port="r1">&#40;1&#41; e -&gt; l '=' &bull;r </td></tr><tr><td align="left" port="r3">&#40;3&#41; l -&gt; &bull;'*' r </td></tr><tr><td align="left" port="r4">&#40;4&#41; l -&gt; &bull;'n' </td></tr><tr><td align="left" port="r5">&#40;5&#41; r -&gt; &bull;l </td></tr></table>> ];
"state8" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #8</font></td></tr><tr><td align="left" port="r1">&#40;1&#41; e -&gt; l '=' r &bull;</td><td bgcolor="grey" align="right">$</td></tr></table>> ];
"state9" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<<table border="0" cellborder="0" cellpadding="3" bgcolor="white"><tr><td bgcolor="black" align="center" colspan="2"><font color="white">State #9</font></td></tr><tr><td align="left" port="r2">&#40;2&#41; e -&gt; r &bull;</td><td bgcolor="grey" align="right">$</td></tr></table>> ];
state0 -> state5 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "e" ];
state0 -> state6 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "l" ];
state0 -> state9 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "r" ];
state0 -> state1 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'*'" ];
state0 -> state2 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'n'" ];
state1 -> state1 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'*'" ];
state1 -> state4 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "r" ];
state1 -> state2 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'n'" ];
state1 -> state3 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "l" ];
state6 -> state7 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'='" ];
state7 -> state8 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "r" ];
state7 -> state1 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'*'" ];
state7 -> state2 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'n'" ];
state7 -> state3 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "l" ];
}

View File

@@ -1,512 +0,0 @@
/*
This is a graphviz-produced layout of the "family tree" of a fraternity and sorority.
Each member in the graph was assigned a "big brother" from one organization and a "big sister" from the other. Blue icons represent Brothers from the fraternity, Pink represents Sisters from the sorority (Purple members are in both organizations - like honoraries.)
Charter members (who can have no parent nodes) are outlined.
...
dot -Tgif -Goverlap=false -o siblings.gif siblings.dot
We're experimenting with different ways of coloring and graphing, but found this the easiest for now. When we have more people in, we might look at different shades depending on generation number -- earlier people would get lighter colors, more recent members darker. Thumbnail images would be an interesting alteration as well.
from Japheth Cleaver
*/
digraph sdsu {
size="36,36";
node [color=grey, style=filled];
node [fontname="Verdana", size="30,30"];
graph [ fontname = "Arial",
fontsize = 36,
style = "bold",
label = "\nKappa Kappa Psi/Tau Beta Sigma\nSan Diego State University\nEta Mu and Zeta Xi Family Tree\n\nto date: November 30th, 2008\n",
ssize = "30,60" ];
"Lori Brede" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=10"];
"Michael Griffith" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=24"];
"Amie Holston" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=30"];
"Michael Griffith" -> "Lori Brede"
"Amie Holston" -> "Lori Brede"
"Casey Carter" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=11"];
"Laura De'Armond" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=14"];
"Laura De'Armond" -> "Casey Carter"
"Japheth Cleaver" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=12"];
"Chuk Gawlik" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=22"];
"Stacy Snyder" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=309"];
"Chuk Gawlik" -> "Japheth Cleaver"
"Stacy Snyder" -> "Japheth Cleaver"
"Jillian Clifton" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=13"];
"David Guthrie" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=25"];
"David Guthrie" -> "Jillian Clifton"
"Japheth Cleaver" -> "Jillian Clifton"
"Tony Sacco" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=55"];
"Heather Smith" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=59"];
"Tony Sacco" -> "Laura De'Armond"
"Heather Smith" -> "Laura De'Armond"
"Kevin Decker" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=15"];
"Alex Hansen" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=26"];
"Wanda Livelsberger" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=53"];
"Alex Hansen" -> "Kevin Decker"
"Wanda Livelsberger" -> "Kevin Decker"
"Patrick Doerr" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=16"];
"Deanna Jagow" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=23"];
"Alex Hansen" -> "Patrick Doerr"
"Deanna Jagow" -> "Patrick Doerr"
"Lori Asaro" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=178"];
"Mark Pearson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=169"];
"Lori Ball" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=167"];
"Mark Pearson" -> "Lori Asaro"
"Lori Ball" -> "Lori Asaro"
"Ryan Farris" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=18"];
"Rob Reiner" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=51"];
"Cindy Teel" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=62"];
"Rob Reiner" -> "Ryan Farris"
"Cindy Teel" -> "Ryan Farris"
"Ginger Palmer" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=180"];
"Mark Newton-John" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=46"];
"Mark Newton-John" -> "Ginger Palmer"
"Matthew FitzGerald" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=19"];
"Mervin Maniago" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=41"];
"Mervin Maniago" -> "Matthew FitzGerald"
"Amie Holston" -> "Matthew FitzGerald"
"Tani Miller" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=195"];
"Mark Pearson" -> "Tani Miller"
"Vienna McMurtry" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=196"];
"Robert Walwick" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=153"];
"Robert Walwick" -> "Vienna McMurtry"
"Ginger Palmer" -> "Vienna McMurtry"
"Chuck Foster" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=20"];
"Karen Saye" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=56"];
"Kevin Decker" -> "Chuck Foster"
"Karen Saye" -> "Chuck Foster"
"Gary Frampton" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=201"];
"Ginger Palmer" -> "Gary Frampton"
"Pat Norris" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=207"];
"Sean Tipps" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=204"];
"Teresa Long" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=194"];
"Sean Tipps" -> "Pat Norris"
"Teresa Long" -> "Pat Norris"
"Marc Martin-ez" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=208"];
"Mark Pearson" -> "Marc Martin-ez"
"Tani Miller" -> "Marc Martin-ez"
"Kristen Villone" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=209"];
"Kelly Erickson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=199"];
"Anna Pedroza" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=197"];
"Kelly Erickson" -> "Kristen Villone"
"Anna Pedroza" -> "Kristen Villone"
"Geoff Frank" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=21"];
"Chris Livelsberger" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=40"];
"Amy Price" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=57"];
"Chris Livelsberger" -> "Geoff Frank"
"Amy Price" -> "Geoff Frank"
"Tracy Murray" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=210"];
"John FitzGibbon" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=92"];
"Judy Dulcich" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=177"];
"John FitzGibbon" -> "Tracy Murray"
"Judy Dulcich" -> "Tracy Murray"
"Ian McIntosh" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=215"];
"Barbara Tollison" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=172"];
"Robert Walwick" -> "Ian McIntosh"
"Barbara Tollison" -> "Ian McIntosh"
"Jayson Smith" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=58"];
"Jayson Smith" -> "Chuk Gawlik"
"Heather Smith" -> "Chuk Gawlik"
"Kelly McKinney" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=222"];
"Mark Nadeau" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=183"];
"Mark Nadeau" -> "Kelly McKinney"
"Judy Dulcich" -> "Kelly McKinney"
"Chris Livelsberger" -> "Deanna Jagow"
"Amy Price" -> "Deanna Jagow"
"Renee Thompson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=231"];
"J. Angeles" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=3"];
"Kelley Smith" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=223"];
"J. Angeles" -> "Renee Thompson"
"Kelley Smith" -> "Renee Thompson"
"Steven Smith" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=233"];
"John FitzGibbon" -> "Steven Smith"
"Charlene Andrews" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=234"];
"Diane Reoch" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=227"];
"Diane Reoch" -> "Charlene Andrews"
"Tonya Alexander" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=238"];
"Gail Vasquez" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=225"];
"Gail Vasquez" -> "Tonya Alexander"
"Spencer Caldwell" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=239"];
"Becky Bernal" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=218"];
"Becky Bernal" -> "Spencer Caldwell"
"Chuk Gawlik" -> "Michael Griffith"
"Wanda Livelsberger" -> "Michael Griffith"
"Russell Grant" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=242"];
"Steven Smith" -> "Russell Grant"
"Tiffany Worthington" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=66"];
"Chuck Foster" -> "David Guthrie"
"Tiffany Worthington" -> "David Guthrie"
"Jerry Maya" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=250"];
"John FitzGibbon" -> "Jerry Maya"
"Melissa Schwartz" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=252"];
"Russell Grant" -> "Melissa Schwartz"
"Delphy Shaulis" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=255"];
"Renee Thompson" -> "Delphy Shaulis"
"Martin Naiman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=45"];
"Janean Angeles" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=86"];
"Martin Naiman" -> "Alex Hansen"
"Janean Angeles" -> "Alex Hansen"
"Leslie Harlow" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=265"];
"Dennis McColl" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=251"];
"Denise Luna" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=236"];
"Dennis McColl" -> "Leslie Harlow"
"Denise Luna" -> "Leslie Harlow"
"Jonathan Yudman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=267"];
"April Ortiz-cloninger" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=258"];
"April Ortiz-cloninger" -> "Jonathan Yudman"
"Michael Elgo" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=268"];
"Carol Kropp" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=254"];
"Spencer Caldwell" -> "Michael Elgo"
"Carol Kropp" -> "Michael Elgo"
"Denmark Vea" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=269"];
"Marc Martin-ez" -> "Denmark Vea"
"Kelley Smith" -> "Denmark Vea"
"Kathleen Hansen" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=27"];
"Martin Naiman" -> "Kathleen Hansen"
"Heather Smith" -> "Kathleen Hansen"
"Laura Stegner" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=274"];
"April Ortiz-cloninger" -> "Laura Stegner"
"Kathy Jones" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=28"];
"J. Angeles" -> "Kathy Jones"
"Eric Gates" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=282"];
"Erick Sugimura" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=280"];
"Erick Sugimura" -> "Eric Gates"
"Laura Stegner" -> "Eric Gates"
"Jennifer Stoewe" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=288"];
"Eric Gates" -> "Jennifer Stoewe"
"Karen Helbling" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=29"];
"Regan Ashker" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=5"];
"Kevin Decker" -> "Karen Helbling"
"Regan Ashker" -> "Karen Helbling"
"Scott Wood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=295"];
"Eric Gates" -> "Scott Wood"
"Greg Flood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=200"];
"Greg Flood" -> "J. Angeles"
"Ginger Palmer" -> "J. Angeles"
"Lynn Reeves" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=48"];
"Chuk Gawlik" -> "Amie Holston"
"Lynn Reeves" -> "Amie Holston"
"Susan Colwell" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=302"];
"Michael Elgo" -> "Susan Colwell"
"Christopher Jouan" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=306"];
"Kevin Owens" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=245"];
"Kevin Owens" -> "Christopher Jouan"
"Kristianna Reynante" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=308"];
"Michael Elgo" -> "Kristianna Reynante"
"Janean Angeles" -> "Kristianna Reynante"
"Amy Berner" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=300"];
"Amy Berner" -> "Stacy Snyder"
"Deanna Johnson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=31"];
"Alex Hansen" -> "Deanna Johnson"
"Laura De'Armond" -> "Deanna Johnson"
"Johnny Richardson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=310"];
"Russell Grant" -> "Johnny Richardson"
"Nathan Fellhauer" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=313"];
"James Rowland" [color=thistle, URL="http://sdsu.kkytbs.net/members/profile.html?who=52"];
"James Rowland" -> "Nathan Fellhauer"
"Kristianna Reynante" -> "Nathan Fellhauer"
"Brian Raneses" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=314"];
"Sean McHenry" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=42"];
"Sean McHenry" -> "Brian Raneses"
"Penny Lewis" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=315"];
"Martin Naiman" -> "Penny Lewis"
"Becky Graham" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=316"];
"Kristen Elgo" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=7"];
"Kristen Elgo" -> "Becky Graham"
"Steven Gross" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=318"];
"Rob Reiner" -> "Steven Gross"
"Stacy Snyder" -> "Steven Gross"
"Sedona Reynolds" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=32"];
"Mark Newton-John" -> "Sedona Reynolds"
"Cindy Teel" -> "Sedona Reynolds"
"Klair Mayerchak" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=320"];
"Nathan Fellhauer" -> "Klair Mayerchak"
"Becky Graham" -> "Klair Mayerchak"
"Shari VerBerkmoes" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=321"];
"Sean McHenry" -> "Shari VerBerkmoes"
"Janean Angeles" -> "Shari VerBerkmoes"
"Anson Summers" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=326"];
"James Rowland" -> "Anson Summers"
"Dusty Jolliff" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=33"];
"Rob Reiner" -> "Dusty Jolliff"
"Stacy Snyder" -> "Dusty Jolliff"
"Jennifer Garman" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=331"];
"James Rowland" -> "Jennifer Garman"
"Kelly Greenhill" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=333"];
"Rob Reiner" -> "Kelly Greenhill"
"Kristen Elgo" -> "Kelly Greenhill"
"Lucinda Farless" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=334"];
"J. Angeles" -> "Lucinda Farless"
"Susan Colwell" -> "Lucinda Farless"
"Alfredo Cardenas" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=335"];
"Chuk Gawlik" -> "Alfredo Cardenas"
"Kathleen Hansen" -> "Alfredo Cardenas"
"Jennifer Jouan" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=34"];
"Andrea Owens" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=276"];
"Andrea Owens" -> "Jennifer Jouan"
"Tamara Scrivner" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=345"];
"Joseph Butler" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=69"];
"Sarah Maltese" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=83"];
"Joseph Butler" -> "Tamara Scrivner"
"Sarah Maltese" -> "Tamara Scrivner"
"Bradley Stouse" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=346"];
"Ryan Underwood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=74"];
"Ryan Underwood" -> "Bradley Stouse"
"Cindy Teel" -> "Bradley Stouse"
"Casondra Brimmage" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=347"];
"Kristopher Lininger" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=85"];
"Ilana Melcher" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=73"];
"Kristopher Lininger" -> "Casondra Brimmage"
"Ilana Melcher" -> "Casondra Brimmage"
"Cassiopeia Guthrie" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=348"];
"Jeremy Frazier" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=79"];
"Christine Mount" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=76"];
"Jeremy Frazier" -> "Cassiopeia Guthrie"
"Christine Mount" -> "Cassiopeia Guthrie"
"Kathleen Moran" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=349"];
"Matthew FitzGerald" -> "Kathleen Moran"
"Lori Brede" -> "Kathleen Moran"
"Tiffany Kalland" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=35"];
"Tony Sacco" -> "Tiffany Kalland"
"Karen Helbling" -> "Tiffany Kalland"
"Kristen Anderson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=350"];
"Jennie Bogart" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=78"];
"David Guthrie" -> "Kristen Anderson"
"Jennie Bogart" -> "Kristen Anderson"
"Laura Simonette" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=351"];
"Jon Weisel" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=89"];
"Jon Weisel" -> "Laura Simonette"
"Japheth Cleaver" -> "Laura Simonette"
"Nathan Williams" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=352"];
"David Guthrie" -> "Nathan Williams"
"Karen Helbling" -> "Nathan Williams"
"Rebecca Hippert" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=353"];
"Ryan Underwood" -> "Rebecca Hippert"
"Tiffany Kalland" -> "Rebecca Hippert"
"Samuel Wallace" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=354"];
"Joseph Butler" -> "Samuel Wallace"
"Deanna Jagow" -> "Samuel Wallace"
"Scott Gardner" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=355"];
"Jeremy Frazier" -> "Scott Gardner"
"Christine Mount" -> "Scott Gardner"
"Alberto Ayon" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=356"];
"Bradley Stouse" -> "Alberto Ayon"
"Jennie Bogart" -> "Alberto Ayon"
"Susannah Clayton" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=357"];
"Nathan Williams" -> "Susannah Clayton"
"Karen Helbling" -> "Susannah Clayton"
"Lisa Gochnauer" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=358"];
"Scott Gardner" -> "Lisa Gochnauer"
"Casondra Brimmage" -> "Lisa Gochnauer"
"Jamie Jackson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=359"];
"Samuel Wallace" -> "Jamie Jackson"
"Tamara Scrivner" -> "Jamie Jackson"
"Christina Kelly" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=36"];
"Matthew FitzGerald" -> "Christina Kelly"
"Lori Brede" -> "Christina Kelly"
"Gara Thornton" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=360"];
"Mark Newton-John" -> "Gara Thornton"
"Laura Simonette" -> "Gara Thornton"
"Robert Winebarger" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=361"];
"Robin Ellison" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=90"];
"Scott Gardner" -> "Robert Winebarger"
"Robin Ellison" -> "Robert Winebarger"
"Jeremy Kirchner" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=37"];
"Rob Reiner" -> "Jeremy Kirchner"
"Sandy Konar" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=38"];
"Jennifer Brandon" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=9"];
"Jennifer Brandon" -> "Sandy Konar"
"Dan Kuhlman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=39"];
"Rob Reiner" -> "Dan Kuhlman"
"Dusty Jolliff" -> "Dan Kuhlman"
"Lindsay Arehart" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=4"];
"Martin Naiman" -> "Lindsay Arehart"
"Jennifer Brandon" -> "Lindsay Arehart"
"J. Angeles" -> "Mervin Maniago"
"Kathy Jones" -> "Mervin Maniago"
"Jarrod Monroe" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=43"];
"Jamie Fratacci" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=44"];
"Mark Newton-John" -> "Jarrod Monroe"
"Jamie Fratacci" -> "Jarrod Monroe"
"Chuk Gawlik" -> "Jamie Fratacci"
"Tiffany Worthington" -> "Jamie Fratacci"
"Russell Grant" -> "Martin Naiman"
"Tonya Alexander" -> "Martin Naiman"
"Edward Givens" [color=lightblue, outline=bold, style=bold, URL="http://sdsu.kkytbs.net/members/profile.html?who=106"];
"Edward Givens" -> "Mark Newton-John"
"Veronica Nickel" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=47"];
"Regan Ashker" -> "Veronica Nickel"
"Wanda Livelsberger" -> "Lynn Reeves"
"Bryan Ransom" [color=thistle, URL="http://sdsu.kkytbs.net/members/profile.html?who=49"];
"Jayson Smith" -> "Bryan Ransom"
"Tony Sacco" -> "Regan Ashker"
"Dusty Jolliff" -> "Regan Ashker"
"Jennifer Stout" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=50"];
"Matthew FitzGerald" -> "Jennifer Stout"
"Deanna Jagow" -> "Jennifer Stout"
"Sean McHenry" -> "James Rowland"
"James Rowland" -> "Wanda Livelsberger"
"Janean Angeles" -> "Wanda Livelsberger"
"Melissa Roy" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=54"];
"Mervin Maniago" -> "Melissa Roy"
"Christina Kelly" -> "Melissa Roy"
"Dennis McColl" -> "Tony Sacco"
"April Ortiz-cloninger" -> "Tony Sacco"
"Tony Sacco" -> "Karen Saye"
"Tony Sacco" -> "Amy Price"
"Kathleen Hansen" -> "Amy Price"
"James Rowland" -> "Jayson Smith"
"Brian Raneses" -> "Heather Smith"
"Kristen Elgo" -> "Heather Smith"
"Josh Atwood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=6"];
"David Guthrie" -> "Josh Atwood"
"Lori Brede" -> "Josh Atwood"
"Katie Browne" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=60"];
"Patrick Doerr" -> "Katie Browne"
"Jamie Fratacci" -> "Katie Browne"
"Kristin Tang" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=61"];
"James Rowland" -> "Kristin Tang"
"Heather Smith" -> "Kristin Tang"
"Mervin Maniago" -> "Cindy Teel"
"Veronica Nickel" -> "Cindy Teel"
"Mike Tulumello" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=63"];
"Matthew FitzGerald" -> "Mike Tulumello"
"Katie Browne" -> "Mike Tulumello"
"Veronica Villanueva" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=64"];
"Ryan Farris" -> "Veronica Villanueva"
"Sedona Reynolds" -> "Veronica Villanueva"
"Mervin Maniago" -> "Tiffany Worthington"
"Jennifer Jouan" -> "Tiffany Worthington"
"Scott Wright" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=67"];
"James Rowland" -> "Scott Wright"
"Kristen Elgo" -> "Scott Wright"
"Jeremy Browne" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=68"];
"Matthew FitzGerald" -> "Jeremy Browne"
"Japheth Cleaver" -> "Jeremy Browne"
"James Fogelman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=688"];
"Alberto Ayon" -> "James Fogelman"
"Susannah Clayton" -> "James Fogelman"
"Sandra Chase" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=689"];
"David Guthrie" -> "Sandra Chase"
"Japheth Cleaver" -> "Sandra Chase"
"Patrick Doerr" -> "Joseph Butler"
"Deanna Jagow" -> "Joseph Butler"
"Laura Fisher" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=690"];
"Nathan Williams" -> "Laura Fisher"
"Casondra Brimmage" -> "Laura Fisher"
"Katie Kozma" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=691"];
"Scott Wright" -> "Katie Kozma"
"Robin Ellison" -> "Katie Kozma"
"Rachel Perkins" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=692"];
"Joseph Butler" -> "Rachel Perkins"
"Cassiopeia Guthrie" -> "Rachel Perkins"
"Sarah Titilah" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=693"];
"Robert Winebarger" -> "Sarah Titilah"
"Karen Helbling" -> "Sarah Titilah"
"Ashley Rehart" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=694"];
"Laura Fisher" -> "Ashley Rehart"
"Cara Yancey" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=695"];
"Katie Kozma" -> "Cara Yancey"
"Ashley Presley" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=698"];
"Cara Yancey" -> "Ashley Presley"
"Leila Wilhelm" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=699"];
"Robin Ellison" -> "Leila Wilhelm"
"Sean McHenry" -> "Kristen Elgo"
"Stacy Snyder" -> "Kristen Elgo"
"Greg Moody" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=70"];
"Ryan Farris" -> "Greg Moody"
"Jennifer Stout" -> "Greg Moody"
"Lisa Fleck" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=700"];
"Rachel Perkins" -> "Lisa Fleck"
"Christine Coyne" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=701"];
"Rachel Perkins" -> "Christine Coyne"
"Jennifer Cooley" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=702"];
"Laura Fisher" -> "Jennifer Cooley"
"Elizabeth Larios" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=703"];
"Ashley Rehart" -> "Elizabeth Larios"
"Cate Threlkeld" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=707"];
"Katie Kozma" -> "Cate Threlkeld"
"Erika Tapia" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=71"];
"Patrick Doerr" -> "Erika Tapia"
"Melissa Roy" -> "Erika Tapia"
"Robbyn Rozelle" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=72"];
"Jarrod Monroe" -> "Robbyn Rozelle"
"Tiffany Kalland" -> "Robbyn Rozelle"
"Ryan Farris" -> "Ilana Melcher"
"Veronica Villanueva" -> "Ilana Melcher"
"Greg Moody" -> "Ryan Underwood"
"Katie Browne" -> "Ryan Underwood"
"Cameron Brown" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=75"];
"Joseph Butler" -> "Cameron Brown"
"Tiffany Kalland" -> "Cameron Brown"
"Ryan Underwood" -> "Christine Mount"
"Lori Brede" -> "Christine Mount"
"Janay Rabe" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=77"];
"Greg Moody" -> "Janay Rabe"
"Cindy Teel" -> "Janay Rabe"
"Jeremy Browne" -> "Jennie Bogart"
"Tiffany Kalland" -> "Jennie Bogart"
"Ryan Farris" -> "Jeremy Frazier"
"Ilana Melcher" -> "Jeremy Frazier"
"Crystal Bozak" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=8"];
"Patrick Doerr" -> "Crystal Bozak"
"Katie Browne" -> "Crystal Bozak"
"Kameka Smith" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=80"];
"Matthew FitzGerald" -> "Kameka Smith"
"Ilana Melcher" -> "Kameka Smith"
"Kyra Sacco" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=81"];
"Joseph Butler" -> "Kyra Sacco"
"Robbyn Rozelle" -> "Kyra Sacco"
"Samuel Behar" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=82"];
"Ryan Underwood" -> "Samuel Behar"
"Lori Brede" -> "Samuel Behar"
"Patrick Doerr" -> "Sarah Maltese"
"Deanna Jagow" -> "Sarah Maltese"
"David Bronson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=84"];
"Kristin Alongi-Hutchins" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=87"];
"Tony Sacco" -> "David Bronson"
"Kristin Alongi-Hutchins" -> "David Bronson"
"Cameron Brown" -> "Kristopher Lininger"
"Kameka Smith" -> "Kristopher Lininger"
"Rakan Abu-Rahma" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=852"];
"Christine Coyne" -> "Rakan Abu-Rahma"
"Jennifer Berry" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=270"];
"Jennifer Berry" -> "Janean Angeles"
"Penny Lewis" -> "Kristin Alongi-Hutchins"
"Melissa Bebak" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=88"];
"Greg Moody" -> "Melissa Bebak"
"Sarah Maltese" -> "Melissa Bebak"
"Scott Wright" -> "Jennifer Brandon"
"Japheth Cleaver" -> "Jennifer Brandon"
"Samuel Behar" -> "Robin Ellison"
"Kyra Sacco" -> "Robin Ellison"
"Teresa Simms" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=91"];
"Joseph Butler" -> "Teresa Simms"
"Janay Rabe" -> "Teresa Simms"
"Robert Schmidtke" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=188"];
"Jean Newman" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=166"];
"Robert Schmidtke" -> "John FitzGibbon"
"Jean Newman" -> "John FitzGibbon"
"Brittany DePew" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=928"];
"Elizabeth Larios" -> "Brittany DePew"
"Kathleen Halberg" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=929"];
"Ashley Rehart" -> "Kathleen Halberg"
"Terrance Hirsch" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=96"];
"J. Angeles" -> "Terrance Hirsch"
"Susan Colwell" -> "Terrance Hirsch"
"Monique Arellano" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=972"];
"Ashley Presley" -> "Monique Arellano"
"Anthony Henderson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=973"];
"Jennifer Cooley" -> "Anthony Henderson"
"Amethyst Tagle" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=974"];
"Cate Threlkeld" -> "Amethyst Tagle"
"Mallory Williams" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=975"];
"Lisa Fleck" -> "Mallory Williams"
}

View File

@@ -1,377 +0,0 @@
digraph G {
size="7,10"
page="8.5,11"
center=""
node[width=.25,height=.375,fontsize=9]
fcfpr1_1_2t_17 -> 341411;
fcfpr1_1t_1 -> 341411;
rdlfpr2_0_rdlt_4 -> 341411;
fpfpr1_0_1t_1 -> 341411;
fpfpr1_1_2t_11 -> 341411;
rtafpr1_1_2t_28 -> 341411;
rtafpr1_1_3t_6 -> 341411;
rdlfpr1_1t_1 -> 358866;
rtafpr1_1_3t_6 -> 358866;
tmfpr1_1_3t_5 -> 358930;
fcfpr1_1_3t_9 -> 358930;
pcfpr1_1_3t_7 -> 358930;
fpfpr1_1_3g_1 -> 358930;
fpfpr1_1_3t_1 -> 358930;
aufpr1_1_3t_1 -> 358930;
rtafpr1_0_3g_1 -> 358930;
rtafpr1_1_3t_6 -> 358930;
msgfpr1_1_1g_12 -> 371943;
rtafpr1_1_1g_8 -> 371943;
rtafpr1_1_1t_35 -> 371943;
rtafpr1_1_1t_45 -> 371943;
rtafpr1_1_3t_6 -> 371943;
tlfpr2_0_rdlg_2 -> 374300;
fcfpr1_1_3t_8 -> 374300;
fcfpr1_1_3t_9 -> 374300;
rtafpr1_1_3t_6 -> 374300;
fcfpr1_0_5g_1 -> 371942;
fcfpr1_1_1t_19 -> 371942;
fcfpr1_1_3t_9 -> 371942;
fcfpr1_1_3t_9 -> 374700;
tymsgfpr1_1_3t_3 -> 374700;
fpfpr1_1_3t_1 -> 374700;
rtafpr1_1_3t_7 -> 374700;
fcfpr1_1_3g_2 -> 374741;
fcfpr1_1_3t_9 -> 374741;
fpfpr1_1_3t_1 -> 374741;
rtafpr1_1_3t_7 -> 374741;
fcfpr1_1_1t_18 -> 374886;
fcfpr1_1_3t_9 -> 374886;
fpfpr1_1_3t_1 -> 374886;
rtafpr1_1_3t_7 -> 374886;
fcfpr1_1_3t_9 -> 375039;
fpfpr1_1_3t_1 -> 375039;
fcfpr1_1_3t_42 -> 375507;
fcfpr1_1_3t_9 -> 375507;
rdlfpr2_0_rdlt_158 -> 375507;
rtafpr1_1_3t_7 -> 375507;
rtafpr1_1_3t_71 -> 375507;
dbfpr1_1_3t_2 -> 375507;
fcfpr1_1_3t_9 -> 375508;
rdlfpr1_1g_13 -> 375508;
rtafpr1_1_3t_7 -> 375508;
rtafpr2_1_rdlg_1 -> 375508;
dbfpr1_1_3t_2 -> 375508;
fcfpr1_1_3t_9 -> 375519;
fpfpr1_1_3g_1 -> 375519;
fpfpr1_1_3t_1 -> 375519;
fcfpr1_1_3t_9 -> 377380;
rdlfpr1_1g_16 -> 377380;
rdlfpr1_1t_100 -> 377380;
fcfpr1_0_2g_1 -> 377719;
fcfpr1_1_3t_10 -> 377719;
fcfpr1_1_3t_7 -> 377719;
fcfpr1_1_3t_9 -> 377719;
rdlfpr2_0_rdlg_12 -> 377719;
rdlfpr2_0_rdlt_108 -> 377719;
rdlfpr2_0_rdlt_27 -> 377719;
rdlfpr2_0_rdlt_30 -> 377719;
fcfpr1_1_3t_9 -> 377763;
fcfpr1_1_3t_9 -> 379848;
fpfpr1_1_3t_1 -> 379848;
fcfpr1_1_3t_9 -> 380571;
fcfpr1_1_3t_9 -> 380604;
fpfpr1_1_3t_1 -> 380604;
fcfpr1_1_3t_9 -> 381211;
fpfpr1_1_3t_1 -> 381211;
fcfpr1_1_3t_9 -> 381835;
fcfpr1_1_3t_9 -> 381897;
fcfpr1_1_3t_9 -> 381901;
fpfpr1_1_3t_1 -> 381901;
fcfpr1_1_3t_9 -> 382103;
rtafpr1_1_3t_7 -> 382103;
fcfpr1_1_3t_9 -> 382161;
fcfpr1_1_3t_9 -> 383174;
fpfpr1_1_3t_1 -> 383174;
rtafpr1_1_3t_7 -> 383174;
fpfpr1_1_3g_1 -> 352010;
fpfpr1_1_3t_1 -> 352010;
fpfpr1_1_3t_1 -> 382409;
fpfpr1_1_3t_1 -> 382827;
fpfpr1_1_3t_1 -> 382928;
rtafpr1_1_3t_7 -> 382928;
tlfpr1_1_1t_5 -> 358224;
tymsgfpr1_1_1t_23 -> 358224;
tymsgfpr1_1_3t_3 -> 358224;
rcfpr0_0_1t_9 -> 358224;
rcfpr1_1_1t_5 -> 358224;
odfpr0_0_1t_8 -> 358224;
odfpr1_1_1t_6 -> 358224;
ecdsgfpr1_1_1t_4 -> 358224;
tymsgfpr1_1_1t_18 -> 358900;
tymsgfpr1_1_3t_3 -> 358900;
rcfpr1_1_1t_100 -> 358900;
rcfpr1_1_1t_22 -> 358900;
rcfpr1_1_1t_37 -> 358900;
odfpr1_1_1t_21 -> 358900;
tymsgfpr1_1_3t_3 -> 372568;
rcfpr1_1_1t_30 -> 372568;
odfpr1_1_1t_31 -> 372568;
tlfpr1_1_1t_20 -> 375557;
tymsgfpr1_1_1t_24 -> 375557;
tymsgfpr1_1_3t_3 -> 375557;
rcfpr1_1_1t_11 -> 375557;
odfpr1_1_1t_9 -> 375557;
ecdsgfpr1_1_1t_19 -> 375557;
rtafpr1_1_1g_14 -> 376956;
rtafpr1_1_1t_64 -> 376956;
rtafpr1_1_2t_18 -> 376956;
rtafpr1_1_3t_30 -> 376956;
rtafpr1_1_3t_7 -> 376956;
rtafpr1_1_3t_7 -> 379339;
rtafpr1_1_1t_14 -> 379422;
rtafpr1_1_1t_20 -> 379422;
rtafpr1_1_3t_7 -> 379422;
rtafpr1_1_3t_7 -> 383039;
fcfpr1_1_1t_18 -> 359471;
fcfpr2_0_1t_1 -> 359471;
fcfpr2_0_1t_2 -> 359471;
ccsfpr2_0_1t_99 -> 359471;
fcfpr1_1_3t_42 -> 384096;
rtafpr1_1_3t_71 -> 384096;
tlfpr1_0_4g_4 -> 354290;
rcfpr0_0_1t_9 -> 354290;
odfpr0_0_1t_8 -> 354290;
pagfpr1_1_1t_23 -> 354290;
rcfpr1_1_1t_5 -> 379864;
rcfpr1_1_1t_100 -> 382574;
rcfpr1_1_1t_22 -> 382574;
rcfpr1_1_1t_37 -> 382574;
rcfpr1_1_1t_30 -> 370706;
rcfpr1_1_1t_30 -> 377908;
rcfpr1_1_1t_30 -> 377924;
rcfpr1_1_1t_30 -> 377971;
rcfpr1_1_1t_30 -> 377980;
odfpr1_1_1t_31 -> 377980;
rcfpr1_1_1t_30 -> 378362;
rcfpr1_1_1t_30 -> 378656;
rcfpr1_1_1t_30 -> 378666;
rcfpr1_1_1t_30 -> 379169;
odfpr1_1_1t_31 -> 379169;
rcfpr1_1_1t_110 -> 379341;
rcfpr1_1_1t_30 -> 379341;
rcfpr1_1_1t_62 -> 379341;
odfpr1_1_1t_31 -> 379341;
rcfpr1_1_1t_30 -> 379972;
rcfpr1_1_1t_30 -> 380298;
rcfpr1_1_1t_30 -> 380448;
rcfpr1_1_1t_30 -> 380475;
odfpr1_1_1t_31 -> 380475;
rcfpr1_1_1t_30 -> 380526;
odfpr1_1_1t_31 -> 357430;
rcfpr1_1_1t_11 -> 379968;
odfpr1_1_1t_9 -> 379968;
ccsfpr2_0_1t_99 -> 359100;
ccsfpr2_0_1t_99 -> 376529;
ccsfpr2_0_1t_99 -> 377801;
ccsfpr2_0_1t_99 -> 379126;
ccsfpr2_0_1t_99 -> 379212;
ccsfpr2_0_1t_99 -> 380285;
ccsfpr2_0_1t_99 -> 380963;
ccsfpr2_0_1t_99 -> 384909;
tlfpr1_0_4g_4 -> 358471;
odfpr0_0_1t_7 -> 358471;
odfpr1_0_1t_36 -> 358471;
odfpr1_0_3t_18 -> 358471;
odfpr1_0_3t_21 -> 358471;
tlfpr1_0_4g_4 -> 375024;
tlfpr1_0_4g_4 -> 375027;
rcfpr1_1_1t_110 -> 381710;
rcfpr1_1_1t_62 -> 381710;
rcfpr1_1_1t_110 -> 381775;
rcfpr1_1_1t_62 -> 381775;
rcfpr1_1_1t_110 -> 382436;
fcfpr1_1_3t_34 -> 382528;
rcfpr1_1_1t_110 -> 382528;
rtafpr1_1_3t_48 -> 382528;
rcfpr1_1_1t_110 -> 382566;
rcfpr1_1_1t_110 -> 382572;
odfpr0_0_1t_7 -> 353506;
rcfpr1_0_1t_35 -> 370509;
odfpr0_0_1t_7 -> 370509;
odfpr0_0_1t_7 -> 370510;
odfpr1_0_1t_38 -> 370510;
tlfpr1_0_4g_5 -> 354546;
rcfpr1_1_1t_61 -> 354546;
odfpr1_0_3t_18 -> 354546;
odfpr1_0_3t_20 -> 354546;
odfpr1_0_3t_18 -> 354757;
odfpr1_0_3t_20 -> 354757;
odfpr1_0_3t_18 -> 354766;
odfpr1_0_3t_20 -> 354766;
odfpr1_0_3t_18 -> 354771;
odfpr1_0_3t_20 -> 354771;
odfpr1_0_3t_18 -> 354785;
odfpr1_0_3t_23 -> 354785;
odfpr1_0_3t_24 -> 354785;
odfpr1_0_3t_18 -> 354878;
odfpr1_0_3t_23 -> 354878;
odfpr1_0_3t_24 -> 354878;
odfpr1_0_3t_18 -> 355080;
odfpr1_0_3t_23 -> 355080;
odfpr1_0_3t_24 -> 355080;
odfpr1_0_3t_18 -> 355288;
odfpr1_0_3t_23 -> 355288;
odfpr1_0_3t_24 -> 355288;
odfpr2_0_03t_13 -> 355288;
odfpr1_0_3t_18 -> 355800;
odfpr1_0_3t_21 -> 355800;
odfpr1_0_3t_18 -> 356116;
odfpr1_0_3t_21 -> 356116;
odfpr1_0_3t_18 -> 356741;
odfpr1_0_3t_21 -> 356741;
odfpr1_0_3t_18 -> 357340;
odfpr1_0_3t_21 -> 357340;
odfpr1_0_3t_18 -> 357538;
odfpr1_0_3t_21 -> 357538;
odfpr1_0_3t_18 -> 357769;
odfpr1_0_3t_21 -> 357769;
odfpr1_0_3t_18 -> 357793;
odfpr1_0_3t_21 -> 357793;
odfpr1_0_3t_18 -> 358155;
odfpr1_0_3t_21 -> 358155;
odfpr1_0_3t_18 -> 358157;
odfpr1_0_3t_21 -> 358157;
odfpr1_0_3t_18 -> 358159;
odfpr1_0_3t_21 -> 358159;
odfpr1_0_3t_18 -> 358584;
odfpr1_0_3t_21 -> 358584;
odfpr1_0_3t_18 -> 360104;
odfpr1_0_3t_21 -> 360104;
odfpr1_0_3t_18 -> 360144;
odfpr1_0_3t_21 -> 360144;
odfpr1_0_3t_18 -> 360672;
odfpr1_0_3t_21 -> 360672;
odfpr1_0_3t_5 -> 360672;
odfpr1_0_3t_18 -> 360839;
odfpr1_0_3t_21 -> 360839;
odfpr1_0_3t_18 -> 371187;
tlfpr1_0_3g_5 -> 373300;
odfpr1_0_3t_12 -> 373300;
odfpr1_0_3t_18 -> 373300;
odfpr1_0_3t_18 -> 375134;
odfpr1_0_5t_18 -> 375134;
rcfpr0_0_1t_10 -> 375319;
odfpr1_0_3t_18 -> 375319;
odfpr1_0_3t_36 -> 375319;
odfpr1_0_5t_17 -> 375319;
odfpr1_0_5t_19 -> 375319;
odfpr1_0_3t_18 -> 375499;
odfpr1_0_3t_18 -> 377220;
odfpr1_0_5t_21 -> 377220;
tlfpr1_0_3g_7 -> 377562;
tlfpr1_1_1t_3 -> 377562;
odfpr1_0_3t_18 -> 377562;
odfpr1_0_3t_36 -> 377562;
odfpr1_0_5t_20 -> 377562;
odfpr1_0_3t_18 -> 378108;
odfpr1_0_3t_6 -> 378108;
odfpr1_0_5t_20 -> 354221;
odfpr0_0_1t_7 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tlfpr1_0_3g_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr0_0_1t_8 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr1_1_1t_61 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_1t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_3t_18 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tlfpr1_0_3g_7 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr1_1_1t_62 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
ccsfpr2_0_1t_99 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tymsgfpr1_1_3t_3 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr0_0_1t_9 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_1t_14 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_3t_30 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr1_1_1t_110 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
dbfpr1_1_3t_2 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_1g_8 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr1_1_1t_30 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tlfpr1_1_1t_20 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_1t_64 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tlfpr2_0_rdlg_2 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_2t_28 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tlfpr1_1_1t_3 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_1_1t_6 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fpfpr1_1_3t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
aufpr1_1_3t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_1_3t_34 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr1_1_1t_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_1_1t_18 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_3t_36 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tlfpr1_1_1t_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_1_1t_19 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_1_1t_9 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_1_3t_7 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr1_1_1t_37 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_1_3t_8 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_1_1t_21 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_1_3t_9 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rdlfpr2_0_rdlt_27 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_1_3g_2 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_1t_35 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_5t_20 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fpfpr1_1_3g_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_5t_21 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fpfpr1_1_2t_11 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
ecdsgfpr1_1_1t_19 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_1t_36 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_1g_14 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tymsgfpr1_1_1t_23 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tymsgfpr1_1_1t_24 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_1t_38 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_0_2g_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rdlfpr1_1t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr0_0_1t_10 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr1_1_1t_100 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rdlfpr2_0_rdlt_108 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
pcfpr1_1_3t_7 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_3t_20 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
ecdsgfpr1_1_1t_4 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tmfpr1_1_3t_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_3t_21 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fpfpr1_0_1t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_3t_23 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr1_1_1t_22 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
pagfpr1_1_1t_23 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_3t_71 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_2t_18 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rdlfpr2_0_rdlt_158 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_3t_6 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_3t_24 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_3t_7 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_0_3g_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_1t_20 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rdlfpr1_1g_13 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr1_0_1t_35 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_1_2t_17 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr2_1_rdlg_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rdlfpr2_0_rdlt_4 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rdlfpr1_1g_16 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr2_0_1t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr2_0_1t_2 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rdlfpr1_1t_100 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
msgfpr1_1_1g_12 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rdlfpr2_0_rdlt_30 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_3t_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tlfpr1_0_4g_4 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_1_3t_42 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_3t_6 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tlfpr1_0_4g_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_3t_48 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_5t_17 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_5t_18 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
tymsgfpr1_1_1t_18 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_5t_19 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_1_3t_10 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
fcfpr1_0_5g_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_0_3t_12 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr2_0_03t_13 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rcfpr1_1_1t_11 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
odfpr1_1_1t_31 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rdlfpr2_0_rdlg_12 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
rtafpr1_1_1t_45 [label="",shape=circle,height=0.12,width=0.12,fontsize=1];
}

View File

@@ -1,60 +0,0 @@
digraph G {
graph [center rankdir=LR bgcolor="#808080"]
edge [dir=none]
node [width=0.3 height=0.3 label=""]
{ node [shape=circle style=invis]
1 2 3 4 5 6 7 8 10 20 30 40 50 60 70 80
}
{ node [shape=circle]
a b c d e f g h i j k l m n o p q r s t u v w x
}
{ node [shape=diamond]
A B C D E F G H I J K L M N O P Q R S T U V W X
}
1 -> a -> {A B} [color="#0000ff"]
2 -> b -> {B A} [color="#ff0000"]
3 -> c -> {C D} [color="#ffff00"]
4 -> d -> {D C} [color="#00ff00"]
5 -> e -> {E F} [color="#000000"]
6 -> f -> {F E} [color="#00ffff"]
7 -> g -> {G H} [color="#ffffff"]
8 -> h -> {H G} [color="#ff00ff"]
{ edge [color="#ff0000:#0000ff"]
A -> i -> {I K}
B -> j -> {J L}
}
{ edge [color="#00ff00:#ffff00"]
C -> k -> {K I}
D -> l -> {L J}
}
{ edge [color="#00ffff:#000000"]
E -> m -> {M O}
F -> n -> {N P}
}
{ edge [color="#ff00ff:#ffffff"]
G -> o -> {O M}
H -> p -> {P N}
}
{ edge [color="#00ff00:#ffff00:#ff0000:#0000ff"]
I -> q -> {Q U}
J -> r -> {R V}
K -> s -> {S W}
L -> t -> {T X}
}
{ edge [color="#ff00ff:#ffffff:#00ffff:#000000"]
M -> u -> {U Q}
N -> v -> {V R}
O -> w -> {W S}
P -> x -> {X T}
}
{ edge [color="#ff00ff:#ffffff:#00ffff:#000000:#00ff00:#ffff00:#ff0000:#0000ff"]
Q -> 10
R -> 20
S -> 30
T -> 40
U -> 50
V -> 60
W -> 70
X -> 80
}
}

View File

@@ -1,28 +0,0 @@
##"I played some days with making an interface between our ConceptBase system (essentially a database system to store models) and graphviz. One example graph is attached. It is a so-called petri net for Dutch traffic lights. The example is actually taken from a book by Wil van der Aalst." Contributed by Manfred Jeusfeld.
##Command to produce the output: "neato -Tpng thisfile > thisfile.png"
digraph TrafficLights {
node [shape=box]; gy2; yr2; rg2; gy1; yr1; rg1;
node [shape=circle,fixedsize=true,width=0.9]; green2; yellow2; red2; safe2; safe1; green1; yellow1; red1;
gy2->yellow2;
rg2->green2;
yr2->safe1;
yr2->red2;
safe2->rg2;
green2->gy2;
yellow2->yr2;
red2->rg2;
gy1->yellow1;
rg1->green1;
yr1->safe2;
yr1->red1;
safe1->rg1;
green1->gy1;
yellow1->yr1;
red1->rg1;
overlap=false
label="PetriNet Model TrafficLights\nExtracted from ConceptBase and layed out by Graphviz"
fontsize=12;
}

View File

@@ -1,105 +0,0 @@
graph G {
// graph [splines=true overlap=false]
graph [truecolor bgcolor="#ff00005f"]
node [style=filled fillcolor="#00ff005f"]
1 -- 30 [f=1];
1 -- 40 [f=14];
8 -- 46 [f=1];
8 -- 16 [f=18];
10 -- 25 [f=1];
10 -- 19 [f=5];
10 -- 33 [f=1];
12 -- 8 [f=1];
12 -- 36 [f=5];
12 -- 17 [f=16];
13 -- 38 [f=1];
13 -- 24 [f=19];
24 -- 49 [f=1];
24 -- 13 [f=1];
24 -- 47 [f=12];
24 -- 12 [f=19];
25 -- 27 [f=1];
25 -- 12 [f=1];
27 -- 12 [f=1];
27 -- 14 [f=8];
29 -- 10 [f=1];
29 -- 8 [f=17];
30 -- 24 [f=1];
30 -- 44 [f=15];
38 -- 29 [f=1];
38 -- 35 [f=15];
2 -- 42 [f=2];
2 -- 35 [f=3];
2 -- 11 [f=19];
14 -- 18 [f=2];
14 -- 24 [f=15];
14 -- 38 [f=18];
18 -- 49 [f=2];
18 -- 47 [f=20];
26 -- 41 [f=2];
26 -- 42 [f=15];
31 -- 39 [f=2];
31 -- 47 [f=17];
31 -- 25 [f=14];
37 -- 26 [f=2];
37 -- 16 [f=14];
39 -- 50 [f=2];
39 -- 14 [f=2];
39 -- 18 [f=17];
39 -- 47 [f=10];
41 -- 31 [f=2];
41 -- 8 [f=16];
42 -- 44 [f=2];
42 -- 29 [f=12];
44 -- 37 [f=2];
44 -- 32 [f=15];
3 -- 20 [f=2];
3 -- 28 [f=19];
6 -- 45 [f=2];
6 -- 28 [f=10];
9 -- 6 [f=2];
9 -- 16 [f=1];
15 -- 16 [f=2];
15 -- 48 [f=2];
16 -- 50 [f=2];
16 -- 32 [f=14];
16 -- 39 [f=8];
20 -- 33 [f=2];
33 -- 9 [f=2];
33 -- 46 [f=3];
33 -- 48 [f=17];
45 -- 15 [f=2];
4 -- 17 [f=4];
4 -- 15 [f=6];
4 -- 12 [f=16];
17 -- 21 [f=4];
19 -- 35 [f=4];
19 -- 15 [f=9];
19 -- 43 [f=4];
21 -- 19 [f=4];
21 -- 50 [f=4];
23 -- 36 [f=4];
34 -- 23 [f=4];
34 -- 24 [f=11];
35 -- 34 [f=4];
35 -- 16 [f=6];
35 -- 18 [f=16];
36 -- 46 [f=4];
5 -- 7 [f=1];
5 -- 36 [f=6];
7 -- 32 [f=1];
7 -- 11 [f=2];
7 -- 14 [f=17];
11 -- 40 [f=1];
11 -- 50 [f=1];
22 -- 46 [f=1];
28 -- 43 [f=1];
28 -- 8 [f=18];
32 -- 28 [f=1];
32 -- 39 [f=13];
32 -- 42 [f=15];
40 -- 22 [f=1];
40 -- 47 [f=1];
43 -- 11 [f=1];
43 -- 17 [f=19];
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,54 +0,0 @@
/* courtesy Ian Darwin and Geoff Collyer, Softquad Inc. */
digraph unix {
size="6,6";
node [color=lightblue2, style=filled];
"5th Edition" -> "6th Edition";
"5th Edition" -> "PWB 1.0";
"6th Edition" -> "LSX";
"6th Edition" -> "1 BSD";
"6th Edition" -> "Mini Unix";
"6th Edition" -> "Wollongong";
"6th Edition" -> "Interdata";
"Interdata" -> "Unix/TS 3.0";
"Interdata" -> "PWB 2.0";
"Interdata" -> "7th Edition";
"7th Edition" -> "8th Edition";
"7th Edition" -> "32V";
"7th Edition" -> "V7M";
"7th Edition" -> "Ultrix-11";
"7th Edition" -> "Xenix";
"7th Edition" -> "UniPlus+";
"V7M" -> "Ultrix-11";
"8th Edition" -> "9th Edition";
"1 BSD" -> "2 BSD";
"2 BSD" -> "2.8 BSD";
"2.8 BSD" -> "Ultrix-11";
"2.8 BSD" -> "2.9 BSD";
"32V" -> "3 BSD";
"3 BSD" -> "4 BSD";
"4 BSD" -> "4.1 BSD";
"4.1 BSD" -> "4.2 BSD";
"4.1 BSD" -> "2.8 BSD";
"4.1 BSD" -> "8th Edition";
"4.2 BSD" -> "4.3 BSD";
"4.2 BSD" -> "Ultrix-32";
"PWB 1.0" -> "PWB 1.2";
"PWB 1.0" -> "USG 1.0";
"PWB 1.2" -> "PWB 2.0";
"USG 1.0" -> "CB Unix 1";
"USG 1.0" -> "USG 2.0";
"CB Unix 1" -> "CB Unix 2";
"CB Unix 2" -> "CB Unix 3";
"CB Unix 3" -> "Unix/TS++";
"CB Unix 3" -> "PDP-11 Sys V";
"USG 2.0" -> "USG 3.0";
"USG 3.0" -> "Unix/TS 3.0";
"PWB 2.0" -> "Unix/TS 3.0";
"Unix/TS 1.0" -> "Unix/TS 3.0";
"Unix/TS 3.0" -> "TS 4.0";
"Unix/TS++" -> "TS 4.0";
"CB Unix 3" -> "TS 4.0";
"TS 4.0" -> "System V.0";
"System V.0" -> "System V.2";
"System V.2" -> "System V.3";
}

View File

@@ -1,67 +0,0 @@
digraph world {
size="7,7";
{rank=same; S8 S24 S1 S35 S30;}
{rank=same; T8 T24 T1 T35 T30;}
{rank=same; 43 37 36 10 2;}
{rank=same; 25 9 38 40 13 17 12 18;}
{rank=same; 26 42 11 3 33 19 39 14 16;}
{rank=same; 4 31 34 21 41 28 20;}
{rank=same; 27 5 22 32 29 15;}
{rank=same; 6 23;}
{rank=same; 7;}
S8 -> 9;
S24 -> 25;
S24 -> 27;
S1 -> 2;
S1 -> 10;
S35 -> 43;
S35 -> 36;
S30 -> 31;
S30 -> 33;
9 -> 42;
9 -> T1;
25 -> T1;
25 -> 26;
27 -> T24;
2 -> {3 ; 16 ; 17 ; T1 ; 18}
10 -> { 11 ; 14 ; T1 ; 13; 12;}
31 -> T1;
31 -> 32;
33 -> T30;
33 -> 34;
42 -> 4;
26 -> 4;
3 -> 4;
16 -> 15;
17 -> 19;
18 -> 29;
11 -> 4;
14 -> 15;
37 -> {39 ; 41 ; 38 ; 40;}
13 -> 19;
12 -> 29;
43 -> 38;
43 -> 40;
36 -> 19;
32 -> 23;
34 -> 29;
39 -> 15;
41 -> 29;
38 -> 4;
40 -> 19;
4 -> 5;
19 -> {21 ; 20 ; 28;}
5 -> {6 ; T35 ; 23;}
21 -> 22;
20 -> 15;
28 -> 29;
6 -> 7;
15 -> T1;
22 -> T35;
22 -> 23;
29 -> T30;
7 -> T8;
23 -> T24;
23 -> T1;
}

View File

@@ -1,54 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 token
var DOTTokens = NewMapFromStrings([]string{
"ε",
"id",
"{",
"}",
";",
"=",
"[",
"]",
",",
":",
"->",
"--",
"graph",
"Graph",
"GRAPH",
"strict",
"Strict",
"STRICT",
"digraph",
"Digraph",
"DiGraph",
"DIGRAPH",
"node",
"Node",
"NODE",
"edge",
"Edge",
"EDGE",
"subgraph",
"Subgraph",
"SubGraph",
"SUBGRAPH",
"string_lit",
"int_lit",
"float_lit",
"html_lit",
})

View File

@@ -1,242 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 token
import (
"bytes"
"fmt"
"io/ioutil"
"regexp"
"strconv"
"strings"
)
type Token struct {
Type Type
Lit []byte
}
func NewToken(typ Type, lit []byte) *Token {
return &Token{typ, lit}
}
func (this *Token) Equals(that *Token) bool {
if this == nil || that == nil {
return this == that
}
if this.Type != that.Type {
return false
}
return bytes.Equal(this.Lit, that.Lit)
}
func (this *Token) String() string {
str := ""
if this.Type == EOF {
str += "\"$\""
} else {
str += "\"" + string(this.Lit) + "\""
}
str += "(" + strconv.Itoa(int(this.Type)) + ")"
return str
}
type Type int
const (
ILLEGAL Type = iota - 1
EOF
)
func (T Type) String() string {
return strconv.Itoa(int(T))
}
// Position describes an arbitrary source position
// including the file, line, and column location.
// A Position is valid if the line number is > 0.
//
type Position struct {
Offset int // offset, starting at 0
Line int // line number, starting at 1
Column int // column number, starting at 1 (character count)
}
// IsValid returns true if the position is valid.
func (pos *Position) IsValid() bool { return pos.Line > 0 }
// String returns a string in one of several forms:
//
// file:line:column valid position with file name
// line:column valid position without file name
// file invalid position with file name
// - invalid position without file name
//
func (pos Position) String() string {
s := ""
if pos.IsValid() {
s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
}
if s == "" {
s = "-"
}
return s
}
func (T *Token) IntValue() (int64, error) {
return strconv.ParseInt(string(T.Lit), 10, 64)
}
func (T *Token) UintValue() (uint64, error) {
return strconv.ParseUint(string(T.Lit), 10, 64)
}
func (T *Token) SDTVal() string {
sdt := string(T.Lit)
rex, err := regexp.Compile("\\$[0-9]+")
if err != nil {
panic(err)
}
idx := rex.FindAllStringIndex(sdt, -1)
res := ""
if len(idx) <= 0 {
res = sdt
} else {
for i, loc := range idx {
if loc[0] > 0 {
if i > 0 {
res += sdt[idx[i-1][1]:loc[0]]
} else {
res += sdt[0:loc[0]]
}
}
res += "X["
res += sdt[loc[0]+1 : loc[1]]
res += "]"
}
if idx[len(idx)-1][1] < len(sdt) {
res += sdt[idx[len(idx)-1][1]:]
}
}
return strings.TrimSpace(res[2 : len(res)-2])
}
//*********** Tokenmap
type TokenMap struct {
tokenMap []string
stringMap map[string]Type
}
func NewMap() *TokenMap {
tm := &TokenMap{make([]string, 0, 10), make(map[string]Type)}
tm.AddToken("$")
tm.AddToken("ε")
return tm
}
func (this *TokenMap) AddToken(str string) {
if _, exists := this.stringMap[str]; exists {
return
}
this.stringMap[str] = Type(len(this.tokenMap))
this.tokenMap = append(this.tokenMap, str)
}
func NewMapFromFile(file string) (*TokenMap, error) {
src, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}
return NewMapFromString(string(src)), nil
}
func NewMapFromStrings(input []string) *TokenMap {
tm := NewMap()
for _, s := range input {
tm.AddToken(s)
}
return tm
}
func NewMapFromString(input string) *TokenMap {
tokens := strings.Fields(input)
return NewMapFromStrings(tokens)
}
func (this *TokenMap) Type(key string) Type {
tok, ok := this.stringMap[key]
if !ok {
return ILLEGAL
}
return tok
}
func (this *TokenMap) TokenString(typ Type) string {
tok := int(typ)
if tok < 0 || tok >= len(this.tokenMap) {
return "illegal " + strconv.Itoa(tok)
}
return this.tokenMap[tok]
}
func (this *TokenMap) String() string {
res := ""
for str, tok := range this.stringMap {
res += str + " : " + strconv.Itoa(int(tok)) + "\n"
}
return res
}
func (this *TokenMap) Strings() []string {
return this.tokenMap[1:]
}
func (this *TokenMap) Equals(that *TokenMap) bool {
if this == nil || that == nil {
return false
}
if len(this.stringMap) != len(that.stringMap) ||
len(this.tokenMap) != len(that.tokenMap) {
return false
}
for str, tok := range this.stringMap {
if tok1, ok := that.stringMap[str]; !ok || tok1 != tok {
return false
}
}
return true
}
func (this *TokenMap) Tokens() []*Token {
res := make([]*Token, 0, len(this.stringMap))
for typ, str := range this.tokenMap {
res = append(res, &Token{Type(typ), []byte(str)})
}
return res
}
func (this *TokenMap) WriteFile(file string) error {
out := ""
for i := 1; i < len(this.tokenMap); i++ {
out += this.TokenString(Type(i)) + "\n"
}
return ioutil.WriteFile(file, []byte(out), 0644)
}

View File

@@ -1,136 +0,0 @@
//Copyright 2013 GoGraphviz Authors
//
//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 gographviz
import (
"fmt"
"github.com/awalterschulze/gographviz/ast"
)
type writer struct {
*Graph
writtenLocations map[string]bool
}
func newWriter(g *Graph) *writer {
return &writer{g, make(map[string]bool)}
}
func appendAttrs(list ast.StmtList, attrs Attrs) ast.StmtList {
for _, name := range attrs.SortedNames() {
stmt := &ast.Attr{
Field: ast.Id(name),
Value: ast.Id(attrs[name]),
}
list = append(list, stmt)
}
return list
}
func (this *writer) newSubGraph(name string) *ast.SubGraph {
sub := this.SubGraphs.SubGraphs[name]
this.writtenLocations[sub.Name] = true
s := &ast.SubGraph{}
s.Id = ast.Id(sub.Name)
s.StmtList = appendAttrs(s.StmtList, sub.Attrs)
children := this.Relations.SortedChildren(name)
for _, child := range children {
s.StmtList = append(s.StmtList, this.newNodeStmt(child))
}
return s
}
func (this *writer) newNodeId(name string, port string) *ast.NodeId {
node := this.Nodes.Lookup[name]
return ast.MakeNodeId(node.Name, port)
}
func (this *writer) newNodeStmt(name string) *ast.NodeStmt {
node := this.Nodes.Lookup[name]
id := ast.MakeNodeId(node.Name, "")
this.writtenLocations[node.Name] = true
return &ast.NodeStmt{
id,
ast.PutMap(node.Attrs),
}
}
func (this *writer) newLocation(name string, port string) ast.Location {
if this.IsNode(name) {
return this.newNodeId(name, port)
} else if this.IsSubGraph(name) {
if len(port) != 0 {
panic(fmt.Sprintf("subgraph cannot have a port: %v", port))
}
return this.newSubGraph(name)
}
panic(fmt.Sprintf("%v is not a node or a subgraph", name))
}
func (this *writer) newEdgeStmt(edge *Edge) *ast.EdgeStmt {
src := this.newLocation(edge.Src, edge.SrcPort)
dst := this.newLocation(edge.Dst, edge.DstPort)
stmt := &ast.EdgeStmt{
Source: src,
EdgeRHS: ast.EdgeRHS{
&ast.EdgeRH{
ast.EdgeOp(edge.Dir),
dst,
},
},
Attrs: ast.PutMap(edge.Attrs),
}
return stmt
}
func (this *writer) Write() *ast.Graph {
t := &ast.Graph{}
t.Strict = this.Strict
t.Type = ast.GraphType(this.Directed)
t.Id = ast.Id(this.Name)
t.StmtList = appendAttrs(t.StmtList, this.Attrs)
for _, edge := range this.Edges.Edges {
t.StmtList = append(t.StmtList, this.newEdgeStmt(edge))
}
subGraphs := this.SubGraphs.Sorted()
for _, s := range subGraphs {
if _, ok := this.writtenLocations[s.Name]; !ok {
t.StmtList = append(t.StmtList, this.newSubGraph(s.Name))
}
}
nodes := this.Nodes.Sorted()
for _, n := range nodes {
if _, ok := this.writtenLocations[n.Name]; !ok {
t.StmtList = append(t.StmtList, this.newNodeStmt(n.Name))
}
}
return t
}
//Creates an Abstract Syntrax Tree from the Graph.
func (g *Graph) WriteAst() *ast.Graph {
w := newWriter(g)
return w.Write()
}
//Returns a DOT string representing the Graph.
func (g *Graph) String() string {
return g.WriteAst().String()
}

View File

@@ -1,14 +0,0 @@
Please fill out the sections below to help us address your issue.
### Version of AWS SDK for Go?
### Version of Go (`go version`)?
### What issue did you see?
### Steps to reproduce
If you have an runnable example, please include it.

View File

@@ -1,21 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature-request
assignees: ''
---
### Is this related to a problem?
A clear and concise description of the issue, e.g. I'm always frustrated when...
### Feature description
Describe what you want to happen.
### Describe alternatives you've considered
Any alternative solutions or features you've considered.
### Additional context
Add any other context or screenshots about the feature request here.

View File

@@ -1,24 +0,0 @@
---
name: General issue
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
Please fill out the sections below to help us address your issue.
### Version of AWS SDK for Go?
### Version of Go (`go version`)?
### What issue did you see?
### Steps to reproduce
If you have an runnable example, please include it.

View File

@@ -1,3 +0,0 @@
For changes to files under the `/model/` folder, and manual edits to autogenerated code (e.g. `/service/s3/api.go`) please create an Issue instead of a PR for those type of changes.
If there is an existing bug or feature this PR is answers please reference it here.

View File

@@ -1,11 +0,0 @@
dist
/doc
/doc-staging
.yardoc
Gemfile.lock
awstesting/integration/smoke/**/importmarker__.go
awstesting/integration/smoke/_test/
/vendor/bin/
/vendor/pkg/
/vendor/src/
/private/model/cli/gen-api/gen-api

View File

@@ -1,14 +0,0 @@
{
"PkgHandler": {
"Pattern": "/sdk-for-go/api/",
"StripPrefix": "/sdk-for-go/api",
"Include": ["/src/github.com/aws/aws-sdk-go/aws", "/src/github.com/aws/aws-sdk-go/service"],
"Exclude": ["/src/cmd", "/src/github.com/aws/aws-sdk-go/awstesting", "/src/github.com/aws/aws-sdk-go/awsmigrate", "/src/github.com/aws/aws-sdk-go/private"],
"IgnoredSuffixes": ["iface"]
},
"Github": {
"Tag": "master",
"Repo": "/aws/aws-sdk-go",
"UseGithub": true
}
}

View File

@@ -1,57 +0,0 @@
language: go
sudo: required
os:
- linux
- osx
go:
- 1.6.x
- 1.7.x
- 1.8.x
- 1.9.x
- 1.10.x
- 1.11.x
- 1.12.x
- tip
matrix:
allow_failures:
- go: tip
- os: windows
exclude:
# OSX 1.6.4 is not present in travis.
# https://github.com/travis-ci/travis-ci/issues/10309
- go: 1.6.x
os: osx
include:
- os: windows
go: 1.12.x
- os: linux
go: 1.5.x
# Use Go 1.5's vendoring experiment for 1.5 tests.
env: GO15VENDOREXPERIMENT=1
before_install:
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then choco install make; fi
script:
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then
make get-deps;
make unit-no-verify;
else
if [ $TRAVIS_GO_VERSION == "1.10.x" ] ||
[ $TRAVIS_GO_VERSION == "1.11.x" ] ||
[ $TRAVIS_GO_VERSION == "1.12.x" ] ||
[ $TRAVIS_GO_VERSION == "tip" ]; then
make get-deps;
make ci-test;
else
make get-deps-tests;
make unit-old-go-race-cover;
fi
fi
branches:
only:
- master

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +0,0 @@
### SDK Features
### SDK Enhancements
### SDK Bugs

View File

@@ -1,4 +0,0 @@
## Code of Conduct
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
opensource-codeofconduct@amazon.com with any additional questions or comments.

View File

@@ -1,127 +0,0 @@
Contributing to the AWS SDK for Go
We work hard to provide a high-quality and useful SDK, and we greatly value
feedback and contributions from our community. Whether it's a bug report,
new feature, correction, or additional documentation, we welcome your issues
and pull requests. Please read through this document before submitting any
issues or pull requests to ensure we have all the necessary information to
effectively respond to your bug report or contribution.
## Filing Bug Reports
You can file bug reports against the SDK on the [GitHub issues][issues] page.
If you are filing a report for a bug or regression in the SDK, it's extremely
helpful to provide as much information as possible when opening the original
issue. This helps us reproduce and investigate the possible bug without having
to wait for this extra information to be provided. Please read the following
guidelines prior to filing a bug report.
1. Search through existing [issues][] to ensure that your specific issue has
not yet been reported. If it is a common issue, it is likely there is
already a bug report for your problem.
2. Ensure that you have tested the latest version of the SDK. Although you
may have an issue against an older version of the SDK, we cannot provide
bug fixes for old versions. It's also possible that the bug may have been
fixed in the latest release.
3. Provide as much information about your environment, SDK version, and
relevant dependencies as possible. For example, let us know what version
of Go you are using, which and version of the operating system, and the
the environment your code is running in. e.g Container.
4. Provide a minimal test case that reproduces your issue or any error
information you related to your problem. We can provide feedback much
more quickly if we know what operations you are calling in the SDK. If
you cannot provide a full test case, provide as much code as you can
to help us diagnose the problem. Any relevant information should be provided
as well, like whether this is a persistent issue, or if it only occurs
some of the time.
## Submitting Pull Requests
We are always happy to receive code and documentation contributions to the SDK.
Please be aware of the following notes prior to opening a pull request:
1. The SDK is released under the [Apache license][license]. Any code you submit
will be released under that license. For substantial contributions, we may
ask you to sign a [Contributor License Agreement (CLA)][cla].
2. If you would like to implement support for a significant feature that is not
yet available in the SDK, please talk to us beforehand to avoid any
duplication of effort.
3. Wherever possible, pull requests should contain tests as appropriate.
Bugfixes should contain tests that exercise the corrected behavior (i.e., the
test should fail without the bugfix and pass with it), and new features
should be accompanied by tests exercising the feature.
4. Pull requests that contain failing tests will not be merged until the test
failures are addressed. Pull requests that cause a significant drop in the
SDK's test coverage percentage are unlikely to be merged until tests have
been added.
5. The JSON files under the SDK's `models` folder are sourced from outside the SDK.
Such as `models/apis/ec2/2016-11-15/api.json`. We will not accept pull requests
directly on these models. If you discover an issue with the models please
create a [GitHub issue][issues] describing the issue.
### Testing
To run the tests locally, running the `make unit` command will `go get` the
SDK's testing dependencies, and run vet, link and unit tests for the SDK.
```
make unit
```
Standard go testing functionality is supported as well. To test SDK code that
is tagged with `codegen` you'll need to set the build tag in the go test
command. The `make unit` command will do this automatically.
```
go test -tags codegen ./private/...
```
See the `Makefile` for additional testing tags that can be used in testing.
To test on multiple platform the SDK includes several DockerFiles under the
`awstesting/sandbox` folder, and associated make recipes to execute
unit testing within environments configured for specific Go versions.
```
make sandbox-test-go18
```
To run all sandbox environments use the following make recipe
```
# Optionally update the Go tip that will be used during the batch testing
make update-aws-golang-tip
# Run all SDK tests for supported Go versions in sandboxes
make sandbox-test
```
In addition the sandbox environment include make recipes for interactive modes
so you can run command within the Docker container and context of the SDK.
```
make sandbox-go18
```
### Changelog
You can see all release changes in the `CHANGELOG.md` file at the root of the
repository. The release notes added to this file will contain service client
updates, and major SDK changes.
[issues]: https://github.com/aws/aws-sdk-go/issues
[pr]: https://github.com/aws/aws-sdk-go/pulls
[license]: http://aws.amazon.com/apache2.0/
[cla]: http://en.wikipedia.org/wiki/Contributor_License_Agreement
[releasenotes]: https://github.com/aws/aws-sdk-go/releases

View File

@@ -1,16 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:13fe471d0ed891e8544eddfeeb0471fd3c9f2015609a1c000aefdedf52a19d40"
name = "github.com/jmespath/go-jmespath"
packages = ["."]
pruneopts = ""
revision = "c2b33e84"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = ["github.com/jmespath/go-jmespath"]
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -1,43 +0,0 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
ignored = [
# Testing/Example/Codegen dependencies
"github.com/stretchr/testify",
"github.com/stretchr/testify/assert",
"github.com/stretchr/testify/require",
"github.com/go-sql-driver/mysql",
"github.com/gucumber/gucumber",
"github.com/pkg/errors",
"golang.org/x/net",
"golang.org/x/net/html",
"golang.org/x/net/http2",
"golang.org/x/text",
"golang.org/x/text/html",
"golang.org/x/tools",
"golang.org/x/tools/go/loader",
]
[[constraint]]
name = "github.com/jmespath/go-jmespath"
revision = "c2b33e84"
#version = "0.2.2"

View File

@@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@@ -1,237 +0,0 @@
LINTIGNOREDOC='service/[^/]+/(api|service|waiters)\.go:.+(comment on exported|should have comment or be unexported)'
LINTIGNORECONST='service/[^/]+/(api|service|waiters)\.go:.+(type|struct field|const|func) ([^ ]+) should be ([^ ]+)'
LINTIGNORESTUTTER='service/[^/]+/(api|service)\.go:.+(and that stutters)'
LINTIGNOREINFLECT='service/[^/]+/(api|errors|service)\.go:.+(method|const) .+ should be '
LINTIGNOREINFLECTS3UPLOAD='service/s3/s3manager/upload\.go:.+struct field SSEKMSKeyId should be '
LINTIGNOREENDPOINTS='aws/endpoints/(defaults|dep_service_ids).go:.+(method|const) .+ should be '
LINTIGNOREDEPS='vendor/.+\.go'
LINTIGNOREPKGCOMMENT='service/[^/]+/doc_custom.go:.+package comment should be of the form'
UNIT_TEST_TAGS="example codegen awsinclude"
# SDK's Core and client packages that are compatable with Go 1.5+.
SDK_CORE_PKGS=./aws/... ./private/... ./internal/...
SDK_CLIENT_PKGS=./service/...
SDK_COMPA_PKGS=${SDK_CORE_PKGS} ${SDK_CLIENT_PKGS}
# SDK additional packages that are used for development of the SDK.
SDK_EXAMPLES_PKGS=./example/...
SDK_TESTING_PKGS=./awstesting/...
SDK_MODELS_PKGS=./models/...
SDK_ALL_PKGS=${SDK_COMPA_PKGS} ${SDK_TESTING_PKGS} ${SDK_EXAMPLES_PKGS} ${SDK_MODELS_PKGS}
all: generate unit
###################
# Code Generation #
###################
generate: cleanup-models gen-test gen-endpoints gen-services
gen-test: gen-protocol-test gen-codegen-test
gen-codegen-test:
@echo "Generating SDK API tests"
go generate ./private/model/api/codegentest/service
gen-services:
@echo "Generating SDK clients"
go generate ./service
gen-protocol-test:
@echo "Generating SDK protocol tests"
go generate ./private/protocol/...
gen-endpoints:
@echo "Generating SDK endpoints"
go generate ./models/endpoints
cleanup-models:
@echo "Cleaning up stale model versions"
go run -tags codegen ./private/model/cli/cleanup-models/* "./models/apis/*/*/api-2.json"
###################
# Unit/CI Testing #
###################
unit-no-verify:
@echo "go test SDK and vendor packages with no linting"
go test -count=1 -tags ${UNIT_TEST_TAGS} ${SDK_ALL_PKGS}
unit: verify
@echo "go test SDK and vendor packages"
go test -count=1 -tags ${UNIT_TEST_TAGS} ${SDK_ALL_PKGS}
unit-with-race-cover: verify
@echo "go test SDK and vendor packages"
go test -count=1 -tags ${UNIT_TEST_TAGS} -race -cpu=1,2,4 ${SDK_ALL_PKGS}
unit-old-go-race-cover:
@echo "go test SDK only packages for old Go versions"
go test -count=1 -race -cpu=1,2,4 ${SDK_COMPA_PKGS}
ci-test: generate unit-with-race-cover ci-test-generate-validate
ci-test-generate-validate:
@echo "CI test validate no generated code changes"
git update-index --assume-unchanged go.mod go.sum
git add . -A
gitstatus=`git diff --cached --ignore-space-change`; \
git update-index --no-assume-unchanged go.mod go.sum
echo "$$gitstatus"; \
if [ "$$gitstatus" != "" ] && [ "$$gitstatus" != "skipping validation" ]; then echo "$$gitstatus"; exit 1; fi
#######################
# Integration Testing #
#######################
integration: core-integ client-integ
core-integ:
@echo "Integration Testing SDK core"
AWS_REGION="" go test -count=1 -tags "integration" -v -run '^TestInteg_' ${SDK_CORE_PKGS} ./awstesting/...
client-integ:
@echo "Integration Testing SDK clients"
AWS_REGION="" go test -count=1 -tags "integration" -v -run '^TestInteg_' ./service/...
s3crypto-integ:
@echo "Integration Testing S3 Cyrpto utility"
AWS_REGION="" go test -count=1 -tags "s3crypto_integ integration" -v -run '^TestInteg_' ./service/s3/s3crypto
cleanup-integ-buckets:
@echo "Cleaning up SDK integraiton resources"
go run -tags "integration" ./awstesting/cmd/bucket_cleanup/main.go "aws-sdk-go-integration"
###################
# Sandbox Testing #
###################
sandbox-tests: sandbox-test-go1.5 sandbox-test-go1.6 sandbox-test-go1.7 sandbox-test-go1.8 sandbox-test-go1.9 sandbox-test-go1.10 sandbox-test-go1.11 sandbox-test-go1.12 sandbox-test-gotip
sandbox-build-go1.5:
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.5 -t "aws-sdk-go-1.5" .
sandbox-go1.5: sandbox-build-go1.5
docker run -i -t aws-sdk-go-1.5 bash
sandbox-test-go1.5: sandbox-build-go1.5
docker run -t aws-sdk-go-1.5
sandbox-build-go1.5-novendorexp:
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.5-novendorexp -t "aws-sdk-go-1.5-novendorexp" .
sandbox-go1.5-novendorexp: sandbox-build-go1.5-novendorexp
docker run -i -t aws-sdk-go-1.5-novendorexp bash
sandbox-test-go1.5-novendorexp: sandbox-build-go1.5-novendorexp
docker run -t aws-sdk-go-1.5-novendorexp
sandbox-build-go1.6:
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.6 -t "aws-sdk-go-1.6" .
sandbox-go1.6: sandbox-build-go1.6
docker run -i -t aws-sdk-go-1.6 bash
sandbox-test-go1.6: sandbox-build-go1.6
docker run -t aws-sdk-go-1.6
sandbox-build-go1.7:
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.7 -t "aws-sdk-go-1.7" .
sandbox-go1.7: sandbox-build-go17
docker run -i -t aws-sdk-go-1.7 bash
sandbox-test-go1.7: sandbox-build-go17
docker run -t aws-sdk-go-1.7
sandbox-build-go1.8:
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.8 -t "aws-sdk-go-1.8" .
sandbox-go1.8: sandbox-build-go1.8
docker run -i -t aws-sdk-go-1.8 bash
sandbox-test-go1.8: sandbox-build-go1.8
docker run -t aws-sdk-go-1.8
sandbox-build-go1.9:
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.9 -t "aws-sdk-go-1.9" .
sandbox-go1.9: sandbox-build-go1.9
docker run -i -t aws-sdk-go-1.9 bash
sandbox-test-go1.9: sandbox-build-go1.9
docker run -t aws-sdk-go-1.9
sandbox-build-go1.10:
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.10 -t "aws-sdk-go-1.10" .
sandbox-go1.10: sandbox-build-go1.10
docker run -i -t aws-sdk-go-1.10 bash
sandbox-test-go1.10: sandbox-build-go1.10
docker run -t aws-sdk-go-1.10
sandbox-build-go1.11:
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.11 -t "aws-sdk-go-1.11" .
sandbox-go1.11: sandbox-build-go1.11
docker run -i -t aws-sdk-go-1.11 bash
sandbox-test-go1.11: sandbox-build-go1.11
docker run -t aws-sdk-go-1.11
sandbox-build-go1.12:
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.12 -t "aws-sdk-go-1.12" .
sandbox-go1.12: sandbox-build-go1.12
docker run -i -t aws-sdk-go-1.12 bash
sandbox-test-go1.12: sandbox-build-go1.12
docker run -t aws-sdk-go-1.12
sandbox-build-gotip:
@echo "Run make update-aws-golang-tip, if this test fails because missing aws-golang:tip container"
docker build -f ./awstesting/sandbox/Dockerfile.test.gotip -t "aws-sdk-go-tip" .
sandbox-gotip: sandbox-build-gotip
docker run -i -t aws-sdk-go-tip bash
sandbox-test-gotip: sandbox-build-gotip
docker run -t aws-sdk-go-tip
update-aws-golang-tip:
docker build --no-cache=true -f ./awstesting/sandbox/Dockerfile.golang-tip -t "aws-golang:tip" .
##################
# Linting/Verify #
##################
verify: lint vet
lint:
@echo "go lint SDK and vendor packages"
@lint=`golint ./...`; \
dolint=`echo "$$lint" | grep -E -v -e ${LINTIGNOREDOC} -e ${LINTIGNORECONST} -e ${LINTIGNORESTUTTER} -e ${LINTIGNOREINFLECT} -e ${LINTIGNOREDEPS} -e ${LINTIGNOREINFLECTS3UPLOAD} -e ${LINTIGNOREPKGCOMMENT} -e ${LINTIGNOREENDPOINTS}`; \
echo "$$dolint"; \
if [ "$$dolint" != "" ]; then exit 1; fi
vet:
go vet -tags "example codegen awsinclude integration" --all ${SDK_ALL_PKGS}
################
# Dependencies #
################
get-deps: get-deps-tests get-deps-x-tests get-deps-codegen get-deps-verify
get-deps-tests:
@echo "go get SDK testing dependencies"
go get github.com/stretchr/testify
get-deps-x-tests:
@echo "go get SDK testing golang.org/x dependencies"
go get golang.org/x/net/http2
get-deps-codegen: get-deps-x-tests
@echo "go get SDK codegen dependencies"
go get golang.org/x/net/html
get-deps-verify:
@echo "go get SDK verification utilities"
go get golang.org/x/lint/golint
##############
# Benchmarks #
##############
bench:
@echo "go bench SDK packages"
go test -count=1 -run NONE -bench . -benchmem -tags 'bench' ${SDK_ALL_PKGS}
bench-protocol:
@echo "go bench SDK protocol marshallers"
go test -count=1 -run NONE -bench . -benchmem -tags 'bench' ./private/protocol/...
#############
# Utilities #
#############
docs:
@echo "generate SDK docs"
$(AWS_DOC_GEN_TOOL) `pwd`
api_info:
@go run private/model/cli/api-info/api-info.go

View File

@@ -1,3 +0,0 @@
AWS SDK for Go
Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Copyright 2014-2015 Stripe, Inc.

View File

@@ -1,503 +0,0 @@
[![API Reference](https://img.shields.io/badge/api-reference-blue.svg)](https://docs.aws.amazon.com/sdk-for-go/api) [![Join the chat at https://gitter.im/aws/aws-sdk-go](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/aws/aws-sdk-go?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://img.shields.io/travis/aws/aws-sdk-go.svg)](https://travis-ci.org/aws/aws-sdk-go) [![Apache V2 License](https://img.shields.io/badge/license-Apache%20V2-blue.svg)](https://github.com/aws/aws-sdk-go/blob/master/LICENSE.txt)
# AWS SDK for Go
aws-sdk-go is the official AWS SDK for the Go programming language.
Checkout our [release notes](https://github.com/aws/aws-sdk-go/releases) for
information about the latest bug fixes, updates, and features added to the SDK.
We [announced](https://aws.amazon.com/blogs/developer/aws-sdk-for-go-2-0-developer-preview/) the Developer Preview for the [v2 AWS SDK for Go](https://github.com/aws/aws-sdk-go-v2). The v2 SDK source is available at https://github.com/aws/aws-sdk-go-v2, and add it to your project with `go get github.com/aws/aws-sdk-go-v2`. Check out the v2 SDK's [changes and updates](https://github.com/aws/aws-sdk-go-v2/blob/master/CHANGELOG.md), and let us know what you think. We want your feedback.
We have a pilot redesign of the [AWS SDK for Go API reference documentation](https://docs.aws.amazon.com/sdk-for-go/v1/api/gosdk-apiref.html). Let us know what you think.
## Installing
Use `go get` to retrieve the SDK to add it to your `GOPATH` workspace, or
project's Go module dependencies.
go get github.com/aws/aws-sdk-go
To update the SDK use `go get -u` to retrieve the latest version of the SDK.
go get -u github.com/aws/aws-sdk-go
### Dependencies
The SDK includes a `vendor` folder containing the runtime dependencies of the
SDK. The metadata of the SDK's dependencies can be found in the Go module file
`go.mod` or Dep file `Gopkg.toml`.
### Go Modules
If you are using Go modules, your `go get` will default to the latest tagged
release version of the SDK. To get a specific release version of the SDK use
`@<tag>` in your `go get` command.
go get github.com/aws/aws-sdk-go@v1.15.77
To get the latest SDK repository change use `@latest`.
go get github.com/aws/aws-sdk-go@latest
### Go 1.5
If you are using Go 1.5 without vendoring enabled, (`GO15VENDOREXPERIMENT=1`),
you will need to use `...` when retrieving the SDK to get its dependencies.
go get github.com/aws/aws-sdk-go/...
This will still include the `vendor` folder. The `vendor` folder can be deleted
if not used by your environment.
rm -rf $GOPATH/src/github.com/aws/aws-sdk-go/vendor
## Getting Help
Please use these community resources for getting help. We use the GitHub issues
for tracking bugs and feature requests.
* Ask a question on [StackOverflow](http://stackoverflow.com/) and tag it with the [`aws-sdk-go`](http://stackoverflow.com/questions/tagged/aws-sdk-go) tag.
* Come join the AWS SDK for Go community chat on [gitter](https://gitter.im/aws/aws-sdk-go).
* Open a support ticket with [AWS Support](http://docs.aws.amazon.com/awssupport/latest/user/getting-started.html).
* If you think you may have found a bug, please open an [issue](https://github.com/aws/aws-sdk-go/issues/new).
## Opening Issues
If you encounter a bug with the AWS SDK for Go we would like to hear about it.
Search the [existing issues](https://github.com/aws/aws-sdk-go/issues) and see
if others are also experiencing the issue before opening a new issue. Please
include the version of AWS SDK for Go, Go language, and OS youre using. Please
also include reproduction case when appropriate.
The GitHub issues are intended for bug reports and feature requests. For help
and questions with using AWS SDK for GO please make use of the resources listed
in the [Getting Help](https://github.com/aws/aws-sdk-go#getting-help) section.
Keeping the list of open issues lean will help us respond in a timely manner.
## Reference Documentation
[`Getting Started Guide`](https://aws.amazon.com/sdk-for-go/) - This document
is a general introduction on how to configure and make requests with the SDK.
If this is your first time using the SDK, this documentation and the API
documentation will help you get started. This document focuses on the syntax
and behavior of the SDK. The [Service Developer
Guide](https://aws.amazon.com/documentation/) will help you get started using
specific AWS services.
[`SDK API Reference
Documentation`](https://docs.aws.amazon.com/sdk-for-go/api/) - Use this
document to look up all API operation input and output parameters for AWS
services supported by the SDK. The API reference also includes documentation of
the SDK, and examples how to using the SDK, service client API operations, and
API operation require parameters.
[`Service Developer Guide`](https://aws.amazon.com/documentation/) - Use this
documentation to learn how to interface with AWS services. These are great
guides both, if you're getting started with a service, or looking for more
information on a service. You should not need this document for coding, though
in some cases, services may supply helpful samples that you might want to look
out for.
[`SDK Examples`](https://github.com/aws/aws-sdk-go/tree/master/example) -
Included in the SDK's repo are several hand crafted examples using the SDK
features and AWS services.
## Overview of SDK's Packages
The SDK is composed of two main components, SDK core, and service clients.
The SDK core packages are all available under the aws package at the root of
the SDK. Each client for a supported AWS service is available within its own
package under the service folder at the root of the SDK.
* aws - SDK core, provides common shared types such as Config, Logger,
and utilities to make working with API parameters easier.
* awserr - Provides the error interface that the SDK will use for all
errors that occur in the SDK's processing. This includes service API
response errors as well. The Error type is made up of a code and message.
Cast the SDK's returned error type to awserr.Error and call the Code
method to compare returned error to specific error codes. See the package's
documentation for additional values that can be extracted such as RequestID.
* credentials - Provides the types and built in credentials providers
the SDK will use to retrieve AWS credentials to make API requests with.
Nested under this folder are also additional credentials providers such as
stscreds for assuming IAM roles, and ec2rolecreds for EC2 Instance roles.
* endpoints - Provides the AWS Regions and Endpoints metadata for the SDK.
Use this to lookup AWS service endpoint information such as which services
are in a region, and what regions a service is in. Constants are also provided
for all region identifiers, e.g UsWest2RegionID for "us-west-2".
* session - Provides initial default configuration, and load
configuration from external sources such as environment and shared
credentials file.
* request - Provides the API request sending, and retry logic for the SDK.
This package also includes utilities for defining your own request
retryer, and configuring how the SDK processes the request.
* service - Clients for AWS services. All services supported by the SDK are
available under this folder.
## How to Use the SDK's AWS Service Clients
The SDK includes the Go types and utilities you can use to make requests to
AWS service APIs. Within the service folder at the root of the SDK you'll find
a package for each AWS service the SDK supports. All service clients follow common pattern of creation and usage.
When creating a client for an AWS service you'll first need to have a Session
value constructed. The Session provides shared configuration that can be shared
between your service clients. When service clients are created you can pass
in additional configuration via the aws.Config type to override configuration
provided by in the Session to create service client instances with custom
configuration.
Once the service's client is created you can use it to make API requests the
AWS service. These clients are safe to use concurrently.
## Configuring the SDK
In the AWS SDK for Go, you can configure settings for service clients, such
as the log level and maximum number of retries. Most settings are optional;
however, for each service client, you must specify a region and your credentials.
The SDK uses these values to send requests to the correct AWS region and sign
requests with the correct credentials. You can specify these values as part
of a session or as environment variables.
See the SDK's [configuration guide][config_guide] for more information.
See the [session][session_pkg] package documentation for more information on how to use Session
with the SDK.
See the [Config][config_typ] type in the [aws][aws_pkg] package for more information on configuration
options.
[config_guide]: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html
[session_pkg]: https://docs.aws.amazon.com/sdk-for-go/api/aws/session/
[config_typ]: https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
[aws_pkg]: https://docs.aws.amazon.com/sdk-for-go/api/aws/
### Configuring Credentials
When using the SDK you'll generally need your AWS credentials to authenticate
with AWS services. The SDK supports multiple methods of supporting these
credentials. By default the SDK will source credentials automatically from
its default credential chain. See the session package for more information
on this chain, and how to configure it. The common items in the credential
chain are the following:
* Environment Credentials - Set of environment variables that are useful
when sub processes are created for specific roles.
* Shared Credentials file (~/.aws/credentials) - This file stores your
credentials based on a profile name and is useful for local development.
* EC2 Instance Role Credentials - Use EC2 Instance Role to assign credentials
to application running on an EC2 instance. This removes the need to manage
credential files in production.
Credentials can be configured in code as well by setting the Config's Credentials
value to a custom provider or using one of the providers included with the
SDK to bypass the default credential chain and use a custom one. This is
helpful when you want to instruct the SDK to only use a specific set of
credentials or providers.
This example creates a credential provider for assuming an IAM role, "myRoleARN"
and configures the S3 service client to use that role for API requests.
```go
// Initial credentials loaded from SDK's default credential chain. Such as
// the environment, shared credentials (~/.aws/credentials), or EC2 Instance
// Role. These credentials will be used to to make the STS Assume Role API.
sess := session.Must(session.NewSession())
// Create the credentials from AssumeRoleProvider to assume the role
// referenced by the "myRoleARN" ARN.
creds := stscreds.NewCredentials(sess, "myRoleArn")
// Create service client value configured for credentials
// from assumed role.
svc := s3.New(sess, &aws.Config{Credentials: creds})
```
See the [credentials][credentials_pkg] package documentation for more information on credential
providers included with the SDK, and how to customize the SDK's usage of
credentials.
The SDK has support for the shared configuration file (~/.aws/config). This
support can be enabled by setting the environment variable, "AWS_SDK_LOAD_CONFIG=1",
or enabling the feature in code when creating a Session via the
Option's SharedConfigState parameter.
```go
sess := session.Must(session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
}))
```
[credentials_pkg]: https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials
### Configuring AWS Region
In addition to the credentials you'll need to specify the region the SDK
will use to make AWS API requests to. In the SDK you can specify the region
either with an environment variable, or directly in code when a Session or
service client is created. The last value specified in code wins if the region
is specified multiple ways.
To set the region via the environment variable set the "AWS_REGION" to the
region you want to the SDK to use. Using this method to set the region will
allow you to run your application in multiple regions without needing additional
code in the application to select the region.
AWS_REGION=us-west-2
The endpoints package includes constants for all regions the SDK knows. The
values are all suffixed with RegionID. These values are helpful, because they
reduce the need to type the region string manually.
To set the region on a Session use the aws package's Config struct parameter
Region to the AWS region you want the service clients created from the session to
use. This is helpful when you want to create multiple service clients, and
all of the clients make API requests to the same region.
```go
sess := session.Must(session.NewSession(&aws.Config{
Region: aws.String(endpoints.UsWest2RegionID),
}))
```
See the [endpoints][endpoints_pkg] package for the AWS Regions and Endpoints metadata.
In addition to setting the region when creating a Session you can also set
the region on a per service client bases. This overrides the region of a
Session. This is helpful when you want to create service clients in specific
regions different from the Session's region.
```go
svc := s3.New(sess, &aws.Config{
Region: aws.String(endpoints.UsWest2RegionID),
})
```
See the [Config][config_typ] type in the [aws][aws_pkg] package for more information and additional
options such as setting the Endpoint, and other service client configuration options.
[endpoints_pkg]: https://docs.aws.amazon.com/sdk-for-go/api/aws/endpoints/
## Making API Requests
Once the client is created you can make an API request to the service.
Each API method takes a input parameter, and returns the service response
and an error. The SDK provides methods for making the API call in multiple ways.
In this list we'll use the S3 ListObjects API as an example for the different
ways of making API requests.
* ListObjects - Base API operation that will make the API request to the service.
* ListObjectsRequest - API methods suffixed with Request will construct the
API request, but not send it. This is also helpful when you want to get a
presigned URL for a request, and share the presigned URL instead of your
application making the request directly.
* ListObjectsPages - Same as the base API operation, but uses a callback to
automatically handle pagination of the API's response.
* ListObjectsWithContext - Same as base API operation, but adds support for
the Context pattern. This is helpful for controlling the canceling of in
flight requests. See the Go standard library context package for more
information. This method also takes request package's Option functional
options as the variadic argument for modifying how the request will be
made, or extracting information from the raw HTTP response.
* ListObjectsPagesWithContext - same as ListObjectsPages, but adds support for
the Context pattern. Similar to ListObjectsWithContext this method also
takes the request package's Option function option types as the variadic
argument.
In addition to the API operations the SDK also includes several higher level
methods that abstract checking for and waiting for an AWS resource to be in
a desired state. In this list we'll use WaitUntilBucketExists to demonstrate
the different forms of waiters.
* WaitUntilBucketExists. - Method to make API request to query an AWS service for
a resource's state. Will return successfully when that state is accomplished.
* WaitUntilBucketExistsWithContext - Same as WaitUntilBucketExists, but adds
support for the Context pattern. In addition these methods take request
package's WaiterOptions to configure the waiter, and how underlying request
will be made by the SDK.
The API method will document which error codes the service might return for
the operation. These errors will also be available as const strings prefixed
with "ErrCode" in the service client's package. If there are no errors listed
in the API's SDK documentation you'll need to consult the AWS service's API
documentation for the errors that could be returned.
```go
ctx := context.Background()
result, err := svc.GetObjectWithContext(ctx, &s3.GetObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("my-key"),
})
if err != nil {
// Cast err to awserr.Error to handle specific error codes.
aerr, ok := err.(awserr.Error)
if ok && aerr.Code() == s3.ErrCodeNoSuchKey {
// Specific error code handling
}
return err
}
// Make sure to close the body when done with it for S3 GetObject APIs or
// will leak connections.
defer result.Body.Close()
fmt.Println("Object Size:", aws.Int64Value(result.ContentLength))
```
### API Request Pagination and Resource Waiters
Pagination helper methods are suffixed with "Pages", and provide the
functionality needed to round trip API page requests. Pagination methods
take a callback function that will be called for each page of the API's response.
```go
objects := []string{}
err := svc.ListObjectsPagesWithContext(ctx, &s3.ListObjectsInput{
Bucket: aws.String(myBucket),
}, func(p *s3.ListObjectsOutput, lastPage bool) bool {
for _, o := range p.Contents {
objects = append(objects, aws.StringValue(o.Key))
}
return true // continue paging
})
if err != nil {
panic(fmt.Sprintf("failed to list objects for bucket, %s, %v", myBucket, err))
}
fmt.Println("Objects in bucket:", objects)
```
Waiter helper methods provide the functionality to wait for an AWS resource
state. These methods abstract the logic needed to check the state of an
AWS resource, and wait until that resource is in a desired state. The waiter
will block until the resource is in the state that is desired, an error occurs,
or the waiter times out. If a resource times out the error code returned will
be request.WaiterResourceNotReadyErrorCode.
```go
err := svc.WaitUntilBucketExistsWithContext(ctx, &s3.HeadBucketInput{
Bucket: aws.String(myBucket),
})
if err != nil {
aerr, ok := err.(awserr.Error)
if ok && aerr.Code() == request.WaiterResourceNotReadyErrorCode {
fmt.Fprintf(os.Stderr, "timed out while waiting for bucket to exist")
}
panic(fmt.Errorf("failed to wait for bucket to exist, %v", err))
}
fmt.Println("Bucket", myBucket, "exists")
```
## Complete SDK Example
This example shows a complete working Go file which will upload a file to S3
and use the Context pattern to implement timeout logic that will cancel the
request if it takes too long. This example highlights how to use sessions,
create a service client, make a request, handle the error, and process the
response.
```go
package main
import (
"context"
"flag"
"fmt"
"os"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
)
// Uploads a file to S3 given a bucket and object key. Also takes a duration
// value to terminate the update if it doesn't complete within that time.
//
// The AWS Region needs to be provided in the AWS shared config or on the
// environment variable as `AWS_REGION`. Credentials also must be provided
// Will default to shared config file, but can load from environment if provided.
//
// Usage:
// # Upload myfile.txt to myBucket/myKey. Must complete within 10 minutes or will fail
// go run withContext.go -b mybucket -k myKey -d 10m < myfile.txt
func main() {
var bucket, key string
var timeout time.Duration
flag.StringVar(&bucket, "b", "", "Bucket name.")
flag.StringVar(&key, "k", "", "Object key name.")
flag.DurationVar(&timeout, "d", 0, "Upload timeout.")
flag.Parse()
// All clients require a Session. The Session provides the client with
// shared configuration such as region, endpoint, and credentials. A
// Session should be shared where possible to take advantage of
// configuration and credential caching. See the session package for
// more information.
sess := session.Must(session.NewSession())
// Create a new instance of the service's client with a Session.
// Optional aws.Config values can also be provided as variadic arguments
// to the New function. This option allows you to provide service
// specific configuration.
svc := s3.New(sess)
// Create a context with a timeout that will abort the upload if it takes
// more than the passed in timeout.
ctx := context.Background()
var cancelFn func()
if timeout > 0 {
ctx, cancelFn = context.WithTimeout(ctx, timeout)
}
// Ensure the context is canceled to prevent leaking.
// See context package for more information, https://golang.org/pkg/context/
if cancelFn {
defer cancelFn()
}
// Uploads the object to S3. The Context will interrupt the request if the
// timeout expires.
_, err := svc.PutObjectWithContext(ctx, &s3.PutObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
Body: os.Stdin,
})
if err != nil {
if aerr, ok := err.(awserr.Error); ok && aerr.Code() == request.CanceledErrorCode {
// If the SDK can determine the request or retry delay was canceled
// by a context the CanceledErrorCode error code will be returned.
fmt.Fprintf(os.Stderr, "upload canceled due to timeout, %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "failed to upload object, %v\n", err)
}
os.Exit(1)
}
fmt.Printf("successfully uploaded file to %s/%s\n", bucket, key)
}
```
## License
This SDK is distributed under the
[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0),
see LICENSE.txt and NOTICE.txt for more information.

View File

@@ -1,86 +0,0 @@
// Package arn provides a parser for interacting with Amazon Resource Names.
package arn
import (
"errors"
"strings"
)
const (
arnDelimiter = ":"
arnSections = 6
arnPrefix = "arn:"
// zero-indexed
sectionPartition = 1
sectionService = 2
sectionRegion = 3
sectionAccountID = 4
sectionResource = 5
// errors
invalidPrefix = "arn: invalid prefix"
invalidSections = "arn: not enough sections"
)
// ARN captures the individual fields of an Amazon Resource Name.
// See http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html for more information.
type ARN struct {
// The partition that the resource is in. For standard AWS regions, the partition is "aws". If you have resources in
// other partitions, the partition is "aws-partitionname". For example, the partition for resources in the China
// (Beijing) region is "aws-cn".
Partition string
// The service namespace that identifies the AWS product (for example, Amazon S3, IAM, or Amazon RDS). For a list of
// namespaces, see
// http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#genref-aws-service-namespaces.
Service string
// The region the resource resides in. Note that the ARNs for some resources do not require a region, so this
// component might be omitted.
Region string
// The ID of the AWS account that owns the resource, without the hyphens. For example, 123456789012. Note that the
// ARNs for some resources don't require an account number, so this component might be omitted.
AccountID string
// The content of this part of the ARN varies by service. It often includes an indicator of the type of resource —
// for example, an IAM user or Amazon RDS database - followed by a slash (/) or a colon (:), followed by the
// resource name itself. Some services allows paths for resource names, as described in
// http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arns-paths.
Resource string
}
// Parse parses an ARN into its constituent parts.
//
// Some example ARNs:
// arn:aws:elasticbeanstalk:us-east-1:123456789012:environment/My App/MyEnvironment
// arn:aws:iam::123456789012:user/David
// arn:aws:rds:eu-west-1:123456789012:db:mysql-db
// arn:aws:s3:::my_corporate_bucket/exampleobject.png
func Parse(arn string) (ARN, error) {
if !strings.HasPrefix(arn, arnPrefix) {
return ARN{}, errors.New(invalidPrefix)
}
sections := strings.SplitN(arn, arnDelimiter, arnSections)
if len(sections) != arnSections {
return ARN{}, errors.New(invalidSections)
}
return ARN{
Partition: sections[sectionPartition],
Service: sections[sectionService],
Region: sections[sectionRegion],
AccountID: sections[sectionAccountID],
Resource: sections[sectionResource],
}, nil
}
// String returns the canonical representation of the ARN
func (arn ARN) String() string {
return arnPrefix +
arn.Partition + arnDelimiter +
arn.Service + arnDelimiter +
arn.Region + arnDelimiter +
arn.AccountID + arnDelimiter +
arn.Resource
}

View File

@@ -1,90 +0,0 @@
// +build go1.7
package arn
import (
"errors"
"testing"
)
func TestParseARN(t *testing.T) {
cases := []struct {
input string
arn ARN
err error
}{
{
input: "invalid",
err: errors.New(invalidPrefix),
},
{
input: "arn:nope",
err: errors.New(invalidSections),
},
{
input: "arn:aws:ecr:us-west-2:123456789012:repository/foo/bar",
arn: ARN{
Partition: "aws",
Service: "ecr",
Region: "us-west-2",
AccountID: "123456789012",
Resource: "repository/foo/bar",
},
},
{
input: "arn:aws:elasticbeanstalk:us-east-1:123456789012:environment/My App/MyEnvironment",
arn: ARN{
Partition: "aws",
Service: "elasticbeanstalk",
Region: "us-east-1",
AccountID: "123456789012",
Resource: "environment/My App/MyEnvironment",
},
},
{
input: "arn:aws:iam::123456789012:user/David",
arn: ARN{
Partition: "aws",
Service: "iam",
Region: "",
AccountID: "123456789012",
Resource: "user/David",
},
},
{
input: "arn:aws:rds:eu-west-1:123456789012:db:mysql-db",
arn: ARN{
Partition: "aws",
Service: "rds",
Region: "eu-west-1",
AccountID: "123456789012",
Resource: "db:mysql-db",
},
},
{
input: "arn:aws:s3:::my_corporate_bucket/exampleobject.png",
arn: ARN{
Partition: "aws",
Service: "s3",
Region: "",
AccountID: "",
Resource: "my_corporate_bucket/exampleobject.png",
},
},
}
for _, tc := range cases {
t.Run(tc.input, func(t *testing.T) {
spec, err := Parse(tc.input)
if tc.arn != spec {
t.Errorf("Expected %q to parse as %v, but got %v", tc.input, tc.arn, spec)
}
if err == nil && tc.err != nil {
t.Errorf("Expected err to be %v, but got nil", tc.err)
} else if err != nil && tc.err == nil {
t.Errorf("Expected err to be nil, but got %v", err)
} else if err != nil && tc.err != nil && err.Error() != tc.err.Error() {
t.Errorf("Expected err to be %v, but got %v", tc.err, err)
}
})
}
}

View File

@@ -1,164 +0,0 @@
// Package awserr represents API error interface accessors for the SDK.
package awserr
// An Error wraps lower level errors with code, message and an original error.
// The underlying concrete error type may also satisfy other interfaces which
// can be to used to obtain more specific information about the error.
//
// Calling Error() or String() will always include the full information about
// an error based on its underlying type.
//
// Example:
//
// output, err := s3manage.Upload(svc, input, opts)
// if err != nil {
// if awsErr, ok := err.(awserr.Error); ok {
// // Get error details
// log.Println("Error:", awsErr.Code(), awsErr.Message())
//
// // Prints out full error message, including original error if there was one.
// log.Println("Error:", awsErr.Error())
//
// // Get original error
// if origErr := awsErr.OrigErr(); origErr != nil {
// // operate on original error.
// }
// } else {
// fmt.Println(err.Error())
// }
// }
//
type Error interface {
// Satisfy the generic error interface.
error
// Returns the short phrase depicting the classification of the error.
Code() string
// Returns the error details message.
Message() string
// Returns the original error if one was set. Nil is returned if not set.
OrigErr() error
}
// BatchError is a batch of errors which also wraps lower level errors with
// code, message, and original errors. Calling Error() will include all errors
// that occurred in the batch.
//
// Deprecated: Replaced with BatchedErrors. Only defined for backwards
// compatibility.
type BatchError interface {
// Satisfy the generic error interface.
error
// Returns the short phrase depicting the classification of the error.
Code() string
// Returns the error details message.
Message() string
// Returns the original error if one was set. Nil is returned if not set.
OrigErrs() []error
}
// BatchedErrors is a batch of errors which also wraps lower level errors with
// code, message, and original errors. Calling Error() will include all errors
// that occurred in the batch.
//
// Replaces BatchError
type BatchedErrors interface {
// Satisfy the base Error interface.
Error
// Returns the original error if one was set. Nil is returned if not set.
OrigErrs() []error
}
// New returns an Error object described by the code, message, and origErr.
//
// If origErr satisfies the Error interface it will not be wrapped within a new
// Error object and will instead be returned.
func New(code, message string, origErr error) Error {
var errs []error
if origErr != nil {
errs = append(errs, origErr)
}
return newBaseError(code, message, errs)
}
// NewBatchError returns an BatchedErrors with a collection of errors as an
// array of errors.
func NewBatchError(code, message string, errs []error) BatchedErrors {
return newBaseError(code, message, errs)
}
// A RequestFailure is an interface to extract request failure information from
// an Error such as the request ID of the failed request returned by a service.
// RequestFailures may not always have a requestID value if the request failed
// prior to reaching the service such as a connection error.
//
// Example:
//
// output, err := s3manage.Upload(svc, input, opts)
// if err != nil {
// if reqerr, ok := err.(RequestFailure); ok {
// log.Println("Request failed", reqerr.Code(), reqerr.Message(), reqerr.RequestID())
// } else {
// log.Println("Error:", err.Error())
// }
// }
//
// Combined with awserr.Error:
//
// output, err := s3manage.Upload(svc, input, opts)
// if err != nil {
// if awsErr, ok := err.(awserr.Error); ok {
// // Generic AWS Error with Code, Message, and original error (if any)
// fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr())
//
// if reqErr, ok := err.(awserr.RequestFailure); ok {
// // A service error occurred
// fmt.Println(reqErr.StatusCode(), reqErr.RequestID())
// }
// } else {
// fmt.Println(err.Error())
// }
// }
//
type RequestFailure interface {
Error
// The status code of the HTTP response.
StatusCode() int
// The request ID returned by the service for a request failure. This will
// be empty if no request ID is available such as the request failed due
// to a connection error.
RequestID() string
}
// NewRequestFailure returns a wrapped error with additional information for
// request status code, and service requestID.
//
// Should be used to wrap all request which involve service requests. Even if
// the request failed without a service response, but had an HTTP status code
// that may be meaningful.
func NewRequestFailure(err Error, statusCode int, reqID string) RequestFailure {
return newRequestError(err, statusCode, reqID)
}
// UnmarshalError provides the interface for the SDK failing to unmarshal data.
type UnmarshalError interface {
awsError
Bytes() []byte
}
// NewUnmarshalError returns an initialized UnmarshalError error wrapper adding
// the bytes that fail to unmarshal to the error.
func NewUnmarshalError(err error, msg string, bytes []byte) UnmarshalError {
return &unmarshalError{
awsError: New("UnmarshalError", msg, err),
bytes: bytes,
}
}

View File

@@ -1,221 +0,0 @@
package awserr
import (
"encoding/hex"
"fmt"
)
// SprintError returns a string of the formatted error code.
//
// Both extra and origErr are optional. If they are included their lines
// will be added, but if they are not included their lines will be ignored.
func SprintError(code, message, extra string, origErr error) string {
msg := fmt.Sprintf("%s: %s", code, message)
if extra != "" {
msg = fmt.Sprintf("%s\n\t%s", msg, extra)
}
if origErr != nil {
msg = fmt.Sprintf("%s\ncaused by: %s", msg, origErr.Error())
}
return msg
}
// A baseError wraps the code and message which defines an error. It also
// can be used to wrap an original error object.
//
// Should be used as the root for errors satisfying the awserr.Error. Also
// for any error which does not fit into a specific error wrapper type.
type baseError struct {
// Classification of error
code string
// Detailed information about error
message string
// Optional original error this error is based off of. Allows building
// chained errors.
errs []error
}
// newBaseError returns an error object for the code, message, and errors.
//
// code is a short no whitespace phrase depicting the classification of
// the error that is being created.
//
// message is the free flow string containing detailed information about the
// error.
//
// origErrs is the error objects which will be nested under the new errors to
// be returned.
func newBaseError(code, message string, origErrs []error) *baseError {
b := &baseError{
code: code,
message: message,
errs: origErrs,
}
return b
}
// Error returns the string representation of the error.
//
// See ErrorWithExtra for formatting.
//
// Satisfies the error interface.
func (b baseError) Error() string {
size := len(b.errs)
if size > 0 {
return SprintError(b.code, b.message, "", errorList(b.errs))
}
return SprintError(b.code, b.message, "", nil)
}
// String returns the string representation of the error.
// Alias for Error to satisfy the stringer interface.
func (b baseError) String() string {
return b.Error()
}
// Code returns the short phrase depicting the classification of the error.
func (b baseError) Code() string {
return b.code
}
// Message returns the error details message.
func (b baseError) Message() string {
return b.message
}
// OrigErr returns the original error if one was set. Nil is returned if no
// error was set. This only returns the first element in the list. If the full
// list is needed, use BatchedErrors.
func (b baseError) OrigErr() error {
switch len(b.errs) {
case 0:
return nil
case 1:
return b.errs[0]
default:
if err, ok := b.errs[0].(Error); ok {
return NewBatchError(err.Code(), err.Message(), b.errs[1:])
}
return NewBatchError("BatchedErrors",
"multiple errors occurred", b.errs)
}
}
// OrigErrs returns the original errors if one was set. An empty slice is
// returned if no error was set.
func (b baseError) OrigErrs() []error {
return b.errs
}
// So that the Error interface type can be included as an anonymous field
// in the requestError struct and not conflict with the error.Error() method.
type awsError Error
// A requestError wraps a request or service error.
//
// Composed of baseError for code, message, and original error.
type requestError struct {
awsError
statusCode int
requestID string
bytes []byte
}
// newRequestError returns a wrapped error with additional information for
// request status code, and service requestID.
//
// Should be used to wrap all request which involve service requests. Even if
// the request failed without a service response, but had an HTTP status code
// that may be meaningful.
//
// Also wraps original errors via the baseError.
func newRequestError(err Error, statusCode int, requestID string) *requestError {
return &requestError{
awsError: err,
statusCode: statusCode,
requestID: requestID,
}
}
// Error returns the string representation of the error.
// Satisfies the error interface.
func (r requestError) Error() string {
extra := fmt.Sprintf("status code: %d, request id: %s",
r.statusCode, r.requestID)
return SprintError(r.Code(), r.Message(), extra, r.OrigErr())
}
// String returns the string representation of the error.
// Alias for Error to satisfy the stringer interface.
func (r requestError) String() string {
return r.Error()
}
// StatusCode returns the wrapped status code for the error
func (r requestError) StatusCode() int {
return r.statusCode
}
// RequestID returns the wrapped requestID
func (r requestError) RequestID() string {
return r.requestID
}
// OrigErrs returns the original errors if one was set. An empty slice is
// returned if no error was set.
func (r requestError) OrigErrs() []error {
if b, ok := r.awsError.(BatchedErrors); ok {
return b.OrigErrs()
}
return []error{r.OrigErr()}
}
type unmarshalError struct {
awsError
bytes []byte
}
// Error returns the string representation of the error.
// Satisfies the error interface.
func (e unmarshalError) Error() string {
extra := hex.Dump(e.bytes)
return SprintError(e.Code(), e.Message(), extra, e.OrigErr())
}
// String returns the string representation of the error.
// Alias for Error to satisfy the stringer interface.
func (e unmarshalError) String() string {
return e.Error()
}
// Bytes returns the bytes that failed to unmarshal.
func (e unmarshalError) Bytes() []byte {
return e.bytes
}
// An error list that satisfies the golang interface
type errorList []error
// Error returns the string representation of the error.
//
// Satisfies the error interface.
func (e errorList) Error() string {
msg := ""
// How do we want to handle the array size being zero
if size := len(e); size > 0 {
for i := 0; i < size; i++ {
msg += fmt.Sprintf("%s", e[i].Error())
// We check the next index to see if it is within the slice.
// If it is, then we append a newline. We do this, because unit tests
// could be broken with the additional '\n'
if i+1 < size {
msg += "\n"
}
}
}
return msg
}

View File

@@ -1,108 +0,0 @@
package awsutil
import (
"io"
"reflect"
"time"
)
// Copy deeply copies a src structure to dst. Useful for copying request and
// response structures.
//
// Can copy between structs of different type, but will only copy fields which
// are assignable, and exist in both structs. Fields which are not assignable,
// or do not exist in both structs are ignored.
func Copy(dst, src interface{}) {
dstval := reflect.ValueOf(dst)
if !dstval.IsValid() {
panic("Copy dst cannot be nil")
}
rcopy(dstval, reflect.ValueOf(src), true)
}
// CopyOf returns a copy of src while also allocating the memory for dst.
// src must be a pointer type or this operation will fail.
func CopyOf(src interface{}) (dst interface{}) {
dsti := reflect.New(reflect.TypeOf(src).Elem())
dst = dsti.Interface()
rcopy(dsti, reflect.ValueOf(src), true)
return
}
// rcopy performs a recursive copy of values from the source to destination.
//
// root is used to skip certain aspects of the copy which are not valid
// for the root node of a object.
func rcopy(dst, src reflect.Value, root bool) {
if !src.IsValid() {
return
}
switch src.Kind() {
case reflect.Ptr:
if _, ok := src.Interface().(io.Reader); ok {
if dst.Kind() == reflect.Ptr && dst.Elem().CanSet() {
dst.Elem().Set(src)
} else if dst.CanSet() {
dst.Set(src)
}
} else {
e := src.Type().Elem()
if dst.CanSet() && !src.IsNil() {
if _, ok := src.Interface().(*time.Time); !ok {
dst.Set(reflect.New(e))
} else {
tempValue := reflect.New(e)
tempValue.Elem().Set(src.Elem())
// Sets time.Time's unexported values
dst.Set(tempValue)
}
}
if src.Elem().IsValid() {
// Keep the current root state since the depth hasn't changed
rcopy(dst.Elem(), src.Elem(), root)
}
}
case reflect.Struct:
t := dst.Type()
for i := 0; i < t.NumField(); i++ {
name := t.Field(i).Name
srcVal := src.FieldByName(name)
dstVal := dst.FieldByName(name)
if srcVal.IsValid() && dstVal.CanSet() {
rcopy(dstVal, srcVal, false)
}
}
case reflect.Slice:
if src.IsNil() {
break
}
s := reflect.MakeSlice(src.Type(), src.Len(), src.Cap())
dst.Set(s)
for i := 0; i < src.Len(); i++ {
rcopy(dst.Index(i), src.Index(i), false)
}
case reflect.Map:
if src.IsNil() {
break
}
s := reflect.MakeMap(src.Type())
dst.Set(s)
for _, k := range src.MapKeys() {
v := src.MapIndex(k)
v2 := reflect.New(v.Type()).Elem()
rcopy(v2, v, false)
dst.SetMapIndex(k, v2)
}
default:
// Assign the value if possible. If its not assignable, the value would
// need to be converted and the impact of that may be unexpected, or is
// not compatible with the dst type.
if src.Type().AssignableTo(dst.Type()) {
dst.Set(src)
}
}
}

View File

@@ -1,353 +0,0 @@
package awsutil_test
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"reflect"
"testing"
"time"
"github.com/aws/aws-sdk-go/aws/awsutil"
)
func ExampleCopy() {
type Foo struct {
A int
B []*string
}
// Create the initial value
str1 := "hello"
str2 := "bye bye"
f1 := &Foo{A: 1, B: []*string{&str1, &str2}}
// Do the copy
var f2 Foo
awsutil.Copy(&f2, f1)
// Print the result
fmt.Println(awsutil.Prettify(f2))
// Output:
// {
// A: 1,
// B: ["hello","bye bye"]
// }
}
func TestCopy1(t *testing.T) {
type Bar struct {
a *int
B *int
c int
D int
}
type Foo struct {
A int
B []*string
C map[string]*int
D *time.Time
E *Bar
}
// Create the initial value
str1 := "hello"
str2 := "bye bye"
int1 := 1
int2 := 2
intPtr1 := 1
intPtr2 := 2
now := time.Now()
f1 := &Foo{
A: 1,
B: []*string{&str1, &str2},
C: map[string]*int{
"A": &int1,
"B": &int2,
},
D: &now,
E: &Bar{
&intPtr1,
&intPtr2,
2,
3,
},
}
// Do the copy
var f2 Foo
awsutil.Copy(&f2, f1)
// Values are equal
if v1, v2 := f2.A, f1.A; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := f2.B, f1.B; !reflect.DeepEqual(v1, v2) {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := f2.C, f1.C; !reflect.DeepEqual(v1, v2) {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := f2.D, f1.D; !v1.Equal(*v2) {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := f2.E.B, f1.E.B; !reflect.DeepEqual(v1, v2) {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := f2.E.D, f1.E.D; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
// But pointers are not!
str3 := "nothello"
int3 := 57
f2.A = 100
*f2.B[0] = str3
*f2.C["B"] = int3
*f2.D = time.Now()
f2.E.a = &int3
*f2.E.B = int3
f2.E.c = 5
f2.E.D = 5
if v1, v2 := f2.A, f1.A; v1 == v2 {
t.Errorf("expected values to be not equivalent, but received %v", v1)
}
if v1, v2 := f2.B, f1.B; reflect.DeepEqual(v1, v2) {
t.Errorf("expected values to be not equivalent, but received %v", v1)
}
if v1, v2 := f2.C, f1.C; reflect.DeepEqual(v1, v2) {
t.Errorf("expected values to be not equivalent, but received %v", v1)
}
if v1, v2 := f2.D, f1.D; v1 == v2 {
t.Errorf("expected values to be not equivalent, but received %v", v1)
}
if v1, v2 := f2.E.a, f1.E.a; v1 == v2 {
t.Errorf("expected values to be not equivalent, but received %v", v1)
}
if v1, v2 := f2.E.B, f1.E.B; v1 == v2 {
t.Errorf("expected values to be not equivalent, but received %v", v1)
}
if v1, v2 := f2.E.c, f1.E.c; v1 == v2 {
t.Errorf("expected values to be not equivalent, but received %v", v1)
}
if v1, v2 := f2.E.D, f1.E.D; v1 == v2 {
t.Errorf("expected values to be not equivalent, but received %v", v1)
}
}
func TestCopyNestedWithUnexported(t *testing.T) {
type Bar struct {
a int
B int
}
type Foo struct {
A string
B Bar
}
f1 := &Foo{A: "string", B: Bar{a: 1, B: 2}}
var f2 Foo
awsutil.Copy(&f2, f1)
// Values match
if v1, v2 := f2.A, f1.A; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := f2.B, f1.B; v1 == v2 {
t.Errorf("expected values to be not equivalent, but received %v", v1)
}
if v1, v2 := f2.B.a, f1.B.a; v1 == v2 {
t.Errorf("expected values to be not equivalent, but received %v", v1)
}
if v1, v2 := f2.B.B, f2.B.B; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
}
func TestCopyIgnoreNilMembers(t *testing.T) {
type Foo struct {
A *string
B []string
C map[string]string
}
f := &Foo{}
if v1 := f.A; v1 != nil {
t.Errorf("expected nil, but received %v", v1)
}
if v1 := f.B; v1 != nil {
t.Errorf("expected nil, but received %v", v1)
}
if v1 := f.C; v1 != nil {
t.Errorf("expected nil, but received %v", v1)
}
var f2 Foo
awsutil.Copy(&f2, f)
if v1 := f2.A; v1 != nil {
t.Errorf("expected nil, but received %v", v1)
}
if v1 := f2.B; v1 != nil {
t.Errorf("expected nil, but received %v", v1)
}
if v1 := f2.C; v1 != nil {
t.Errorf("expected nil, but received %v", v1)
}
fcopy := awsutil.CopyOf(f)
f3 := fcopy.(*Foo)
if v1 := f3.A; v1 != nil {
t.Errorf("expected nil, but received %v", v1)
}
if v1 := f3.B; v1 != nil {
t.Errorf("expected nil, but received %v", v1)
}
if v1 := f3.C; v1 != nil {
t.Errorf("expected nil, but received %v", v1)
}
}
func TestCopyPrimitive(t *testing.T) {
str := "hello"
var s string
awsutil.Copy(&s, &str)
if v1, v2 := "hello", s; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
}
func TestCopyNil(t *testing.T) {
var s string
awsutil.Copy(&s, nil)
if v1, v2 := "", s; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
}
func TestCopyReader(t *testing.T) {
var buf io.Reader = bytes.NewReader([]byte("hello world"))
var r io.Reader
awsutil.Copy(&r, buf)
b, err := ioutil.ReadAll(r)
if err != nil {
t.Errorf("expected no error, but received %v", err)
}
if v1, v2 := []byte("hello world"), b; !bytes.Equal(v1, v2) {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
// empty bytes because this is not a deep copy
b, err = ioutil.ReadAll(buf)
if err != nil {
t.Errorf("expected no error, but received %v", err)
}
if v1, v2 := []byte(""), b; !bytes.Equal(v1, v2) {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
}
func TestCopyDifferentStructs(t *testing.T) {
type SrcFoo struct {
A int
B []*string
C map[string]*int
SrcUnique string
SameNameDiffType int
unexportedPtr *int
ExportedPtr *int
}
type DstFoo struct {
A int
B []*string
C map[string]*int
DstUnique int
SameNameDiffType string
unexportedPtr *int
ExportedPtr *int
}
// Create the initial value
str1 := "hello"
str2 := "bye bye"
int1 := 1
int2 := 2
f1 := &SrcFoo{
A: 1,
B: []*string{&str1, &str2},
C: map[string]*int{
"A": &int1,
"B": &int2,
},
SrcUnique: "unique",
SameNameDiffType: 1,
unexportedPtr: &int1,
ExportedPtr: &int2,
}
// Do the copy
var f2 DstFoo
awsutil.Copy(&f2, f1)
// Values are equal
if v1, v2 := f2.A, f1.A; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := f2.B, f1.B; !reflect.DeepEqual(v1, v2) {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := f2.C, f1.C; !reflect.DeepEqual(v1, v2) {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := "unique", f1.SrcUnique; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := 1, f1.SameNameDiffType; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := 0, f2.DstUnique; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := "", f2.SameNameDiffType; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := int1, *f1.unexportedPtr; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1 := f2.unexportedPtr; v1 != nil {
t.Errorf("expected nil, but received %v", v1)
}
if v1, v2 := int2, *f1.ExportedPtr; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
if v1, v2 := int2, *f2.ExportedPtr; v1 != v2 {
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
}
}
func ExampleCopyOf() {
type Foo struct {
A int
B []*string
}
// Create the initial value
str1 := "hello"
str2 := "bye bye"
f1 := &Foo{A: 1, B: []*string{&str1, &str2}}
// Do the copy
v := awsutil.CopyOf(f1)
var f2 *Foo = v.(*Foo)
// Print the result
fmt.Println(awsutil.Prettify(f2))
// Output:
// {
// A: 1,
// B: ["hello","bye bye"]
// }
}

View File

@@ -1,27 +0,0 @@
package awsutil
import (
"reflect"
)
// DeepEqual returns if the two values are deeply equal like reflect.DeepEqual.
// In addition to this, this method will also dereference the input values if
// possible so the DeepEqual performed will not fail if one parameter is a
// pointer and the other is not.
//
// DeepEqual will not perform indirection of nested values of the input parameters.
func DeepEqual(a, b interface{}) bool {
ra := reflect.Indirect(reflect.ValueOf(a))
rb := reflect.Indirect(reflect.ValueOf(b))
if raValid, rbValid := ra.IsValid(), rb.IsValid(); !raValid && !rbValid {
// If the elements are both nil, and of the same type they are equal
// If they are of different types they are not equal
return reflect.TypeOf(a) == reflect.TypeOf(b)
} else if raValid != rbValid {
// Both values must be valid to be equal
return false
}
return reflect.DeepEqual(ra.Interface(), rb.Interface())
}

View File

@@ -1,30 +0,0 @@
package awsutil_test
import (
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awsutil"
)
func TestDeepEqual(t *testing.T) {
cases := []struct {
a, b interface{}
equal bool
}{
{"a", "a", true},
{"a", "b", false},
{"a", aws.String(""), false},
{"a", nil, false},
{"a", aws.String("a"), true},
{(*bool)(nil), (*bool)(nil), true},
{(*bool)(nil), (*string)(nil), false},
{nil, nil, true},
}
for i, c := range cases {
if awsutil.DeepEqual(c.a, c.b) != c.equal {
t.Errorf("%d, a:%v b:%v, %t", i, c.a, c.b, c.equal)
}
}
}

View File

@@ -1,222 +0,0 @@
package awsutil
import (
"reflect"
"regexp"
"strconv"
"strings"
"github.com/jmespath/go-jmespath"
)
var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`)
// rValuesAtPath returns a slice of values found in value v. The values
// in v are explored recursively so all nested values are collected.
func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTerm bool) []reflect.Value {
pathparts := strings.Split(path, "||")
if len(pathparts) > 1 {
for _, pathpart := range pathparts {
vals := rValuesAtPath(v, pathpart, createPath, caseSensitive, nilTerm)
if len(vals) > 0 {
return vals
}
}
return nil
}
values := []reflect.Value{reflect.Indirect(reflect.ValueOf(v))}
components := strings.Split(path, ".")
for len(values) > 0 && len(components) > 0 {
var index *int64
var indexStar bool
c := strings.TrimSpace(components[0])
if c == "" { // no actual component, illegal syntax
return nil
} else if caseSensitive && c != "*" && strings.ToLower(c[0:1]) == c[0:1] {
// TODO normalize case for user
return nil // don't support unexported fields
}
// parse this component
if m := indexRe.FindStringSubmatch(c); m != nil {
c = m[1]
if m[2] == "" {
index = nil
indexStar = true
} else {
i, _ := strconv.ParseInt(m[2], 10, 32)
index = &i
indexStar = false
}
}
nextvals := []reflect.Value{}
for _, value := range values {
// pull component name out of struct member
if value.Kind() != reflect.Struct {
continue
}
if c == "*" { // pull all members
for i := 0; i < value.NumField(); i++ {
if f := reflect.Indirect(value.Field(i)); f.IsValid() {
nextvals = append(nextvals, f)
}
}
continue
}
value = value.FieldByNameFunc(func(name string) bool {
if c == name {
return true
} else if !caseSensitive && strings.ToLower(name) == strings.ToLower(c) {
return true
}
return false
})
if nilTerm && value.Kind() == reflect.Ptr && len(components[1:]) == 0 {
if !value.IsNil() {
value.Set(reflect.Zero(value.Type()))
}
return []reflect.Value{value}
}
if createPath && value.Kind() == reflect.Ptr && value.IsNil() {
// TODO if the value is the terminus it should not be created
// if the value to be set to its position is nil.
value.Set(reflect.New(value.Type().Elem()))
value = value.Elem()
} else {
value = reflect.Indirect(value)
}
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
if !createPath && value.IsNil() {
value = reflect.ValueOf(nil)
}
}
if value.IsValid() {
nextvals = append(nextvals, value)
}
}
values = nextvals
if indexStar || index != nil {
nextvals = []reflect.Value{}
for _, valItem := range values {
value := reflect.Indirect(valItem)
if value.Kind() != reflect.Slice {
continue
}
if indexStar { // grab all indices
for i := 0; i < value.Len(); i++ {
idx := reflect.Indirect(value.Index(i))
if idx.IsValid() {
nextvals = append(nextvals, idx)
}
}
continue
}
// pull out index
i := int(*index)
if i >= value.Len() { // check out of bounds
if createPath {
// TODO resize slice
} else {
continue
}
} else if i < 0 { // support negative indexing
i = value.Len() + i
}
value = reflect.Indirect(value.Index(i))
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
if !createPath && value.IsNil() {
value = reflect.ValueOf(nil)
}
}
if value.IsValid() {
nextvals = append(nextvals, value)
}
}
values = nextvals
}
components = components[1:]
}
return values
}
// ValuesAtPath returns a list of values at the case insensitive lexical
// path inside of a structure.
func ValuesAtPath(i interface{}, path string) ([]interface{}, error) {
result, err := jmespath.Search(path, i)
if err != nil {
return nil, err
}
v := reflect.ValueOf(result)
if !v.IsValid() || (v.Kind() == reflect.Ptr && v.IsNil()) {
return nil, nil
}
if s, ok := result.([]interface{}); ok {
return s, err
}
if v.Kind() == reflect.Map && v.Len() == 0 {
return nil, nil
}
if v.Kind() == reflect.Slice {
out := make([]interface{}, v.Len())
for i := 0; i < v.Len(); i++ {
out[i] = v.Index(i).Interface()
}
return out, nil
}
return []interface{}{result}, nil
}
// SetValueAtPath sets a value at the case insensitive lexical path inside
// of a structure.
func SetValueAtPath(i interface{}, path string, v interface{}) {
if rvals := rValuesAtPath(i, path, true, false, v == nil); rvals != nil {
for _, rval := range rvals {
if rval.Kind() == reflect.Ptr && rval.IsNil() {
continue
}
setValue(rval, v)
}
}
}
func setValue(dstVal reflect.Value, src interface{}) {
if dstVal.Kind() == reflect.Ptr {
dstVal = reflect.Indirect(dstVal)
}
srcVal := reflect.ValueOf(src)
if !srcVal.IsValid() { // src is literal nil
if dstVal.CanAddr() {
// Convert to pointer so that pointer's value can be nil'ed
// dstVal = dstVal.Addr()
}
dstVal.Set(reflect.Zero(dstVal.Type()))
} else if srcVal.Kind() == reflect.Ptr {
if srcVal.IsNil() {
srcVal = reflect.Zero(dstVal.Type())
} else {
srcVal = reflect.ValueOf(src).Elem()
}
dstVal.Set(srcVal)
} else {
dstVal.Set(srcVal)
}
}

View File

@@ -1,182 +0,0 @@
package awsutil_test
import (
"strings"
"testing"
"github.com/aws/aws-sdk-go/aws/awsutil"
)
type Struct struct {
A []Struct
z []Struct
B *Struct
D *Struct
C string
E map[string]string
}
var data = Struct{
A: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}},
z: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}},
B: &Struct{B: &Struct{C: "terminal"}, D: &Struct{C: "terminal2"}},
C: "initial",
}
var data2 = Struct{A: []Struct{
{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}},
{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}},
}}
func TestValueAtPathSuccess(t *testing.T) {
var testCases = []struct {
expect []interface{}
data interface{}
path string
}{
{[]interface{}{"initial"}, data, "C"},
{[]interface{}{"value1"}, data, "A[0].C"},
{[]interface{}{"value2"}, data, "A[1].C"},
{[]interface{}{"value3"}, data, "A[2].C"},
{[]interface{}{"value3"}, data, "a[2].c"},
{[]interface{}{"value3"}, data, "A[-1].C"},
{[]interface{}{"value1", "value2", "value3"}, data, "A[].C"},
{[]interface{}{"terminal"}, data, "B . B . C"},
{[]interface{}{"initial"}, data, "A.D.X || C"},
{[]interface{}{"initial"}, data, "A[0].B || C"},
{[]interface{}{
Struct{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}},
Struct{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}},
}, data2, "A"},
}
for i, c := range testCases {
v, err := awsutil.ValuesAtPath(c.data, c.path)
if err != nil {
t.Errorf("case %v, expected no error, %v", i, c.path)
}
if e, a := c.expect, v; !awsutil.DeepEqual(e, a) {
t.Errorf("case %v, %v", i, c.path)
}
}
}
func TestValueAtPathFailure(t *testing.T) {
var testCases = []struct {
expect []interface{}
errContains string
data interface{}
path string
}{
{nil, "", data, "C.x"},
{nil, "SyntaxError: Invalid token: tDot", data, ".x"},
{nil, "", data, "X.Y.Z"},
{nil, "", data, "A[100].C"},
{nil, "", data, "A[3].C"},
{nil, "", data, "B.B.C.Z"},
{nil, "", data, "z[-1].C"},
{nil, "", nil, "A.B.C"},
{[]interface{}{}, "", Struct{}, "A"},
{nil, "", data, "A[0].B.C"},
{nil, "", data, "D"},
}
for i, c := range testCases {
v, err := awsutil.ValuesAtPath(c.data, c.path)
if c.errContains != "" {
if !strings.Contains(err.Error(), c.errContains) {
t.Errorf("case %v, expected error, %v", i, c.path)
}
continue
} else {
if err != nil {
t.Errorf("case %v, expected no error, %v", i, c.path)
}
}
if e, a := c.expect, v; !awsutil.DeepEqual(e, a) {
t.Errorf("case %v, %v", i, c.path)
}
}
}
func TestSetValueAtPathSuccess(t *testing.T) {
var s Struct
awsutil.SetValueAtPath(&s, "C", "test1")
awsutil.SetValueAtPath(&s, "B.B.C", "test2")
awsutil.SetValueAtPath(&s, "B.D.C", "test3")
if e, a := "test1", s.C; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
if e, a := "test2", s.B.B.C; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
if e, a := "test3", s.B.D.C; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
awsutil.SetValueAtPath(&s, "B.*.C", "test0")
if e, a := "test0", s.B.B.C; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
if e, a := "test0", s.B.D.C; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
var s2 Struct
awsutil.SetValueAtPath(&s2, "b.b.c", "test0")
if e, a := "test0", s2.B.B.C; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
awsutil.SetValueAtPath(&s2, "A", []Struct{{}})
if e, a := []Struct{{}}, s2.A; !awsutil.DeepEqual(e, a) {
t.Errorf("expected %v, but received %v", e, a)
}
str := "foo"
s3 := Struct{}
awsutil.SetValueAtPath(&s3, "b.b.c", str)
if e, a := "foo", s3.B.B.C; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
s3 = Struct{B: &Struct{B: &Struct{C: str}}}
awsutil.SetValueAtPath(&s3, "b.b.c", nil)
if e, a := "", s3.B.B.C; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
s3 = Struct{}
awsutil.SetValueAtPath(&s3, "b.b.c", nil)
if e, a := "", s3.B.B.C; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
s3 = Struct{}
awsutil.SetValueAtPath(&s3, "b.b.c", &str)
if e, a := "foo", s3.B.B.C; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
var s4 struct{ Name *string }
awsutil.SetValueAtPath(&s4, "Name", str)
if e, a := str, *s4.Name; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
s4 = struct{ Name *string }{}
awsutil.SetValueAtPath(&s4, "Name", nil)
if e, a := (*string)(nil), s4.Name; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
s4 = struct{ Name *string }{Name: &str}
awsutil.SetValueAtPath(&s4, "Name", nil)
if e, a := (*string)(nil), s4.Name; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
s4 = struct{ Name *string }{}
awsutil.SetValueAtPath(&s4, "Name", &str)
if e, a := str, *s4.Name; e != a {
t.Errorf("expected %v, but received %v", e, a)
}
}

View File

@@ -1,113 +0,0 @@
package awsutil
import (
"bytes"
"fmt"
"io"
"reflect"
"strings"
)
// Prettify returns the string representation of a value.
func Prettify(i interface{}) string {
var buf bytes.Buffer
prettify(reflect.ValueOf(i), 0, &buf)
return buf.String()
}
// prettify will recursively walk value v to build a textual
// representation of the value.
func prettify(v reflect.Value, indent int, buf *bytes.Buffer) {
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
switch v.Kind() {
case reflect.Struct:
strtype := v.Type().String()
if strtype == "time.Time" {
fmt.Fprintf(buf, "%s", v.Interface())
break
} else if strings.HasPrefix(strtype, "io.") {
buf.WriteString("<buffer>")
break
}
buf.WriteString("{\n")
names := []string{}
for i := 0; i < v.Type().NumField(); i++ {
name := v.Type().Field(i).Name
f := v.Field(i)
if name[0:1] == strings.ToLower(name[0:1]) {
continue // ignore unexported fields
}
if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice || f.Kind() == reflect.Map) && f.IsNil() {
continue // ignore unset fields
}
names = append(names, name)
}
for i, n := range names {
val := v.FieldByName(n)
buf.WriteString(strings.Repeat(" ", indent+2))
buf.WriteString(n + ": ")
prettify(val, indent+2, buf)
if i < len(names)-1 {
buf.WriteString(",\n")
}
}
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
case reflect.Slice:
strtype := v.Type().String()
if strtype == "[]uint8" {
fmt.Fprintf(buf, "<binary> len %d", v.Len())
break
}
nl, id, id2 := "", "", ""
if v.Len() > 3 {
nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
}
buf.WriteString("[" + nl)
for i := 0; i < v.Len(); i++ {
buf.WriteString(id2)
prettify(v.Index(i), indent+2, buf)
if i < v.Len()-1 {
buf.WriteString("," + nl)
}
}
buf.WriteString(nl + id + "]")
case reflect.Map:
buf.WriteString("{\n")
for i, k := range v.MapKeys() {
buf.WriteString(strings.Repeat(" ", indent+2))
buf.WriteString(k.String() + ": ")
prettify(v.MapIndex(k), indent+2, buf)
if i < v.Len()-1 {
buf.WriteString(",\n")
}
}
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
default:
if !v.IsValid() {
fmt.Fprint(buf, "<invalid value>")
return
}
format := "%v"
switch v.Interface().(type) {
case string:
format = "%q"
case io.ReadSeeker, io.Reader:
format = "buffer(%p)"
}
fmt.Fprintf(buf, format, v.Interface())
}
}

View File

@@ -1,88 +0,0 @@
package awsutil
import (
"bytes"
"fmt"
"reflect"
"strings"
)
// StringValue returns the string representation of a value.
func StringValue(i interface{}) string {
var buf bytes.Buffer
stringValue(reflect.ValueOf(i), 0, &buf)
return buf.String()
}
func stringValue(v reflect.Value, indent int, buf *bytes.Buffer) {
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
switch v.Kind() {
case reflect.Struct:
buf.WriteString("{\n")
for i := 0; i < v.Type().NumField(); i++ {
ft := v.Type().Field(i)
fv := v.Field(i)
if ft.Name[0:1] == strings.ToLower(ft.Name[0:1]) {
continue // ignore unexported fields
}
if (fv.Kind() == reflect.Ptr || fv.Kind() == reflect.Slice) && fv.IsNil() {
continue // ignore unset fields
}
buf.WriteString(strings.Repeat(" ", indent+2))
buf.WriteString(ft.Name + ": ")
if tag := ft.Tag.Get("sensitive"); tag == "true" {
buf.WriteString("<sensitive>")
} else {
stringValue(fv, indent+2, buf)
}
buf.WriteString(",\n")
}
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
case reflect.Slice:
nl, id, id2 := "", "", ""
if v.Len() > 3 {
nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
}
buf.WriteString("[" + nl)
for i := 0; i < v.Len(); i++ {
buf.WriteString(id2)
stringValue(v.Index(i), indent+2, buf)
if i < v.Len()-1 {
buf.WriteString("," + nl)
}
}
buf.WriteString(nl + id + "]")
case reflect.Map:
buf.WriteString("{\n")
for i, k := range v.MapKeys() {
buf.WriteString(strings.Repeat(" ", indent+2))
buf.WriteString(k.String() + ": ")
stringValue(v.MapIndex(k), indent+2, buf)
if i < v.Len()-1 {
buf.WriteString(",\n")
}
}
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
default:
format := "%v"
switch v.Interface().(type) {
case string:
format = "%q"
}
fmt.Fprintf(buf, format, v.Interface())
}
}

View File

@@ -1,51 +0,0 @@
// +build go1.7
package awsutil
import (
"testing"
"github.com/aws/aws-sdk-go/aws"
)
type testStruct struct {
Field1 string
Field2 *string
Field3 []byte `sensitive:"true"`
Value []*string
}
func TestStringValue(t *testing.T) {
cases := map[string]struct {
Value interface{}
Expect string
}{
"general": {
Value: testStruct{
Field1: "abc123",
Field2: aws.String("abc123"),
Field3: []byte("don't show me"),
Value: []*string{
aws.String("first"),
aws.String("second"),
},
},
Expect: `{
Field1: "abc123",
Field2: "abc123",
Field3: <sensitive>,
Value: ["first","second"],
}`,
},
}
for d, c := range cases {
t.Run(d, func(t *testing.T) {
actual := StringValue(c.Value)
if e, a := c.Expect, actual; e != a {
t.Errorf("expect:\n%v\nactual:\n%v\n", e, a)
}
})
}
}

View File

@@ -1,96 +0,0 @@
package client
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/request"
)
// A Config provides configuration to a service client instance.
type Config struct {
Config *aws.Config
Handlers request.Handlers
Endpoint string
SigningRegion string
SigningName string
// States that the signing name did not come from a modeled source but
// was derived based on other data. Used by service client constructors
// to determine if the signin name can be overridden based on metadata the
// service has.
SigningNameDerived bool
}
// ConfigProvider provides a generic way for a service client to receive
// the ClientConfig without circular dependencies.
type ConfigProvider interface {
ClientConfig(serviceName string, cfgs ...*aws.Config) Config
}
// ConfigNoResolveEndpointProvider same as ConfigProvider except it will not
// resolve the endpoint automatically. The service client's endpoint must be
// provided via the aws.Config.Endpoint field.
type ConfigNoResolveEndpointProvider interface {
ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) Config
}
// A Client implements the base client request and response handling
// used by all service clients.
type Client struct {
request.Retryer
metadata.ClientInfo
Config aws.Config
Handlers request.Handlers
}
// New will return a pointer to a new initialized service client.
func New(cfg aws.Config, info metadata.ClientInfo, handlers request.Handlers, options ...func(*Client)) *Client {
svc := &Client{
Config: cfg,
ClientInfo: info,
Handlers: handlers.Copy(),
}
switch retryer, ok := cfg.Retryer.(request.Retryer); {
case ok:
svc.Retryer = retryer
case cfg.Retryer != nil && cfg.Logger != nil:
s := fmt.Sprintf("WARNING: %T does not implement request.Retryer; using DefaultRetryer instead", cfg.Retryer)
cfg.Logger.Log(s)
fallthrough
default:
maxRetries := aws.IntValue(cfg.MaxRetries)
if cfg.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries {
maxRetries = 3
}
svc.Retryer = DefaultRetryer{NumMaxRetries: maxRetries}
}
svc.AddDebugHandlers()
for _, option := range options {
option(svc)
}
return svc
}
// NewRequest returns a new Request pointer for the service API
// operation and parameters.
func (c *Client) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request {
return request.New(c.Config, c.ClientInfo, c.Handlers, c.Retryer, operation, params, data)
}
// AddDebugHandlers injects debug logging handlers into the service to log request
// debug information.
func (c *Client) AddDebugHandlers() {
if !c.Config.LogLevel.AtLeast(aws.LogDebug) {
return
}
c.Handlers.Send.PushFrontNamed(LogHTTPRequestHandler)
c.Handlers.Send.PushBackNamed(LogHTTPResponseHandler)
}

Some files were not shown because too many files have changed in this diff Show More