1 /*
2  * Copyright (C) 2018-2019 Muhammad Tayyab Akram
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <SBConfig.h>
18 
19 #include "SBAssert.h"
20 #include "SBBase.h"
21 #include "ScriptStack.h"
22 
ScriptStackReset(ScriptStackRef stack)23 SB_INTERNAL void ScriptStackReset(ScriptStackRef stack)
24 {
25     stack->top = -1;
26     stack->count = 0;
27     stack->open = 0;
28 }
29 
ScriptStackPush(ScriptStackRef stack,SBScript script,SBCodepoint mirror)30 SB_INTERNAL void ScriptStackPush(ScriptStackRef stack, SBScript script, SBCodepoint mirror)
31 {
32     stack->count = SBNumberLimitIncrement(stack->count, _SBScriptStackCapacity);
33     stack->open = SBNumberLimitIncrement(stack->open, _SBScriptStackCapacity);
34 
35     stack->top = SBNumberRingIncrement(stack->top, _SBScriptStackCapacity);
36     stack->_elements[stack->top].script = script;
37     stack->_elements[stack->top].mirror = mirror;
38 }
39 
ScriptStackPop(ScriptStackRef stack)40 SB_INTERNAL void ScriptStackPop(ScriptStackRef stack)
41 {
42     /* There must be at least one entry in the stack. */
43     SBAssert(stack->count > 0);
44 
45     stack->count -= 1;
46     stack->open = SBNumberLimitDecrement(stack->open, 0);
47     stack->top = SBNumberRingDecrement(stack->top, _SBScriptStackCapacity);
48 
49     if (ScriptStackIsEmpty(stack)) {
50         stack->top = -1;
51     }
52 }
53 
ScriptStackLeavePairs(ScriptStackRef stack)54 SB_INTERNAL void ScriptStackLeavePairs(ScriptStackRef stack)
55 {
56     stack->open = 0;
57 }
58 
ScriptStackSealPairs(ScriptStackRef stack,SBScript script)59 SB_INTERNAL void ScriptStackSealPairs(ScriptStackRef stack, SBScript script)
60 {
61     SBInteger index = SBNumberRingSubtract(stack->top, (SBInteger)stack->open, _SBScriptStackCapacity);
62 
63     while (stack->open) {
64         index = SBNumberRingIncrement(index, _SBScriptStackCapacity);
65         stack->_elements[index].script = script;
66         stack->open -= 1;
67     }
68 }
69 
ScriptStackIsEmpty(ScriptStackRef stack)70 SB_INTERNAL SBBoolean ScriptStackIsEmpty(ScriptStackRef stack)
71 {
72     return (stack->count == 0);
73 }
74 
ScriptStackGetScript(ScriptStackRef stack)75 SB_INTERNAL SBScript ScriptStackGetScript(ScriptStackRef stack)
76 {
77     return stack->_elements[stack->top].script;
78 }
79 
ScriptStackGetMirror(ScriptStackRef stack)80 SB_INTERNAL SBCodepoint ScriptStackGetMirror(ScriptStackRef stack)
81 {
82     return stack->_elements[stack->top].mirror;
83 }
84