Beispiel #1
0
void *Trie_get(const Trie* trie, const char *key) {
    int first, last, mid;

    if(!key[0]) {
	return trie->value;
    }

    /* The transitions are stored in alphabetical order.  Do a binary
     * search to find the proper one.
     */
    first = 0;
    last = trie->num_transitions-1;
    while(first <= last) {
	Transition* transition;
	char *suffix;
	int c;
	mid = (first+last)/2;
	transition = &trie->transitions[mid];
	suffix = transition->suffix;
	/* If suffix is a substring of key, then get the value from
	   the next trie.
	*/
	c = strncmp(key, suffix, strlen(suffix));
	if(c < 0)
	    last = mid-1;
	else if(c > 0)
	    first = mid+1;
	else
	    return Trie_get(transition->next, key+strlen(suffix));
    }
    return NULL;
}
Beispiel #2
0
static void
_get_approximate_trie(const Trie* trie, const char *key, const int k,
		      void (*callback)(const char *key,
				       const void *value,
				       const int mismatches,
				       void *data),
		      void *data,
		      const int mismatches,
		      char *current_key, const int max_key
		      )
{
    int i;

    /* If there's no more key to match, then I'm done. */
    if(!key[0]) {
	if(trie->value)
	    (*callback)(current_key, trie->value, mismatches, data);
    }
    /* If there are no more mismatches allowed, then fall back to the
       faster Trie_get. */
    else if(!k) {
	void *value = Trie_get(trie, key);
	if(value) {
	    int l = strlen(current_key);
	    /* Make sure I have enough space for the full key. */
	    if(l + strlen(key) < max_key) {
		strcat(current_key, key);
		(*callback)(current_key, value, mismatches, data);
		current_key[l] = 0;
	    }
	    /* BUG: Ran out of space for the key.  This fails
	       silently, but should signal an error. */
	}
    }
    /* If there are no more transitions, then all the characters left
       in the key are mismatches. */
    else if(!trie->num_transitions) {
	if(trie->value && (strlen(key) <= k)) {
	    (*callback)(current_key, trie->value,
			mismatches+strlen(key), data);
	}
    }
    /* Otherwise, try to match each of the transitions. */
    else {
	for(i=0; i<trie->num_transitions; i++) {
	    Transition* transition = &trie->transitions[i];
	    const char *suffix = transition->suffix;
	    _get_approximate_transition(key, k, transition, suffix,
					callback, data,
					mismatches, current_key, max_key);
	}
    }

}
Beispiel #3
0
static PyObject *
trie_get(trieobject *mp, PyObject *args)
{
    const char *key;
    PyObject *py_value;
    PyObject *py_failobj = Py_None;

    if (!PyArg_ParseTuple(args, "s|O:get", &key, &py_failobj))
        return NULL;
    py_value = Trie_get(mp->trie, key);
    if(!py_value)
        py_value = py_failobj;
    Py_INCREF(py_value);
    return py_value;
}
Beispiel #4
0
static PyObject *
trie_subscript(trieobject *mp, PyObject *py_key)
{
    unsigned char *key;
    PyObject *py_value;

    /* Make sure key is a string. */
    if(!PyString_Check(py_key)) {
	PyErr_SetString(PyExc_TypeError, "key must be a string");
	return NULL;
    }
    key = (unsigned char *)PyString_AS_STRING(py_key);
    py_value = (PyObject *)Trie_get(mp->trie, key);
    if(py_value == NULL)
	PyErr_SetString(PyExc_KeyError, (char *)key);
    else
	Py_INCREF(py_value);
    return py_value;
}
Beispiel #5
0
static int
trie_ass_sub(trieobject *mp, PyObject *py_key, PyObject *py_value)
{
    unsigned char *key;
    PyObject *py_prev;

    /* Make sure key is a string. */
    if(!PyString_Check(py_key)) {
	PyErr_SetString(PyExc_TypeError, "key must be a string");
	return -1;
    }
    key = (unsigned char *)PyString_AS_STRING((char *)py_key);
    
    /* Check to see whether something already exists at that key.  If
       there's already an object there, then I will have to remove it.
    */
    py_prev = (PyObject *)Trie_get(mp->trie, key);
    if(py_prev) {
	Py_DECREF(py_prev);
    }

    /* The client wants to delete a key from a dictionary.  The Trie
       API doesn't support this, so I will just overwrite it with
       NULL. */
    if(!py_value) {
	/* If the key doesn't exist, raise a KeyError. */
	if(!py_prev) {
	    PyErr_SetString(PyExc_KeyError, (char *)key);
	    return -1;
	}
	Trie_set(mp->trie, key, NULL);
    }
    /* The client wants to set a key in the dictionary. */
    else {
	Py_INCREF(py_value);
	if(Trie_set(mp->trie, key, py_value)) {
	    PyErr_SetString(PyExc_AssertionError, "error setting trie");
	    return -1;
	}
    }
    return 0;
}
Beispiel #6
0
static PyObject *
trie_subscript(trieobject *mp, PyObject *py_key)
{
    const char *key;
    PyObject *py_value;

    /* Make sure key is a string. */
#ifdef IS_PY3K
    if(!PyUnicode_Check(py_key)) {
#else
    if(!PyString_Check(py_key)) {
#endif
        PyErr_SetString(PyExc_TypeError, "key must be a string");
        return NULL;
    }
#ifdef IS_PY3K
    /* TODO - Review next line for buffer usage */
    key = PyBytes_AS_STRING(PyUnicode_AsASCIIString(py_key));
#else
    key = PyString_AS_STRING(py_key);
#endif
    py_value = Trie_get(mp->trie, key);
    if(py_value == NULL)
        PyErr_SetString(PyExc_KeyError, key);
    else
        Py_INCREF(py_value);
    return py_value;
}

static int
trie_ass_sub(trieobject *mp, PyObject *py_key, PyObject *py_value)
{
    int result = -1;
    const char *key;
    PyObject *py_prev;
#ifdef IS_PY3K
    PyObject* bytes;
#endif

    /* Make sure key is a string. */
#ifdef IS_PY3K
    if(!PyUnicode_Check(py_key)) {
#else
    if(!PyString_Check(py_key)) {
#endif
        PyErr_SetString(PyExc_TypeError, "key must be a string");
        return -1;
    }
#ifdef IS_PY3K
    bytes = PyUnicode_AsASCIIString(py_key);
    if(!bytes) {
        PyErr_SetString(PyExc_TypeError, "key must be an ASCII string");
        return -1;
    }
    key = PyBytes_AsString(bytes);
#else
    key = PyString_AS_STRING(py_key);
#endif

    /* Check to see whether something already exists at that key.  If
       there's already an object there, then I will have to remove it.
    */
    py_prev = Trie_get(mp->trie, key);
    if(py_prev) {
        Py_DECREF(py_prev);
    }

    /* The client wants to delete a key from a dictionary.  The Trie
       API doesn't support this, so I will just overwrite it with
       NULL. */
    if(!py_value) {
        /* If the key doesn't exist, raise a KeyError. */
        if(!py_prev)
            PyErr_SetString(PyExc_KeyError, key);
        else {
            Trie_set(mp->trie, key, NULL);
            result = 0;
        }
    }
    /* The client wants to set a key in the dictionary. */
    else {
        Py_INCREF(py_value);
        if(Trie_set(mp->trie, key, py_value))
            PyErr_SetString(PyExc_AssertionError, "error setting trie");
        else
            result = 0;
    }
#ifdef IS_PY3K
    Py_DECREF(bytes);
#endif
    return result;
}

static int trie_contains(trieobject *mp, PyObject* py_key)
{
    int result;
#ifdef IS_PY3K
    PyObject* bytes;
#endif
    const char *key;
    /* Make sure key is a string. */
#ifdef IS_PY3K
    if(!PyUnicode_Check(py_key)) {
#else
    if(!PyString_Check(py_key)) {
#endif
        PyErr_SetString(PyExc_TypeError, "key must be a string");
        return -1;
    }
#ifdef IS_PY3K
    bytes = PyUnicode_AsASCIIString(py_key);
    if(!bytes) {
        PyErr_SetString(PyExc_TypeError, "key must be an ASCII string");
        return -1;
    }
    key = PyBytes_AsString(bytes);
#else
    key = PyString_AS_STRING(py_key);
#endif
    result = Trie_has_key(mp->trie, key);
#ifdef IS_PY3K
    Py_DECREF(bytes);
#endif
    return result;
}

static char has_key__doc__[] =
    "D.has_key(k) -> 1 if D has a key k, else 0";

static PyObject *
trie_has_key(trieobject *mp, PyObject *py_key)
{
    int has_key = trie_contains(mp, py_key);
    if (has_key==-1) return NULL;
#ifdef IS_PY3K
    return PyLong_FromLong((long)has_key);
#else
    return PyInt_FromLong((long)has_key);
#endif
}
Beispiel #7
0
int Trie_has_key(const Trie* trie, const char *key)
{
    return Trie_get(trie, key) != NULL;
}