Add "nocopy" json tag to return unsafe string reference

When large amounts of data are unmarshaled for immediate non long live use than
copying of strings from original buffer can be avoided and instead a
reference to the original buffer returned in the field value.

Note, if the value requires unescaping, than it will be processed as
normally done with copying.

Signed-off-by: Kirill Korotaev <kirillx@gmail.com>
diff --git a/Makefile b/Makefile
index f1c386b..92f3c43 100644
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,8 @@
 		./tests/type_declaration.go \
 		./tests/members_escaped.go \
 		./tests/members_unescaped.go \
-		./tests/intern.go
+		./tests/intern.go \
+		./tests/nocopy.go \
 
 	bin/easyjson -all ./tests/data.go
 	bin/easyjson -all ./tests/nothing.go
@@ -44,6 +45,7 @@
 	bin/easyjson ./tests/members_escaped.go
 	bin/easyjson -disable_members_unescape ./tests/members_unescaped.go
 	bin/easyjson ./tests/intern.go
+	bin/easyjson ./tests/nocopy.go
 
 test: generate
 	go test \
diff --git a/README.md b/README.md
index 91494c9..67ee8fc 100644
--- a/README.md
+++ b/README.md
@@ -80,6 +80,18 @@
 
 * `-build_tags` will add the specified build tags to generated Go sources.
 
+## Structure json tag options
+
+Besides standart json tag options like 'omitempty' the following are supported:
+
+* 'nocopy' - disables allocation and copying of string values, making them
+  refer to original json buffer memory. This works great for short lived
+  objects which are not hold in memory after decoding and immediate usage.
+  Note if string requires unescaping it will be processed as normally.
+* 'intern' - string "interning" (deduplication) to save memory when the very
+  same string dictionory values are often met all over the structure.
+  See below for more details.
+
 ## Generated Marshaler/Unmarshaler Funcs
 
 For Go struct types, easyjson generates the funcs `MarshalEasyJSON` /
diff --git a/gen/decoder.go b/gen/decoder.go
index b2b6bdc..4fddbff 100644
--- a/gen/decoder.go
+++ b/gen/decoder.go
@@ -121,6 +121,9 @@
 		if tags.intern && t.Kind() == reflect.String {
 			dec = "in.StringIntern()"
 		}
+		if tags.noCopy && t.Kind() == reflect.String {
+			dec = "in.UnsafeString()"
+		}
 		fmt.Fprintln(g.out, ws+out+" = "+g.getType(t)+"("+dec+")")
 		return nil
 	}
diff --git a/gen/encoder.go b/gen/encoder.go
index f9650e7..893d9e8 100644
--- a/gen/encoder.go
+++ b/gen/encoder.go
@@ -59,6 +59,7 @@
 	asString    bool
 	required    bool
 	intern      bool
+	noCopy      bool
 }
 
 // parseFieldTags parses the json field tag into a structure.
@@ -81,6 +82,8 @@
 			ret.required = true
 		case s == "intern":
 			ret.intern = true
+		case s == "nocopy":
+			ret.noCopy = true
 		}
 	}
 
diff --git a/tests/nocopy.go b/tests/nocopy.go
new file mode 100644
index 0000000..3d3c7f3
--- /dev/null
+++ b/tests/nocopy.go
@@ -0,0 +1,7 @@
+package tests
+
+//easyjson:json
+type NocopyStruct struct {
+	A string `json:"a"`
+	B string `json:"b,nocopy"`
+}
diff --git a/tests/nocopy_test.go b/tests/nocopy_test.go
new file mode 100644
index 0000000..fdd0651
--- /dev/null
+++ b/tests/nocopy_test.go
@@ -0,0 +1,41 @@
+package tests
+
+import (
+	"reflect"
+	"testing"
+	"unsafe"
+
+	"github.com/mailru/easyjson"
+)
+
+// verifies if string pointer belongs to the given buffer or outside of it
+func strBelongsTo(s string, buf []byte) bool {
+	sPtr := (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
+	bufPtr := (*reflect.SliceHeader)(unsafe.Pointer(&buf)).Data
+
+	if bufPtr <= sPtr && sPtr < bufPtr+uintptr(len(buf)) {
+		return true
+	}
+	return false
+}
+
+func TestNocopy(t *testing.T) {
+	data := []byte(`{"a": "valueA", "b": "valueB"}`)
+	exp := NocopyStruct{
+		A: "valueA",
+		B: "valueB",
+	}
+	res := NocopyStruct{}
+
+	easyjson.Unmarshal(data, &res)
+	if !reflect.DeepEqual(exp, res) {
+		t.Errorf("TestNocopy(): got=%+v, exp=%+v", res, exp)
+	}
+
+	if strBelongsTo(res.A, data) {
+		t.Error("TestNocopy(): field A was not copied and refers to buffer")
+	}
+	if !strBelongsTo(res.B, data) {
+		t.Error("TestNocopy(): field B was copied rather than refer to bufferr")
+	}
+}