Open Chinese Convert 0.4.3 A project for conversion between Traditional and Simplified Chinese

- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- Examples

- File List
- Globals

All Data Structures Files Functions Variables Groups Pages
utils.c
1 /*
2 * Open Chinese Convert
3 *
4 * Copyright 2010-2013 BYVoid <byvoid@byvoid.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include "utils.h"
20 #include <unistd.h>
21
22 #ifdef __APPLE__
23 #include "TargetConditionals.h"
24 #ifdef TARGET_OS_MAC
25 #include <mach-o/dyld.h>
26 #elif TARGET_OS_IPHONE
27 #elif TARGET_IPHONE_SIMULATOR
28 #else /* ifdef TARGET_OS_MAC */
29 #endif /* ifdef TARGET_OS_MAC */
30 #elif defined _WIN32 || defined _WIN64
31 #include "Windows.h"
32 #endif /* ifdef __APPLE__ */
33
34 #if defined _WIN32 || defined _WIN64
35 #define PATH_SEPARATOR '\\'
36 #else
37 #define PATH_SEPARATOR '/'
38 #endif
39
40 #define PATH_BUFFER_SIZE 4096
41
42 void perr(const char* str) {
43 fputs(str, stderr);
44 }
45
46 int qsort_int_cmp(const void* a, const void* b) {
47 return *((int*)a) - *((int*)b);
48 }
49
50 char* mstrcpy(const char* str) {
51 char* strbuf = (char*)malloc(sizeof(char) * (strlen(str) + 1));
52
53 strcpy(strbuf, str);
54 return strbuf;
55 }
56
57 char* mstrncpy(const char* str, size_t n) {
58 char* strbuf = (char*)malloc(sizeof(char) * (n + 1));
59
60 strncpy(strbuf, str, n);
61 strbuf[n] = '\0';
62 return strbuf;
63 }
64
65 void skip_utf8_bom(FILE* fp) {
66 int bom[3];
67 int n;
68
69 /* UTF-8 BOM is EF BB BF */
70 if (fp == NULL) {
71 return;
72 }
73
74 /* If we are not at beginning of file, return */
75 if (ftell(fp) != 0) {
76 return;
77 }
78
79 /* Try to read first 3 bytes */
80 for (n = 0; n <= 2 && (bom[n] = getc(fp)) != EOF; n++) {}
81
82 /* If we can only read <3 bytes, push them back */
83 /* Or if first 3 bytes is not BOM, push them back */
84 if ((n < 3) || (bom[0] != 0xEF) || (bom[1] != 0xBB) || (bom[2] != 0xBF)) {
85 for (n--; n >= 0; n--) {
86 ungetc(bom[n], fp);
87 }
88 }
89
90 /* Otherwise, BOM is already skipped */
91 }
92
93 const char* executable_path(void) {
94 static char path_buffer[PATH_BUFFER_SIZE];
95 static int calculated = 0;
96
97 if (!calculated) {
98 #ifdef __linux
99 ssize_t res = readlink("/proc/self/exe", path_buffer, sizeof(path_buffer));
100 assert(res != -1);
101 #elif __APPLE__
102 uint32_t size = sizeof(path_buffer);
103 int res = _NSGetExecutablePath(path_buffer, &size);
104 assert(res == 0);
105 #elif _WIN32 || _WIN64
106 // NOTE: for "C:\\opencc.exe" on Windows, the returned path "C:" is
107 // incorrect until a '/' is appended to it later in try_open_file()
108 DWORD res = GetModuleFileNameA(NULL, path_buffer, PATH_BUFFER_SIZE);
109 assert(res != 0);
110 #else
111 /* Other unsupported os */
112 assert(0);
113 #endif /* ifdef __linux */
114 char* last_sep = strrchr(path_buffer, PATH_SEPARATOR);
115 assert(last_sep != NULL);
116 *last_sep = '\0';
117 calculated = 1;
118 }
119 return path_buffer;
120 }
121
122 char* try_open_file(const char* path) {
123 /* Try to find file in current working directory */
124 FILE* fp = fopen(path, "r");
125
126 if (fp) {
127 fclose(fp);
128 return mstrcpy(path);
129 }
130
131 /* If path is absolute, return NULL */
132 if (is_absolute_path(path)) {
133 return NULL;
134 }
135
136 /* Try to find file in executable directory */
137 const char* exe_dir = executable_path();
138 char* filename =
139 (char*)malloc(sizeof(char) * (strlen(path) + strlen(exe_dir) + 2));
140 sprintf(filename, "%s/%s", exe_dir, path);
141 fp = fopen(filename, "r");
142
143 if (fp) {
144 fclose(fp);
145 return filename;
146 }
147 free(filename);
148
149 /* Try to use PKGDATADIR */
150 filename =
151 (char*)malloc(sizeof(char) * (strlen(path) + strlen(PKGDATADIR) + 2));
152 sprintf(filename, "%s/%s", PKGDATADIR, path);
153 fp = fopen(filename, "r");
154
155 if (fp) {
156 fclose(fp);
157 return filename;
158 }
159 free(filename);
160 return NULL;
161 }
162
163 char* get_file_path(const char* filename) {
164 const char* last_sep = strrchr(filename, '/');
165
166 if (last_sep == NULL) {
167 last_sep = filename;
168 }
169 char* path = mstrncpy(filename, last_sep - filename);
170 return path;
171 }
172
173 int is_absolute_path(const char* path) {
174 if (path[0] == '/') {
175 return 1;
176 }
177
178 if (path[1] == ':') {
179 return 1;
180 }
181 return 0;
182 }