<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>c/include/field_index.h</filename>
    </added>
    <added>
      <filename>c/src/field_index.c</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,5 +1,6 @@
-These wonderful documentation standards were taken from merb. 
-Every method should have documentation above the method definition that fits this basic model...
+These excellent documentation standards were taken from merb. 
+Every Ruby method should have documentation above the method definition that
+fits this basic model...
 
 # Render the specified item, with the specified options.
 #
@@ -21,7 +22,7 @@ Every method should have documentation above the method definition that fits thi
 #   be either the controller_name or application. If you
 #   want to use an alternative content-type than the one
 #   that the base template was rendered as, you will need
-#   to do :layout =&gt; &#8220;foo.#{content_type}&#8221; (i.e. &#8220;foo.json&#8221;)
+#   to do :layout =&gt; +foo.#{content_type}+ (i.e. +foo.json+)
 #
 # ==== Returns
 # String:: The rendered template, including layout, if appropriate.
@@ -32,9 +33,8 @@ Every method should have documentation above the method definition that fits thi
 #
 # ==== Alternatives
 # If you pass a Hash as the first parameter, it will be moved to
-# opts and &#8220;thing&#8221; will be the current action
+# opts and +thing+ will be the current action
 #
-#&#8212;
 # @public
 def render(thing = nil, opts = {})
   &lt;snip&gt;</diff>
      <filename>DOCUMENTATION_STANDARDS</filename>
    </modified>
    <modified>
      <diff>@@ -40,7 +40,7 @@ q_filtered_query.o  q_fuzzy.o            q_match_all.o      q_multi_term.o    \
 q_parser.o          q_phrase.o           q_prefix.o         q_range.o         \
 q_span.o            q_term.o             q_wildcard.o       ram_store.o       \
 search.o            similarity.o         sort.o             stopwords.o       \
-store.o             term_vectors.o
+store.o             term_vectors.o			 field_index.o
 
 TEST_OBJS = \
 test_multimapper.o       test_q_const_score.o     test_threading.o     \</diff>
      <filename>c/Makefile</filename>
    </modified>
    <modified>
      <diff>@@ -772,7 +772,8 @@ struct IndexReader
     SegmentInfos *sis;
     FieldInfos   *fis;
     HashTable    *cache;
-    HashTable    *sort_cache;
+    HashTable    *field_index_cache;
+    mutex_t       field_index_mutex;
     uchar        *fake_norms;
     mutex_t       mutex;
     bool          has_changes : 1;</diff>
      <filename>c/include/index.h</filename>
    </modified>
    <modified>
      <diff>@@ -8,6 +8,7 @@ typedef struct Scorer Scorer;
 #include &quot;index.h&quot;
 #include &quot;bitvector.h&quot;
 #include &quot;similarity.h&quot;
+#include &quot;field_index.h&quot;
 
 /***************************************************************************
  *
@@ -633,6 +634,22 @@ extern bool scorer_doc_less_than(const Scorer *s1, const Scorer *s2);
 extern int scorer_doc_cmp(const void *p1, const void *p2);
 
 /***************************************************************************
+ * Comparable
+ ***************************************************************************/
+
+typedef struct Comparable
+{
+    int type;
+    union {
+        long  l;
+        float f;
+        char *s;
+        void *p;
+    } val;
+    bool reverse : 1;
+} Comparable;
+
+/***************************************************************************
  *
  * Sort
  *
@@ -650,47 +667,27 @@ enum SORT_TYPE
 };
 
 /***************************************************************************
- * Comparable
- ***************************************************************************/
-
-typedef struct Comparable
-{
-    int type;
-    union {
-        int i;
-        float f;
-        char *s;
-        void *p;
-    } val;
-    bool reverse : 1;
-} Comparable;
-
-/***************************************************************************
  * SortField
  ***************************************************************************/
 
 typedef struct SortField
 {
-    mutex_t         mutex;
-    char           *field;
-    enum SORT_TYPE  type;
-    bool            reverse : 1;
-    void           *index;
-    int             (*compare)(void *index_ptr, Hit *hit1, Hit *hit2);
-    void            (*get_val)(void *index_ptr, Hit *hit1, Comparable *comparable);
-    void           *(*create_index)(int size);
-    void            (*destroy_index)(void *p);
-    void            (*handle_term)(void *index, TermDocEnum *tde, char *text);
+    char                  *field;
+    enum SORT_TYPE         type;
+    bool                   reverse : 1;
+    const FieldIndexClass *field_index_class;
+    int         (*compare)(void *index_ptr, Hit *hit1, Hit *hit2);
+    void        (*get_val)(void *index_ptr, Hit *hit1, Comparable *comparable);
 } SortField;
 
-extern SortField *sort_field_new(char *field, enum SORT_TYPE type, bool reverse);
+extern SortField *sort_field_new(const char *field, enum SORT_TYPE type, bool reverse);
 extern SortField *sort_field_score_new(bool reverse);
 extern SortField *sort_field_doc_new(bool reverse);
