少年修仙传客户端基础资源
hch
2024-04-01 d01413b00ef631ac20347716b23818b0b811f65f
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/**
 * \file
 * Unity icall support for Mono.
 *
 * Copyright 2016 Unity
 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
#include <glib.h>
#include "mono/utils/mono-compiler.h"
#include <mono/metadata/class-internals.h>
#include <mono/metadata/domain-internals.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/object.h>
#include <mono/metadata/object-internals.h>
 
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
 
/*
 * Magic number to convert a time which is relative to
 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
 */
#define    EPOCH_ADJUST    ((guint64)62135596800LL)
 
/*
 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
 */
#define FILETIME_ADJUST ((guint64)504911232000000000LL)
 
#ifdef PLATFORM_WIN32
/* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
static void
convert_to_absolute_date(SYSTEMTIME *date)
{
#define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
    static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    /* from the calendar FAQ */
    int a = (14 - date->wMonth) / 12;
    int y = date->wYear - a;
    int m = date->wMonth + 12 * a - 2;
    int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
 
    /* d is now the day of the week for the first of the month (0 == Sunday) */
 
    int day_of_week = date->wDayOfWeek;
 
    /* set day_in_month to the first day in the month which falls on day_of_week */    
    int day_in_month = 1 + (day_of_week - d);
    if (day_in_month <= 0)
        day_in_month += 7;
 
    /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
    date->wDay = day_in_month + (date->wDay - 1) * 7;
    if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
        date->wDay -= 7;
}
#endif
 
#ifndef PLATFORM_WIN32
/*
 * Return's the offset from GMT of a local time.
 * 
 *  tm is a local time
 *  t  is the same local time as seconds.
 */
static int 
gmt_offset(struct tm *tm, time_t t)
{
#if defined (HAVE_TM_GMTOFF)
    return tm->tm_gmtoff;
#else
    struct tm g;
    time_t t2;
    g = *gmtime(&t);
    g.tm_isdst = tm->tm_isdst;
    t2 = mktime(&g);
    return (int)difftime(t, t2);
#endif
}
#endif
/*
 * This is heavily based on zdump.c from glibc 2.2.
 *
 *  * data[0]:  start of daylight saving time (in DateTime ticks).
 *  * data[1]:  end of daylight saving time (in DateTime ticks).
 *  * data[2]:  utcoffset (in TimeSpan ticks).
 *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
 *  * name[0]:  name of this timezone when not daylight saving.
 *  * name[1]:  name of this timezone when daylight saving.
 *
 *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
 *         the class library allows years between 1 and 9999.
 *
 *  Returns true on success and zero on failure.
 */
guint32
ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names, MonoBoolean *daylight_inverted)
{
    MonoError error;
#ifndef PLATFORM_WIN32
    MonoDomain *domain = mono_domain_get ();
    struct tm start, tt;
    time_t t;
 
    long int gmtoff_start;
    long int gmtoff;
    int is_transitioned = 0, day;
    char tzone [64];
 
    MONO_CHECK_ARG_NULL (data, FALSE);
    MONO_CHECK_ARG_NULL (names, FALSE);
 
    mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new_checked (domain, mono_defaults.int64_class, 4, &error));
    mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new_checked (domain, mono_defaults.string_class, 2, &error));
 
    /* 
     * no info is better than crashing: we'll need our own tz data
     * to make this work properly, anyway. The range is probably
     * reduced to 1970 .. 2037 because that is what mktime is
     * guaranteed to support (we get into an infinite loop
     * otherwise).
     */
 
    memset (&start, 0, sizeof (start));
 
    start.tm_mday = 1;
    start.tm_year = year-1900;
 
    t = mktime (&start);
 
    if ((year < 1970) || (year > 2037) || (t == -1)) {
        t = time (NULL);
        tt = *localtime (&t);
        strftime (tzone, sizeof (tzone), "%Z", &tt);
        mono_array_setref ((*names), 0, mono_string_new_checked (domain, tzone, &error));
        mono_array_setref ((*names), 1, mono_string_new_checked (domain, tzone, &error));
        *daylight_inverted = 0;
        return 1;
    }
 
    *daylight_inverted = start.tm_isdst;
 
    gmtoff = gmt_offset (&start, t);
    gmtoff_start = gmtoff;
 
    /* For each day of the year, calculate the tm_gmtoff. */
    for (day = 0; day < 365; day++) {
 
        t += 3600*24;
        tt = *localtime (&t);
 
        /* Daylight saving starts or ends here. */
        if (gmt_offset (&tt, t) != gmtoff) {
            struct tm tt1;
            time_t t1;
 
            /* Try to find the exact hour when daylight saving starts/ends. */
            t1 = t;
            do {
                t1 -= 3600;
                tt1 = *localtime (&t1);
            } while (gmt_offset (&tt1, t1) != gmtoff);
 
            /* Try to find the exact minute when daylight saving starts/ends. */
            do {
                t1 += 60;
                tt1 = *localtime (&t1);
            } while (gmt_offset (&tt1, t1) == gmtoff);
            t1+=gmtoff;
            strftime (tzone, sizeof (tzone), "%Z", &tt);
            
            /* Write data, if we're already in daylight saving, we're done. */
            if (is_transitioned) {
                if (!start.tm_isdst)
                    mono_array_setref ((*names), 0, mono_string_new_checked (domain, tzone, &error));
                else
                    mono_array_setref ((*names), 1, mono_string_new_checked (domain, tzone, &error));
 
                mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
                return 1;
            } else {
                if (!start.tm_isdst)
                    mono_array_setref ((*names), 1, mono_string_new_checked (domain, tzone, &error));
                else
                    mono_array_setref ((*names), 0, mono_string_new_checked (domain, tzone, &error));
 
                mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
                is_transitioned = 1;
            }
 
            /* This is only set once when we enter daylight saving. */
            if (*daylight_inverted == 0) {
                mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
                mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
            } else {
                mono_array_set ((*data), gint64, 2, (gint64)(gmtoff_start + (gmt_offset (&tt, t) - gmtoff)) * 10000000L);
                mono_array_set ((*data), gint64, 3, (gint64)(gmtoff - gmt_offset (&tt, t)) * 10000000L);
            }
 
 
            gmtoff = gmt_offset (&tt, t);
        }
    }
 
    if (!is_transitioned) {
        strftime (tzone, sizeof (tzone), "%Z", &tt);
        mono_array_setref ((*names), 0, mono_string_new_checked (domain, tzone, &error));
        mono_array_setref ((*names), 1, mono_string_new_checked (domain, tzone, &error));
        mono_array_set ((*data), gint64, 0, 0);
        mono_array_set ((*data), gint64, 1, 0);
        mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
        mono_array_set ((*data), gint64, 3, 0);
        *daylight_inverted = 0;
    }
 
    return 1;
#else
    //On Windows, we should always load timezones in managed
    return 0;
#endif
}