[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
integerMatch type
I am trying to make better use of the schema in OpenLDAP here at Carnegie
Mellon to stop bad data from getting into our directory. I would like to
use the "integer" equality and syntax to force some attributes to be only
digits, preceeded by either a plus or a minus sign (or nothing).
I filled in and touched up the functions
integerMatch()
integerValidate()
integerNormalize()
integerIndexer()
integerFilter()
in schema_init.c. I was hoping some people could look at my work to see if
they see any glaring problems. Even if there is a different direction that
people think integer schema is supposed to take, I'd like to hear it. I
didn't see any RFC's that mention integer schema.
The functions are attached to this message, and will also available for a
while at the URL
http://nil.andrew.cmu.edu/integer.c
Thanks for your time.
Mark Adamson
Carnegie Mellon
/* Insert this into schema_init.c and remove these macros from the file:
#define integerMatch caseIgnoreIA5Match
#define integerIndexer caseIgnoreIA5Indexer
#define integerFilter caseIgnoreIA5Filter
*/
static int
integerMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
char *v, *av;
int vsign=0, avsign=0;
struct berval *asserted;
ber_len_t vlen, avlen;
/* Start off pessimistic */
*matchp = 1;
/* Skip past leading spaces/zeros, and get the sign of the *value number */
v = value->bv_val;
vlen = value->bv_len;
while( vlen ) {
if( ASCII_SPACE(*v) || ( *v == '0' )) {
/* empty -- skip spaces */
}
else if ( *v == '+' ) {
vsign = 1;
}
else if ( *v == '-' ) {
vsign = -1;
}
else if ( ASCII_DIGIT(*v) ) {
if ( vsign == 0 ) vsign = 1;
vsign *= 2;
break;
}
v++;
vlen--;
}
/* Skip past leading spaces/zeros, and get the sign of the *assertedValue
number */
asserted = (struct berval *) assertedValue;
av = asserted->bv_val;
avlen = asserted->bv_len;
while( avlen ) {
if( ASCII_SPACE(*av) || ( *av == '0' )) {
/* empty -- skip spaces */
}
else if ( *av == '+' ) {
avsign = 1;
}
else if ( *av == '-' ) {
avsign = -1;
}
else if ( ASCII_DIGIT(*av) ) {
if ( avsign == 0 ) avsign = 1;
avsign *= 2;
break;
}
av++;
avlen--;
}
/* The two ?sign vars are now one of :
-2 negative non-zero number
-1 -0 \
0 0 collapse these three to 0
+1 +0 /
+2 positive non-zero number
*/
if ( abs( vsign ) == 1 ) vsign = 0;
if ( abs( avsign ) == 1 ) avsign = 0;
if( vsign != avsign ) return LDAP_SUCCESS;
/* Check the significant digits */
while( vlen && avlen ) {
if( *v != *av ) break;
v++;
vlen--;
av++;
avlen--;
}
/* If all digits compared equal, the numbers are equal */
if(( vlen == 0 ) && ( avlen == 0 )) {
*matchp = 0;
}
return LDAP_SUCCESS;
}
static int
integerValidate(
Syntax *syntax,
struct berval *val )
{
ber_len_t i;
if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
if( val->bv_val[0] == '+' || val->bv_val[0] == '-' ) {
if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
} else if( !ASCII_DIGIT(val->bv_val[0]) ) {
return LDAP_INVALID_SYNTAX;
}
for(i=1; i < val->bv_len; i++) {
if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
}
return LDAP_SUCCESS;
}
static int
integerNormalize(
Syntax *syntax,
struct berval *val,
struct berval **normalized )
{
int negative, len;
struct berval *newval;
char *p;
p = val->bv_val;
len = val->bv_len;
/* Ignore leading spaces */
while ( *p == ' ' ) {
p++;
len--;
}
/* save sign */
negative = ( *p == '-' );
if(( *p == '-' ) || ( *p == '+' )) {
p++;
len--;
}
/* Ignore leading zeros */
while ( *p == '0' ) {
p++;
len--;
}
newval = (struct berval *) ch_malloc( sizeof(struct berval) );
/* If there are no non-zero digits left, the number is zero, otherwise
allocate space for the number and copy it into the buffer */
if( len == 0 ) {
newval->bv_val = ch_strdup("0");
newval->bv_len = 1;
}
else {
newval->bv_len = len+negative;
newval->bv_val = ch_malloc( newval->bv_len );
if( negative ) {
newval->bv_val[0] = '-';
}
memcpy( newval->bv_val + negative, p, len );
}
*normalized = newval;
return LDAP_SUCCESS;
}
/* Index generation function */
int integerIndexer(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
struct berval **values,
struct berval ***keysp )
{
int i;
struct berval **keys;
/* we should have at least one value at this point */
assert( values != NULL && values[0] != NULL );
for( i=0; values[i] != NULL; i++ ) {
/* empty -- just count them */
}
keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
for( i=0; values[i] != NULL; i++ ) {
integerNormalize( syntax, values[i], &keys[i] );
}
keys[i] = NULL;
*keysp = keys;
return LDAP_SUCCESS;
}
/* Index generation function */
int integerFilter(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
void * assertValue,
struct berval ***keysp )
{
struct berval **keys;
keys = ch_malloc( sizeof( struct berval * ) * 2 );
integerNormalize( syntax, assertValue, &keys[0] );
keys[1] = NULL;
*keysp = keys;
return LDAP_SUCCESS;
}