Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
build: i18n: WIP: check exepath for ICU data
Browse files Browse the repository at this point in the history
==WORK IN PROGRESS==

If the user hasn't otherwise specified a directory,
append `NODE_EXEPATH_ICUDIR` ( default: ../share/node/icu/ )
and set it as the ICU dir.

If we are in `small-icu` mode, ALSO actually verify the aforementioned
directory exists (thx libuv) and suppress loading the small-icu data
in that case.

(If we aren't in `small-icu` mode, there's no reason to incur the cost
of hitting the FS to check whether the directory exists or not at
startup time.)

// cc: @tjfontaine
  • Loading branch information
srl295 committed Dec 19, 2014
1 parent d1c4872 commit 12d619f
Showing 1 changed file with 77 additions and 1 deletion.
78 changes: 77 additions & 1 deletion src/node_i18n.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,16 @@

#if defined(NODE_HAVE_I18N_SUPPORT)

#include "uv.h"
#include <limits.h> // PATH_MAX
#include <unicode/putil.h>
#include <unicode/udata.h>

#ifndef NODE_EXEPATH_ICUDIR
#define NODE_EXEPATH_ICUDIR "../share/node/icu/"
// TODO: if windows, mac, ...
#endif

#ifdef NODE_HAVE_SMALL_ICU
/* if this is defined, we have a 'secondary' entry point.
compare following to utypes.h defs for U_ICUDATA_ENTRY_POINT */
Expand All @@ -66,15 +73,84 @@ extern "C" const char U_DATA_API SMALL_ICUDATA_ENTRY_POINT[];
namespace node {
namespace i18n {

/**
* Modify 'path' to remove the final (leaf) entry.
* so /path/to/something -> /path/to
* and /path/to/dir/ -> /path/to/dir
*/
static char* my_dirname(char* path) {
char *p = strrchr(path, U_FILE_SEP_CHAR);
#if ( (U_FILE_SEP_CHAR) != (U_FILE_ALT_SEP_CHAR) )
// windows: use '/' if further out than '\'
char *p2 = strrchr(path, U_FILE_ALT_SEP_CHAR);
if(p && p2 && (p2>p)) p = p2;
#endif
if(p) {
*p = 0;
}
return path;
}

#if NODE_HAVE_SMALL_ICU
/**
* @return true if path is a directory
*/
static bool my_isdir(const char* path) {
int r;
uv_fs_t req;
r = uv_fs_stat(uv_default_loop(), &req, path, NULL);
bool ret = ((r == 0) && (req.result == 0) && (req.statbuf.st_mode & S_IFDIR));
printf("my_isdir %s = %c\n", path, (ret)?'T':'f');
printf("r: %d, result: %d, flags: %x\n", r, req.result, req.statbuf.st_flags);
//printf("#: %x\n", ((uv_stat_t*)req.ptr)->st_mode);
puts(uv_strerror(r));
uv_fs_req_cleanup(&req);
return ret;
}


#endif

bool InitializeICUDirectory(const char* icu_data_path) {
if (icu_data_path != NULL) {
u_setDataDirectory(icu_data_path);
return true; // no error
} else {
UErrorCode status = U_ZERO_ERROR;
#ifdef NODE_HAVE_SMALL_ICU
bool doSetCommonData = true; //< true iff we should call setCommonData
#endif
// get the exe path
size_t exec_path_len = 2 * PATH_MAX;
char* exec_path = new char[exec_path_len];
char* exec_subpath = new char[exec_path_len];
if (uv_exepath(exec_path, &exec_path_len) == 0) {
// TODO strNcat!
::strcpy(exec_subpath, exec_path);
my_dirname(exec_subpath); // trim off '/node'
::strcat(exec_subpath, U_FILE_SEP_STRING); // "/"-ish
::strcat(exec_subpath, NODE_EXEPATH_ICUDIR);

// always set the path. May or may not be extant
u_setDataDirectory(exec_subpath);

#ifdef NODE_HAVE_SMALL_ICU
// in the small-icu case, we should check whether this
// directory actually exists.
if (my_isdir(exec_subpath)) {
puts("skipping setcommondata");
doSetCommonData = false;
}
#endif
}
delete [] exec_path;
delete [] exec_subpath;

#ifdef NODE_HAVE_SMALL_ICU
// install the 'small' data.
udata_setCommonData(&SMALL_ICUDATA_ENTRY_POINT, &status);
if (doSetCommonData) {
udata_setCommonData(&SMALL_ICUDATA_ENTRY_POINT, &status);
}
#else // !NODE_HAVE_SMALL_ICU
// no small data, so nothing to do.
#endif // !NODE_HAVE_SMALL_ICU
Expand Down

0 comments on commit 12d619f

Please sign in to comment.