#define __STDC_LIMIT_MACROS 1
#include "unicode/utypes.h"
#if !UCONFIG_NO_BREAK_ITERATION && U_PLATFORM_IS_DARWIN_BASED
#include "brkeng.h"
#include "dictbe.h"
#include "aaplbfct.h"
#include "unicode/uscript.h"
#include "unicode/uniset.h"
#include "unicode/ucnv.h"
#include "unicode/uchar.h"
#include <limits.h>
#include <unistd.h>
#include <glob.h>
#include <strings.h>
#include <NSSystemDirectories.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <time.h>
#include <stdio.h>
#include <stdint.h>
#include <TargetConditionals.h>
U_NAMESPACE_BEGIN
AppleLanguageBreakFactory::AppleLanguageBreakFactory(UErrorCode &status)
: ICULanguageBreakFactory(status)
{
}
AppleLanguageBreakFactory::~AppleLanguageBreakFactory() {
}
#if !TARGET_OS_EMBEDDED
#if 0
static __attribute__((always_inline)) inline UChar nextUChar(const UChar *&p, ptrdiff_t &l) {
if (l > 0) {
l -= 1;
return *p++;
}
else {
return 0;
}
}
static void addDictFile(MutableTrieDictionary *to, const char *path) {
UErrorCode status = U_ZERO_ERROR;
off_t fileLength;
const char *dictRawData = (const char *) -1;
const UChar *dictData = NULL;
ptrdiff_t dictDataLength = 0;
UChar *dictBuffer = NULL;
const char *encoding = NULL;
int32_t signatureLength = 0;
int dictFile = open(path, O_RDONLY, 0);
if (dictFile == -1) {
status = U_FILE_ACCESS_ERROR;
}
if (U_SUCCESS(status)) {
fileLength = lseek(dictFile, 0, SEEK_END);
(void) lseek(dictFile, 0, SEEK_SET);
if (fileLength < 0 || fileLength > PTRDIFF_MAX) {
status = U_FILE_ACCESS_ERROR;
}
}
if (U_SUCCESS(status)) {
dictRawData = (const char *) mmap(0, (size_t) fileLength, PROT_READ, MAP_SHARED, dictFile, 0);
if ((intptr_t)dictRawData == -1) {
status = U_FILE_ACCESS_ERROR;
}
}
if (dictFile != -1) {
(void) close(dictFile);
}
if (U_SUCCESS(status)) {
encoding = ucnv_detectUnicodeSignature(dictRawData, fileLength, &signatureLength, &status);
}
if (U_SUCCESS(status) && encoding != NULL) {
UConverter *conv = ucnv_open(encoding, &status);
uint32_t destCap = ucnv_toUChars(conv, NULL, 0, dictRawData, fileLength, &status);
if (status == U_BUFFER_OVERFLOW_ERROR) {
status = U_ZERO_ERROR;
}
if (U_SUCCESS(status)) {
dictBuffer = new UChar[destCap+1];
}
(void) ucnv_toUChars(conv, dictBuffer, destCap+1, dictRawData, fileLength, &status);
dictData = dictBuffer;
dictDataLength = destCap;
if (U_SUCCESS(status) && dictData[0] == 0xFEFF) { dictData += 1;
dictDataLength -= 1;
}
ucnv_close(conv);
}
if (U_SUCCESS(status) && dictData == NULL) {
dictData = (const UChar *) dictRawData;
dictDataLength = fileLength/sizeof(UChar);
}
if (U_SUCCESS(status)) {
UnicodeSet breaks(UNICODE_STRING_SIMPLE("[[:lb=BK:][:lb=CR:][:lb=LF:][:lb=NL:]]"), status);
const UChar *candidate = dictData;
int32_t length = 0;
UChar uc = nextUChar(dictData, dictDataLength);
while (U_SUCCESS(status) && uc) {
while (uc && !u_isspace(uc)) {
length += 1;
uc = nextUChar(dictData, dictDataLength);
}
if (length > 0) {
to->addWord(candidate, length, status);
}
while (uc && !breaks.contains(uc)) {
uc = nextUChar(dictData, dictDataLength);
}
while (uc && breaks.contains(uc)) {
uc = nextUChar(dictData, dictDataLength);
}
candidate = dictData-1;
length = 0;
}
}
if ((intptr_t) dictRawData != -1) {
(void) munmap((void *)dictRawData, (size_t) fileLength);
}
delete [] dictBuffer;
}
#if U_IS_BIG_ENDIAN
static const char sArchType[] = "";
#else
static const char sArchType[] = ".le"; #endif
#endif
#endif
DictionaryMatcher *
AppleLanguageBreakFactory::loadDictionaryMatcherFor(UScriptCode script, int32_t breakType) {
DictionaryMatcher *icuDictMatcher = ICULanguageBreakFactory::loadDictionaryMatcherFor(script, breakType);
#if !TARGET_OS_EMBEDDED
#if 0
if (icuDictMatcher != NULL) {
UErrorCode status = U_ZERO_ERROR;
const char *scriptName = uscript_getName(script);
char path[256]; char cachePath[128];
char cacheTargetPath[256];
glob_t dirGlob;
glob_t fileGlob;
struct stat cacheStat;
struct stat dictStat;
bool cacheGood = true;
int globFlags = (GLOB_NOESCAPE|GLOB_NOSORT|GLOB_TILDE);
const CompactTrieDictionary *cacheDict = NULL;
NSSearchPathEnumerationState state = NSStartSearchPathEnumeration(NSLibraryDirectory, (NSSearchPathDomainMask) (NSUserDomainMask|NSLocalDomainMask|NSNetworkDomainMask));
while ((state = NSGetNextSearchPathEnumeration(state, path)) != 0) {
strlcat(path, "/Dictionaries", sizeof(path));
if (!glob(path, globFlags, NULL, &dirGlob)) {
globFlags |= GLOB_APPEND;
}
}
if (dirGlob.gl_pathc == 0) {
globfree(&dirGlob);
return icuDictMatcher;
}
state = NSStartSearchPathEnumeration(NSCachesDirectory, NSLocalDomainMask);
state = NSGetNextSearchPathEnumeration(state, cachePath); snprintf(cacheTargetPath, sizeof(cacheTargetPath), "%s/com.apple.ICUUserDictionaryCache%s.%s.%d", cachePath, sArchType, scriptName, getuid());
if (stat(cacheTargetPath, &cacheStat) || cacheStat.st_mode != (S_IFREG|S_IRUSR|S_IWUSR)) {
cacheGood = false; }
globFlags &= ~GLOB_APPEND;
char **pathsp = dirGlob.gl_pathv;
const char *dictpath;
while ((dictpath = *pathsp++) != NULL) {
if (!stat(dictpath, &dictStat)) {
snprintf(path, sizeof(path), "%s/*-%s.txt", dictpath, scriptName);
if (!glob(path, globFlags, NULL, &fileGlob)) {
globFlags |= GLOB_APPEND;
}
if (cacheGood && (dictStat.st_mtimespec.tv_sec > cacheStat.st_mtimespec.tv_sec || (dictStat.st_mtimespec.tv_sec == cacheStat.st_mtimespec.tv_sec && dictStat.st_mtimespec.tv_nsec > cacheStat.st_mtimespec.tv_nsec))) {
cacheGood = false;
}
}
}
globfree(&dirGlob);
if (fileGlob.gl_pathc == 0) {
globfree(&fileGlob);
return icuDictMatcher;
}
pathsp = fileGlob.gl_pathv;
while (cacheGood && (dictpath = *pathsp++)) {
if (!stat(dictpath, &dictStat) && (dictStat.st_mtimespec.tv_sec > cacheStat.st_mtimespec.tv_sec || (dictStat.st_mtimespec.tv_sec == cacheStat.st_mtimespec.tv_sec && dictStat.st_mtimespec.tv_nsec > cacheStat.st_mtimespec.tv_nsec))) {
cacheGood = false;
}
}
if (!cacheGood) {
MutableTrieDictionary *sum = icuDictMatcher->cloneMutable(status);
pathsp = fileGlob.gl_pathv;
while (U_SUCCESS(status) && (dictpath = *pathsp++)) {
addDictFile(sum, dictpath);
}
CompactTrieDictionary compact(*sum, status);
delete sum;
if (U_SUCCESS(status)) {
strlcat(cachePath, "/temp.XXXXXXXXXX", sizeof(cachePath));
int temp = mkstemp(cachePath);
if (temp == -1) {
status = U_FILE_ACCESS_ERROR;
}
size_t dictSize = compact.dataSize();
if (U_SUCCESS(status) && write(temp, compact.data(), dictSize) != dictSize) {
status = U_FILE_ACCESS_ERROR;
}
if (U_SUCCESS(status)) {
if (rename(cachePath, cacheTargetPath)) {
status = U_FILE_ACCESS_ERROR;
(void) unlink(cachePath); }
}
if (temp != -1) {
close(temp);
}
}
}
globfree(&fileGlob);
if (U_SUCCESS(status)) {
int cache = open(cacheTargetPath, O_RDONLY, 0);
off_t length;
const void *cacheData = (const void *) -1;
if (cache == -1) {
status = U_FILE_ACCESS_ERROR;
}
if (U_SUCCESS(status)) {
length = lseek(cache, 0, SEEK_END);
(void) lseek(cache, 0, SEEK_SET);
if (length < 0 || length > PTRDIFF_MAX) {
status = U_FILE_ACCESS_ERROR;
}
}
if (U_SUCCESS(status)) {
cacheData = mmap(0, (size_t) length, PROT_READ, MAP_SHARED, cache, 0);
if ((intptr_t)cacheData == -1) {
status = U_FILE_ACCESS_ERROR;
}
}
if (cache != -1) {
(void) close(cache);
}
if (U_SUCCESS(status)) {
cacheDict = new CompactTrieDictionary(cacheData, status);
}
if (U_FAILURE(status) && (intptr_t)cacheData != -1) {
(void) munmap((void *)cacheData, (size_t) length);
}
}
if (U_SUCCESS(status)) {
delete icuDictMatcher;
return cacheDict;
}
else {
delete cacheDict;
}
}
#endif
#endif
return icuDictMatcher;
}
U_NAMESPACE_END
#endif