Skip to content

Commit

Permalink
Reduced internal memory footprint and allocation count. This change
Browse files Browse the repository at this point in the history
leads to an API-Change: ExecuteRW is being removed; instead it is
replaced by a more general ExecuteWriter() which takes a Context and
an io.Writer.
  • Loading branch information
flosch committed Jul 18, 2014
1 parent e700c63 commit a1fab22
Show file tree
Hide file tree
Showing 18 changed files with 138 additions and 90 deletions.
12 changes: 5 additions & 7 deletions nodes.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
package pongo2

import (
"strings"
"bytes"
)

// The root document
type nodeDocument struct {
Nodes []INode
}

func (doc *nodeDocument) Execute(ctx *ExecutionContext) (string, error) {
collection := make([]string, 0, len(doc.Nodes))
func (doc *nodeDocument) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) error {
for _, n := range doc.Nodes {
buf, err := n.Execute(ctx)
err := n.Execute(ctx, buffer)
if err != nil {
return "", err
return err
}
collection = append(collection, buf)
}
return strings.Join(collection, ""), nil
return nil
}
9 changes: 7 additions & 2 deletions nodes_html.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package pongo2

import (
"bytes"
)

type nodeHTML struct {
token *Token
}

func (n *nodeHTML) Execute(ctx *ExecutionContext) (string, error) {
return n.token.Val, nil
func (n *nodeHTML) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) error {
buffer.WriteString(n.token.Val)
return nil
}
12 changes: 5 additions & 7 deletions nodes_wrapper.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
package pongo2

import (
"strings"
"bytes"
)

type NodeWrapper struct {
Endtag string
nodes []INode
}

func (wrapper *NodeWrapper) Execute(ctx *ExecutionContext) (string, error) {
container := make([]string, 0, len(wrapper.nodes))
func (wrapper *NodeWrapper) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) error {
for _, n := range wrapper.nodes {
buf, err := n.Execute(ctx)
err := n.Execute(ctx, buffer)
if err != nil {
return "", err
return err
}
container = append(container, buf)
}
return strings.Join(container, ""), nil
return nil
}
3 changes: 2 additions & 1 deletion parser.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pongo2

