1 /*
2   Native File Dialog
3 
4   http://www.frogtoss.com/labs
5  */
6 
7 #include <stdlib.h>
8 #include <assert.h>
9 #include <string.h>
10 #include "nfd_common.h"
11 
12 static char g_errorstr[NFD_MAX_STRLEN] = {0};
13 
14 /* public routines */
15 
NFD_FreePath(nfdchar_t * outPath)16 void NFD_FreePath( nfdchar_t *outPath )
17 {
18 	NFDi_Free( outPath );
19 }
20 
NFD_GetError(void)21 const char *NFD_GetError( void )
22 {
23     return g_errorstr;
24 }
25 
NFD_PathSet_GetCount(const nfdpathset_t * pathset)26 size_t NFD_PathSet_GetCount( const nfdpathset_t *pathset )
27 {
28     assert(pathset);
29     return pathset->count;
30 }
31 
NFD_PathSet_GetPath(const nfdpathset_t * pathset,size_t num)32 nfdchar_t *NFD_PathSet_GetPath( const nfdpathset_t *pathset, size_t num )
33 {
34     assert(pathset);
35     assert(num < pathset->count);
36 
37     return pathset->buf + pathset->indices[num];
38 }
39 
NFD_PathSet_Free(nfdpathset_t * pathset)40 void NFD_PathSet_Free( nfdpathset_t *pathset )
41 {
42     assert(pathset);
43     NFDi_Free( pathset->indices );
44     NFDi_Free( pathset->buf );
45 }
46 
47 /* internal routines */
48 
NFDi_Malloc(size_t bytes)49 void *NFDi_Malloc( size_t bytes )
50 {
51     void *ptr = malloc(bytes);
52     if ( !ptr )
53         NFDi_SetError("NFDi_Malloc failed.");
54 
55     return ptr;
56 }
57 
NFDi_Free(void * ptr)58 void NFDi_Free( void *ptr )
59 {
60     assert(ptr);
61     free(ptr);
62 }
63 
NFDi_SetError(const char * msg)64 void NFDi_SetError( const char *msg )
65 {
66     int bTruncate = NFDi_SafeStrncpy( g_errorstr, msg, NFD_MAX_STRLEN );
67     assert( !bTruncate );  _NFD_UNUSED(bTruncate);
68 }
69 
70 
NFDi_SafeStrncpy(char * dst,const char * src,size_t maxCopy)71 int NFDi_SafeStrncpy( char *dst, const char *src, size_t maxCopy )
72 {
73     size_t n = maxCopy;
74     char *d = dst;
75 
76     assert( src );
77     assert( dst );
78 
79     while ( n > 0 && *src != '\0' )
80     {
81         *d++ = *src++;
82         --n;
83     }
84 
85     /* Truncation case -
86        terminate string and return true */
87     if ( n == 0 )
88     {
89         dst[maxCopy-1] = '\0';
90         return 1;
91     }
92 
93     /* No truncation.  Append a single NULL and return. */
94     *d = '\0';
95     return 0;
96 }
97 
98 
99 /* adapted from microutf8 */
NFDi_UTF8_Strlen(const nfdchar_t * str)100 size_t NFDi_UTF8_Strlen( const nfdchar_t *str )
101 {
102 	/* This function doesn't properly check validity of UTF-8 character
103 	sequence, it is supposed to use only with valid UTF-8 strings. */
104 
105 	size_t character_count = 0;
106 	size_t i = 0; /* Counter used to iterate over string. */
107 	nfdchar_t maybe_bom[4];
108 
109 	/* If there is UTF-8 BOM ignore it. */
110 	if (strlen(str) > 2)
111 	{
112 		strncpy(maybe_bom, str, 3);
113 		maybe_bom[3] = 0;
114 		if (strcmp(maybe_bom, (nfdchar_t*)NFD_UTF8_BOM) == 0)
115 			i += 3;
116 	}
117 
118 	while(str[i])
119 	{
120 		if (str[i] >> 7 == 0)
121         {
122             /* If bit pattern begins with 0 we have ascii character. */
123 			++character_count;
124         }
125 		else if (str[i] >> 6 == 3)
126         {
127 		/* If bit pattern begins with 11 it is beginning of UTF-8 byte sequence. */
128 			++character_count;
129         }
130 		else if (str[i] >> 6 == 2)
131 			;		/* If bit pattern begins with 10 it is middle of utf-8 byte sequence. */
132 		else
133         {
134             /* In any other case this is not valid UTF-8. */
135 			return (size_t)(-1);
136         }
137 		++i;
138 	}
139 
140 	return character_count;
141 }
142 
NFDi_IsFilterSegmentChar(char ch)143 int NFDi_IsFilterSegmentChar( char ch )
144 {
145     return (ch==','||ch==';'||ch=='\0');
146 }
147 
148