Open Chinese Convert  0.4.3
A project for conversion between Traditional and Simplified Chinese
/usr/src/RPM/BUILD/opencc-0.4.3/src/utils.c
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 }
 All Data Structures Files Functions Variables Defines