forked from Velocidex/vfilter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
aggregates.go
149 lines (121 loc) · 3.28 KB
/
aggregates.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// VQL functions to deal with aggregates. This is mostly useful with
// group by clause.
package vfilter
import (
"context"
"github.com/Velocidex/ordereddict"
)
type _CountFunctionArgs struct {
Items Any `vfilter:"optional,field=items"`
}
type _CountFunction struct{}
func (self _CountFunction) Info(scope *Scope, type_map *TypeMap) *FunctionInfo {
return &FunctionInfo{
Name: "count",
Doc: "Counts the items.",
ArgType: type_map.AddType(scope, _CountFunctionArgs{}),
IsAggregate: true,
}
}
func (self _CountFunction) Call(
ctx context.Context,
scope *Scope,
args *ordereddict.Dict) Any {
arg := &_CountFunctionArgs{}
err := ExtractArgs(scope, args, arg)
if err != nil {
scope.Log("count: %s", err.Error())
return Null{}
}
count := uint64(0)
previous_value_any := scope.GetContext(GetID(self))
if previous_value_any != nil {
count = previous_value_any.(uint64)
}
count += 1
scope.SetContext(GetID(self), count)
return count
}
type _MinFunction struct{}
func (self _MinFunction) Info(scope *Scope, type_map *TypeMap) *FunctionInfo {
return &FunctionInfo{
Name: "min",
Doc: "Finds the smallest item in the aggregate.",
ArgType: type_map.AddType(scope, _CountFunctionArgs{}),
IsAggregate: true,
}
}
func (self _MinFunction) Call(
ctx context.Context,
scope *Scope,
args *ordereddict.Dict) Any {
arg := &_CountFunctionArgs{}
err := ExtractArgs(scope, args, arg)
if err != nil {
scope.Log("min: %s", err.Error())
return Null{}
}
var min_value Any = arg.Items
previous_value := scope.GetContext(GetID(self))
if previous_value != nil && !scope.Lt(min_value, previous_value) {
min_value = previous_value
}
scope.SetContext(GetID(self), min_value)
return min_value
}
type _MaxFunction struct{}
func (self _MaxFunction) Info(scope *Scope, type_map *TypeMap) *FunctionInfo {
return &FunctionInfo{
Name: "max",
Doc: "Finds the largest item in the aggregate.",
ArgType: type_map.AddType(scope, _CountFunctionArgs{}),
IsAggregate: true,
}
}
func (self _MaxFunction) Call(
ctx context.Context,
scope *Scope,
args *ordereddict.Dict) Any {
arg := &_CountFunctionArgs{}
err := ExtractArgs(scope, args, arg)
if err != nil {
scope.Log("min: %s", err.Error())
return Null{}
}
var max_value Any = arg.Items
previous_value := scope.GetContext(GetID(self))
if previous_value != nil && scope.Lt(max_value, previous_value) {
max_value = previous_value
}
scope.SetContext(GetID(self), max_value)
return max_value
}
type _EnumerateFunction struct{}
func (self _EnumerateFunction) Info(scope *Scope, type_map *TypeMap) *FunctionInfo {
return &FunctionInfo{
Name: "enumerate",
Doc: "Collect all the items in each group by bin.",
ArgType: type_map.AddType(scope, _CountFunctionArgs{}),
IsAggregate: true,
}
}
func (self _EnumerateFunction) Call(
ctx context.Context,
scope *Scope,
args *ordereddict.Dict) Any {
arg := &_CountFunctionArgs{}
err := ExtractArgs(scope, args, arg)
if err != nil {
scope.Log("enumerate: %s", err.Error())
return Null{}
}
var value Any
previous_value, ok := scope.GetContext(GetID(self)).([]Any)
if ok {
value = append(previous_value, arg.Items)
} else {
value = []Any{arg.Items}
}
scope.SetContext(GetID(self), value)
return value
}