Merge pull request #3 from Aetheus/master

Add Delete function
diff --git a/README.md b/README.md
index dbe4d50..0005924 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,39 @@
 # gojsonpointer
 An implementation of JSON Pointer - Go language
 
+## Usage
+	jsonText := `{
+		"name": "Bobby B",
+		"occupation": {
+			"title" : "King",
+			"years" : 15,
+			"heir" : "Joffrey B"			
+		}
+	}`
+	
+    var jsonDocument map[string]interface{}
+    json.Unmarshal([]byte(jsonText), &jsonDocument)
+    
+    //create a JSON pointer
+    pointerString := "/occupation/title"
+    pointer, _ := NewJsonPointer(pointerString)
+    
+    //SET a new value for the "title" in the document     
+    pointer.Set(jsonDocument, "Supreme Leader of Westeros")
+    
+    //GET the new "title" from the document
+    title, _, _ := pointer.Get(jsonDocument)
+    fmt.Println(title) //outputs "Supreme Leader of Westeros"
+    
+    //DELETE the "heir" from the document
+    deletePointer := NewJsonPointer("/occupation/heir")
+    deletePointer.Delete(jsonDocument)
+    
+    b, _ := json.Marshal(jsonDocument)
+    fmt.Println(string(b))
+    //outputs `{"name":"Bobby B","occupation":{"title":"Supreme Leader of Westeros","years":15}}`
+
+
 ## References
 http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
 
diff --git a/pointer.go b/pointer.go
index 06f1918..7faf5d7 100644
--- a/pointer.go
+++ b/pointer.go
@@ -90,6 +90,13 @@
 
 }
 
+// Uses the pointer to delete a value from a JSON document
+func (p *JsonPointer) Delete(document interface{}) (interface{}, error) {
+	is := &implStruct{mode: "DEL", inDocument: document}
+	p.implementation(is)
+	return document, is.outError
+}
+
 // Both Get and Set functions use the same implementation to avoid code duplication
 func (p *JsonPointer) implementation(i *implStruct) {
 
@@ -106,9 +113,14 @@
 
 	node := i.inDocument
 
+	previousNodes := make([]interface{}, len(p.referenceTokens))
+	previousTokens := make([]string, len(p.referenceTokens))
+
 	for ti, token := range p.referenceTokens {
 
 		isLastToken := ti == len(p.referenceTokens)-1
+		previousNodes[ti] = node
+		previousTokens[ti] = token
 
 		switch v := node.(type) {
 
@@ -118,7 +130,11 @@
 				node = v[decodedToken]
 				if isLastToken && i.mode == "SET" {
 					v[decodedToken] = i.setInValue
+				} else if isLastToken && i.mode =="DEL" {
+					delete(v,decodedToken)
 				}
+			} else if (isLastToken && i.mode == "SET") {
+				v[decodedToken] = i.setInValue
 			} else {
 				i.outError = fmt.Errorf("Object has no key '%s'", decodedToken)
 				i.getOutKind = reflect.Map
@@ -144,6 +160,11 @@
 			node = v[tokenIndex]
 			if isLastToken && i.mode == "SET" {
 				v[tokenIndex] = i.setInValue
+			}  else if isLastToken && i.mode =="DEL" {
+				v[tokenIndex] = v[len(v)-1]
+				v[len(v)-1] = nil
+				v = v[:len(v)-1]
+				previousNodes[ti-1].(map[string]interface{})[previousTokens[ti-1]] = v
 			}
 
 		default:
diff --git a/pointer_test.go b/pointer_test.go
index 9e66d51..612f76e 100644
--- a/pointer_test.go
+++ b/pointer_test.go
@@ -245,3 +245,103 @@
 	}
 
 }
+
+func TestSetEmptyNode(t *testing.T) {
+
+	jsonText := `{}`
+
+	var jsonDocument interface{}
+	json.Unmarshal([]byte(jsonText), &jsonDocument)
+
+	in := "/a"
+
+	p, err := NewJsonPointer(in)
+	if err != nil {
+		t.Errorf("NewJsonPointer(%v) error %v", in, err.Error())
+	}
+
+	_, err = p.Set(jsonDocument, 999)
+	if err != nil {
+		t.Errorf("Set(%v) error %v", in, err.Error())
+	}
+
+	firstNode := jsonDocument.(map[string]interface{})
+	target := firstNode["a"].(int)
+	if target != 999 {
+		t.Errorf("Set(%s) failed", in)
+	}
+}
+
+func TestDelObject(t *testing.T) {
+	jsonText := `{
+		"a":["apple sauce", "ketchup", "soy sauce"],
+		"d": {
+			"z" : {
+				"v" : {
+					"name" : "donald mcbobble",
+					"occupation" : "corporate overlord"
+				}
+			}
+		}
+	}`
+
+	var jsonDocument map[string]interface{}
+	json.Unmarshal([]byte(jsonText), &jsonDocument)
+
+	//Deleting an object key
+	in := "/d/z/v/occupation"
+	p, err := NewJsonPointer(in)
+	if err != nil {
+		t.Errorf("NewJsonPointer(%v) error %v", in, err.Error())
+	}
+
+	_,  err = p.Delete(jsonDocument)
+	if err != nil {
+		t.Errorf("Delete(%v) error %v", in, err.Error())
+	}
+
+	var d map[string]interface{} = jsonDocument["d"].(map[string]interface{})
+	var z map[string]interface{} = d["z"].(map[string]interface{})
+	var v map[string]interface{} = z["v"].(map[string]interface{})
+
+	if _, present := v["occupation"]; present {
+		t.Errorf("Delete (%s) failed: key is still present in the map", in)
+	}
+}
+
+
+func TestDelArray(t *testing.T) {
+	jsonText := `{
+		"a":["applesauce", "ketchup", "soysauce", "oliveoil"],
+		"d": {
+			"z" : {
+				"v" : {
+					"name" : "donald mcbobble",
+					"occupation" : "corporate overlord",
+					"responsibilities" : ["managing", "hiring"]
+				}
+			}
+		}
+	}`
+
+	var jsonDocument map[string]interface{}
+	json.Unmarshal([]byte(jsonText), &jsonDocument)
+
+	//Deleting an array member
+	in := "/a/2"
+	p, err := NewJsonPointer(in)
+	if err != nil {
+		t.Errorf("NewJsonPointer(%v) error %v", in, err.Error())
+	}
+
+	_,  err = p.Delete(jsonDocument)
+	if err != nil {
+		t.Errorf("Delete(%v) error %v", in, err.Error())
+	}
+
+	a := jsonDocument["a"].([]interface{})
+	if len(a) != 3 || a[2] == "soysauce" {
+		t.Errorf("Delete(%v) error (%s)", in, a)
+	}
+
+}