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