]> gitweb.fperrin.net Git - Dictionary.git/commitdiff
go
authorthadh <thadh@THADH-MTV.ad.corp.google.com>
Tue, 10 Feb 2009 05:33:33 +0000 (21:33 -0800)
committerthadh <thadh@THADH-MTV.ad.corp.google.com>
Tue, 10 Feb 2009 05:33:33 +0000 (21:33 -0800)
AndroidManifest.xml [new file with mode: 0755]
res/drawable/icon.png [new file with mode: 0755]
res/layout/main.xml [new file with mode: 0755]
res/values/strings.xml [new file with mode: 0755]
src/com/hughes/android/dictionary/Dictionary.java [new file with mode: 0755]
src/com/hughes/android/dictionary/Entry.java [new file with mode: 0755]
src/com/hughes/android/dictionary/Index.java [new file with mode: 0755]
src/com/hughes/android/dictionary/R.java [new file with mode: 0755]

diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100755 (executable)
index 0000000..640d31d
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.hughes.android.dictionary"
+      android:versionCode="1"
+      android:versionName="1.0.0">
+    <application android:icon="@drawable/icon" android:label="@string/app_name">
+        <activity android:name=".Dictionary"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest> 
\ No newline at end of file
diff --git a/res/drawable/icon.png b/res/drawable/icon.png
new file mode 100755 (executable)
index 0000000..7502484
Binary files /dev/null and b/res/drawable/icon.png differ
diff --git a/res/layout/main.xml b/res/layout/main.xml
new file mode 100755 (executable)
index 0000000..4c08a55
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+
+<EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/SearchText" android:hint="Search Text"></EditText>
+
+<ListView android:layout_width="wrap_content" android:layout_height="fill_parent" android:id="@+id/SearchResults" android:choiceMode="singleChoice"></ListView>
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100755 (executable)
index 0000000..61f6cd4
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="hello">Hello World, Dictionary</string>
+    <string name="app_name">Dictionary</string>
+</resources>
diff --git a/src/com/hughes/android/dictionary/Dictionary.java b/src/com/hughes/android/dictionary/Dictionary.java
new file mode 100755 (executable)
index 0000000..52b46b4
--- /dev/null
@@ -0,0 +1,130 @@
+package com.hughes.android.dictionary;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.List;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.TextView;
+
+public class Dictionary extends Activity {
+
+  private String searchText = "";
+  
+  private List<Entry> entries = new ArrayList<Entry>(100);
+
+  public static final String INDEX_FORMAT = "%s_index_%d"; 
+  private final File dictionaryFile = new File("/sdcard/dict-de-en.txt");
+  private final Index[] indexes = new Index[2];
+  private final byte lang = Entry.LANG1; 
+
+  private DictionaryListAdapter dictionaryListAdapter = new DictionaryListAdapter();
+  
+
+  /** Called when the activity is first created. */
+  @Override
+  public void onCreate(Bundle savedInstanceState) {
+    Log.d("THAD", "onCreate");
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.main);
+
+    EditText searchText = (EditText) findViewById(R.id.SearchText);
+    searchText.addTextChangedListener(new DictionaryTextWatcher());
+
+    ListView searchResults = (ListView) findViewById(R.id.SearchResults);
+    searchResults.setAdapter(dictionaryListAdapter);
+
+    try {
+      loadIndex();
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+
+  }
+
+  private void loadIndex() throws IOException, ClassNotFoundException {
+    Log.d("THAD", "enter loadIndex");
+    indexes[0] = new Index(String.format(INDEX_FORMAT, dictionaryFile.getAbsolutePath(), Entry.LANG1));
+    Log.d("THAD", "exit loadIndex");
+  }
+
+  void onSearchTextChange(final String searchText) {
+    this.searchText = searchText;
+    final Index.Node node = indexes[lang].lookup(searchText);
+
+    try {
+      final long length = dictionaryFile.length();
+      Log.d("THAD", "Dictionary file length=" + length);
+
+      final RandomAccessFile raf = new RandomAccessFile(dictionaryFile, "r");
+      raf.seek(length / 2);
+//      final InputStreamReader dictionaryReader = new InputStreamReader(new BufferedInputStream(new FileInputStream("/sdcard/dict-de-en.txt")));
+//      skip(dictionaryReader, length / 2);
+
+      for (int i = 0; i < entries.length; ++i) {
+        entries[i] = raf.readLine();
+        raf.skipBytes((int) (length / 100000));
+      }
+      
+      raf.close();
+
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+
+    dictionaryListAdapter.notifyDataSetChanged();
+  }
+  
+  private class DictionaryListAdapter extends BaseAdapter {
+
+    public int getCount() {
+      return 1000000;
+
+    }
+
+    public Object getItem(int position) {
+      return searchText + position + entries[position % entries.length];
+    }
+
+    public long getItemId(int position) {
+      return position;
+    }
+
+    public View getView(int position, View convertView, ViewGroup parent) {
+      TextView result = null;
+      if (convertView instanceof TextView) {
+        result = (TextView) convertView;
+      } else {
+        result = new TextView(parent.getContext());
+      }
+      result.setText((String) getItem(position));
+      return result;
+    }
+
+  }
+
+  private class DictionaryTextWatcher implements TextWatcher {
+    public void afterTextChanged(Editable searchText) {
+      onSearchTextChange(searchText.toString());
+    }
+
+    public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
+        int arg3) {
+    }
+
+    public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/src/com/hughes/android/dictionary/Entry.java b/src/com/hughes/android/dictionary/Entry.java
new file mode 100755 (executable)
index 0000000..3bb7b67
--- /dev/null
@@ -0,0 +1,47 @@
+package com.hughes.android.dictionary;\r
+\r
+import java.util.regex.Pattern;\r
+\r
+public final class Entry {\r
+\r
+  static final byte LANG1 = 0;\r
+  static final byte LANG2 = 1;\r
+\r
+  static final Pattern lineSplitPattern = Pattern.compile("\\s+::\\s+");\r
+\r
+  String lang1 = "";\r
+  String lang2 = "";\r
+\r
+  boolean parseFromLine(final String line) {\r
+    final String[] parts = lineSplitPattern.split(line);\r
+    if (parts.length != 2) {\r
+      System.err.println("Entry:" + "Invalid line: " + line);\r
+      return false;\r
+    }\r
+    lang1 = parts[0];\r
+    lang2 = parts[1];\r
+    return true;\r
+  }\r
+\r
+  String getAllText(final byte lang) {\r
+    if (lang == LANG1) {\r
+      return lang1;\r
+    }\r
+    assert lang == LANG2;\r
+    return lang2;\r
+  }\r
+  \r
+  String getIndexableText(final byte lang) {\r
+    String text = getAllText(lang);\r
+    text = text.replaceAll("[\"\\.!?,]", "");\r
+    text = text.replaceAll("\\{[^}]+\\}", "");\r
+    return text;\r
+  }\r
+\r
+  public String normalizeToken(final String token, final byte lang) {\r
+    return token.toLowerCase().replaceAll("ß", "ss").replaceAll("ä", "ae")\r
+        .replaceAll("ö", "oe").replaceAll("ü", "ue")\r
+        .replaceAll("[^A-Za-z]", "");\r
+  }\r
+\r
+}\r
diff --git a/src/com/hughes/android/dictionary/Index.java b/src/com/hughes/android/dictionary/Index.java
new file mode 100755 (executable)
index 0000000..89024ff
--- /dev/null
@@ -0,0 +1,81 @@
+package com.hughes.android.dictionary;\r
+\r
+import java.io.IOException;\r
+import java.io.RandomAccessFile;\r
+import java.util.Map;\r
+import java.util.TreeMap;\r
+\r
+import com.hughes.util.LRUCacheMap;\r
+\r
+\r
+public final class Index {\r
+  \r
+  final String filename;\r
+  final RandomAccessFile file;\r
+  \r
+  final Node root;\r
+  final Map<Integer,Node> locationToNode = new LRUCacheMap<Integer,Node>(5000);\r
+  \r
+  \r
+  public Index(final String filename) throws IOException {\r
+    this.filename = filename;\r
+    file = new RandomAccessFile(filename, "r");\r
+    root = getNode("", 0);\r
+  }\r
+  \r
+  public Node lookup(final String text) throws IOException {\r
+    return lookup(text, 0, root);\r
+  }\r
+  \r
+  private Node lookup(final String text, final int pos, final Node n) throws IOException {\r
+    if (pos == text.length()) {\r
+      return n;\r
+    }\r
+    for (int i = pos + 1; i <= text.length(); ++i) {\r
+      final Integer child = n.children.get(text.substring(pos, i));\r
+      if (child != null) {\r
+        return lookup(text, i, getNode(text.substring(0, i), child));\r
+      }\r
+    }\r
+    return n;\r
+  }\r
+  \r
+  private Node getNode(final String text, final int location) throws IOException {\r
+    Node node = locationToNode.get(location);\r
+    if (node == null) {\r
+      node = new Node(text, location);\r
+      locationToNode.put(location, node);\r
+    }\r
+    return node;\r
+  }\r
+\r
+  final class Node {\r
+    final String text;\r
+    final int location;\r
+    final TreeMap<String,Integer> children;\r
+    final int[] offsets;\r
+    \r
+    Node(final String text, final int location) throws IOException {\r
+      this.text = text;\r
+      this.location = location;\r
+      \r
+      file.seek(location);\r
+      final int numChildren = file.readInt();\r
+      children = new TreeMap<String, Integer>();\r
+      for (int i = 0; i < numChildren; ++i) {\r
+        final String chunk = file.readUTF().intern();\r
+        if (chunk.length() == 0) {\r
+          throw new IOException("Empty string chunk.");\r
+        }\r
+        children.put(chunk, file.readInt());\r
+      }\r
+      \r
+      final int numOffsets = file.readInt();\r
+      offsets = new int[numOffsets];\r
+      for (int i = 0; i < offsets.length; ++i) {\r
+        offsets[i] = file.readInt();\r
+      }\r
+    }\r
+  }\r
+\r
+}\r
diff --git a/src/com/hughes/android/dictionary/R.java b/src/com/hughes/android/dictionary/R.java
new file mode 100755 (executable)
index 0000000..88153f5
--- /dev/null
@@ -0,0 +1,27 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.\r
+ *\r
+ * This class was automatically generated by the\r
+ * aapt tool from the resource data it found.  It\r
+ * should not be modified by hand.\r
+ */\r
+\r
+package com.hughes.android.dictionary;\r
+\r
+public final class R {\r
+    public static final class attr {\r
+    }\r
+    public static final class drawable {\r
+        public static final int icon=0x7f020000;\r
+    }\r
+    public static final class id {\r
+        public static final int SearchResults=0x7f050001;\r
+        public static final int SearchText=0x7f050000;\r
+    }\r
+    public static final class layout {\r
+        public static final int main=0x7f030000;\r
+    }\r
+    public static final class string {\r
+        public static final int app_name=0x7f040001;\r
+        public static final int hello=0x7f040000;\r
+    }\r
+}\r