bug 685214 - use URI spec rather than file path to specify hyphenation dictionary, and read using nsIInputStream rather than stdio. r=bsmedberg
authorJonathan Kew <jfkthame@gmail.com>
Wed, 14 Sep 2011 20:20:26 +0100
changeset 76974 2118b37a8389aab49ec17e29b1a34a18720aff8e
parent 76973 44977dedb48546dc11ecc611b83238afdb610771
child 76975 ea752547a5b6932795c0114b63cae2335821fd42
push id21164
push usereakhgari@mozilla.com
push dateThu, 15 Sep 2011 13:41:38 +0000
treeherdermozilla-central@c6a405d01a1d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs685214
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 685214 - use URI spec rather than file path to specify hyphenation dictionary, and read using nsIInputStream rather than stdio. r=bsmedberg
intl/hyphenation/src/Makefile.in
intl/hyphenation/src/hnjalloc.h
intl/hyphenation/src/hnjstdio.cpp
intl/hyphenation/src/nsHyphenator.cpp
--- a/intl/hyphenation/src/Makefile.in
+++ b/intl/hyphenation/src/Makefile.in
@@ -46,11 +46,12 @@ MODULE           = hyphenation
 LIBRARY_NAME     = hyphenation_s
 LIBXUL_LIBRARY   = 1
 
 CSRCS            = hyphen.c \
                    $(NULL)
 
 CPPSRCS          = nsHyphenator.cpp \
                    nsHyphenationManager.cpp \
+                   hnjstdio.cpp \
                    $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/intl/hyphenation/src/hnjalloc.h
+++ b/intl/hyphenation/src/hnjalloc.h
@@ -43,8 +43,41 @@
  */
 
 #include "mozilla/mozalloc.h"
 
 #define hnj_malloc(size)      moz_xmalloc(size)
 #define hnj_realloc(p, size)  moz_xrealloc(p, size)
 #define hnj_free(p)           moz_free(p)
 
+/*
+ * To enable us to load hyphenation dictionaries from arbitrary resource URIs,
+ * not just through file paths using stdio, we override the (few) stdio APIs
+ * that hyphen.c uses and provide our own reimplementation that calls Gecko
+ * i/o methods.
+ */
+
+#include <stdio.h> /* ensure stdio.h is loaded before our macros */
+
+#undef FILE
+#define FILE hnjFile
+
+#define fopen(path,mode)      hnjFopen(path,mode)
+#define fclose(file)          hnjFclose(file)
+#define fgets(buf,count,file) hnjFgets(buf,count,file)
+
+typedef struct hnjFile_ hnjFile;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+hnjFile* hnjFopen(const char* aURISpec, const char* aMode);
+
+int hnjFclose(hnjFile* f);
+
+char* hnjFgets(char* s, int n, hnjFile* f);
+
+#ifdef __cplusplus
+}
+#endif
+
+
new file mode 100644
--- /dev/null
+++ b/intl/hyphenation/src/hnjstdio.cpp
@@ -0,0 +1,137 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Hyphenation Service.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jonathan Kew <jfkthame@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This file provides substitutes for the basic stdio routines used by hyphen.c
+// to read its dictionary files. We #define the stdio names to these versions
+// in hnjalloc.h, so that we can use nsIURI and nsIInputStream to specify and
+// access the dictionary resources.
+
+#include "hnjalloc.h"
+#include "nsNetUtil.h"
+
+#define BUFSIZE 1024
+
+struct hnjFile_ {
+    nsCOMPtr<nsIInputStream> mStream;
+    char                     mBuffer[BUFSIZE];
+    PRUint32                 mCurPos;
+    PRUint32                 mLimit;
+};
+
+// replacement for fopen()
+// (not a full substitute: only supports read access)
+hnjFile*
+hnjFopen(const char* aURISpec, const char* aMode)
+{
+    // this override only needs to support "r"
+    NS_ASSERTION(!strcmp(aMode, "r"), "unsupported fopen() mode in hnjFopen");
+
+    nsCOMPtr<nsIURI> uri;
+    nsresult rv = NS_NewURI(getter_AddRefs(uri), aURISpec);
+    if (NS_FAILED(rv)) {
+        return nsnull;
+    }
+
+    nsCOMPtr<nsIInputStream> instream;
+    rv = NS_OpenURI(getter_AddRefs(instream), uri);
+    if (NS_FAILED(rv)) {
+        return nsnull;
+    }
+
+    hnjFile *f = new hnjFile;
+    f->mStream = instream;
+    f->mCurPos = 0;
+    f->mLimit = 0;
+
+    return f;
+}
+
+// replacement for fclose()
+int
+hnjFclose(hnjFile* f)
+{
+    NS_ASSERTION(f && f->mStream, "bad argument to hnjFclose");
+
+    int result = 0;
+    nsresult rv = f->mStream->Close();
+    if (NS_FAILED(rv)) {
+        result = EOF;
+    }
+    f->mStream = nsnull;
+
+    delete f;
+    return result;
+}
+
+// replacement for fgets()
+// (not a full reimplementation, but sufficient for libhyphen's needs)
+char*
+hnjFgets(char* s, int n, hnjFile* f)
+{
+    NS_ASSERTION(s && f, "bad argument to hnjFgets");
+
+    int i = 0;
+    while (i < n - 1) {
+        if (f->mCurPos < f->mLimit) {
+            char c = f->mBuffer[f->mCurPos++];
+            s[i++] = c;
+            if (c == '\n' || c == '\r') {
+                break;
+            }
+            continue;
+        }
+
+        f->mCurPos = 0;
+
+        nsresult rv = f->mStream->Read(f->mBuffer, BUFSIZE, &f->mLimit);
+        if (NS_FAILED(rv)) {
+            f->mLimit = 0;
+            return nsnull;
+        }
+
+        if (f->mLimit == 0) {
+            break;
+        }
+    }
+
+    if (i == 0) {
+        return nsnull; // end of file
+    }
+
+    s[i] = '\0'; // null-terminate the returned string
+    return s;
+}
--- a/intl/hyphenation/src/nsHyphenator.cpp
+++ b/intl/hyphenation/src/nsHyphenator.cpp
@@ -35,33 +35,35 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsHyphenator.h"
 #include "nsIFile.h"
 #include "nsUTF8Utils.h"
 #include "nsIUGenCategory.h"
 #include "nsUnicharUtilCIID.h"
+#include "nsNetUtil.h"
 
 #include "hyphen.h"
 
 nsHyphenator::nsHyphenator(nsIFile *aFile)
   : mDict(nsnull)
 {
-  nsCString path;
-  aFile->GetNativePath(path);
-  mDict = hnj_hyphen_load(path.get());
+  nsCString urlSpec;
+  nsresult rv = NS_GetURLSpecFromFile(aFile, urlSpec);
+  if (NS_FAILED(rv)) {
+    return;
+  }
+  mDict = hnj_hyphen_load(urlSpec.get());
 #ifdef DEBUG
   if (mDict) {
-    printf("loaded hyphenation patterns from %s\n", path.get());
+    printf("loaded hyphenation patterns from %s\n", urlSpec.get());
   }
 #endif
-  nsresult rv;
-  mCategories =
-    do_GetService(NS_UNICHARCATEGORY_CONTRACTID, &rv);
+  mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID, &rv);
   NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get category service");
 }
 
 nsHyphenator::~nsHyphenator()
 {
   if (mDict != nsnull) {
     hnj_hyphen_free((HyphenDict*)mDict);
     mDict = nsnull;