-extern SortField *sort_field_int_new(char *field, bool reverse);
-extern SortField *sort_field_byte_new(char *field, bool reverse);
-extern SortField *sort_field_float_new(char *field, bool reverse);
-extern SortField *sort_field_string_new(char *field, bool reverse);
-extern SortField *sort_field_auto_new(char *field, bool reverse);
+extern SortField *sort_field_int_new(const char *field, bool reverse);
+extern SortField *sort_field_byte_new(const char *field, bool reverse);
+extern SortField *sort_field_float_new(const char *field, bool reverse);
+extern SortField *sort_field_string_new(const char *field, bool reverse);
+extern SortField *sort_field_auto_new(const char *field, bool reverse);
 extern void sort_field_destroy(void *p);
 extern char *sort_field_to_s(SortField *self);
 </diff>
      <filename>c/include/search.h</filename>
    </modified>
    <modified>
      <diff>@@ -3893,6 +3893,7 @@ IndexReader *ir_setup(IndexReader *ir, Store *store, SegmentInfos *sis,
                       FieldInfos *fis, int is_owner)
 {
     mutex_init(&amp;ir-&gt;mutex, NULL);
+    mutex_init(&amp;ir-&gt;field_index_mutex, NULL);
 
     if (store) {
         ir-&gt;store = store;
@@ -4123,8 +4124,8 @@ void ir_close(IndexReader *ir)
         if (ir-&gt;cache) {
             h_destroy(ir-&gt;cache);
         }
-        if (ir-&gt;sort_cache) {
-            h_destroy(ir-&gt;sort_cache);
+        if (ir-&gt;field_index_cache) {
+            h_destroy(ir-&gt;field_index_cache);
         }
         if (ir-&gt;deleter &amp;&amp; ir-&gt;is_owner) {
             deleter_destroy(ir-&gt;deleter);
@@ -4132,6 +4133,7 @@ void ir_close(IndexReader *ir)
         free(ir-&gt;fake_norms);
 
         mutex_destroy(&amp;ir-&gt;mutex);
+        mutex_destroy(&amp;ir-&gt;field_index_mutex);
         free(ir);
     }
     else {</diff>
      <filename>c/src/index.c</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,7 @@
 #include &lt;string.h&gt;
 #include &quot;search.h&quot;
 #include &quot;index.h&quot;
+#include &quot;field_index.h&quot;
 
 /***************************************************************************
  *
@@ -8,53 +9,24 @@
  *
  ***************************************************************************/
 
-unsigned long sort_field_hash(const void *p)
-{
-    SortField *self = (SortField *)p;
-    return str_hash(self-&gt;field) ^ (self-&gt;type*37);
-}
-
-int sort_field_eq(const void *p1, const void *p2)
-{
-    SortField *key1 = (SortField *)p1;
-    SortField *key2 = (SortField *)p2;
-    return (strcmp(key1-&gt;field, key2-&gt;field) == 0)
-        &amp;&amp; key1-&gt;type == key2-&gt;type;
-}
-
-static int sort_field_cache_eq(const void *p1, const void *p2)
-{
-    SortField *key1 = (SortField *)p1;
-    SortField *key2 = (SortField *)p2;
-    int equal = (strcmp(key1-&gt;field, key2-&gt;field) == 0)
-        &amp;&amp; key1-&gt;type == key2-&gt;type;
-
-    return equal;
-}
-
-static SortField *sort_field_clone(SortField *self)
-{
-    SortField *clone = ALLOC(SortField);
-    memcpy(clone, self, sizeof(SortField));
-    mutex_init(&amp;clone-&gt;mutex, NULL);
-    clone-&gt;field = estrdup(self-&gt;field);
-    return clone;
-}
-
-static SortField *sort_field_alloc(char *field, int type, bool reverse)
-{
-    SortField *self = ALLOC(SortField);
-    mutex_init(&amp;self-&gt;mutex, NULL);
-    self-&gt;field         = field ? estrdup(field) : NULL;
-    self-&gt;type          = type;
-    self-&gt;reverse       = reverse;
-    self-&gt;index         = NULL;
-    self-&gt;destroy_index = &amp;free;
-    self-&gt;compare       = NULL;
+static INLINE SortField *sort_field_alloc(const char *field,
+    enum SORT_TYPE type,
+    bool reverse,
+    int (*compare)(void *index_ptr, Hit *hit1, Hit *hit2),
+    void (*get_val)(void *index_ptr, Hit *hit1, Comparable *comparable),
+    const FieldIndexClass *field_index_class)
+{
+    SortField *self         = ALLOC(SortField);
+    self-&gt;field             = field ? estrdup(field) : NULL;
+    self-&gt;type              = type;
+    self-&gt;reverse           = reverse;
+    self-&gt;field_index_class = field_index_class;
+    self-&gt;compare           = compare;
+    self-&gt;get_val           = get_val;
     return self;
 }
 
-SortField *sort_field_new(char *field, enum SORT_TYPE type, bool reverse)
+SortField *sort_field_new(const char *field, enum SORT_TYPE type, bool reverse)
 {
     SortField *sf = NULL;
     switch (type) {
@@ -86,11 +58,7 @@ SortField *sort_field_new(char *field, enum SORT_TYPE type, bool reverse)
 void sort_field_destroy(void *p)
 {
     SortField *self = (SortField *)p;
-    if (self-&gt;index) {
-        self-&gt;destroy_index(self-&gt;index);
-    }
     free(self-&gt;field);
-    mutex_destroy(&amp;self-&gt;mutex);
     free(p);
 }
 
@@ -125,10 +93,11 @@ char *sort_field_to_s(SortField *self)
             break;
     }
     if (self-&gt;field) {
-        str = ALLOC_N(char, 10 + strlen(self-&gt;field) + strlen(type));
+        str = ALLOC_N(char, 3 + strlen(self-&gt;field) + strlen(type));
         sprintf(str, &quot;%s:%s%s&quot;, self-&gt;field, type, (self-&gt;reverse ? &quot;!&quot; : &quot;&quot;));
-    } else {
-        str = ALLOC_N(char, 10 + strlen(type));
+    }
+    else {
+        str = ALLOC_N(char, 2 + strlen(type));
         sprintf(str, &quot;%s%s&quot;, type, (self-&gt;reverse ? &quot;!&quot; : &quot;&quot;));
     }
     return str;
@@ -138,13 +107,13 @@ char *sort_field_to_s(SortField *self)
  * ScoreSortField
  ***************************************************************************/
 
-void sf_score_get_val(void *index, Hit *hit, Comparable *comparable)
+static void sf_score_get_val(void *index, Hit *hit, Comparable *comparable)
 {
     (void)index;
     comparable-&gt;val.f = hit-&gt;score;
 }
 
-int sf_score_compare(void *index_ptr, Hit *hit2, Hit *hit1)
+static int sf_score_compare(void *index_ptr, Hit *hit2, Hit *hit1)
 {
     float val1 = hit1-&gt;score;
     float val2 = hit2-&gt;score;
@@ -157,49 +126,39 @@ int sf_score_compare(void *index_ptr, Hit *hit2, Hit *hit1)
 
 SortField *sort_field_score_new(bool reverse)
 {
-    SortField *self = sort_field_alloc(NULL, SORT_TYPE_SCORE, reverse);
-    self-&gt;compare   = &amp;sf_score_compare;
-    self-&gt;get_val   = &amp;sf_score_get_val;
-    return self;
+    return sort_field_alloc(NULL, SORT_TYPE_SCORE, reverse,
+                            &amp;sf_score_compare, &amp;sf_score_get_val, NULL);
 }
 
 const SortField SORT_FIELD_SCORE = {
-    MUTEX_INITIALIZER,
     NULL,               /* field */
     SORT_TYPE_SCORE,    /* type */
     false,              /* reverse */
-    NULL,               /* index */
+    NULL,               /* field_index_class */
     &amp;sf_score_compare,  /* compare */
     &amp;sf_score_get_val,  /* get_val */
-    NULL,               /* create_index */
-    NULL,               /* destroy_index */
-    NULL,               /* handle_term */
 };
 
 const SortField SORT_FIELD_SCORE_REV = {
-    MUTEX_INITIALIZER,
     NULL,               /* field */
     SORT_TYPE_SCORE,    /* type */
     true,               /* reverse */
-    NULL,               /* index */
+    NULL,               /* field_index_class */
     &amp;sf_score_compare,  /* compare */
     &amp;sf_score_get_val,  /* get_val */
-    NULL,               /* create_index */
-    NULL,               /* destroy_index */
-    NULL,               /* handle_term */
 };
 
 /**************************************************************************
  * DocSortField
  ***************************************************************************/
 
-void sf_doc_get_val(void *index, Hit *hit, Comparable *comparable)
+static void sf_doc_get_val(void *index, Hit *hit, Comparable *comparable)
 {
     (void)index;
-    comparable-&gt;val.i = hit-&gt;doc;
+    comparable-&gt;val.l = hit-&gt;doc;
 }
 
-int sf_doc_compare(void *index_ptr, Hit *hit1, Hit *hit2)
+static int sf_doc_compare(void *index_ptr, Hit *hit1, Hit *hit2)
 {
     int val1 = hit1-&gt;doc;
     int val2 = hit2-&gt;doc;
@@ -212,36 +171,26 @@ int sf_doc_compare(void *index_ptr, Hit *hit1, Hit *hit2)
 
 SortField *sort_field_doc_new(bool reverse)
 {
-    SortField *self = sort_field_alloc(NULL, SORT_TYPE_DOC, reverse);
-    self-&gt;compare   = &amp;sf_doc_compare;
-    self-&gt;get_val   = &amp;sf_doc_get_val;
-    return self;
+    return sort_field_alloc(NULL, SORT_TYPE_DOC, reverse,
+                            &amp;sf_doc_compare, &amp;sf_doc_get_val, NULL);
 }
 
 const SortField SORT_FIELD_DOC = {
-    MUTEX_INITIALIZER,
     NULL,               /* field */
     SORT_TYPE_DOC,      /* type */
     false,              /* reverse */
-    NULL,               /* index */
+    NULL,               /* field_index_class */
     &amp;sf_doc_compare,    /* compare */
     &amp;sf_doc_get_val,    /* get_val */
-    NULL,               /* create_index */
-    NULL,               /* destroy_index */
-    NULL,               /* handle_term */
 };
 
 const SortField SORT_FIELD_DOC_REV = {
-    MUTEX_INITIALIZER,
     NULL,               /* field */
     SORT_TYPE_DOC,      /* type */
     true,               /* reverse */
-    NULL,               /* index */
+    NULL,               /* field_index_class */
     &amp;sf_doc_compare,    /* compare */
     &amp;sf_doc_get_val,    /* get_val */
-    NULL,               /* create_index */
-    NULL,               /* destroy_index */
-    NULL,               /* handle_term */
 };
 
 /***************************************************************************
@@ -250,117 +199,60 @@ const SortField SORT_FIELD_DOC_REV = {
 
 static void sf_byte_get_val(void *index, Hit *hit, Comparable *comparable)
 {
-    comparable-&gt;val.i = ((int *)index)[hit-&gt;doc];
+    comparable-&gt;val.l = ((long *)index)[hit-&gt;doc];
 }
 
 static int sf_byte_compare(void *index, Hit *hit1, Hit *hit2)
 {
-    int val1 = ((int *)index)[hit1-&gt;doc];
-    int val2 = ((int *)index)[hit2-&gt;doc];
+    long val1 = ((long *)index)[hit1-&gt;doc];
+    long val2 = ((long *)index)[hit2-&gt;doc];
     if (val1 &gt; val2) return 1;
     else if (val1 &lt; val2) return -1;
     else return 0;
 }
 
-static void *sf_byte_create_index(int size)
-{
-    int *index = ALLOC_AND_ZERO_N(int, size + 1);
-    index[0]++;
-    return &amp;index[1];
-}
-
-static void sf_byte_destroy_index(void *p)
+SortField *sort_field_byte_new(const char *field, bool reverse)
 {
-    int *index = (int *)p;
-    free(&amp;index[-1]);
-}
-
-static void sf_byte_handle_term(void *index_ptr, TermDocEnum *tde, char *text)
-{
-    int *index = (int *)index_ptr;
-    int val = index[-1]++;
-    (void)text;
-    while (tde-&gt;next(tde)) {
-        index[tde-&gt;doc_num(tde)] = val;
-    }
-}
-
-static void sort_field_byte_methods(SortField *self)
-{
-    self-&gt;type          = SORT_TYPE_BYTE;
-    self-&gt;compare       = &amp;sf_byte_compare;
-    self-&gt;get_val       = &amp;sf_byte_get_val;
-    self-&gt;create_index  = &amp;sf_byte_create_index;
-    self-&gt;destroy_index = &amp;sf_byte_destroy_index;
-    self-&gt;handle_term   = &amp;sf_byte_handle_term;
-}
-
-SortField *sort_field_byte_new(char *field, bool reverse)
-{
-    SortField *self = sort_field_alloc(field, SORT_TYPE_BYTE, reverse);
-    sort_field_byte_methods(self);
-    return self;
+    return sort_field_alloc(field, SORT_TYPE_BYTE, reverse,
+                            &amp;sf_byte_compare, &amp;sf_byte_get_val,
+                            &amp;BYTE_FIELD_INDEX_CLASS);
 }
 
 /***************************************************************************
  * IntegerSortField
  ***************************************************************************/
 
-void sf_int_get_val(void *index, Hit *hit, Comparable *comparable)
+static void sf_int_get_val(void *index, Hit *hit, Comparable *comparable)
 {
-    comparable-&gt;val.i = ((int *)index)[hit-&gt;doc];
+    comparable-&gt;val.l = ((long *)index)[hit-&gt;doc];
 }
 
-int sf_int_compare(void *index, Hit *hit1, Hit *hit2)
+static int sf_int_compare(void *index, Hit *hit1, Hit *hit2)
 {
-    int val1 = ((int *)index)[hit1-&gt;doc];
-    int val2 = ((int *)index)[hit2-&gt;doc];
+    long val1 = ((long *)index)[hit1-&gt;doc];
+    long val2 = ((long *)index)[hit2-&gt;doc];
     if (val1 &gt; val2) return 1;
     else if (val1 &lt; val2) return -1;
     else return 0;
 }
 
-void *sf_int_create_index(int size)
+SortField *sort_field_int_new(const char *field, bool reverse)
 {
-    return ALLOC_AND_ZERO_N(int, size);
-}
-
-void sf_int_handle_term(void *index_ptr, TermDocEnum *tde, char *text)
-{
-    int *index = (int *)index_ptr;
-    int val;
-    sscanf(text, &quot;%d&quot;, &amp;val);
-    while (tde-&gt;next(tde)) {
-        index[tde-&gt;doc_num(tde)] = val;
-    }
-}
-
-void sort_field_int_methods(SortField *self)
-{
-    self-&gt;type          = SORT_TYPE_INTEGER;
-    self-&gt;compare       = &amp;sf_int_compare;
-    self-&gt;get_val       = &amp;sf_int_get_val;
-    self-&gt;create_index  = &amp;sf_int_create_index;
-    self-&gt;handle_term   = &amp;sf_int_handle_term;
-}
-
-SortField *sort_field_int_new(char *field, bool reverse)
-{
-    SortField *self = sort_field_alloc(field, SORT_TYPE_INTEGER, reverse);
-    sort_field_int_methods(self);
-    return self;
+    return sort_field_alloc(field, SORT_TYPE_INTEGER, reverse,
+                            &amp;sf_int_compare, &amp;sf_int_get_val,
+                            &amp;INTEGER_FIELD_INDEX_CLASS);
 }
 
 /***************************************************************************
  * FloatSortField
  ***************************************************************************/
 
-void sf_float_get_val(void *index, Hit *hit, Comparable *comparable)
+static void sf_float_get_val(void *index, Hit *hit, Comparable *comparable)
 {
     comparable-&gt;val.f = ((float *)index)[hit-&gt;doc];
 }
 
-int sf_float_compare(void *index, Hit *hit1, Hit *hit2)
+static int sf_float_compare(void *index, Hit *hit1, Hit *hit2)
 {
     float val1 = ((float *)index)[hit1-&gt;doc];
     float val2 = ((float *)index)[hit2-&gt;doc];
@@ -369,58 +261,25 @@ int sf_float_compare(void *index, Hit *hit1, Hit *hit2)
     else return 0;
 }
 
-void *sf_float_create_index(int size)
+SortField *sort_field_float_new(const char *field, bool reverse)
 {
-    return ALLOC_AND_ZERO_N(float, size);
-}
-
-void sf_float_handle_term(void *index_ptr, TermDocEnum *tde, char *text)
-{
-    float *index = (float *)index_ptr;
-    float val;
-    sscanf(text, &quot;%g&quot;, &amp;val);
-    while (tde-&gt;next(tde)) {
-        index[tde-&gt;doc_num(tde)] = val;
-    }
-}
-
-void sort_field_float_methods(SortField *self)
-{
-    self-&gt;type          = SORT_TYPE_FLOAT;
-    self-&gt;compare       = &amp;sf_float_compare;
-    self-&gt;get_val       = &amp;sf_float_get_val;
-    self-&gt;create_index  = &amp;sf_float_create_index;
-    self-&gt;handle_term   = &amp;sf_float_handle_term;
-}
-
-SortField *sort_field_float_new(char *field, bool reverse)
-{
-    SortField *self = sort_field_alloc(field, SORT_TYPE_FLOAT, reverse);
-    sort_field_float_methods(self);
-    return self;
+    return sort_field_alloc(field, SORT_TYPE_FLOAT, reverse,
+                            &amp;sf_float_compare, &amp;sf_float_get_val,
+                            &amp;FLOAT_FIELD_INDEX_CLASS);
 }
 
 /***************************************************************************
  * StringSortField
  ***************************************************************************/
 
-#define VALUES_ARRAY_START_SIZE 8
-typedef struct StringIndex {
-    int size;
-    int *index;
-    char **values;
-    int v_size;
-    int v_capa;
-} StringIndex;
-
-void sf_string_get_val(void *index, Hit *hit, Comparable *comparable)
+static void sf_string_get_val(void *index, Hit *hit, Comparable *comparable)
 {
     comparable-&gt;val.s
         = ((StringIndex *)index)-&gt;values[
         ((StringIndex *)index)-&gt;index[hit-&gt;doc]];
 }
 
-int sf_string_compare(void *index, Hit *hit1, Hit *hit2)
+static int sf_string_compare(void *index, Hit *hit1, Hit *hit2)
 {
     char *s1 = ((StringIndex *)index)-&gt;values[
         ((StringIndex *)index)-&gt;index[hit1-&gt;doc]];
@@ -447,151 +306,20 @@ int sf_string_compare(void *index, Hit *hit1, Hit *hit2)
     */
 }
 
-void *sf_string_create_index(int size)
-{
-    StringIndex *self = ALLOC_AND_ZERO(StringIndex);
-    self-&gt;size = size;
-    self-&gt;index = ALLOC_AND_ZERO_N(int, size);
-    self-&gt;v_capa = VALUES_ARRAY_START_SIZE;
-    self-&gt;v_size = 1; /* leave the first value as NULL */
-    self-&gt;values = ALLOC_AND_ZERO_N(char *, VALUES_ARRAY_START_SIZE);
-    return self;
-}
-
-void sf_string_destroy_index(void *p)
-{
-    StringIndex *self = (StringIndex *)p;
-    int i;
-    free(self-&gt;index);
-    for (i = 0; i &lt; self-&gt;v_size; i++) {
-        free(self-&gt;values[i]);
-    }
-    free(self-&gt;values);
-    free(self);
-}
-
-void sf_string_handle_term(void *index_ptr, TermDocEnum *tde, char *text)
-{
-    StringIndex *index = (StringIndex *)index_ptr;
-    if (index-&gt;v_size &gt;= index-&gt;v_capa) {
-        index-&gt;v_capa *= 2;
-        index-&gt;values = REALLOC_N(index-&gt;values, char *, index-&gt;v_capa);
-    }
-    index-&gt;values[index-&gt;v_size] = estrdup(text);
-    while (tde-&gt;next(tde)) {
-        index-&gt;index[tde-&gt;doc_num(tde)] = index-&gt;v_size;
-    }
-    index-&gt;v_size++;
-}
-
-void sort_field_string_methods(SortField *self)
-{
-    self-&gt;type          = SORT_TYPE_STRING;
-    self-&gt;compare       = &amp;sf_string_compare;
-    self-&gt;get_val       = &amp;sf_string_get_val;
-    self-&gt;create_index  = &amp;sf_string_create_index;
-    self-&gt;destroy_index = &amp;sf_string_destroy_index;
-    self-&gt;handle_term   = &amp;sf_string_handle_term;
-}
-
-SortField *sort_field_string_new(char *field, bool reverse)
+SortField *sort_field_string_new(const char *field, bool reverse)
 {
-    SortField *self = sort_field_alloc(field, SORT_TYPE_STRING, reverse);
-    sort_field_string_methods(self);
-    return self;
+    return sort_field_alloc(field, SORT_TYPE_STRING, reverse,
+                            &amp;sf_string_compare, &amp;sf_string_get_val,
+                            &amp;STRING_FIELD_INDEX_CLASS);
 }
 
 /***************************************************************************
  * AutoSortField
  ***************************************************************************/
 
-void sort_field_auto_evaluate(SortField *sf, char *text)
-{
-    int int_val;
-    float float_val;
-    int text_len = 0, scan_len = 0;
-
-    text_len = (int)strlen(text);
-    sscanf(text, &quot;%d%n&quot;, &amp;int_val, &amp;scan_len);
-    if (scan_len == text_len) {
-        sort_field_int_methods(sf);
-    } else {
-        sscanf(text, &quot;%f%n&quot;, &amp;float_val, &amp;scan_len);
-        if (scan_len == text_len) {
-            sort_field_float_methods(sf);
-        } else {
-            sort_field_string_methods(sf);
-        }
-    }
-}
-
-SortField *sort_field_auto_new(char *field, bool reverse)
-{
-    return sort_field_alloc(field, SORT_TYPE_AUTO, reverse);
-}
-
-/***************************************************************************
- *
- * FieldCache
- *
- ***************************************************************************/
-
-void *field_cache_get_index(IndexReader *ir, SortField *sf)
+SortField *sort_field_auto_new(const char *field, bool reverse)
 {
-    void *volatile index = NULL;
-    int length = 0;
-    TermEnum *volatile te = NULL;
-    TermDocEnum *volatile tde = NULL;
-    SortField *sf_clone;
-    const int field_num = fis_get_field_num(ir-&gt;fis, sf-&gt;field);
-
-    if (field_num &lt; 0) {
-        RAISE(ARG_ERROR,
-              &quot;Cannot sort by field \&quot;%s\&quot;. It doesn't exist in the index.&quot;,
-              sf-&gt;field);
-    }
-
-    mutex_lock(&amp;sf-&gt;mutex);
-    if (!ir-&gt;sort_cache) {
-        ir-&gt;sort_cache = h_new(&amp;sort_field_hash, &amp;sort_field_cache_eq,
-                               &amp;sort_field_destroy, NULL);
-    }
-
-    if (sf-&gt;type == SORT_TYPE_AUTO) {
-        te = ir-&gt;terms(ir, field_num);
-        if (!te-&gt;next(te) &amp;&amp; (ir-&gt;num_docs(ir) &gt; 0)) {
-            RAISE(ARG_ERROR,
-                  &quot;Cannot sort by field \&quot;%s\&quot; as there are no terms &quot;
-                  &quot;in that field in the index.&quot;, sf-&gt;field);
-        }
-        sort_field_auto_evaluate(sf, te-&gt;curr_term);
-        te-&gt;close(te);
-    }
-
-    index = h_get(ir-&gt;sort_cache, sf);
-
-    if (index == NULL) {
-        length = ir-&gt;max_doc(ir);
-        if (length &gt; 0) {
-            TRY
-                tde = ir-&gt;term_docs(ir);
-                te = ir-&gt;terms(ir, field_num);
-                index = sf-&gt;create_index(length);
-                while (te-&gt;next(te)) {
-                    tde-&gt;seek_te(tde, te);
-                    sf-&gt;handle_term(index, tde, te-&gt;curr_term);
-                }
-            XFINALLY
-                tde-&gt;close(tde);
-            te-&gt;close(te);
-            XENDTRY
-        }
-        sf_clone = sort_field_clone(sf);
-        sf_clone-&gt;index = index;
-        h_set(ir-&gt;sort_cache, sf_clone, index);
-    }
-    mutex_unlock(&amp;sf-&gt;mutex);
-    return index;
+    return sort_field_alloc(field, SORT_TYPE_AUTO, reverse, NULL, NULL, NULL);
 }
 
 /***************************************************************************
@@ -630,12 +358,88 @@ typedef struct Sorter {
     Sort *sort;
 } Sorter;
 
+#define SET_AUTO(upper_type, lower_type) \
+    sf-&gt;type = SORT_TYPE_ ## upper_type;\
+    sf-&gt;field_index_class = &amp;upper_type ## _FIELD_INDEX_CLASS;\
+    sf-&gt;compare = sf_ ## lower_type ## _compare;\
+    sf-&gt;get_val = sf_ ## lower_type ## _get_val
+
+static void sort_field_auto_evaluate(SortField *sf, char *text)
+{
+    int int_val;
+    float float_val;
+    int text_len = 0, scan_len = 0;
+
+    text_len = (int)strlen(text);
+    sscanf(text, &quot;%d%n&quot;, &amp;int_val, &amp;scan_len);
+    if (scan_len == text_len) {
+        SET_AUTO(INTEGER, int);
+    } else {
+        sscanf(text, &quot;%f%n&quot;, &amp;float_val, &amp;scan_len);
+        if (scan_len == text_len) {
+            SET_AUTO(FLOAT, float);
+        } else {
+            SET_AUTO(STRING, string);
+        }
+    }
+}
+/*
+static INLINE void set_auto(SortField *sf,
+    enum SORT_TYPE type,
+    const FieldIndexClass *field_index_class,
+    int  (*compare)(void *index_ptr, Hit *hit1, Hit *hit2),
+    void (*get_val)(void *index_ptr, Hit *hit1, Comparable *comparable))
+{
+    sf-&gt;type = type;
+    sf-&gt;field_index_class = field_index_class;
+    sf-&gt;compare = compare;
+    sf-&gt;get_val = get_val;
+}
+
+static void sort_field_auto_evaluate(SortField *sf, char *text)
+{
+    int int_val;
+    float float_val;
+    int text_len = 0, scan_len = 0;
+
+    text_len = (int)strlen(text);
+    sscanf(text, &quot;%d%n&quot;, &amp;int_val, &amp;scan_len);
+    if (scan_len == text_len) {
+        set_auto(sf, SORT_TYPE_INTEGER, &amp;INTEGER_FIELD_INDEX_CLASS,
+                 sf_int_compare, sf_int_get_val);
+    } else {
+        sscanf(text, &quot;%f%n&quot;, &amp;float_val, &amp;scan_len);
+        if (scan_len == text_len) {
+            set_auto(sf, SORT_TYPE_FLOAT, &amp;FLOAT_FIELD_INDEX_CLASS,
+                     sf_float_compare, sf_float_get_val);
+        } else {
+            set_auto(sf, SORT_TYPE_STRING, &amp;STRING_FIELD_INDEX_CLASS,
+                     sf_string_compare, sf_string_get_val);
+        }
+    }
+}
+*/
+
 Comparator *sorter_get_comparator(SortField *sf, IndexReader *ir)
 {
     void *index = NULL;
 
     if (sf-&gt;type &gt; SORT_TYPE_DOC) {
-        index = field_cache_get_index(ir, sf);
+        FieldIndex *field_index = NULL;
+        if (sf-&gt;type == SORT_TYPE_AUTO) {
+            TermEnum *te = ir_terms(ir, sf-&gt;field);
+            if (!te-&gt;next(te) &amp;&amp; (ir-&gt;num_docs(ir) &gt; 0)) {
+                RAISE(ARG_ERROR,
+                      &quot;Cannot sort by field \&quot;%s\&quot; as there are no terms &quot;
+                      &quot;in that field in the index.&quot;, sf-&gt;field);
+            }
+            sort_field_auto_evaluate(sf, te-&gt;curr_term);
+            te-&gt;close(te);
+        }
+        mutex_lock(&amp;ir-&gt;field_index_mutex);
+        field_index = field_index_new(ir, sf-&gt;field, sf-&gt;field_index_class);
+        mutex_unlock(&amp;ir-&gt;field_index_mutex);
+        index = field_index-&gt;index;
     }
     return comparator_new(index, sf-&gt;reverse, sf-&gt;compare);
 }
@@ -864,12 +668,12 @@ bool fdshq_lt(FieldDoc *fd1, FieldDoc *fd2)
                 if (fd1-&gt;hit.doc &lt; fd2-&gt;hit.doc) c = -1;
                 break;
             case SORT_TYPE_INTEGER:
-                if (cmps1[i].val.i &gt; cmps2[i].val.i) c =  1;
-                if (cmps1[i].val.i &lt; cmps2[i].val.i) c = -1;
+                if (cmps1[i].val.l &gt; cmps2[i].val.l) c =  1;
+                if (cmps1[i].val.l &lt; cmps2[i].val.l) c = -1;
                 break;
             case SORT_TYPE_BYTE:
-                if (cmps1[i].val.i &gt; cmps2[i].val.i) c =  1;
-                if (cmps1[i].val.i &lt; cmps2[i].val.i) c = -1;
+                if (cmps1[i].val.l &gt; cmps2[i].val.l) c =  1;
+                if (cmps1[i].val.l &lt; cmps2[i].val.l) c = -1;
                 break;
             case SORT_TYPE_STRING:
                 do {</diff>
      <filename>c/src/sort.c</filename>
    </modified>
    <modified>
      <diff>@@ -122,9 +122,9 @@ static void do_test_top_docs(tst_case *tc, Searcher *searcher, Query *query,
                     case SORT_TYPE_FLOAT:
                         printf(&quot;f:%f &quot;, fd-&gt;comparables[j].val.f); break;
                     case SORT_TYPE_DOC:
-                        printf(&quot;d:%d &quot;, fd-&gt;comparables[j].val.i); break;
+                        printf(&quot;d:%ld &quot;, fd-&gt;comparables[j].val.l); break;
                     case SORT_TYPE_INTEGER:
-                        printf(&quot;i:%d &quot;, fd-&gt;comparables[j].val.i); break;
+                        printf(&quot;i:%ld &quot;, fd-&gt;comparables[j].val.l); break;
                     case SORT_TYPE_STRING:
                         printf(&quot;s:%s &quot;, fd-&gt;comparables[j].val.s); break;
                     default:</diff>
      <filename>c/test/test_sort.c</filename>
    </modified>
    <modified>
      <diff>@@ -16,66 +16,22 @@ end
 
 objs = Dir[&quot;src/*.c&quot;].map {|full_path| File.basename(full_path).gsub(/c$/, &quot;o&quot;)}
 objs &lt;&lt; &quot;q_parser.o&quot; unless objs.index(&quot;q_parser.o&quot;)
-test_objs = Dir[&quot;test/*.c&quot;].map {|full_path| File.basename(full_path).gsub(/c$/, &quot;o&quot;)}
+OBJS = objs.join(' ')
+TEST_OBJS = Dir[&quot;test/*.c&quot;].map {|full_path| File.basename(full_path).gsub(/c$/, &quot;o&quot;)}.join(' ')
 
-print &quot;&quot;&quot;
-CFLAGS = -std=c99 -pedantic -fno-stack-protector -Wall -Wextra -Iinclude -Ilib/libstemmer_c/include -fno-common -g -DDEBUG -D_FILE_OFFSET_BITS=64
-
-LFLAGS = -lm -lpthread
-
-include lib/libstemmer_c/mkinc.mak
-
-STEMMER_OBJS = $(patsubst %.c,src/libstemmer_c/%.o, $(snowball_sources))
-
-TEST_OBJS = #{test_objs.join(&quot; &quot;)}
-
-OBJS = #{objs.join(&quot; &quot;)} libstemmer.o
-
-vpath %.c test src
-
-vpath %.h test include lib/libstemmer_c/include
-
-runtests: testall
-	./testall -v -f -q
-
-testall: $(OBJS) $(TEST_OBJS)
-	$(CC) $(CFLAGS) $(LFLAGS) $(OBJS) $(TEST_OBJS) -o testall
-
-valgrind: testall
-	valgrind --leak-check=yes --show-reachable=yes --workaround-gcc296-bugs=yes -v ./testall -q
-
-bench: bench.c $(OBJS)
-	$(CC) $(CFLAGS) -lpthread bench.c $(OBJS) $(LFLAGS) -o bench
-
-search_bench: search_bench.c $(OBJS)
-	$(CC) $(CFLAGS) search_bench.c $(OBJS) $(LFLAGS) -o search_bench
-
-sort_bench: sort_bench.c $(OBJS)
-	$(CC) $(CFLAGS) sort_bench.c $(OBJS) $(LFLAGS) -o sort_bench
-
-libstemmer.o: $(snowball_sources:%.c=lib/libstemmer_c/%.o)
-	$(AR) -cru $@ $^
-
-q_parser.o: src/q_parser.c
-	$(CC) $(CFLAGS) src/q_parser.c -c
-
-src/q_parser.c: src/q_parser.y
-
-.PHONY: clean
-clean:
-	rm -f *.o testall gmon.out bench search_bench
-&quot;&quot;&quot;
-
-def get_deps(src)
+def get_deps(src_file)
   deps = Set.new
-  direct_deps = $dep_tree[src]
+  direct_deps = $dep_tree[src_file]
   return deps unless direct_deps
   deps.merge(direct_deps)
   direct_deps.each {|dep| deps.merge(get_deps(dep))}
   deps
 end
 
-$dep_tree.each_key do |src|
-  next unless src =~ /\.c$/
-  puts src.gsub(/c$/, &quot;o&quot;) + &quot;: &quot; + get_deps(src).to_a.join(&quot; &quot;) + &quot;\n\n&quot;
-end
+OBJECT_DEPENDENCIES = $dep_tree.keys.map {|src_file|
+  next unless src_file =~ /\.c$/
+  src_file.gsub(/c$/, &quot;o&quot;) + &quot;: &quot; + get_deps(src_file).to_a.join(&quot; &quot;)
+}.compact.join(&quot;\n\n&quot;)
+
+MAKEFILE_TEMPLATE = File.read(File.join(File.dirname(__FILE__), '../Makefile.template'))
+puts MAKEFILE_TEMPLATE.gsub(/%([A-Z_]+)%/) {eval($1)}</diff>
      <filename>c/tools/make_makefile.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>c/tools/mkmf.pl</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>8bc2898052585f89aa8a9838fe95fd4b42edd65d</id>
    </parent>
  </parents>
  <author>
    <name>dbalmain</name>
    <email>dbalmain@06fd6eb0-0002-0410-a719-e5602cce40bc</email>
  </author>
  <url>http://github.com/dbalmain/ferret/commit/a98ed8eff04bfb75b9e9bef649018bb2ffc652b6</url>
  <id>a98ed8eff04bfb75b9e9bef649018bb2ffc652b6</id>
  <committed-date>2008-03-21T19:59:19-07:00</committed-date>
  <authored-date>2008-03-21T19:59:19-07:00</authored-date>
  <message>* removed obsolete Perl makefile generator
* extracted field-index functionality from sort. For example;

    FieldIndex *field_index = field_index_new(index_reader, &quot;integer-field&quot;,
                                              INTEGER_FIELD_INDEX_CLASS);
    long val_in_doc_10 = ((long *)field_index-&gt;index)[10];


git-svn-id: svn+ssh://davebalmain.com/home/dave/repos/ferret/trunk@873 06fd6eb0-0002-0410-a719-e5602cce40bc</message>
  <tree>101ae45f6585a5bd136059ff2e27e781dc8eab34</tree>
  <committer>
    <name>dbalmain</name>
    <email>dbalmain@06fd6eb0-0002-0410-a719-e5602cce40bc</email>
  </committer>
</commit>