import (
"bytes"
"errors"
"fmt"
"strings"
Expand All @@ -12,7 +13,7 @@ type IEvaluator interface {
}

type INode interface {
Execute(*ExecutionContext) (string, error)
Execute(*ExecutionContext, *bytes.Buffer) error
}

type INodeEvaluator interface {
Expand Down
8 changes: 5 additions & 3 deletions parser_expression.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pongo2

import (
"bytes"
"fmt"
"math"
)
Expand Down Expand Up @@ -62,12 +63,13 @@ func (p *power) FilterApplied(name string) bool {
(p.power2 != nil && p.power2.FilterApplied(name)))
}

func (expr *Expression) Execute(ctx *ExecutionContext) (string, error) {
func (expr *Expression) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) error {
value, err := expr.Evaluate(ctx)
if err != nil {
return "", err
return err
}
return value.String(), nil
buffer.WriteString(value.String())
return nil
}

func (expr *Expression) Evaluate(ctx *ExecutionContext) (*Value, error) {
Expand Down
11 changes: 6 additions & 5 deletions tags_block.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pongo2

import (
"bytes"
"fmt"
)

Expand All @@ -21,7 +22,7 @@ func (node *tagBlockNode) getBlockWrapperByName(tpl *Template) *NodeWrapper {
return t
}

func (node *tagBlockNode) Execute(ctx *ExecutionContext) (string, error) {
func (node *tagBlockNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) error {
tpl := ctx.template
if tpl == nil {
panic("internal error: tpl == nil")
Expand All @@ -30,16 +31,16 @@ func (node *tagBlockNode) Execute(ctx *ExecutionContext) (string, error) {
block_wrapper := node.getBlockWrapperByName(tpl)
if block_wrapper == nil {
// fmt.Printf("could not find: %s\n", node.name)
return "", ctx.Error("internal error: block_wrapper == nil in tagBlockNode.Execute()", nil)
return ctx.Error("internal error: block_wrapper == nil in tagBlockNode.Execute()", nil)
}
rv, err := block_wrapper.Execute(ctx)
err := block_wrapper.Execute(ctx, buffer)
if err != nil {
return "", err
return err
}

// TODO: Add support for {{ block.super }}

return rv, nil
return nil
}

func tagBlockParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, error) {
Expand Down
8 changes: 6 additions & 2 deletions tags_comment.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package pongo2

import (
"bytes"
)

type tagCommentNode struct{}

func (node *tagCommentNode) Execute(ctx *ExecutionContext) (string, error) {
return "", nil
func (node *tagCommentNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) error {
return nil
}

func tagCommentParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, error) {
Expand Down
5 changes: 3 additions & 2 deletions tags_extends.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package pongo2

import (
"bytes"
"path/filepath"
)

type tagExtendsNode struct {
filename string
}

func (node *tagExtendsNode) Execute(ctx *ExecutionContext) (string, error) {
return "", nil
func (node *tagExtendsNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) error {
return nil
}

func tagExtendsParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, error) {
Expand Down
21 changes: 6 additions & 15 deletions tags_for.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package pongo2

import (
"strings"
"bytes"
)

type tagForNode struct {
Expand All @@ -23,7 +23,7 @@ type tagForLoopInformation struct {
Parentloop *tagForLoopInformation
}

func (node *tagForNode) Execute(ctx *ExecutionContext) (s string, forError error) {
func (node *tagForNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) (forError error) {
// Backup forloop (as parentloop in public context), key-name and value-name
forCtx := NewExecutionContext(ctx)
parentloop := forCtx.Private["forloop"]
Expand All @@ -41,11 +41,9 @@ func (node *tagForNode) Execute(ctx *ExecutionContext) (s string, forError error
// Register loopInfo in public context
forCtx.Private["forloop"] = loopInfo

container := make([]string, 0)

obj, err := node.object_evaluator.Evaluate(forCtx)
if err != nil {
return "", err
return err
}

obj.Iterate(func(idx, count int, key, value *Value) bool {
Expand All @@ -68,30 +66,23 @@ func (node *tagForNode) Execute(ctx *ExecutionContext) (s string, forError error
loopInfo.Revcounter0 = count - (idx + 1) // TODO: Not sure about this, have to look it up

// Render elements with updated context
s, err := node.bodyWrapper.Execute(forCtx)
err := node.bodyWrapper.Execute(forCtx, buffer)
if err != nil {
forError = err
return false
}
container = append(container, s)
return true
}, func() {
// Nothing to iterate over (maybe wrong type or no items)
if node.emptyWrapper != nil {
s, err := node.emptyWrapper.Execute(forCtx)
err := node.emptyWrapper.Execute(forCtx, buffer)
if err != nil {
forError = err
}
container = append(container, s)
}
})

if forError != nil {
return
}

// Return the rendered template
return strings.Join(container, ""), nil
return nil
}

func tagForParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, error) {
Expand Down
14 changes: 9 additions & 5 deletions tags_if.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
package pongo2

import (
"bytes"
)

type tagIfNode struct {
condition IEvaluator
thenWrapper *NodeWrapper
elseWrapper *NodeWrapper
}

func (node *tagIfNode) Execute(ctx *ExecutionContext) (string, error) {
func (node *tagIfNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) error {
result, err := node.condition.Evaluate(ctx)
if err != nil {
return "", err
return err
}

if result.IsTrue() {
return node.thenWrapper.Execute(ctx)
return node.thenWrapper.Execute(ctx, buffer)
} else {
if node.elseWrapper != nil {
return node.elseWrapper.Execute(ctx)
return node.elseWrapper.Execute(ctx, buffer)
}
}
return "", nil
return nil
}

func tagIfParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, error) {
Expand Down
16 changes: 9 additions & 7 deletions tags_ifequal.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
package pongo2

//import "fmt"
import (
"bytes"
)

type tagIfEqualNode struct {
var1, var2 IEvaluator
thenWrapper *NodeWrapper
elseWrapper *NodeWrapper
}

func (node *tagIfEqualNode) Execute(ctx *ExecutionContext) (string, error) {
func (node *tagIfEqualNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) error {
r1, err := node.var1.Evaluate(ctx)
if err != nil {
return "", err
return err
}
r2, err := node.var2.Evaluate(ctx)
if err != nil {
return "", err
return err
}

result := r1.EqualValueTo(r2)

if result {
return node.thenWrapper.Execute(ctx)
return node.thenWrapper.Execute(ctx, buffer)
} else {
if node.elseWrapper != nil {
return node.elseWrapper.Execute(ctx)
return node.elseWrapper.Execute(ctx, buffer)
}
}
return "", nil
return nil
}

func tagIfEqualParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, error) {
Expand Down
16 changes: 9 additions & 7 deletions tags_ifnotequal.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
package pongo2

//import "fmt"
import (
"bytes"
)

type tagIfNotEqualNode struct {
var1, var2 IEvaluator
thenWrapper *NodeWrapper
elseWrapper *NodeWrapper
}

func (node *tagIfNotEqualNode) Execute(ctx *ExecutionContext) (string, error) {
func (node *tagIfNotEqualNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) error {
r1, err := node.var1.Evaluate(ctx)
if err != nil {
return "", err
return err
}
r2, err := node.var2.Evaluate(ctx)
if err != nil {
return "", err
return err
}

result := !r1.EqualValueTo(r2)

if result {
return node.thenWrapper.Execute(ctx)
return node.thenWrapper.Execute(ctx, buffer)
} else {
if node.elseWrapper != nil {
return node.elseWrapper.Execute(ctx)
return node.elseWrapper.Execute(ctx, buffer)
}
}
return "", nil
return nil
}

func tagIfNotEqualParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, error) {
Expand Down

0 comments on commit a1fab22

Please sign in to comment.