-
Notifications
You must be signed in to change notification settings - Fork 0
/
containers.tf
166 lines (141 loc) · 5.61 KB
/
containers.tf
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
;
; tf-util/containers.tf
;
; Some simple data structures to use.
;
; Queue
;
; Stack
;
; Dequeue
;
; Both queues and stacks are implemented in terms of dequeues and can
; be used interchangably. Queue and stack functions are simply ways
; to clarify intent.
;
; Dequeues are implemented as strings with each value textencoded
; and separated by spaces. For search simplicity and speed, the queue
; values should always begin and end with a space.
;
; Note that storing the empty string in any of these data structures
; is not supported.
;
/require -q tf-util/variables.tf
/require -q tf-util/unit-test.tf
/def dequeue_init = \
/let _queueName=%{1}%;\
/test setVar(_queueName, " ")
/def dequeue_length = \
/let _queueName=%{1}%;\
/let _queueData=$[getVar(_queueName)]%;\
/result strlen(_queueData) - strlen(replace(" ", "", _queueData)) - 1
/def dequeue_append = \
/let _queueName=%{1}%;\
/let _queueData=$[getVar(_queueName)]%;\
/let _val=%{2}%;\
/let _encodedVal=$[textencode(_val)]%;\
/if (strlen(_queueData) == 0) \
/test _queueData := " "%;\
/endif%;\
/let _newQueueData=$[strcat(_queueData, _encodedVal, " ")]%;\
/test setVar(_queueName, _newQueueData)
/def dequeue_popFirst = \
/let _queueName=%{1}%;\
/let _queueData=$[getVar(_queueName)]%;\
/if (strlen(_queueData) <= 1) \
/result ""%;\
/endif%;\
/let _endIdx=$[strstr(_queueData, " ", 1)]%;\
/let _retVal=$[textdecode(substr(_queueData, 1, _endIdx - 1))]%;\
/let _newQueueData=$[substr(_queueData, _endIdx)]%;\
/test setVar(_queueName, _newQueueData)%;\
/result _retVal
/def dequeue_popLast = \
/let _queueName=%{1}%;\
/let _queueData=$[getVar(_queueName)]%;\
/if (strlen(_queueData) <= 1) \
/result ""%;\
/endif%;\
/let _startIdx=$[strrchr(_queueData, " ", strlen(_queueData)-2)]%;\
/let _retVal=$[textdecode(substr(_queueData, _startIdx + 1, strlen(_queueData) - _startIdx - 2))]%;\
/let _newQueueData=$[substr(_queueData, 0, _startIdx + 1)]%;\
/test setVar(_queueName, _newQueueData)%;\
/result _retVal
; Queue aliases
;
; These don't add funcitonality but given meaningful aliases.
/def queue_init = \
/test dequeue_init({1})
/def queue_push = \
/test dequeue_append({1}, {2})
/def queue_pop = \
/let _queueName=%{1}%;\
/result dequeue_popFirst({_queueName})
/def queue_length = \
/result dequeue_length({1})
; Stack aliases
;
; These don't add funcitonality but given meaningful aliases.
/def stack_init = \
/test dequeue_init({1})
/def stack_push = \
/test dequeue_append({1}, {2})
/def stack_pop = \
/let _stackName=%{1}%;\
/result dequeue_popLast({_stackName})
/def stack_length = \
/result dequeue_length({1})
/tfunit_declareGroup tf_util_container
/def test_tf_util_container_Basic_Dequeue = \
/dequeue_init testQueue%;\
/let _first=$[dequeue_popFirst("testQueue")]%;\
/test tfunit_assertStrEqual("", _first, "New queue should be empty.")%;\
/dequeue_append testQueue first%;\
/let _len=$[dequeue_length("testQueue")]%;\
/test tfunit_assertEqual(1, _len, "Queue length should be 1 after initial append.")%;\
/let _first=$[dequeue_popFirst("testQueue")]%;\
/test tfunit_assertStrEqual("first", _first, "New queue should be empty.")%;\
/let _len=$[dequeue_length("testQueue")]%;\
/test tfunit_assertEqual(0, _len, "Queue length should be 1 after initial append.")
/def test_tf_util_container_Init_Resets_Dequeue = \
/dequeue_init testQueue%;\
/test dequeue_append("testQueue", "first item")%;\
/let _len=$[dequeue_length("testQueue")]%;\
/test tfunit_assertEqual(1, _len, "Queue should have one item after append.")%;\
/test dequeue_init("testQueue")%;\
/test _len := dequeue_length("testQueue")%;\
/test tfunit_assertEqual(0, _len, "Queue should have one item after append.")
/def test_tf_util_container_Dequeue_Handles_Data_With_Spaces = \
/dequeue_init testQueue%;\
/test dequeue_append("testQueue", "first item")%;\
/test dequeue_append("testQueue", "second item")%;\
/test dequeue_append("testQueue", "third item")%;\
/let _next=$[dequeue_popFirst("testQueue")]%;\
/test tfunit_assertStrEqual("first item", _next, "popFirst should preserve spaces")%;\
/let _next=$[dequeue_popLast("testQueue")]%;\
/test tfunit_assertStrEqual("third item", _next, "popLast should preserve spaces")
/def test_tf_util_container_Queue_Ordering = \
/queue_init testQueue%;\
/queue_push testQueue first%;\
/queue_push testQueue second%;\
/queue_push testQueue third%;\
/let _next=$[queue_pop("testQueue")]%;\
/test tfunit_assertStrEqual("first", _next, "Queues should be first-in/first-out")%;\
/test _next := queue_pop("testQueue")%;\
/test tfunit_assertStrEqual("second", _next, "Queues should be first-in/first-out")%;\
/test _next := queue_pop("testQueue")%;\
/test tfunit_assertStrEqual("third", _next, "Queues should be first-in/first-out")%;\
/test _next := queue_pop("testQueue")
/def test_tf_util_container_Stack_Ordering = \
/stack_init teststack%;\
/stack_push teststack first%;\
/stack_push teststack second%;\
/stack_push teststack third%;\
/let _next=$[stack_pop("teststack")]%;\
/test tfunit_assertStrEqual("third", _next, "stacks should be first-in/first-out")%;\
/test _next := stack_pop("teststack")%;\
/test tfunit_assertStrEqual("second", _next, "stacks should be first-in/first-out")%;\
/test _next := stack_pop("teststack")%;\
/test tfunit_assertStrEqual("first", _next, "stacks should be first-in/first-out")%;\
/test _next := stack_pop("teststack")
/tfunit_endGroup