1 /*
2    Copyright (c) by Valery Goryachev (Wal)
3 */
4 
5 
6 #ifndef WAL_SYS_API_H
7 #define WAL_SYS_API_H
8 
9 #ifdef _WIN32
10 #  if !defined( NOMINMAX )
11 #     define NOMINMAX
12 #  endif
13 #  include <windows.h>
14 #else
15 #  include <sys/types.h>
16 #  include <sys/stat.h>
17 #  include <fcntl.h>
18 #  include <unistd.h>
19 #  include <pthread.h>
20 #  include <string.h>
21 #  include <stdlib.h>
22 #endif
23 
24 #include <errno.h>
25 
26 #include "System/Types.h"
27 
28 namespace wal
29 {
30 	typedef wchar_t unicode_t;
31 
32 	typedef int64_t seek_t;
33 
34 #ifdef _WIN32
35 	//typedef unsigned short sys_char_t;
36 	typedef wchar_t sys_char_t;
37 
sys_strlen(const sys_char_t * s)38 	inline int sys_strlen( const sys_char_t* s ) { return int( wcslen( s ) ); }
39 
40 	typedef HANDLE file_t;
41 
42 #  define FILE_NULL INVALID_HANDLE_VALUE
43 
valid_file(file_t fd)44 	inline bool valid_file( file_t fd ) { return fd != FILE_NULL; }
45 
46 #  define DIR_SPLITTER '\\'
47 
48 #else
49 	typedef char sys_char_t;
sys_strlen(const sys_char_t * s)50 	inline int sys_strlen( const sys_char_t* s ) { return strlen( s ); }
51 
52 	typedef int file_t;
53 
54 	enum {FILE_NULL = -1 };
55 
valid_file(file_t fd)56 	inline bool valid_file( file_t fd ) { return fd >= 0; }
57 
58 #  define DIR_SPLITTER '/'
59 
60 	typedef pthread_t thread_t;
61 	typedef pthread_mutex_t mutex_t;
62 	typedef pthread_cond_t cond_t;
63 
64 
65 #endif
66 
67 /////////////////////////////////////////// charset defs
68 	struct charset_struct
69 	{
70 		int id;
71 		const char* name;
72 		const char* comment;
73 
74 		char tabChar;
75 
76 		unicode_t* ( *cs_to_unicode )( unicode_t* buf, const char* s, int size, int* badCount );
77 		char* ( *unicode_to_cs )( char* s, const unicode_t* buf, int usize, int* badCount );
78 		int ( *symbol_count )( const char* s, int size );
79 		int ( *string_buffer_len )( const unicode_t* s, int ulen );
80 
IsTabcharset_struct81 		bool IsTab( char* s, char* endLine ) { return ( s && s < endLine && *s == tabChar ); }
82 		char* ( *GetNext )( char* s, char* endLine );
83 		char* ( *_GetPrev )( char* s, char* beginLine );
84 		unicode_t ( *GetChar )( char* s, char* endLine );
85 		int ( *SetChar )( char* buf, unicode_t ch ); //return count of chars in buffer (buf is 8 chars minimun)
86 		char* GetPrev( char* s, char* beginLine );
87 
88 		charset_struct( int _id, const char* _name, const char* _comment );
89 	};
90 
GetPrev(char * s,char * beginLine)91 	inline char* charset_struct::GetPrev( char* s, char* beginLine )
92 	{
93 		if ( _GetPrev ) { return _GetPrev( s, beginLine ); }
94 
95 		if ( s <=  beginLine ) { return 0; }
96 
97 		char* p = 0;
98 		char* t = beginLine;
99 
100 		while ( t )
101 		{
102 			p = t;
103 			t = GetNext( t, s );
104 		}
105 
106 		return p;
107 	}
108 
109 
110 	enum CHARSET_ID
111 	{
112 		CS_LATIN1 = 0,
113 		CS_ISO8859_1 = 0,
114 		CS_UTF8 = 1,
115 		CS_CP437,
116 		CS_CP737,
117 		CS_CP775,
118 		CS_CP850,
119 		CS_CP852,
120 		CS_CP855,
121 		CS_CP857,
122 		CS_CP860,
123 		CS_CP861,
124 		CS_CP862,
125 		CS_CP863,
126 		CS_CP864,
127 		CS_CP865,
128 		CS_CP866,
129 		CS_CP869,
130 		CS_CP874,
131 		CS_EBCDIC_037,
132 		CS_EBCDIC_1025,
133 		CS_EBCDIC_1026,
134 		CS_EBCDIC_500,
135 		CS_EBCDIC_875,
136 
137 		CS_ISO8859_2,
138 		CS_ISO8859_3,
139 		CS_ISO8859_4,
140 		CS_ISO8859_5,
141 		CS_ISO8859_6,
142 		CS_ISO8859_7,
143 		CS_ISO8859_8,
144 		CS_ISO8859_9,
145 		CS_ISO8859_10,
146 		CS_ISO8859_11,
147 		CS_ISO8859_13,
148 		CS_ISO8859_14,
149 		CS_ISO8859_15,
150 		CS_ISO8859_16,
151 		CS_KOI8R,
152 		CS_KOI8U,
153 		CS_MAC_CYRILLIC,
154 		CS_MAC_GREEK,
155 		CS_MAC_ICELAND,
156 		CS_MAC_LATIN2,
157 		CS_MAC_ROMAN,
158 		CS_MAC_TURKISH,
159 		CS_WIN1250,
160 		CS_WIN1251,
161 		CS_WIN1252,
162 		CS_WIN1253,
163 		CS_WIN1254,
164 		CS_WIN1255,
165 		CS_WIN1256,
166 		CS_WIN1257,
167 		CS_WIN1258
168 		//CS_end
169 	};
170 
171 
172 #ifndef _WIN32
173 	extern int sys_charset_id;
174 #endif
175 
176 	extern charset_struct charsetLatin1;
177 //extern charset_struct charsetUtf8;
178 
179 	class CharsetTable
180 	{
181 //public:
182 		enum { TABLESIZE = 128 };
183 		charset_struct* table[TABLESIZE];
184 	public:
185 		CharsetTable(); //{ for (int i = 0; i<TABLESIZE; i++) table[i]=&charsetLatin1; }
186 		void Add( charset_struct* );
Get(int id)187 		charset_struct* Get( int id ) { return id >= 0 && id < TABLESIZE && table[id] ? table[id] : &charsetLatin1; }
188 		charset_struct* operator [] ( int id ) { return Get( id ); }
189 		const char* NameById( int id );
190 		int IdByName( const char* s );
191 		int GetList( charset_struct**, int size );
192 	};
193 
194 	extern CharsetTable charset_table;
195 
196 	/*inline charset_struct* get_charset(int id){
197 	   charset_struct *p = charset_table;
198 	   while (p->id != id && p->id>=0) p++;
199 	   return p->id >=0 ? p : 0;
200 	}*/
201 
202 	/*
203 	const char *CharsetNameByID(int id);
204 	int CharsetIdByName(const char *s);
205 	*/
206 
207 //////////////////////////////////////////
208 
209 	enum OPEN_FILE_FLAG
210 	{
211 		FOPEN_READ = 1,
212 		FOPEN_WRITE = 2,
213 		FOPEN_RW = 3,
214 
215 		FOPEN_CREATE = 4, //open if exist and create if not exist
216 		FOPEN_SYNC = 8,
217 		FOPEN_TRUNC = 16 //truncate if exist
218 	};
219 
220 	enum SEEK_FILE_MODE
221 	{
222 #ifdef _WIN32
223 		FSEEK_BEGIN = FILE_BEGIN,
224 		FSEEK_POS   = FILE_CURRENT,
225 		FSEEK_END   = FILE_END
226 #else
227 		FSEEK_BEGIN = SEEK_SET,
228 		FSEEK_POS   = SEEK_CUR,
229 		FSEEK_END   = SEEK_END
230 #endif
231 	};
232 
233 #ifdef _WIN32
SysErrorIsFileNotFound(int e)234 	inline bool SysErrorIsFileNotFound( int e ) { return e == ERROR_FILE_NOT_FOUND; }
235 #else
SysErrorIsFileNotFound(int e)236 	inline bool SysErrorIsFileNotFound( int e ) { return e == ENOENT; }
237 #endif
238 
239 
240 #ifdef _WIN32
241 
242 	//return count of characters (length of buffer for conversion to unicode)
243 	extern int sys_symbol_count( const sys_char_t* s, int len = -1 );
244 
245 	//return count of sys_chars for saving s
246 	extern int sys_string_buffer_len( const unicode_t* s, int ulen = -1 ); //not including \0
247 
248 	// return point of appended \0
249 	extern unicode_t* sys_to_unicode(
250 	   unicode_t* buf,
251 	   const sys_char_t* s, int len = -1,
252 	   int* badCount = 0 );
253 
254 	// return point of appended \0
255 	extern sys_char_t* unicode_to_sys(
256 	   sys_char_t* s,
257 	   const unicode_t* buf, int ulen = -1,
258 	   int* badCount = 0 );
259 
260 #else
261 	//return count of characters (length of buffer for conversion to unicode)
262 	extern int ( *fp_sys_symbol_count )( const sys_char_t* s, int len );
263 
264 	//return count of sys_chars for saving s
265 	extern int ( *fp_sys_string_buffer_len )( const unicode_t* s, int ulen ); //not including \0
266 
267 	// return point of appended \0
268 	extern unicode_t* ( *fp_sys_to_unicode )(
269 	   unicode_t* buf,
270 	   const sys_char_t* s, int len,
271 	   int* badCount );
272 
273 	// return point of appended \0
274 	extern sys_char_t* ( *fp_unicode_to_sys )(
275 	   sys_char_t* s,
276 	   const unicode_t* buf, int len,
277 	   int* badCount );
278 
279 	inline int sys_symbol_count( const sys_char_t* s, int len = -1 ) { return  fp_sys_symbol_count( s, len ); } ;
280 	inline int sys_string_buffer_len( const unicode_t* s, int ulen = -1 ) { return fp_sys_string_buffer_len( s, ulen ); }
281 	inline unicode_t* sys_to_unicode(
282 	   unicode_t* buf,
283 	   const sys_char_t* s, int len = -1,
284 	   int* badCount = 0 ) { return fp_sys_to_unicode( buf, s, len, badCount ); }
285 
286 	inline sys_char_t* unicode_to_sys(
287 	   sys_char_t* s,
288 	   const unicode_t* buf, int ulen = -1,
289 	   int* badCount = 0 ) { return fp_unicode_to_sys( s, buf, ulen, badCount ); }
290 #endif
291 
292 	unicode_t*  latin1_to_unicode ( unicode_t* buf, const char* s, int size = -1, int* badCount = 0 );
293 	char*    unicode_to_latin1 ( char* s, const unicode_t* buf, int usize = -1, int* badCount = 0 );
294 	int      latin1_symbol_count  ( const char* s, int size = -1 );
295 	int      latin1_string_buffer_len( const unicode_t* buf, int ulen = -1 );
296 
297 	unicode_t*  utf8_to_unicode      ( unicode_t* buf, const char* s, int size = -1, int* badCount = 0 );
298 	char*    unicode_to_utf8      ( char* s, const unicode_t* buf, int usize = -1, int* badCount = 0 );
299 	int      utf8_symbol_count ( const char* s, int size = -1 );
300 	int      utf8_string_buffer_len  ( const unicode_t* buf, int ulen = -1 );
301 
302 
get_sys_error()303 	inline int get_sys_error()
304 	{
305 #ifdef _WIN32
306 		return GetLastError();
307 #else
308 		return errno;
309 #endif
310 	}
311 
set_sys_error(int e)312 	inline void set_sys_error( int e )
313 	{
314 #ifdef _WIN32
315 		SetLastError( e );
316 #else
317 		errno = e;
318 #endif
319 	}
320 
321 	sys_char_t* sys_error_str( int err, sys_char_t* buf, int size );
322 
323 	int unicode_strlen( const unicode_t* s );
324 	unicode_t* unicode_strchr( const unicode_t* s, unicode_t c );
325 	unicode_t* unicode_strrchr(const unicode_t* s, unicode_t c );
326 	unicode_t* unicode_strcpy( unicode_t* d, const unicode_t* s );
327 	// copy unlit end of string, or when n chars copid, whichever comes first.
328 	// d is always 0-ended
329 	unicode_t* unicode_strncpy0( unicode_t* d, const unicode_t* s, int n );
330 	void unicode_strcat( unicode_t* d, const unicode_t* s );
331 	unicode_t* unicode_strdup( const unicode_t* s );
332 
333 //for internal use
334 	class SysStringStruct
335 	{
336 #define SSS_BUF_SIZE 1024
337 #define SSS_UNICODE_BUF_SIZE 1024
338 
339 		sys_char_t buffer[SSS_BUF_SIZE];
340 		sys_char_t* p;
341 
set_oom()342 		void set_oom()
343 		{
344 #ifdef _WIN32
345 			set_sys_error( ERROR_OUTOFMEMORY );
346 #else
347 			set_sys_error( ENOMEM );
348 #endif
349 		}
350 
351 		void set_unicode( const unicode_t* s, int len = -1 )
352 		{
353 			int sys_len = sys_string_buffer_len( s, len );
354 
355 			if ( sys_len < SSS_BUF_SIZE ) { p = buffer; }
356 			else { p = ( sys_char_t* ) malloc( sizeof( sys_char_t ) * ( sys_len + 1 ) ); }
357 
358 			if ( p )
359 			{
360 				unicode_to_sys( p, s, len );
361 				/*
362 				printf("len=%i\n", len);
363 				char *t =p;
364 				for (;*t;t++)
365 				   printf("!'%c'\n", char(*t));
366 				*/
367 
368 			}
369 			else { set_oom(); }
370 		}
371 #undef SSS_BUF_SIZE
372 
373 
374 		void set_utf8( const char* s, int len = -1 )
375 		{
376 			unicode_t unicode_buffer[SSS_UNICODE_BUF_SIZE];
377 			int unicode_len = utf8_symbol_count( s, len );
378 			unicode_t* uPtr = ( unicode_len < SSS_UNICODE_BUF_SIZE ) ? unicode_buffer : ( unicode_t* )malloc( sizeof( unicode_t ) * ( unicode_len + 1 ) );
379 
380 			if ( uPtr )
381 			{
382 				utf8_to_unicode( uPtr, s, len );
383 				/*
384 				unicode_t *t =uPtr;
385 				for (;*t;t++)
386 				   printf("'%c'\n", char(*t));
387 				*/
388 
389 				set_unicode( uPtr, unicode_len );
390 
391 				if ( uPtr != unicode_buffer ) { free( uPtr ); }
392 			}
393 			else { set_oom(); }
394 		}
395 
396 	public:
SysStringStruct(const char * s)397 		SysStringStruct( const char* s ): p( 0 ) { set_utf8( s );}
get()398 		const sys_char_t* get() { return p; }
~SysStringStruct()399 		~SysStringStruct() { if ( p && p != buffer ) { free( p ); } }
400 	};
401 
402 
403 	file_t file_open( const sys_char_t* filename,  int open_flag = FOPEN_READ );
404 	file_t file_open_utf8( const char* filename, int open_flag = FOPEN_READ );
405 
file_read(file_t fid,void * buf,int size)406 	inline int file_read( file_t fid, void* buf, int size )
407 	{
408 #ifdef _WIN32
409 		DWORD retsize;
410 		return ReadFile( fid, buf, size, &retsize, 0 ) ? retsize : -1;
411 #else
412 		return read( fid, buf, size );
413 #endif
414 	}
415 
file_write(file_t fid,void * buf,int size)416 	inline int file_write( file_t fid, void* buf, int size )
417 	{
418 #ifdef _WIN32
419 		DWORD retsize;
420 		return WriteFile( fid, buf, size, &retsize, 0 ) ? retsize : -1;
421 #else
422 		return write( fid, buf, size );
423 #endif
424 	}
425 
426 	inline seek_t file_seek( file_t fid, seek_t distance, SEEK_FILE_MODE method = FSEEK_BEGIN )
427 	{
428 #ifdef _WIN32
429 		LARGE_INTEGER li;
430 		li.QuadPart = distance;
431 		li.LowPart = SetFilePointer ( fid, li.LowPart, &li.HighPart, method );
432 
433 		if ( li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
434 		{
435 			return -1;
436 		}
437 
438 		return li.QuadPart;
439 #else
440 		return lseek( fid, distance, method );
441 #endif
442 	}
443 
file_close(file_t fid)444 	inline int file_close( file_t fid )
445 	{
446 #ifdef _WIN32
447 		return CloseHandle( fid ) ? 0 : -1;
448 #else
449 		return close( fid );
450 #endif
451 	}
452 
453 #ifdef _WIN32
454 
455 	struct _thread_info;
456 	typedef _thread_info* thread_t;
457 
458 	typedef CRITICAL_SECTION mutex_t;
459 
460 	struct cond_t
461 	{
462 		HANDLE ev[2]; //??volatile
463 	};
464 
465 	int thread_create( thread_t* th, void* ( *f )( void* ), void* arg, bool detached = false );
466 	int thread_join( thread_t th, void** val );
467 	thread_t thread_self();
thread_equal(thread_t a,thread_t b)468 	inline bool thread_equal( thread_t a, thread_t b ) { return a == b; }
469 
mutex_create(mutex_t * m)470 	inline int mutex_create( mutex_t* m ) { InitializeCriticalSection( m ); return 0; }
mutex_delete(mutex_t * m)471 	inline int mutex_delete( mutex_t* m ) { DeleteCriticalSection( m ); return 0; }
mutex_lock(mutex_t * m)472 	inline int mutex_lock( mutex_t* m ) { EnterCriticalSection( m ); return 0; }
mutex_trylock(mutex_t * m)473 	inline int mutex_trylock( mutex_t* m ) { return TryEnterCriticalSection( m ) ? 0 : EBUSY ; }
mutex_unlock(mutex_t * m)474 	inline int mutex_unlock( mutex_t* m ) { LeaveCriticalSection( m ); return 0; }
475 
476 	int cond_create( cond_t* c );
477 	int cond_delete( cond_t* c );
478 	int cond_wait( cond_t* c, mutex_t* m );
479 	int cond_signal( cond_t* c );
480 	int cond_broadcast( cond_t* c );
481 
482 
483 //...
484 #else
485 	inline int thread_create( thread_t* th, void* ( *f )( void* ), void* arg, bool detached = false )
486 	{
487 		int r = pthread_create( th, 0, f, arg );
488 
489 		if ( !r && detached ) { r = pthread_detach( *th ); }
490 
491 		return r;
492 	}
493 
thread_join(thread_t th,void ** val)494 	inline int thread_join( thread_t th, void** val ) { return pthread_join( th, val ); }
mutex_create(mutex_t * m)495 	inline int mutex_create( mutex_t* m ) { return pthread_mutex_init( m, 0 ); }
mutex_delete(mutex_t * m)496 	inline int mutex_delete( mutex_t* m ) { return pthread_mutex_destroy( m ); }
mutex_lock(mutex_t * m)497 	inline int mutex_lock( mutex_t* m ) { return pthread_mutex_lock( m ); }
mutex_trylock(mutex_t * m)498 	inline int mutex_trylock( mutex_t* m ) { return pthread_mutex_trylock( m ); }
mutex_unlock(mutex_t * m)499 	inline int mutex_unlock( mutex_t* m ) { return pthread_mutex_unlock( m ); }
cond_create(cond_t * c)500 	inline int cond_create( cond_t* c ) { return pthread_cond_init( c, 0 ); }
cond_delete(cond_t * c)501 	inline int cond_delete( cond_t* c ) { return pthread_cond_destroy( c ); }
cond_wait(cond_t * c,mutex_t * m)502 	inline int cond_wait( cond_t* c, mutex_t* m ) { return pthread_cond_wait( c, m ); }
cond_signal(cond_t * c)503 	inline int cond_signal( cond_t* c ) { return pthread_cond_signal( c );}
cond_broadcast(cond_t * c)504 	inline int cond_broadcast( cond_t* c ) { return pthread_cond_broadcast( c );};
thread_self()505 	inline thread_t thread_self() { return pthread_self(); }
thread_equal(thread_t a,thread_t b)506 	inline bool thread_equal( thread_t a, thread_t b ) { return pthread_equal( a, b ) != 0; }
507 
508 #endif
509 
510 
511 #ifdef _DEBUG
512 	void dbg_printf( const char* format, ... );
513 #else
dbg_printf(const char * format,...)514 	inline void dbg_printf( const char* format, ... ) { }
515 #endif
516 
517 	const char* sys_locale_lang();
518 	const char* sys_locale_ter();
519 	const char* sys_locale_lang_ter();
520 
521 }; //namespace wal
522 
523 using namespace wal;
524 
525 #endif
526