HI all, Judy is one of the most useful libraries out there and I use it all
the time. Something that always bothered me about it is the somewhat unusual
calling conventions, the use of macros and silent casting of 'void *'s
meaning it is very easy to accidentally use the API incorrectly and it's
conventions differ from pretty much every other library out there making
combining code problematic.

I went ahead and used c99's features
(inline functions, immediate struct values, defined uintptr_t and bool
types) to make a typesafe and more conformant api. I figured I post it if
anyone else found it handy. It declares everything using inline functions
rather than macros so they behave exactly as you would expect when it comes
to type promotion and whatnot, I also used my c 'newtype' method
(http://notanumber.net/archives/33/newtype-in-c-a-touch-of-strong-typing-using-compound-literals)
to give judy arrays unique types. I do give up the advanced error handling
features of libjudy though, it would be possible to get back but I have not
had need of it yet.

A sample of the API is here, it is in the attached sjudy.h and uses only
portable C99 features. The names follow a common scheme, judy1_t and judyl_t
are distinct types but generic functions can be implemented with mild macro
use but I tried to keep usage of them to the minimum.

judyl_t map = JUDY_INIT;

uintptr_t *jlIns(judyl_t *j, uintptr_t i);
uintptr_t *jlGet(judyl_t j, uintptr_t i);
bool       jlDel(judyl_t *j, uintptr_t i);
size_t     jlCount(judyl_t j, uintptr_t i1, uintptr_t i2);
uintptr_t *jlByCount(judyl_t j, size_t count, uintptr_t *i);

In addition I have versions that take pointers in addition to words as
arguments, using thees should remove the need for all explicit coercions
when using integral or pointer types as keys.

void **   jlppIns(judyl_t *j, void *i);
void **   jlppGet(judyl_t j, void *i);
bool      jlppDel(judyl_t *j, void *i);



For the more advanterous, I also made a version that uses all the GCC
specific trickery to make truely strongly typed judyL arrays, it is in the
attached sjudyt.h file. To use it you can do something like this

struct list_head {
     struct list_entry *head;
};
list_insert(struct list_head *head, void *data);

// declare typed JudyL array of floats to struct list_head. (the actual
// struct directly is held in the JudyL map, _not_ a pointer to one)

JUDYL_TYPED(float, struct list_head) weight_map;

list_insert(jltIns(&weight_map, 3.0), data);


It uses a trick of adding dummy zero length entries to the structure that
encode the types inside the map, then using the gcc __typeof__ extension, it
will verify all uses of the API statically, it requires a recent version of
gcc to use.

Hope someone finds them useful.
#ifndef SJUDY_H
#define SJUDY_H

#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
#error This must be compiled under c99 mode.
#endif

// Platform assumptions:
// sizeof(uintptr_t) == sizeof(Word_t) as defined by Judy.
// The null pointer is represented as the all zero bit pattern.

// Naming scheme, all functions have the scheme
// j[t][k][v]Action
//
// where t is the type of array (L for map, 1 for bitset). if missing, the
// funcition is generic to both.
// k is the type of the index w for word, p for pointer.
// v is the type of the value w for word, p for pointer.
// when the argument types are omitted, 'w' is assumed.
//
// The action names match the names of the judy functions.
// 'word' is used as a synonym for a value of type uintptr_t.
// Although defined as macros, some exported names use the function
// naming convention when the forced use of a macro is independent of how it
// should be used. Such routines behave as functions would with respect to their
// arguments/return values.

#include <stdbool.h>
#include <stdint.h>

#include <Judy.h>

// psuedo-prototypes for macros
//
// JUDY_INIT - static initializer.
//
// uintptr_t jToWord(judyx_t a);
// bool jEmpty(judyx_t x);
// bool jWordIsArray(uintptr_t);
// judyl_t jlFromWord(uintptr_t w);
// judy1_t j1FromWord(uintptr_t w);

#define _JINLINE static inline

// JudyL
typedef struct { Pvoid_t v; } judyl_t;

// uintptr_t -> uintptr_t
_JINLINE uintptr_t *jlIns(judyl_t *j, uintptr_t i);
_JINLINE uintptr_t *jlGet(judyl_t j, uintptr_t i);
_JINLINE bool       jlDel(judyl_t *j, uintptr_t i);
_JINLINE size_t     jlCount(judyl_t j, uintptr_t i1, uintptr_t i2);
_JINLINE uintptr_t *jlByCount(judyl_t j, size_t count, uintptr_t *i);
_JINLINE size_t     jlFree(judyl_t *j);
_JINLINE size_t     jlMemUsed(judyl_t j);
_JINLINE uintptr_t *jlFirst(judyl_t a, uintptr_t *i);
_JINLINE uintptr_t *jlNext(judyl_t a, uintptr_t *i);
_JINLINE uintptr_t *jlLast(judyl_t a, uintptr_t *i);
_JINLINE uintptr_t *jlPrev(judyl_t a, uintptr_t *i);
_JINLINE bool       jlFirstEmpty(judyl_t a, uintptr_t *i);
_JINLINE bool       jlNextEmpty(judyl_t a, uintptr_t *i);
_JINLINE bool       jlLastEmpty(judyl_t a, uintptr_t *i);
_JINLINE bool       jlPrevEmpty(judyl_t a, uintptr_t *i);

// uintptr_t -> void *
_JINLINE void **    jlwpIns(judyl_t *j, uintptr_t i);
_JINLINE void **    jlwpGet(judyl_t j, uintptr_t i);
_JINLINE bool       jlwpDel(judyl_t *j, uintptr_t i);
_JINLINE size_t     jlwpCount(judyl_t j, uintptr_t i1, uintptr_t i2);
_JINLINE void **    jlwpByCount(judyl_t j, size_t count, uintptr_t *i);
_JINLINE void **    jlwpFirst(judyl_t a, uintptr_t *i);
_JINLINE void **    jlwpNext(judyl_t a, uintptr_t *i);
_JINLINE void **    jlwpLast(judyl_t a, uintptr_t *i);
_JINLINE void **    jlwpPrev(judyl_t a, uintptr_t *i);
_JINLINE bool       jlwpFirstEmpty(judyl_t a, uintptr_t *i);
_JINLINE bool       jlwpNextEmpty(judyl_t a, uintptr_t *i);
_JINLINE bool       jlwpLastEmpty(judyl_t a, uintptr_t *i);
_JINLINE bool       jlwpPrevEmpty(judyl_t a, uintptr_t *i);

// void * -> void *
_JINLINE void **   jlppIns(judyl_t *j, void *i);
_JINLINE void **   jlppGet(judyl_t j, void *i);
_JINLINE bool      jlppDel(judyl_t *j, void *i);
_JINLINE size_t    jlppCount(judyl_t j, void *i1, void *i2);
_JINLINE void **   jlppByCount(judyl_t j, size_t count, void **i);
_JINLINE void **   jlppFirst(judyl_t a, void **i);
_JINLINE void **   jlppNext(judyl_t a, void **i);
_JINLINE void **   jlppLast(judyl_t a, void **i);
_JINLINE void **   jlppPrev(judyl_t a, void **i);
_JINLINE bool      jlppFirstEmpty(judyl_t a, void **i);
_JINLINE bool      jlppNextEmpty(judyl_t a, void **i);
_JINLINE bool      jlppLastEmpty(judyl_t a, void **i);
_JINLINE bool      jlppPrevEmpty(judyl_t a, void **i);

// void * -> uintptr_t
_JINLINE uintptr_t* jlpwIns(judyl_t *j, void *i);
_JINLINE uintptr_t* jlpwGet(judyl_t j, void *i);
_JINLINE bool       jlpwDel(judyl_t *j, void *i);
_JINLINE size_t     jlpwCount(judyl_t j, void *i1, void *i2);
_JINLINE uintptr_t* jlpwByCount(judyl_t j, size_t count, void **i);
_JINLINE uintptr_t* jlpwFirst(judyl_t a, void **i);
_JINLINE uintptr_t* jlpwNext(judyl_t a, void **i);
_JINLINE uintptr_t* jlpwLast(judyl_t a, void **i);
_JINLINE uintptr_t* jlpwPrev(judyl_t a, void **i);
_JINLINE bool       jlpwFirstEmpty(judyl_t a, void **i);
_JINLINE bool       jlpwNextEmpty(judyl_t a, void **i);
_JINLINE bool       jlpwLastEmpty(judyl_t a, void **i);
_JINLINE bool       jlpwPrevEmpty(judyl_t a, void **i);

// Judy1

typedef struct { Pvoid_t v; } judy1_t;

_JINLINE bool   j1Set(judy1_t *j, uintptr_t i);
_JINLINE bool   j1Unset(judy1_t *j, uintptr_t i);
_JINLINE bool   j1Test(judy1_t j, uintptr_t i);
_JINLINE bool   j1ByCount(judy1_t j, size_t count, uintptr_t *i);
_JINLINE size_t j1Count(judy1_t j, uintptr_t i1, uintptr_t i2);
_JINLINE size_t j1Free(judy1_t *j);
_JINLINE size_t j1MemUsed(judy1_t j);
_JINLINE bool   j1FirstEmpty(judy1_t a, uintptr_t *i);
_JINLINE bool   j1NextEmpty(judy1_t a, uintptr_t *i);
_JINLINE bool   j1LastEmpty(judy1_t a, uintptr_t *i);
_JINLINE bool   j1PrevEmpty(judy1_t a, uintptr_t *i);
_JINLINE bool   j1First(judy1_t a, uintptr_t *i);
_JINLINE bool   j1Next(judy1_t a, uintptr_t *i);
_JINLINE bool   j1Last(judy1_t a, uintptr_t *i);
_JINLINE bool   j1Prev(judy1_t a, uintptr_t *i);

/*
 defined as macros:
_JINLINE bool   j1pSet(judy1_t *arr, void *index);
_JINLINE bool   j1pUnset(judy1_t *arr, void *index);
_JINLINE bool   j1pTest(judy1_t arr, void *index);
_JINLINE bool   j1pByCount(judy1_t arr, size_t count, void **index);
_JINLINE size_t j1pCount(judy1_t arr, void *i1, void *i2);
_JINLINE size_t j1pFree(judy1_t *arr);
_JINLINE size_t j1pMemUsed(judy1_t arr);
_JINLINE bool   j1pFirstEmpty(judy1_t a, void **i);
_JINLINE bool   j1pNextEmpty(judy1_t a, void **i);
_JINLINE bool   j1pLastEmpty(judy1_t a, void **i);
_JINLINE bool   j1pPrevEmpty(judy1_t a, void **i);
_JINLINE bool   j1pFirst(judy1_t a, void **i);
_JINLINE bool   j1pNext(judy1_t a, void **i);
_JINLINE bool   j1pLast(judy1_t a, void **i);
_JINLINE bool   j1pPrev(judy1_t a, void **i);
*/

#define JUDY_INIT { .v = 0 }

// Convert a judy array to a word sized integer, use the appropriate FromWord
// routine to convert back.
#define jToWord(j)  ((uintptr_t)((j).v))
#define jEmpty(j) (jToWord(j) == 0)
#define jWordIsArray(w) (!((w) & JLAP_INVALID))

// takes a word obtained from jToWord and convert it back to a judyl_t
#define jlFromWord(w)  (judyl_t){ .v = (Pvoid_t)w; }

uintptr_t *
jlIns(judyl_t *arr, uintptr_t index)
{
        return (uintptr_t *)JudyLIns(&arr->v, index, PJE0);
}

uintptr_t *
jlGet(judyl_t arr, uintptr_t index)
{
        return (uintptr_t *)JudyLGet(arr.v, index, PJE0);
}

bool
jlDel(judyl_t * arr, uintptr_t index)
{
        return (bool)JudyLDel(&arr->v, index, PJE0);
}

size_t
jlCount(judyl_t arr, uintptr_t i1, uintptr_t i2)
{
        return JudyLCount(arr.v, i1, i2, PJE0);
}

uintptr_t *
jlByCount(judyl_t arr, size_t count, uintptr_t *index)
{
        return (uintptr_t *)JudyLByCount(arr.v, count, index, PJE0);
}

size_t
jlFree(judyl_t * arr)
{
        return (size_t)JudyLFreeArray(&arr->v, PJE0);
}

size_t
jlMemUsed(judyl_t arr)
{
        return (size_t)JudyLMemUsed(arr.v);
}

#define SJUDY_ITER(x)   \
        uintptr_t *jl##x(judyl_t arr, uintptr_t * index) \
        { return (uintptr_t *)JudyL##x(arr.v, index, PJE0); }\
        bool jl##x##Empty(judyl_t arr, uintptr_t * index) \
        { return (bool)JudyL##x##Empty(arr.v, index, PJE0); }

SJUDY_ITER(First)
SJUDY_ITER(Next)
SJUDY_ITER(Last)
SJUDY_ITER(Prev)

#undef SJUDY_ITER

#define JLPP(func,p,r) \
            r jlpp##func(judyl_t p a, void *i) { \
                    return (r)jl##func(a, (uintptr_t)i); }     \
            r jlwp##func(judyl_t p a, uintptr_t i) { \
                    return (r)jl##func(a, i); }   \
            uintptr_t *jlpw##func(judyl_t p a, void *i) { \
                    return jl##func(a, (uintptr_t)i); }
#define JLPP2(func,p,r) \
            r jlpp##func(judyl_t p a, void *i1, void *i2) { \
                    return (r)jl##func(a, (uintptr_t)i1, (uintptr_t)i2); }        \
            r jlwp##func(judyl_t p a, uintptr_t i1, uintptr_t i2) { \
                    return (r)jl##func(a, i1, i2); }                              \
            uintptr_t jlpw##func(judyl_t p a, void *i1, void *i2) { \
                    return jl##func(a, (uintptr_t)i1, (uintptr_t)i2); }
#define JLPPI(func) \
            void **jlpp##func(judyl_t a, void **i) { \
                    return (void **)jl##func(a, (uintptr_t *)i); }  \
            bool jlpp##func##Empty(judyl_t a, void **i) { \
                    return jl##func##Empty(a, (uintptr_t *)i); }       \
            void **jlwp##func(judyl_t a, uintptr_t *i) { \
                    return (void **)jl##func(a, i); }  \
            bool jlwp##func##Empty(judyl_t a, uintptr_t *i) { \
                    return jl##func##Empty(a, i); } \
            uintptr_t *jlpw##func(judyl_t a, void **i) { \
                    return jl##func(a, (uintptr_t *)i); }  \
            bool jlpw##func##Empty(judyl_t a, void **i) { \
                    return jl##func##Empty(a, (uintptr_t *)i); }
#define JLPD(pw, ai) \
             bool jl##pw##Del(judyl_t *a, ai i) { \
                    return jlDel(a, (uintptr_t)i); }
#define _JLBC(pw, r, ai) \
             r *jl##pw##ByCount(judyl_t a, size_t count, ai *i2) { \
                    return (r *)jlByCount(a, count, (uintptr_t *)i2); }

JLPP(Ins,*,void **);
JLPP(Get,,void **);
JLPD(pp, void *);
JLPD(wp, uintptr_t);
JLPD(pw, void *);

_JLBC(pp, void *, void *);
_JLBC(wp, void *,uintptr_t);
_JLBC(pw, uintptr_t, void *);

JLPP2(Count,,size_t);
JLPPI(First);
JLPPI(Prev);
JLPPI(Last);
JLPPI(Next);

#undef _JLBC
#undef JLPP2
#undef JLPPI

// Judy1 Bitsets

static inline bool
j1Set(judy1_t * arr, uintptr_t index)
{
        return (bool)Judy1Set(&arr->v, index, PJE0);
}
static inline bool
j1Unset(judy1_t * arr, uintptr_t index)
{
        return (bool)Judy1Unset(&arr->v, index, PJE0);
}

static inline bool
j1Test(judy1_t arr, uintptr_t index)
{
        return (bool)Judy1Test(arr.v, index, PJE0);
}

static inline bool
j1ByCount(judy1_t arr, size_t count, uintptr_t *index)
{
        return (bool)Judy1ByCount(arr.v, count, index, PJE0);
}

static inline size_t
j1Count(judy1_t arr, uintptr_t i1, uintptr_t i2)
{
        return Judy1Count(arr.v, i1, i2, PJE0);
}

static inline size_t
j1Free(judy1_t * arr)
{
        return (size_t)Judy1FreeArray(&arr->v, PJE0);
}

static inline size_t
j1MemUsed(judy1_t arr)
{
        return (size_t)Judy1MemUsed(arr.v);
}

#define SJUDY_ITER(x)   \
        static inline bool \
        j1##x(judy1_t arr, uintptr_t * index) \
        { return (bool)Judy1##x(arr.v, index, PJE0); }\
        static inline bool \
        j1##x##Empty(judy1_t arr, uintptr_t * index) \
        { return (bool)Judy1##x##Empty(arr.v, index, PJE0); }

SJUDY_ITER(First)
SJUDY_ITER(Next)
SJUDY_ITER(Last)
SJUDY_ITER(Prev)

#undef SJUDY_ITER

#define j1pSet(a,i) j1Set(a, (uintptr_t)(i))
#define j1pUnset(a,i) j1Unset(a, (uintptr_t)(i))
#define j1pTest(a,i) j1Test(a, (uintptr_t)(i))
#define j1pCount(a,i1,i2) j1Count(a, (uintptr_t)(i1), (uintptr_t)(i2))
#define j1pFirst(a,pi) j1First(a, (uintptr_t)(pi))
#define j1pNext(a,pi) j1Next(a, (uintptr_t)(pi))
#define j1pPrev(a,pi) j1Prev(a, (uintptr_t)(pi))
#define j1pLast(a,pi) j1Last(a, (uintptr_t)(pi))
#define j1pFirstEmpty(a,pi) j1FirstEmpty(a, (uintptr_t)(pi))
#define j1pNextEmpty(a,pi) j1NextEmpty(a, (uintptr_t)(pi))
#define j1pPrevEmpty(a,pi) j1PrevEmpty(a, (uintptr_t)(pi))
#define j1pLastEmpty(a,pi) j1LastEmpty(a, (uintptr_t)(pi))

/*
Copyright (c) John Meacham, 2014
http://notanumber.net

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#endif
#ifndef SJUDYT_T
#define SJUDYT_T

#ifndef __GNUC__
#error strongly typed judy arrays require GCC extensions.
#endif

// Uses GCC extensions to create a strongly typed version of JudyL arrays.
//
// Declare one with the JUDYL_TYPED macro such as
//
// struct list_head {
//      struct list_entry *head;
// };
//
// JUDYL_TYPED(struct list_head, float) weight_map;
//
// which will declare a map from struct list_head's to a float. This avoids
// issues like silently casting the float to an integral type losing the
// mantissa or having to break abstraction to dig into the internal structure of
// the struct.
//
// The Following constraints on the types used must be followed
// sizeof(key type) == sizeof(uintptr_t)
// sizeof(value type) <= sizeof(uintptr_t)
// There are static assertions that will produce a compile time error if these
// rules are broken.
//
// The jltFoo routines as well as jFoo routines are then fully generic over
// such declared maps.
//
// Possible Platform Restriction: punning via 'union' behaves in the same way as
// accessing the value via an aliased pointer for the 'key' type.
// if this is not true for your chosen key, or your key type has a smaller size
// than a uintptr_t then use coercions. There is no such restriction on the value type.

#include "sjudy.h"

// Declare a typed version of a judyL array.

#define JUDYL_TYPED(kt,vt) \
union { judyl_t j;         \
        Pvoid_t v;         \
        kt kdummy[0];      \
        vt vdummy[0];      \
_Static_assert(sizeof(kt) == sizeof(uintptr_t), "key type size must be == sizeof(uintptr_t)"); \
_Static_assert(sizeof(vt) <= sizeof(uintptr_t), "value type size must be <= sizeof(uintptr_t)"); \
_Static_assert(__alignof__(kt) <= __alignof__(uintptr_t), "key type alignment must be <= alignof(uintptr_t)"); \
_Static_assert(__alignof__(vt) <= __alignof__(uintptr_t), "value type alignment must be <= alignof(uintptr_t)"); \
}

// Cast a value via punning.
#define PCAST(x,fty,tty) ((union { fty in; tty out;}){ .in = (x) }).out

#define _JLT_TYPE(v)  __typeof__ (&(v)->vdummy[0])
#define _JLT_KTYPE(v)  __typeof__ ((v)->kdummy[0])
#define _JLT_DTYPE(v)  __typeof__ (&(v).vdummy[0])
#define _JLT_DKTYPE(v)  __typeof__ ((v).kdummy[0])

//#define jltIns(a,i) (_JLT_TYPE(a))jlIns(&(a)->j,PCAST(i,_JLT_KTYPE(a),uintptr_t))
#define jltIns(a,i) (_JLT_TYPE(a))jlIns(&(a)->j,PCAST(i,_JLT_KTYPE(a),uintptr_t))
#define jltGet(a,i) (_JLT_TYPE(a))jlGet((a).j, PCAST(i,_JLT_KTYPE(a),uintptr_t))
#define jltDel(a,i) jlDel(&(a)->j, PCAST(i,_JLT_KTYPE(a),uintptr_t))
#define jltFirst(a,pi) ({_Static_assert(__builtin_types_compatible_p(_JLT_DKTYPE(a) *, __typeof__ (pi)), "invalid key type"); (_JLT_DTYPE(a))jlFirst((a).j, (uintptr_t *)(pi)); })
#define jltNext(a,pi) ({_Static_assert(__builtin_types_compatible_p(_JLT_DKTYPE(a) *, __typeof__ (pi)), "invalid key type"); (_JLT_DTYPE(a))jlNext((a).j, (uintptr_t *)(pi)); })
#define jltPrev(a,pi) ({_Static_assert(__builtin_types_compatible_p(_JLT_DKTYPE(a) *, __typeof__ (pi)), "invalid key type"); (_JLT_DTYPE(a))jlPrev((a).j, (uintptr_t *)(pi)); })
#define jltLast(a,pi) ({_Static_assert(__builtin_types_compatible_p(_JLT_DKTYPE(a) *, __typeof__ (pi)), "invalid key type"); (_JLT_DTYPE(a))jlLast((a).j, (uintptr_t *)(pi)); })

#define jltFirstEmpty(a,pi) ({_Static_assert(__builtin_types_compatible_p(_JLT_DKTYPE(a) *, __typeof__ (pi)), "invalid key type"); jlFirstEmpty((a).j, (uintptr_t *)(pi)); })
#define jltNextEmpty(a,pi) ({_Static_assert(__builtin_types_compatible_p(_JLT_DKTYPE(a) *, __typeof__ (pi)), "invalid key type"); jlNextEmpty((a).j, (uintptr_t *)(pi)); })
#define jltPrevEmpty(a,pi) ({_Static_assert(__builtin_types_compatible_p(_JLT_DKTYPE(a) *, __typeof__ (pi)), "invalid key type"); jlPrevEmpty((a).j, (uintptr_t *)(pi)); })
#define jltLastEmpty(a,pi) ({_Static_assert(__builtin_types_compatible_p(_JLT_DKTYPE(a) *, __typeof__ (pi)), "invalid key type"); jlLastEmpty((a).j, (uintptr_t *)(pi)); })

/*
Copyright (c) John Meacham, 2014
http://notanumber.net

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#endif
------------------------------------------------------------------------------
Android apps run on BlackBerry 10
Introducing the new BlackBerry 10.2.1 Runtime for Android apps.
Now with support for Jelly Bean, Bluetooth, Mapview and more.
Get your Android app in front of a whole new audience.  Start now.
http://pubads.g.doubleclick.net/gampad/clk?id=124407151&iu=/4140/ostg.clktrk
_______________________________________________
Judy-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/judy-devel

Reply via email to