fis-gtm/sr_port/global_map.c

93 lines
3.2 KiB
C

/****************************************************************
* *
* Copyright 2001, 2011 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include "gtm_string.h"
#include "global_map.h"
#include "min_max.h"
/* "map[]" is assumed to be an array of mstrs whose last mstr has a NULL value for its "addr" field.
* "map[]" contains even number of mstrs, each consecutive pair of mstrs (starting from map[0]) point to a range of names.
* Also "map[]" is an array of strings arranged in non-decreasing alphabetical order.
* Thus "map[]" is an array representing a set of ranges starting from the smallest to the largest.
* "beg" and "end" are the end-points of the range (both inclusive) to be inserted into this sorted range set.
* Note that a point is represented as a range whose begin and end are the same.
*/
void global_map(mstr map[], mstr *beg, mstr *end)
{
mstr *left, *right, rangestart, rangeend, tmpmstr;
int rslt;
DEBUG_ONLY(
MSTRP_CMP(beg, end, rslt);
assert(0 >= rslt);
)
for (left = map; left->addr; left++)
{
MSTRP_CMP(left, beg, rslt);
if (0 <= rslt)
break;
}
/* left now points to the first mstr in the array that is >= beg */
for (right = left; right->addr; right++)
{
MSTRP_CMP(right, end, rslt);
if (0 < rslt)
break;
}
/* right now points to the first mstr in the array that is > end */
if (left == right)
{ /* the usual case where {beg, end} has no or complete intersections with any existing range in map[].
* in the case of complete intersection return.
* in case of no intersection, insert {beg, end} maintaining sorted order by shifting all higher existing ranges
* two positions to the right */
if ((right - map) & 1)
return;
rangestart = *beg;
rangeend = *end;
while (left->addr)
{ /* {rangestart, rangeend} is the current range to be inserted */
tmpmstr = *left;
*left++ = rangestart;
rangestart = tmpmstr;
tmpmstr = *left;
*left++ = rangeend;
rangeend = tmpmstr;
}
*left++ = rangestart;
*left++ = rangeend;
left->addr = 0;
return;
}
/* case where {beg, end} has partial intersections with existing ranges in map[].
* replace intersecting ranges with one union range e.g. replace {1, 10} {5, 15} {12, 20} with {1, 20}
*/
if (0 == ((left - map) & 1))
*left++ = *beg;
if (0 == ((right - map) & 1))
*(--right) = *end;
if (left == right) /* possible if {beg, end} is exactly equal to an existing range in map[] */
return;
do
{
*left++ = *right;
} while ((right++)->addr);
/* note that replacing atleast 2 existing ranges with {begin, end} into one union range will cause a reduction
* in the number of ranges in map[] effectively causing higher-valued ranges on the right to shift left.
* In that case, we have to be also left-shift the null-valued mstr.addr, hence the ++ is done in the check
* for (right++)->addr in the "while" above instead of having "*left++ = *right++" in the loop.
*/
return;
}