Open Chinese Convert
0.4.3
A project for conversion between Traditional and Simplified Chinese
|
00001 /* 00002 * Open Chinese Convert 00003 * 00004 * Copyright 2010-2013 BYVoid <byvoid@byvoid.com> 00005 * 00006 * Licensed under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 00019 #include "utils.h" 00020 #include <unistd.h> 00021 00022 #ifdef __APPLE__ 00023 #include "TargetConditionals.h" 00024 #ifdef TARGET_OS_MAC 00025 #include <mach-o/dyld.h> 00026 #elif TARGET_OS_IPHONE 00027 #elif TARGET_IPHONE_SIMULATOR 00028 #else /* ifdef TARGET_OS_MAC */ 00029 #endif /* ifdef TARGET_OS_MAC */ 00030 #elif defined _WIN32 || defined _WIN64 00031 #include "Windows.h" 00032 #endif /* ifdef __APPLE__ */ 00033 00034 #if defined _WIN32 || defined _WIN64 00035 #define PATH_SEPARATOR '\\' 00036 #else 00037 #define PATH_SEPARATOR '/' 00038 #endif 00039 00040 #define PATH_BUFFER_SIZE 4096 00041 00042 void perr(const char* str) { 00043 fputs(str, stderr); 00044 } 00045 00046 int qsort_int_cmp(const void* a, const void* b) { 00047 return *((int*)a) - *((int*)b); 00048 } 00049 00050 char* mstrcpy(const char* str) { 00051 char* strbuf = (char*)malloc(sizeof(char) * (strlen(str) + 1)); 00052 00053 strcpy(strbuf, str); 00054 return strbuf; 00055 } 00056 00057 char* mstrncpy(const char* str, size_t n) { 00058 char* strbuf = (char*)malloc(sizeof(char) * (n + 1)); 00059 00060 strncpy(strbuf, str, n); 00061 strbuf[n] = '\0'; 00062 return strbuf; 00063 } 00064 00065 void skip_utf8_bom(FILE* fp) { 00066 int bom[3]; 00067 int n; 00068 00069 /* UTF-8 BOM is EF BB BF */ 00070 if (fp == NULL) { 00071 return; 00072 } 00073 00074 /* If we are not at beginning of file, return */ 00075 if (ftell(fp) != 0) { 00076 return; 00077 } 00078 00079 /* Try to read first 3 bytes */ 00080 for (n = 0; n <= 2 && (bom[n] = getc(fp)) != EOF; n++) {} 00081 00082 /* If we can only read <3 bytes, push them back */ 00083 /* Or if first 3 bytes is not BOM, push them back */ 00084 if ((n < 3) || (bom[0] != 0xEF) || (bom[1] != 0xBB) || (bom[2] != 0xBF)) { 00085 for (n--; n >= 0; n--) { 00086 ungetc(bom[n], fp); 00087 } 00088 } 00089 00090 /* Otherwise, BOM is already skipped */ 00091 } 00092 00093 const char* executable_path(void) { 00094 static char path_buffer[PATH_BUFFER_SIZE]; 00095 static int calculated = 0; 00096 00097 if (!calculated) { 00098 #ifdef __linux 00099 ssize_t res = readlink("/proc/self/exe", path_buffer, sizeof(path_buffer)); 00100 assert(res != -1); 00101 #elif __APPLE__ 00102 uint32_t size = sizeof(path_buffer); 00103 int res = _NSGetExecutablePath(path_buffer, &size); 00104 assert(res == 0); 00105 #elif _WIN32 || _WIN64 00106 // NOTE: for "C:\\opencc.exe" on Windows, the returned path "C:" is 00107 // incorrect until a '/' is appended to it later in try_open_file() 00108 DWORD res = GetModuleFileNameA(NULL, path_buffer, PATH_BUFFER_SIZE); 00109 assert(res != 0); 00110 #else 00111 /* Other unsupported os */ 00112 assert(0); 00113 #endif /* ifdef __linux */ 00114 char* last_sep = strrchr(path_buffer, PATH_SEPARATOR); 00115 assert(last_sep != NULL); 00116 *last_sep = '\0'; 00117 calculated = 1; 00118 } 00119 return path_buffer; 00120 } 00121 00122 char* try_open_file(const char* path) { 00123 /* Try to find file in current working directory */ 00124 FILE* fp = fopen(path, "r"); 00125 00126 if (fp) { 00127 fclose(fp); 00128 return mstrcpy(path); 00129 } 00130 00131 /* If path is absolute, return NULL */ 00132 if (is_absolute_path(path)) { 00133 return NULL; 00134 } 00135 00136 /* Try to find file in executable directory */ 00137 const char* exe_dir = executable_path(); 00138 char* filename = 00139 (char*)malloc(sizeof(char) * (strlen(path) + strlen(exe_dir) + 2)); 00140 sprintf(filename, "%s/%s", exe_dir, path); 00141 fp = fopen(filename, "r"); 00142 00143 if (fp) { 00144 fclose(fp); 00145 return filename; 00146 } 00147 free(filename); 00148 00149 /* Try to use PKGDATADIR */ 00150 filename = 00151 (char*)malloc(sizeof(char) * (strlen(path) + strlen(PKGDATADIR) + 2)); 00152 sprintf(filename, "%s/%s", PKGDATADIR, path); 00153 fp = fopen(filename, "r"); 00154 00155 if (fp) { 00156 fclose(fp); 00157 return filename; 00158 } 00159 free(filename); 00160 return NULL; 00161 } 00162 00163 char* get_file_path(const char* filename) { 00164 const char* last_sep = strrchr(filename, '/'); 00165 00166 if (last_sep == NULL) { 00167 last_sep = filename; 00168 } 00169 char* path = mstrncpy(filename, last_sep - filename); 00170 return path; 00171 } 00172 00173 int is_absolute_path(const char* path) { 00174 if (path[0] == '/') { 00175 return 1; 00176 } 00177 00178 if (path[1] == ':') { 00179 return 1; 00180 } 00181 return 0; 00182 }