long long int into octets (and back again) 
Author Message
 long long int into octets (and back again)

I'm working on some ASN.1 encoding/decoding for ASN Integers. This is
some scratch pad code to handle converting to the minimum number of
octets and back again. I'd be graiteful for any comments.
TIA,
Greg.

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>

int maxOctets(unsigned long long int rem)
{
        int bits = 0;

        while((rem /= 2) > 0)
                ++bits;

        return (bits + (8 - (bits % 8)))/8;

Quote:
}

unsigned char *getOctets(long long int num)
{
        int i = 0;
        void *pnum;
        unsigned char *octets;
        pnum = &num;

        octets = malloc( maxOctets(abs(num)));
        if(octets == NULL)
        {
                printf("malloc failed\n");
                exit(EXIT_FAILURE);
        }

        for(;i < maxOctets(abs(num)); ++i)
        {
                memcpy(&octets[i], pnum, 1);
                pnum++;        
        }
        return octets;

Quote:
}

long long int getNumber(unsigned char *octets, int len)
{
        long long int num = 0;
        void *pnum = &num;
        int i = 0;

        for(;i < len; ++i)
        {
                memcpy(pnum, octets, 1);
                ++pnum;
        }

        if(((octets[len - 1] >> ((len * 8) - 1)) % 2) != 0)
        {
                num += (ULONG_LONG_MAX << (len * 8));
        }

        return num;

Quote:
}

int main(void)
{
        long long int num = -7;

        unsigned char *octets = getOctets(num);

        assert(num == getNumber(octets, maxOctets(abs(num))));

        free(octets);

        return EXIT_SUCCESS;

Quote:
}



Fri, 11 Feb 2005 08:21:19 GMT  
 long long int into octets (and back again)

Quote:

>I'm working on some ASN.1 encoding/decoding for ASN Integers. This is
>some scratch pad code to handle converting to the minimum number of
>octets and back again. I'd be graiteful for any comments.
>TIA,
>Greg.

>#include <stdio.h>
>#include <stdlib.h>
>#include <limits.h>
>#include <assert.h>

>int maxOctets(unsigned long long int rem)
>{
>    int bits = 0;

>    while((rem /= 2) > 0)
>            ++bits;

>    return (bits + (8 - (bits % 8)))/8;
>}

>unsigned char *getOctets(long long int num)
>{
>    int i = 0;
>    void *pnum;
>    unsigned char *octets;
>    pnum = &num;

>    octets = malloc( maxOctets(abs(num)));

You call maxOctets numerous times to evaluate the same number.
Recommend you save the return value once in an int (let's call it mO)
and use that as often as you need it.

Quote:
>    if(octets == NULL)
>    {
>            printf("malloc failed\n");
>            exit(EXIT_FAILURE);
>    }

>    for(;i < maxOctets(abs(num)); ++i)
>    {
>            memcpy(&octets[i], pnum, 1);
>            pnum++;        
>    }

You will always copy mO bytes.  The first byte is copied from &num to
octets.  The remaining bytes follow in sequence.  Therefore, you could
replace this loop with the much simpler
        memcpy(octets, &num, mO);

Quote:
>    return octets;
>}

>long long int getNumber(unsigned char *octets, int len)
>{
>    long long int num = 0;
>    void *pnum = &num;
>    int i = 0;

>    for(;i < len; ++i)
>    {
>            memcpy(pnum, octets, 1);
>            ++pnum;
>    }

You never increment octets so you copy the same byte len times to
succeeding bytes in num.  Replace this loop with
        memcpy(&num, octets, len);

Quote:

>    if(((octets[len - 1] >> ((len * 8) - 1)) % 2) != 0)

This doesn't do what you think.  len*8-1 will be bigger than 8
whenever len is 2 or more.  shifting any unsigned char 8 or more will
result in 0.  0 % 2 is always 0 so the if is always false.

Quote:
>    {
>            num += (ULONG_LONG_MAX << (len * 8));

The draft standard calls this ULLONG_MAX.

I haven't been able to figure out what you intend to accomplish here
but if len is equal to sizeof(unsigned long long int), then the right
hand expression evaluates to 0.

Furthermore, num is signed.  Adding a value to it greater than
LLONG_MAX (which the right hand expression is when len is less than
sizeof(unsigned long long int)) could cause overflow.

- Show quoted text -

Quote:
>    }

>    return num;
>}

>int main(void)
>{
>    long long int num = -7;

>    unsigned char *octets = getOctets(num);

>    assert(num == getNumber(octets, maxOctets(abs(num))));

>    free(octets);

>    return EXIT_SUCCESS;
>}

<<Remove the del for email>>


Fri, 11 Feb 2005 09:56:26 GMT  
 long long int into octets (and back again)

Quote:


>>I'm working on some ASN.1 encoding/decoding for ASN Integers. This is
>>some scratch pad code to handle converting to the minimum number of
>>octets and back again. I'd be graiteful for any comments.

>I haven't been able to figure out what you intend to accomplish here
>but if len is equal to sizeof(unsigned long long int), then the right
>hand expression evaluates to 0.

>Furthermore, num is signed.  Adding a value to it greater than
>LLONG_MAX (which the right hand expression is when len is less than
>sizeof(unsigned long long int)) could cause overflow.

Thanks for your comments Barry. I cancelled the original post when I
realised I had overlooked somethings. I'll repost (with appropriate
comments) once I've finished running some tests. I'm currently running
all numbers between LONG_LONG_MIN and LONG_LONG_MAX - I expect it will
take a while.


Fri, 11 Feb 2005 10:15:42 GMT  
 long long int into octets (and back again)

Quote:

> >       for(;i < len; ++i)
> >       {
> >               memcpy(pnum, octets, 1);
> >               ++pnum;
> >       }

> You never increment octets so you copy the same byte len times to
> succeeding bytes in num.  Replace this loop with
>         memcpy(&num, octets, len);

I suppose you mean memset ?

Laurent.



Sat, 12 Feb 2005 03:14:08 GMT  
 long long int into octets (and back again)
On Mon, 26 Aug 2002 21:14:08 +0200, Laurent Vogel

Quote:


>> >       for(;i < len; ++i)
>> >       {
>> >               memcpy(pnum, octets, 1);
>> >               ++pnum;
>> >       }

>> You never increment octets so you copy the same byte len times to
>> succeeding bytes in num.  Replace this loop with
>>         memcpy(&num, octets, len);

>I suppose you mean memset ?

On the assumption that the OP really intended to copy the data at
octets, I meant memcpy.

If the OP really intended to set every byte of pnum to the first byte
of octets, then the correct code would be
        memset(&num, *octets, len);

<<Remove the del for email>>



Sat, 12 Feb 2005 08:40:01 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. char size (was long long long long long int)

2. typecasting int to long long int

3. long long long long integers

4. long long again...

5. Long int to byte and back

6. long long int

7. long long int

8. unsigned long long int

9. long long int

10. Assigning and printing long long int's

11. long int versus long

12. long long int

 

 
Powered by phpBB® Forum Software