Reduce use of pointer in the LoadTimeZoneRule logic
This commit is contained in:
parent
7efb073ac9
commit
d3968e933e
1 changed files with 182 additions and 168 deletions
|
@ -197,30 +197,38 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe char* GetQZName(char* name, char delimiter)
|
private static int GetQZName(char[] name, int namePosition, char delimiter)
|
||||||
{
|
{
|
||||||
while (*name != '\0' && *name != delimiter)
|
int i = namePosition;
|
||||||
|
|
||||||
|
while (name[i] != '\0' && name[i] != delimiter)
|
||||||
{
|
{
|
||||||
name++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe char* GetTZName(char* name)
|
private static int GetTZName(char[] name, int namePosition)
|
||||||
{
|
{
|
||||||
while (*name != '\0' && !char.IsDigit(*name) && *name != ',' && *name != '-' && *name != '+')
|
int i = namePosition;
|
||||||
|
|
||||||
|
char c = name[i];
|
||||||
|
|
||||||
|
while (c != '\0' && !char.IsDigit(c) && c != ',' && c != '-' && c != '+')
|
||||||
{
|
{
|
||||||
name++;
|
c = name[i];
|
||||||
}
|
i++;
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe bool GetNum(ref char* name, out int num, int min, int max)
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool GetNum(char[] name, ref int namePosition, out int num, int min, int max)
|
||||||
{
|
{
|
||||||
num = 0;
|
num = 0;
|
||||||
|
|
||||||
char c = *name;
|
char c = name[namePosition];
|
||||||
|
|
||||||
if (!char.IsDigit(c))
|
if (!char.IsDigit(c))
|
||||||
{
|
{
|
||||||
|
@ -235,7 +243,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = *++name;
|
c = name[++namePosition];
|
||||||
}
|
}
|
||||||
while (char.IsDigit(c));
|
while (char.IsDigit(c));
|
||||||
|
|
||||||
|
@ -247,33 +255,33 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe bool GetSeconds(ref char* name, out int seconds)
|
private static bool GetSeconds(char[] name, ref int namePosition, out int seconds)
|
||||||
{
|
{
|
||||||
seconds = 0;
|
seconds = 0;
|
||||||
|
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
bool isValid = GetNum(ref name, out num, 0, HoursPerDays * DaysPerWekk - 1);
|
bool isValid = GetNum(name, ref namePosition, out num, 0, HoursPerDays * DaysPerWekk - 1);
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
seconds = num * SecondsPerHour;
|
seconds = num * SecondsPerHour;
|
||||||
if (*name == ':')
|
if (name[namePosition] == ':')
|
||||||
{
|
{
|
||||||
name++;
|
namePosition++;
|
||||||
isValid = GetNum(ref name, out num, 0, MinutesPerHour - 1);
|
isValid = GetNum(name, ref namePosition, out num, 0, MinutesPerHour - 1);
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
seconds += num * SecondsPerMinute;
|
seconds += num * SecondsPerMinute;
|
||||||
if (*name == ':')
|
if (name[namePosition] == ':')
|
||||||
{
|
{
|
||||||
name++;
|
namePosition++;
|
||||||
isValid = GetNum(ref name, out num, 0, SecondsPerMinute);
|
isValid = GetNum(name, ref namePosition, out num, 0, SecondsPerMinute);
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -285,21 +293,21 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe bool GetOffset(ref char* name, ref int offset)
|
private static bool GetOffset(char[] name, ref int namePosition, ref int offset)
|
||||||
{
|
{
|
||||||
bool isNegative = false;
|
bool isNegative = false;
|
||||||
|
|
||||||
if (*name == '-')
|
if (name[namePosition] == '-')
|
||||||
{
|
{
|
||||||
isNegative = true;
|
isNegative = true;
|
||||||
name++;
|
namePosition++;
|
||||||
}
|
}
|
||||||
else if (*name == '+')
|
else if (name[namePosition] == '+')
|
||||||
{
|
{
|
||||||
name++;
|
namePosition++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValid = GetSeconds(ref name, out offset);
|
bool isValid = GetSeconds(name, ref namePosition, out offset);
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -313,53 +321,53 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe bool GetRule(ref char* name, out Rule rule)
|
private static bool GetRule(char[] name, ref int namePosition, out Rule rule)
|
||||||
{
|
{
|
||||||
rule = new Rule();
|
rule = new Rule();
|
||||||
|
|
||||||
bool isValid = false;
|
bool isValid = false;
|
||||||
|
|
||||||
if (*name == 'J')
|
if (name[namePosition] == 'J')
|
||||||
{
|
{
|
||||||
name++;
|
namePosition++;
|
||||||
|
|
||||||
rule.Type = RuleType.JulianDay;
|
rule.Type = RuleType.JulianDay;
|
||||||
isValid = GetNum(ref name, out rule.Day, 1, DaysPerNYear);
|
isValid = GetNum(name, ref namePosition, out rule.Day, 1, DaysPerNYear);
|
||||||
}
|
}
|
||||||
else if (*name == 'M')
|
else if (name[namePosition] == 'M')
|
||||||
{
|
{
|
||||||
name++;
|
namePosition++;
|
||||||
|
|
||||||
rule.Type = RuleType.MonthNthDayOfWeek;
|
rule.Type = RuleType.MonthNthDayOfWeek;
|
||||||
isValid = GetNum(ref name, out rule.Month, 1, MonthsPerYear);
|
isValid = GetNum(name, ref namePosition, out rule.Month, 1, MonthsPerYear);
|
||||||
|
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*name++ != '.')
|
if (name[namePosition++] != '.')
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid = GetNum(ref name, out rule.Week, 1, 5);
|
isValid = GetNum(name, ref namePosition, out rule.Week, 1, 5);
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*name++ != '.')
|
if (name[namePosition++] != '.')
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid = GetNum(ref name, out rule.Day, 0, DaysPerWekk - 1);
|
isValid = GetNum(name, ref namePosition, out rule.Day, 0, DaysPerWekk - 1);
|
||||||
}
|
}
|
||||||
else if (char.IsDigit(*name))
|
else if (char.IsDigit(name[namePosition]))
|
||||||
{
|
{
|
||||||
rule.Type = RuleType.DayOfYear;
|
rule.Type = RuleType.DayOfYear;
|
||||||
isValid = GetNum(ref name, out rule.Day, 0, DaysPerLYear - 1);
|
isValid = GetNum(name, ref namePosition, out rule.Day, 0, DaysPerLYear - 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -371,10 +379,10 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*name == '/')
|
if (name[namePosition] == '/')
|
||||||
{
|
{
|
||||||
name++;
|
namePosition++;
|
||||||
return GetOffset(ref name, ref rule.TransitionTime);
|
return GetOffset(name, ref namePosition, ref rule.TransitionTime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -394,7 +402,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe bool ParsePosixName(char* name, out TimeZoneRule outRules, bool lastDitch)
|
private static bool ParsePosixName(Span<char> name, out TimeZoneRule outRules, bool lastDitch)
|
||||||
{
|
{
|
||||||
outRules = new TimeZoneRule
|
outRules = new TimeZoneRule
|
||||||
{
|
{
|
||||||
|
@ -406,39 +414,48 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
|
|
||||||
int stdLen;
|
int stdLen;
|
||||||
|
|
||||||
char* stdName = name;
|
int namePosition = 0;
|
||||||
|
|
||||||
|
Span<char> stdName = name;
|
||||||
int stdOffset = 0;
|
int stdOffset = 0;
|
||||||
|
|
||||||
if (lastDitch)
|
if (lastDitch)
|
||||||
{
|
{
|
||||||
stdLen = 3;
|
stdLen = 3;
|
||||||
name += stdLen;
|
namePosition += stdLen;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (*name == '<')
|
if (name[namePosition] == '<')
|
||||||
{
|
{
|
||||||
name++;
|
namePosition++;
|
||||||
stdName = name;
|
|
||||||
name = GetQZName(name, '>');
|
stdName = name.Slice(namePosition);
|
||||||
if (*name != '>')
|
|
||||||
|
int stdNamePosition = namePosition;
|
||||||
|
|
||||||
|
namePosition = GetQZName(name.ToArray(), namePosition, '>');
|
||||||
|
if (name[namePosition] != '>')
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
stdLen = (int)(name - stdName);
|
|
||||||
name++;
|
stdLen = namePosition - stdNamePosition;
|
||||||
|
namePosition++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
name = GetTZName(name);
|
namePosition = GetTZName(name.ToArray(), namePosition);
|
||||||
stdLen = (int)(name - stdName);
|
stdLen = namePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stdLen == 0)
|
if (stdLen == 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool isValid = GetOffset(ref name, ref stdOffset);
|
|
||||||
|
bool isValid = GetOffset(name.ToArray(), ref namePosition, ref stdOffset);
|
||||||
|
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -449,31 +466,35 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
int destLen = 0;
|
int destLen = 0;
|
||||||
int dstOffset = 0;
|
int dstOffset = 0;
|
||||||
|
|
||||||
char* destName = name;
|
Span<char> destName = name.Slice(namePosition);
|
||||||
|
|
||||||
if (TzCharsArraySize < charCount)
|
if (TzCharsArraySize < charCount)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*name != '\0')
|
if (name[namePosition] != '\0')
|
||||||
{
|
{
|
||||||
if (*name == '<')
|
if (name[namePosition] == '<')
|
||||||
{
|
{
|
||||||
destName = ++name;
|
destName = name.Slice(++namePosition);
|
||||||
name = GetQZName(name, '>');
|
int destNamePosition = namePosition;
|
||||||
if (*name != '>')
|
|
||||||
|
namePosition = GetQZName(name.ToArray(), namePosition, '>');
|
||||||
|
|
||||||
|
if (name[namePosition] != '>')
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
destLen = (int)(name - destName);
|
|
||||||
name++;
|
destLen = namePosition - destNamePosition;
|
||||||
|
namePosition++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
destName = name;
|
destName = name.Slice(namePosition);
|
||||||
name = GetTZName(name);
|
namePosition = GetTZName(name.ToArray(), namePosition);
|
||||||
destLen = (int)(name - destName);
|
destLen = namePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destLen == 0)
|
if (destLen == 0)
|
||||||
|
@ -481,15 +502,16 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
charCount += (int)destLen + 1;
|
charCount += destLen + 1;
|
||||||
if (TzCharsArraySize < charCount)
|
if (TzCharsArraySize < charCount)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*name != '\0' && *name != ',' && *name != ';')
|
if (name[namePosition] != '\0' && name[namePosition] != ',' && name[namePosition] != ';')
|
||||||
{
|
{
|
||||||
bool isValid = GetOffset(ref name, ref dstOffset);
|
bool isValid = GetOffset(name.ToArray(), ref namePosition, ref dstOffset);
|
||||||
|
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -500,36 +522,34 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
dstOffset = stdOffset - SecondsPerHour;
|
dstOffset = stdOffset - SecondsPerHour;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*name == '\0')
|
if (name[namePosition] == '\0')
|
||||||
{
|
{
|
||||||
fixed (char* defaultTz = TimeZoneDefaultRule.ToCharArray())
|
name = TimeZoneDefaultRule.ToCharArray();
|
||||||
{
|
namePosition = 0;
|
||||||
name = defaultTz;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*name == ',' || *name == ';')
|
if (name[namePosition] == ',' || name[namePosition] == ';')
|
||||||
{
|
{
|
||||||
name++;
|
namePosition++;
|
||||||
|
|
||||||
bool IsRuleValid = GetRule(ref name, out Rule start);
|
bool IsRuleValid = GetRule(name.ToArray(), ref namePosition, out Rule start);
|
||||||
if (!IsRuleValid)
|
if (!IsRuleValid)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*name++ != ',')
|
if (name[namePosition++] != ',')
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IsRuleValid = GetRule(ref name, out Rule end);
|
IsRuleValid = GetRule(name.ToArray(), ref namePosition, out Rule end);
|
||||||
if (!IsRuleValid)
|
if (!IsRuleValid)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*name != '\0')
|
if (name[namePosition] != '\0')
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -639,7 +659,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (*name == '\0')
|
if (name[namePosition] == '\0')
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -727,25 +747,23 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
|
|
||||||
outRules.CharCount = charCount;
|
outRules.CharCount = charCount;
|
||||||
|
|
||||||
fixed (char* chars = outRules.Chars)
|
int charsPosition = 0;
|
||||||
{
|
|
||||||
char* cp = chars;
|
|
||||||
|
|
||||||
for (int i = 0; i < stdLen; i++)
|
for (int i = 0; i < stdLen; i++)
|
||||||
{
|
{
|
||||||
cp[i] = stdName[i];
|
outRules.Chars[i] = stdName[i];
|
||||||
}
|
}
|
||||||
cp += stdLen;
|
|
||||||
*cp++ = '\0';
|
charsPosition += stdLen;
|
||||||
|
outRules.Chars[charsPosition++] = '\0';
|
||||||
|
|
||||||
if (destLen != 0)
|
if (destLen != 0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < destLen; i++)
|
for (int i = 0; i < destLen; i++)
|
||||||
{
|
{
|
||||||
cp[i] = destName[i];
|
outRules.Chars[charsPosition + i] = destName[i];
|
||||||
}
|
|
||||||
*(cp + destLen) = '\0';
|
|
||||||
}
|
}
|
||||||
|
outRules.Chars[charsPosition + destLen] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -883,13 +901,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
|
|
||||||
public static bool ParsePosixName(string name, out TimeZoneRule outRules)
|
public static bool ParsePosixName(string name, out TimeZoneRule outRules)
|
||||||
{
|
{
|
||||||
unsafe
|
return ParsePosixName(name.ToCharArray(), out outRules, false);
|
||||||
{
|
|
||||||
fixed (char *namePtr = name.ToCharArray())
|
|
||||||
{
|
|
||||||
return ParsePosixName(namePtr, out outRules, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe bool LoadTimeZoneRules(out TimeZoneRule outRules, Stream inputData)
|
public static unsafe bool LoadTimeZoneRules(out TimeZoneRule outRules, Stream inputData)
|
||||||
|
@ -1081,16 +1093,17 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
char[] name = new char[TzNameMax + 1];
|
char[] tempName = new char[TzNameMax + 1];
|
||||||
Array.Copy(workBuffer, position, name, 0, nread);
|
Array.Copy(workBuffer, position, tempName, 0, nread);
|
||||||
|
|
||||||
if (nread > 2 && name[0] == '\n' && name[nread - 1] == '\n' && outRules.TypeCount + 2 <= TzMaxTypes)
|
if (nread > 2 && tempName[0] == '\n' && tempName[nread - 1] == '\n' && outRules.TypeCount + 2 <= TzMaxTypes)
|
||||||
{
|
{
|
||||||
name[nread - 1] = '\0';
|
tempName[nread - 1] = '\0';
|
||||||
|
|
||||||
fixed (char* namePtr = &name[1])
|
char[] name = new char[TzNameMax];
|
||||||
{
|
Array.Copy(tempName, 1, name, 0, nread - 1);
|
||||||
if (ParsePosixName(namePtr, out TimeZoneRule tempRules, false))
|
|
||||||
|
if (ParsePosixName(name, out TimeZoneRule tempRules, false))
|
||||||
{
|
{
|
||||||
int abbreviationCount = 0;
|
int abbreviationCount = 0;
|
||||||
charCount = outRules.CharCount;
|
charCount = outRules.CharCount;
|
||||||
|
@ -1125,6 +1138,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
}
|
}
|
||||||
|
|
||||||
charCount = j + abbreviationLength + 1;
|
charCount = j + abbreviationLength + 1;
|
||||||
|
|
||||||
tempRules.Ttis[i].AbbreviationListIndex = j;
|
tempRules.Ttis[i].AbbreviationListIndex = j;
|
||||||
abbreviationCount++;
|
abbreviationCount++;
|
||||||
}
|
}
|
||||||
|
@ -1156,6 +1170,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
{
|
{
|
||||||
outRules.Ats[outRules.TimeCount] = tempRules.Ats[i];
|
outRules.Ats[outRules.TimeCount] = tempRules.Ats[i];
|
||||||
outRules.Types[outRules.TimeCount] = (byte)(outRules.TypeCount + (byte)tempRules.Types[i]);
|
outRules.Types[outRules.TimeCount] = (byte)(outRules.TypeCount + (byte)tempRules.Types[i]);
|
||||||
|
|
||||||
outRules.TimeCount++;
|
outRules.TimeCount++;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -1168,7 +1183,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (outRules.TypeCount == 0)
|
if (outRules.TypeCount == 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue