summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/MinKD.c
blob: a96752bff64c3e1f6fa1bc8dac9be1933517176d (plain)
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
#include "kd.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <memory.h>
#include <pthread.h>
#include <dirent.h>


KDFile* kdFopen(const KDchar* pathname, const KDchar* mode)
{
	FILE* retval;
	retval = fopen( pathname, mode );
	return (KDFile*)retval;
}


KDsize kdFread(void *buffer, KDsize size, KDsize count, KDFile *file)
{
	return fread( buffer, size, count, (FILE*)file );
}

/* kdFwrite: Write to a file. */
KDsize kdFwrite(const void *buffer, KDsize size, KDsize count, KDFile *file)
{
	return fwrite( buffer, size, count, (FILE*)file );
}

KDint kdFclose(KDFile *file)
{
	return fclose( (FILE*)file );
}

/* kdCosf: Cosine function. */
KDfloat32 kdCosf(KDfloat32 x) { return cosf( x ); }

/* kdSinf: Sine function. */
KDfloat32 kdSinf(KDfloat32 x) { return sinf( x ); }

KDfloat32 kdSqrtf(KDfloat32 x ) { return sqrtf( x ); }

KDfloat32 kdTanf( KDfloat32 x ) { return tanf( x ); }

KDint kdAbs(KDint i)
{
	return i < 0 ? -i : i;
}


KDfloat32 kdFabsf(KDfloat32 i) { return fabs( i ); }

/* kdStrcpy_s: Copy a string with an overrun check. */

KDint kdStrcpy_s(KDchar* buf, KDsize buflen, const KDchar* src)
{
    return kdStrncpy_s(buf, buflen, src, -1);
}

/* kdStrncpy_s: Copy a string with an overrun check. */
KDint kdStrncpy_s(KDchar* buf, KDsize buflen, const KDchar* src, KDsize srclen)
{
	if ( srclen == (KDsize)-1)
		srclen = buflen;
    const char* term = memchr(src, 0, srclen);
    if (term)
        srclen = term - src;
    if (srclen >= buflen) {
        if (buflen)
            *buf = 0;
        return KD_EINVAL;
    }
    memcpy(buf, src, srclen);
    buf[srclen] = 0;
    return 0;
}

/* kdStrncat_s: Concatenate two strings. */
KDint kdStrncat_s(KDchar* buf, KDsize buflen, const KDchar* src, KDsize srcmaxlen)
{
    size_t origlen = strlen(buf);
    const char* p = memchr(src, 0, srcmaxlen);
    if (p)
        srcmaxlen = p - src;
    if (origlen + srcmaxlen >= buflen)
    {
        /* spec says "buf[0] is set to 0". But that's bad if buflen == 0!
         * kdStrncpy_s's spec is better here. */
        if (buflen)
            buf[0] = 0;
        return KD_ERANGE;
    }
    memcpy(buf + origlen, src, srcmaxlen);
    buf[origlen + srcmaxlen] = 0;
    return 0;
}
/* kdMemset: Set bytes in memory to a value. */
void* kdMemset(void *buf, KDint byte, KDsize len) { return memset( buf, byte, len ); }

/* kdStrcmp: Compares two strings. */
KDint kdStrcmp(const KDchar *str1, const KDchar *str2) { return strcmp( str1, str2); }

/* kdStrlen: Determine the length of a string. */
KDsize kdStrlen(const KDchar *str) { return strlen( str ); }

void* kdMalloc( KDsize size ) { return malloc(size); }

void kdFree( void* ptr ) { free( ptr ); }

void* kdMemcpy(void *buf, const void *src, KDsize len) { return memcpy( buf, src, len ); }

struct KDThreadMutex
{
    pthread_mutex_t p_mutex;
};

/* kdThreadMutexCreate: Create a mutex. */
KD_API KDThreadMutex* kdThreadMutexCreate(const void *mutexattr)
{
	KDThreadMutex* mutex = malloc(sizeof(KDThreadMutex));
	if (mutex)
	{
		if (pthread_mutex_init(&mutex->p_mutex, NULL) == 0)
		{
			return mutex;
		}
		free(mutex);
	}

	return KD_NULL;
}

/* kdThreadMutexFree: Free a mutex. */
KDint kdThreadMutexFree(KDThreadMutex *mutex)
{
    int res;
    res = pthread_mutex_destroy(&mutex->p_mutex);
    // If the mutex destroy failed, don't free the memory.
    // Per OpenKODE spec, this is undefined behaviour, and
    // we can leak the memory. The reason for this is that
    // later allocations may fail if they happen to go
    // to the same memory
    if (!res)
        free(mutex);
    return 0;
}

/* kdThreadMutexLock: Lock a mutex. */
KDint kdThreadMutexLock(KDThreadMutex *mutex)
{
    (void)pthread_mutex_lock(&mutex->p_mutex);
    return 0;
}

/* kdThreadMutexUnlock: Unlock a mutex. */
KDint kdThreadMutexUnlock(KDThreadMutex *mutex)
{
    pthread_mutex_unlock(&mutex->p_mutex);
    return 0;
}

struct KDThreadAttr
{
    pthread_attr_t p_attr;
};

struct KDThread
{
    pthread_t           Handle;
    uint8_t             Detached;
    uint8_t             IsRunning;
    uint8_t             UserThread;
    void*               (*UserThreadProc)(void*);
    void*               UserArg;
};
/* kdThreadCreate: Create a new thread. */
KDThread * kdThreadCreate(const KDThreadAttr *attr, void *(*start_routine)(void *), void *arg)
{
	pthread_t thread;
	int retval;
	const pthread_attr_t* p_attr;
	if ( attr )
		p_attr = &attr->p_attr;
	else
		p_attr = KD_NULL;

	retval = pthread_create( &thread, p_attr, start_routine, arg );
	if ( retval != 0 )
	{
		return KD_NULL;
	}
	KDThread* newThread = (KDThread*)malloc( sizeof( KDThread ) );
	if ( newThread == KD_NULL ) return KD_NULL;
	newThread->Handle = thread;
	newThread->Detached = 0;
	newThread->IsRunning = 1;
	newThread->UserThread = 1;
	newThread->UserThreadProc = start_routine;
	newThread->UserArg = arg;
	return newThread;
}

/* kdThreadExit: Terminate this thread. */
void kdThreadExit(void *retval)
{
	pthread_exit( retval );
}

/* kdThreadJoin: Wait for termination of another thread. */
KDint kdThreadJoin(KDThread *thread, void **retval)
{
	int join_retval;
	join_retval = pthread_join( thread->Handle, retval );
	if ( join_retval == 0 ) free( thread );
	return join_retval;
}

typedef struct KDDirInternal {
    DIR *dir;
    KDDirent ent;
} KDDirInternal;

/* kdOpenDir: Open a directory ready for listing. */
KDDir *kdOpenDir(const KDchar *pathname)
{
	DIR* dir = opendir( pathname );
	if ( dir == KD_NULL ) return KD_NULL;
	KDDirInternal* retval = (KDDirInternal*)malloc( sizeof( KDDirInternal ));
	if ( retval == KD_NULL ) return KD_NULL;
	memset( retval, 0, sizeof( *retval ) );
	retval->dir = dir;
	return (KDDir*)retval;
}

/* kdReadDir: Return the next file in a directory. */
KDDirent* kdReadDir(KDDir *dir)
{
    struct dirent *sysDirEnt;
    KDDirent *dirent = NULL;

    sysDirEnt = readdir(((KDDirInternal *)dir)->dir);

    if (sysDirEnt) {
        dirent = &((KDDirInternal *)dir)->ent;
        dirent->d_name = sysDirEnt->d_name;
    }
    return dirent;
}

/* kdCloseDir: Close a directory. */
KDint kdCloseDir(KDDir *dir)
{
    closedir(((KDDirInternal *)dir)->dir);
    free(dir);
    return 0;
}

KDint kdSetWindowPropertyiv(KDWindow * win, KDint prop, const KDint32 * val)
{
	return 0;
}

void kdDefaultEvent(const KDEvent *event )
{

}

typedef long long NvS64;

KDust kdGetTimeUST(void)
{
    struct timespec tp;
    clock_gettime(CLOCK_MONOTONIC, &tp);

    return (NvS64)tp.tv_sec * (NvS64)1000000000 +
           (NvS64)tp.tv_nsec;
}

static KDTm* gmlocaltime(
    const KDtime *timep,
    KDTm *result,
    struct tm* (* func)(const time_t* timep, struct tm* result))
{
    struct tm tm;
    time_t t = *timep;
    (*func)(&t, &tm);
    result->tm_sec = tm.tm_sec;
    result->tm_min = tm.tm_min;
    result->tm_hour = tm.tm_hour;
    result->tm_mday = tm.tm_mday;
    result->tm_mon = tm.tm_mon;
    result->tm_year = tm.tm_year;
    result->tm_wday = tm.tm_wday;
    result->tm_yday = tm.tm_yday;
    return result;
}

/* kdGmtime_r, kdLocaltime_r: Convert a seconds-since-epoch time into broken-down time. */
KDTm* kdGmtime_r(const KDtime* timep, KDTm* result)
{
    return gmlocaltime(timep, result, &gmtime_r);
}

KDTm* kdLocaltime_r(const KDtime* timep, KDTm* result)
{
    return gmlocaltime(timep, result, &localtime_r);
}

//===========================================================================
// kdCreateEvent: Create an event for posting.
//===========================================================================
KDEvent* kdCreateEvent(void)
{
	//Memory leak and there isn't much I am going to do about this now
	KDEvent* newEvent = (KDEvent*)malloc( sizeof( KDEvent ));
	memset( newEvent, 0, sizeof( KDEvent ));
	return newEvent;
}