TODO: Implement gAddressExt group
[libisds.git] / src / win32.c
blob8492cdc2c74dbc3cbc614b3e9063bb1ccf1722fd
1 #include <stdio.h>
2 #include <string.h>
3 #include "isds.h"
4 #include "isds_priv.h"
5 #include "utils.h"
6 #include "win32.h"
8 #if HAVE_LIBCURL
9 static void yday2mday(struct tm *time) {
10 static int mtab[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
11 int i, year = 1900 + time->tm_year;
13 mtab[1] = (!(year % 4) && ((year % 100) || !(year %400))) ? 29 : 28;
14 time->tm_mday = time->tm_yday + 1;
16 for (i = 0; i < 12; i++) {
17 if (time->tm_mday > mtab[i]) {
18 time->tm_mday -= mtab[i];
19 } else {
20 break;
24 time->tm_mon = i;
27 /* Convert UTF-8 @string representation of ISO 8601 date to @time.
28 * XXX: Not all ISO formats are supported */
29 isds_error _isds_datestring2tm(const xmlChar *string, struct tm *time) {
30 char *ptr;
31 int len, tmp;
32 if (!string || !time) return IE_INVAL;
34 memset(time, 0, sizeof(*time));
36 if (sscanf((const char*)string, "%d-%d-%d%n",
37 &time->tm_year, &time->tm_mon, &time->tm_mday, &tmp) >= 3
38 && tmp == strlen((const char*)string)) {
39 time->tm_mon--;
40 time->tm_year -= 1900;
41 return IE_SUCCESS;
44 memset(time, 0, sizeof(*time));
46 if (sscanf((const char*)string, "%d-%d%n",
47 &time->tm_year, &time->tm_yday, &tmp) >= 2
48 && tmp == strlen((const char*)string)) {
49 time->tm_yday--;
50 time->tm_year -= 1900;
51 yday2mday(time);
52 return IE_SUCCESS;
55 memset(time, 0, sizeof(*time));
56 len = strlen((const char*)string);
58 if (len < 4) {
59 return IE_NOTSUP;
62 ptr = strdup((const char*)string);
64 if (sscanf(ptr + len - 2, "%d%n", &time->tm_mday, &tmp) < 1 || tmp < 2) {
65 free(ptr);
66 return IE_NOTSUP;
69 ptr[len - 2] = '\0';
71 if (sscanf(ptr + len - 4, "%d%n", &time->tm_mon, &tmp) < 1 || tmp < 2) {
72 free(ptr);
73 return IE_NOTSUP;
76 ptr[len - 4] = '\0';
78 if (sscanf(ptr, "%d%n", &time->tm_year, &tmp) < 1 || tmp < len - 4) {
79 free(ptr);
80 return IE_NOTSUP;
83 free(ptr);
84 time->tm_mon--;
85 time->tm_year -= 1900;
86 return IE_SUCCESS;
88 #endif
90 /* MSVCRT gmtime() uses thread-local buffer. This is reentrant. */
91 _hidden struct tm *gmtime_r(const time_t *timep, struct tm *result) {
92 struct tm *buf;
94 buf = gmtime(timep);
96 if (!buf) {
97 return NULL;
100 memcpy(result, buf, sizeof(struct tm));
101 return result;
104 _hidden char *strndup(const char *s, size_t n) {
105 char *ret;
106 size_t len;
108 len = strlen(s);
109 len = len > n ? n : len;
110 ret = malloc((len + 1) * sizeof(char));
112 if (!ret) {
113 return NULL;
116 strncpy(ret, s, len);
117 ret[len] = '\0';
118 return ret;
121 /* Convert UTC broken time to time_t.
122 * @broken_utc it time in UTC in broken format. Despite its content is not
123 * touched, it'sw not-const because underlying POSIX function has non-const
124 * signature.
125 * @return (time_t) -1 in case of error */
126 _hidden time_t _isds_timegm(struct tm *broken_utc) {
127 time_t ret;
128 time_t diff;
129 struct tm broken, *tmp;
131 ret = time(0);
132 tmp = gmtime(&ret);
134 if (!tmp) {
135 return (time_t)-1;
138 tmp->tm_isdst = broken_utc->tm_isdst;
139 diff = ret - mktime(tmp);
140 memcpy(&broken, broken_utc, sizeof(struct tm));
141 broken.tm_isdst = tmp->tm_isdst; /* handle broken_utc->tm_isdst < 0 */
142 ret = mktime(&broken) + diff;
143 return ret;
146 ssize_t getline(char **bufptr, size_t *length, FILE *fp) {
147 int pos = 0;
148 char *ret = NULL;
150 if (!*bufptr || *length < 1) {
151 free(*bufptr);
152 *length = 256;
153 *bufptr = malloc(*length * sizeof(char));
156 if (!*bufptr) {
157 *length = 0;
158 return -1;
161 do {
162 if (ret) {
163 *length *= 2;
164 ret = realloc(*bufptr, *length * sizeof(char));
166 if (!ret) {
167 free(*bufptr);
168 *bufptr = NULL;
169 *length = 0;
170 return -1;
173 *bufptr = ret;
176 ret = fgets(*bufptr + pos, *length, fp);
178 if (ret) {
179 pos = strlen(*bufptr);
181 } while (ret && (*bufptr)[pos - 1] != '\n');
183 return pos || ret ? pos : -1;