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

Commit 12d619f

Browse files
committed
build: i18n: WIP: check exepath for ICU data
==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
1 parent d1c4872 commit 12d619f

1 file changed

Lines changed: 77 additions & 1 deletion

File tree

src/node_i18n.cc

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,16 @@
4545

4646
#if defined(NODE_HAVE_I18N_SUPPORT)
4747

48+
#include "uv.h"
49+
#include <limits.h> // PATH_MAX
4850
#include <unicode/putil.h>
4951
#include <unicode/udata.h>
5052

53+
#ifndef NODE_EXEPATH_ICUDIR
54+
#define NODE_EXEPATH_ICUDIR "../share/node/icu/"
55+
// TODO: if windows, mac, ...
56+
#endif
57+
5158
#ifdef NODE_HAVE_SMALL_ICU
5259
/* if this is defined, we have a 'secondary' entry point.
5360
compare following to utypes.h defs for U_ICUDATA_ENTRY_POINT */
@@ -66,15 +73,84 @@ extern "C" const char U_DATA_API SMALL_ICUDATA_ENTRY_POINT[];
6673
namespace node {
6774
namespace i18n {
6875

76+
/**
77+
* Modify 'path' to remove the final (leaf) entry.
78+
* so /path/to/something -> /path/to
79+
* and /path/to/dir/ -> /path/to/dir
80+
*/
81+
static char* my_dirname(char* path) {
82+
char *p = strrchr(path, U_FILE_SEP_CHAR);
83+
#if ( (U_FILE_SEP_CHAR) != (U_FILE_ALT_SEP_CHAR) )
84+
// windows: use '/' if further out than '\'
85+
char *p2 = strrchr(path, U_FILE_ALT_SEP_CHAR);
86+
if(p && p2 && (p2>p)) p = p2;
87+
#endif
88+
if(p) {
89+
*p = 0;
90+
}
91+
return path;
92+
}
93+
94+
#if NODE_HAVE_SMALL_ICU
95+
/**
96+
* @return true if path is a directory
97+
*/
98+
static bool my_isdir(const char* path) {
99+
int r;
100+
uv_fs_t req;
101+
r = uv_fs_stat(uv_default_loop(), &req, path, NULL);
102+
bool ret = ((r == 0) && (req.result == 0) && (req.statbuf.st_mode & S_IFDIR));
103+
printf("my_isdir %s = %c\n", path, (ret)?'T':'f');
104+
printf("r: %d, result: %d, flags: %x\n", r, req.result, req.statbuf.st_flags);
105+
//printf("#: %x\n", ((uv_stat_t*)req.ptr)->st_mode);
106+
puts(uv_strerror(r));
107+
uv_fs_req_cleanup(&req);
108+
return ret;
109+
}
110+
111+
112+
#endif
113+
69114
bool InitializeICUDirectory(const char* icu_data_path) {
70115
if (icu_data_path != NULL) {
71116
u_setDataDirectory(icu_data_path);
72117
return true; // no error
73118
} else {
74119
UErrorCode status = U_ZERO_ERROR;
120+
#ifdef NODE_HAVE_SMALL_ICU
121+
bool doSetCommonData = true; //< true iff we should call setCommonData
122+
#endif
123+
// get the exe path
124+
size_t exec_path_len = 2 * PATH_MAX;
125+
char* exec_path = new char[exec_path_len];
126+
char* exec_subpath = new char[exec_path_len];
127+
if (uv_exepath(exec_path, &exec_path_len) == 0) {
128+
// TODO strNcat!
129+
::strcpy(exec_subpath, exec_path);
130+
my_dirname(exec_subpath); // trim off '/node'
131+
::strcat(exec_subpath, U_FILE_SEP_STRING); // "/"-ish
132+
::strcat(exec_subpath, NODE_EXEPATH_ICUDIR);
133+
134+
// always set the path. May or may not be extant
135+
u_setDataDirectory(exec_subpath);
136+
137+
#ifdef NODE_HAVE_SMALL_ICU
138+
// in the small-icu case, we should check whether this
139+
// directory actually exists.
140+
if (my_isdir(exec_subpath)) {
141+
puts("skipping setcommondata");
142+
doSetCommonData = false;
143+
}
144+
#endif
145+
}
146+
delete [] exec_path;
147+
delete [] exec_subpath;
148+
75149
#ifdef NODE_HAVE_SMALL_ICU
76150
// install the 'small' data.
77-
udata_setCommonData(&SMALL_ICUDATA_ENTRY_POINT, &status);
151+
if (doSetCommonData) {
152+
udata_setCommonData(&SMALL_ICUDATA_ENTRY_POINT, &status);
153+
}
78154
#else // !NODE_HAVE_SMALL_ICU
79155
// no small data, so nothing to do.
80156
#endif // !NODE_HAVE_SMALL_ICU

0 commit comments

Comments
 (0)