stk-code_catmod/lib/sheenbidi/Source/BracketQueue.c

231 lines
6.1 KiB
C

/*
* Copyright (C) 2014-2019 Muhammad Tayyab Akram
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <SBConfig.h>
#include <stddef.h>
#include <stdlib.h>
#include "BidiChain.h"
#include "SBAssert.h"
#include "SBBase.h"
#include "BracketQueue.h"
static void BracketQueueFinalizePairs(BracketQueueRef queue, BracketQueueListRef list, SBInteger top)
{
do {
SBInteger limit = (list == queue->_rearList ? queue->_rearTop : BracketQueueList_MaxIndex);
while (++top <= limit) {
if (list->openingLink[top] != BidiLinkNone
&& list->closingLink[top] == BidiLinkNone) {
list->openingLink[top] = BidiLinkNone;
}
}
list = list->next;
top = 0;
} while (list);
}
SB_INTERNAL void BracketQueueInitialize(BracketQueueRef queue)
{
queue->_firstList.previous = NULL;
queue->_firstList.next = NULL;
queue->_frontList = NULL;
queue->_rearList = NULL;
queue->count = 0;
queue->shouldDequeue = SBFalse;
}
SB_INTERNAL void BracketQueueReset(BracketQueueRef queue, SBBidiType direction)
{
queue->_frontList = &queue->_firstList;
queue->_rearList = &queue->_firstList;
queue->_frontTop = 0;
queue->_rearTop = -1;
queue->count = 0;
queue->shouldDequeue = SBFalse;
queue->_direction = direction;
}
SB_INTERNAL void BracketQueueEnqueue(BracketQueueRef queue,
BidiLink priorStrongLink, BidiLink openingLink, SBCodepoint bracket)
{
BracketQueueListRef list;
SBInteger top;
/* The queue can only take a maximum of 63 elements. */
SBAssert(queue->count < BracketQueueGetMaxCapacity());
if (queue->_rearTop != BracketQueueList_MaxIndex) {
list = queue->_rearList;
top = ++queue->_rearTop;
} else {
BracketQueueListRef rearList;
rearList = queue->_rearList;
list = rearList->next;
if (!list) {
list = malloc(sizeof(BracketQueueList));
list->previous = rearList;
list->next = NULL;
rearList->next = list;
}
queue->_rearList = list;
queue->_rearTop = top = 0;
}
queue->count += 1;
list->priorStrongLink[top] = priorStrongLink;
list->openingLink[top] = openingLink;
list->closingLink[top] = BidiLinkNone;
list->bracket[top] = bracket;
list->strongType[top] = SBBidiTypeNil;
}
SB_INTERNAL void BracketQueueDequeue(BracketQueueRef queue)
{
/* The queue must NOT be empty. */
SBAssert(queue->count != 0);
if (queue->_frontTop != BracketQueueList_MaxIndex) {
queue->_frontTop += 1;
} else {
BracketQueueListRef frontList = queue->_frontList;
if (frontList == queue->_rearList) {
queue->_rearTop = -1;
} else {
queue->_frontList = frontList->next;
}
queue->_frontTop = 0;
}
queue->count -= 1;
}
SB_INTERNAL void BracketQueueSetStrongType(BracketQueueRef queue, SBBidiType strongType)
{
BracketQueueListRef list = queue->_rearList;
SBInteger top = queue->_rearTop;
while (1) {
SBInteger limit = (list == queue->_frontList ? queue->_frontTop : 0);
do {
if (list->closingLink[top] == BidiLinkNone
&& list->strongType[top] != queue->_direction) {
list->strongType[top] = strongType;
}
} while (top-- > limit);
if (list == queue->_frontList) {
break;
}
list = list->previous;
top = BracketQueueList_MaxIndex;
}
}
SB_INTERNAL void BracketQueueClosePair(BracketQueueRef queue, BidiLink closingLink, SBCodepoint bracket)
{
BracketQueueListRef list = queue->_rearList;
SBInteger top = queue->_rearTop;
SBCodepoint canonical;
switch (bracket) {
case 0x232A:
canonical = 0x3009;
break;
case 0x3009:
canonical = 0x232A;
break;
default:
canonical = bracket;
break;
}
while (1) {
SBBoolean isFrontList = (list == queue->_frontList);
SBInteger limit = (isFrontList ? queue->_frontTop : 0);
do {
if (list->openingLink[top] != BidiLinkNone
&& list->closingLink[top] == BidiLinkNone
&& (list->bracket[top] == bracket || list->bracket[top] == canonical)) {
list->closingLink[top] = closingLink;
BracketQueueFinalizePairs(queue, list, top);
if (isFrontList && top == queue->_frontTop) {
queue->shouldDequeue = SBTrue;
}
return;
}
} while (top-- > limit);
if (isFrontList) {
break;
}
list = list->previous;
top = BracketQueueList_MaxIndex;
}
}
SB_INTERNAL SBBoolean BracketQueueShouldDequeue(BracketQueueRef queue)
{
return queue->shouldDequeue;
}
SB_INTERNAL BidiLink BracketQueueGetPriorStrongLink(BracketQueueRef queue)
{
return queue->_frontList->priorStrongLink[queue->_frontTop];
}
SB_INTERNAL BidiLink BracketQueueGetOpeningLink(BracketQueueRef queue)
{
return queue->_frontList->openingLink[queue->_frontTop];
}
SB_INTERNAL BidiLink BracketQueueGetClosingLink(BracketQueueRef queue)
{
return queue->_frontList->closingLink[queue->_frontTop];
}
SB_INTERNAL SBBidiType BracketQueueGetStrongType(BracketQueueRef queue)
{
return queue->_frontList->strongType[queue->_frontTop];
}
SB_INTERNAL void BracketQueueFinalize(BracketQueueRef queue)
{
BracketQueueListRef list = queue->_firstList.next;
while (list) {
BracketQueueListRef next = list->next;
free(list);
list = next;
}
}