Problem on using a casted void pointer

Discussion in 'C Programming' started by kkirtac, Sep 23, 2007.

  1. kkirtac

    kkirtac Guest

    Hi, i have a void pointer and i cast it to an appropriate known type
    before using. The types which i cast this void* to are, from the
    Intel's open source computer vision library. Here is my piece of non-
    working code:

    CvMat *rowVect = cvCreateMat(1,nfeatures,CV_MAKETYPE(images[0]-
    >depth,1));

    //rowVect is a pointer to CvMat type

    cvReshape( images[0], rowVect, 0, 1 ); //vectorize the image; readrow
    is a 1xN matrix(vector)

    void* ptr;

    switch (images[0]->depth)
    {
    case IPL_DEPTH_8U :
    ptr = (unsigned char *) rowVect->data.ptr ; //ptr is defined as an
    unsigned char pointer
    break; //
    data is 'union' type

    case IPL_DEPTH_8S :
    ptr = (signed char *) rowVect->data.ptr ;
    break;

    case IPL_DEPTH_16S :
    ptr = (unsigned short *) rowVect->data.ptr ;
    break;

    case IPL_DEPTH_32S :
    ptr = (int *) rowVect->data.i ; // i is defined as an int pointer
    break;

    case IPL_DEPTH _32F :
    ptr = (float *) rowVect->data.fl ; // fl is defined as float
    pointer
    break;

    case IPL_DEPTH_64F :
    ptr = (double *) rowVect->data.db ; // db is a double
    break;

    }

    int i=0, k;
    while(i<nsamples)
    {
    cvReshape( images, readrow, 0, 1 );
    for(k=0; k<nfeatures; k++)
    Data->data.db[i*(Data->width)+k] = (double) ptr[k]; // errors occur
    here
    //fill the Data matrix
    i++;
    }

    Error : 1) 'void*' : unknown size
    2) 'typecast' : cannot convert from void to double

    i m sorry if it is illegal to point a 3rd party library here, but it
    has also been written in standard C. But my problem is a pure "C
    language" problem i think. I cast a void pointer but then i cant use
    it...

    Regards
     
    kkirtac, Sep 23, 2007
    #1
    1. Advertising

  2. kkirtac

    Guest

    On Sep 23, 7:14 pm, kkirtac <> wrote:
    > Hi, i have a void pointer and i cast it to an appropriate known type
    > before using. The types which i cast this void* to are, from the
    > Intel's open source computer vision library. Here is my piece of non-
    > working code:
    >
    > CvMat *rowVect = cvCreateMat(1,nfeatures,CV_MAKETYPE(images[0]->depth,1));
    >
    > //rowVect is a pointer to CvMat type
    >
    > cvReshape( images[0], rowVect, 0, 1 ); //vectorize the image; readrow
    > is a 1xN matrix(vector)
    >
    > void* ptr;
    >
    > switch (images[0]->depth)
    > {
    > case IPL_DEPTH_8U :
    > ptr = (unsigned char *) rowVect->data.ptr ; //ptr is defined as an
    > unsigned char pointer
    > break; //
    > data is 'union' type
    >
    > case IPL_DEPTH_8S :
    > ptr = (signed char *) rowVect->data.ptr ;
    > break;
    >
    > case IPL_DEPTH_16S :
    > ptr = (unsigned short *) rowVect->data.ptr ;
    > break;
    >
    > case IPL_DEPTH_32S :
    > ptr = (int *) rowVect->data.i ; // i is defined as an int pointer
    > break;
    >
    > case IPL_DEPTH _32F :
    > ptr = (float *) rowVect->data.fl ; // fl is defined as float
    > pointer
    > break;
    >
    > case IPL_DEPTH_64F :
    > ptr = (double *) rowVect->data.db ; // db is a double
    > break;
    >
    > }
    >
    > int i=0, k;
    > while(i<nsamples)
    > {
    > cvReshape( images, readrow, 0, 1 );
    > for(k=0; k<nfeatures; k++)
    > Data->data.db[i*(Data->width)+k] = (double) ptr[k]; // errors occur
    > here
    > //fill the Data matrix
    > i++;
    > }
    >
    > Error : 1) 'void*' : unknown size
    > 2) 'typecast' : cannot convert from void to double
    >
    > i m sorry if it is illegal to point a 3rd party library here, but it
    > has also been written in standard C. But my problem is a pure "C
    > language" problem i think. I cast a void pointer but then i cant use
    > it...
    >
    > Regards




    Try rewriting (double) ptr[k] as ((double *)ptr)[k]

    Regards,
    B.
     
    , Sep 23, 2007
    #2
    1. Advertising

  3. kkirtac

    kkirtac Guest

    On Sep 23, 12:50 pm, wrote:
    > On Sep 23, 7:14 pm, kkirtac <> wrote:
    >
    >
    >
    > > Hi, i have a void pointer and i cast it to an appropriate known type
    > > before using. The types which i cast this void* to are, from the
    > > Intel's open source computer vision library. Here is my piece of non-
    > > working code:

    >
    > > CvMat *rowVect = cvCreateMat(1,nfeatures,CV_MAKETYPE(images[0]->depth,1));

    >
    > > //rowVect is a pointer to CvMat type

    >
    > > cvReshape( images[0], rowVect, 0, 1 ); //vectorize the image; readrow
    > > is a 1xN matrix(vector)

    >
    > > void* ptr;

    >
    > > switch (images[0]->depth)
    > > {
    > > case IPL_DEPTH_8U :
    > > ptr = (unsigned char *) rowVect->data.ptr ; //ptr is defined as an
    > > unsigned char pointer
    > > break; //
    > > data is 'union' type

    >
    > > case IPL_DEPTH_8S :
    > > ptr = (signed char *) rowVect->data.ptr ;
    > > break;

    >
    > > case IPL_DEPTH_16S :
    > > ptr = (unsigned short *) rowVect->data.ptr ;
    > > break;

    >
    > > case IPL_DEPTH_32S :
    > > ptr = (int *) rowVect->data.i ; // i is defined as an int pointer
    > > break;

    >
    > > case IPL_DEPTH _32F :
    > > ptr = (float *) rowVect->data.fl ; // fl is defined as float
    > > pointer
    > > break;

    >
    > > case IPL_DEPTH_64F :
    > > ptr = (double *) rowVect->data.db ; // db is a double
    > > break;

    >
    > > }

    >
    > > int i=0, k;
    > > while(i<nsamples)
    > > {
    > > cvReshape( images, readrow, 0, 1 );
    > > for(k=0; k<nfeatures; k++)
    > > Data->data.db[i*(Data->width)+k] = (double) ptr[k]; // errors occur
    > > here
    > > //fill the Data matrix
    > > i++;
    > > }

    >
    > > Error : 1) 'void*' : unknown size
    > > 2) 'typecast' : cannot convert from void to double

    >
    > > i m sorry if it is illegal to point a 3rd party library here, but it
    > > has also been written in standard C. But my problem is a pure "C
    > > language" problem i think. I cast a void pointer but then i cant use
    > > it...

    >
    > > Regards

    >
    > Try rewriting (double) ptr[k] as ((double *)ptr)[k]
    >
    > Regards,
    > B.


    Hmm thank you but the problem here is, if we set a double* in front of
    ptr, then it reads amount of bytes that corresponds to type 'double'.
    What i want to do here is to decide the amount of bytes(the type that
    will come in front of 'ptr') in the upper 'switch-case' statement
    once, and read that amount of bytes in each iteration, cast it to
    double type. For instance, if the switch-case decides that ptr will be
    an unsigned char* , then instead of the double* in the while loop, i
    want unsigned char* be placed there, and then convert the result to
    double like this : (double)((unsigned char *)ptr)[k] . But problem is
    i want this to happen automatically..that i dont want to run the
    switch-case inside the while loop to decide for that..I m sorry if it
    got too complicated..
    Regards
     
    kkirtac, Sep 23, 2007
    #3
  4. kkirtac

    Ian Collins Guest

    kkirtac wrote:
    >
    > Hmm thank you but the problem here is, if we set a double* in front of
    > ptr, then it reads amount of bytes that corresponds to type 'double'.
    > What i want to do here is to decide the amount of bytes(the type that
    > will come in front of 'ptr') in the upper 'switch-case' statement
    > once, and read that amount of bytes in each iteration, cast it to
    > double type. For instance, if the switch-case decides that ptr will be
    > an unsigned char* , then instead of the double* in the while loop, i
    > want unsigned char* be placed there, and then convert the result to
    > double like this : (double)((unsigned char *)ptr)[k] .


    That doesn't make sense, if ptr is unsigned char*, ptr[k+1] will be one
    byte on from ptr[k], so it makes no sense and is potentially crash
    inducing to cast these arbitrary byte sequence to double.

    --
    Ian Collins.
     
    Ian Collins, Sep 23, 2007
    #4
  5. kkirtac

    kkirtac Guest

    On Sep 23, 1:33 pm, Ian Collins <> wrote:
    > kkirtac wrote:
    >
    > > Hmm thank you but the problem here is, if we set a double* in front of
    > > ptr, then it reads amount of bytes that corresponds to type 'double'.
    > > What i want to do here is to decide the amount of bytes(the type that
    > > will come in front of 'ptr') in the upper 'switch-case' statement
    > > once, and read that amount of bytes in each iteration, cast it to
    > > double type. For instance, if the switch-case decides that ptr will be
    > > an unsigned char* , then instead of the double* in the while loop, i
    > > want unsigned char* be placed there, and then convert the result to
    > > double like this : (double)((unsigned char *)ptr)[k] .

    >
    > That doesn't make sense, if ptr is unsigned char*, ptr[k+1] will be one
    > byte on from ptr[k], so it makes no sense and is potentially crash
    > inducing to cast these arbitrary byte sequence to double.
    >
    > --
    > Ian Collins.


    hmm it just turns 47 to 47.0000000 ..nothing more than that , but my
    prob. is not that..
     
    kkirtac, Sep 23, 2007
    #5
  6. kkirtac

    Ian Collins Guest

    kkirtac wrote:
    > On Sep 23, 1:33 pm, Ian Collins <> wrote:
    >> kkirtac wrote:
    >>
    >>> Hmm thank you but the problem here is, if we set a double* in front of
    >>> ptr, then it reads amount of bytes that corresponds to type 'double'.
    >>> What i want to do here is to decide the amount of bytes(the type that
    >>> will come in front of 'ptr') in the upper 'switch-case' statement
    >>> once, and read that amount of bytes in each iteration, cast it to
    >>> double type. For instance, if the switch-case decides that ptr will be
    >>> an unsigned char* , then instead of the double* in the while loop, i
    >>> want unsigned char* be placed there, and then convert the result to
    >>> double like this : (double)((unsigned char *)ptr)[k] .

    >> That doesn't make sense, if ptr is unsigned char*, ptr[k+1] will be one
    >> byte on from ptr[k], so it makes no sense and is potentially crash
    >> inducing to cast these arbitrary byte sequence to double.
    >>

    >
    > hmm it just turns 47 to 47.0000000 ..nothing more than that , but my
    > prob. is not that..
    >

    Ah, sorry, I misread your parenthesis (common problem with yucky code!).
    In that case, the cast is unnecessary.

    The casts in you original are also unnecessary.

    Your best bet is to put the switch in a function and call that from the
    loop.

    --
    Ian Collins.
     
    Ian Collins, Sep 23, 2007
    #6
  7. kkirtac

    pete Guest

    kkirtac wrote:

    > Error : 1) 'void*' : unknown size
    > 2) 'typecast' : cannot convert from void to double


    Does you compiler really use the word "typecast"?

    --
    pete
     
    pete, Sep 23, 2007
    #7
  8. kkirtac

    CBFalconer Guest

    kkirtac wrote:
    >
    > Hi, i have a void pointer and i cast it to an appropriate known
    > type before using. The types which i cast this void* to are, from
    > the Intel's open source computer vision library. Here is my piece
    > of non-working code:
    >

    .... snip ...
    >
    > void* ptr;
    >

    .... snip ...
    >
    > case IPL_DEPTH_8S: ptr = (signed char *) rowVect->data.ptr;
    > break;
    >

    .... snip ...
    >
    > Error : 1) 'void*' : unknown size
    > 2) 'typecast' : cannot convert from void to double


    Don't cast there. You are placing the result of the cast in a
    void*, which immediately casts it right back to a void*, which
    can't be dereferenced, etc.

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Sep 23, 2007
    #8
  9. CBFalconer <> writes:
    > kkirtac wrote:
    >> Hi, i have a void pointer and i cast it to an appropriate known
    >> type before using. The types which i cast this void* to are, from
    >> the Intel's open source computer vision library. Here is my piece
    >> of non-working code:
    >>

    > ... snip ...
    >>
    >> void* ptr;
    >>

    > ... snip ...
    >>
    >> case IPL_DEPTH_8S: ptr = (signed char *) rowVect->data.ptr;
    >> break;
    >>

    > ... snip ...
    >>
    >> Error : 1) 'void*' : unknown size
    >> 2) 'typecast' : cannot convert from void to double

    >
    > Don't cast there. You are placing the result of the cast in a
    > void*, which immediately casts it right back to a void*, which
    > can't be dereferenced, etc.


    No, it's immediately *converted* back to void*. A cast is an explicit
    operator; there's no such thing as an implicit cast.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Sep 23, 2007
    #9
  10. On Sun, 23 Sep 2007 , kkirtac <> wrote:

    >Hi, i have a void pointer and i cast it to an appropriate known type
    >before using.


    Unfortunately, that is not what you have. What you have is a void
    pointer to which you assign a cast-ed value, thereby losing any
    information the cast might have provided.

    >The types which i cast this void* to are, from the
    >Intel's open source computer vision library. Here is my piece of non-
    >working code:
    >
    > CvMat *rowVect = cvCreateMat(1,nfeatures,CV_MAKETYPE(images[0]->depth,1));
    >
    >
    > //rowVect is a pointer to CvMat type
    >
    > cvReshape( images[0], rowVect, 0, 1 ); //vectorize the image; readrow
    >is a 1xN matrix(vector)


    There is no readrow. The major, perhaps only, benefit of comments is
    help someone reading the code understand what is happening. Incorrect
    or misleading comments perform the opposite function.

    If anyone is tempted to try to compile your code, your use of // style
    comments makes it impractical. Line wrap is a fact of life in Usenet.
    Use /* */ style comments and eliminate syntax errors introduced by
    message readers.

    >
    >
    > void* ptr;
    >
    >
    > switch (images[0]->depth)
    > {
    > case IPL_DEPTH_8U :
    > ptr = (unsigned char *) rowVect->data.ptr ; //ptr is defined as an
    >unsigned char pointer


    Nothing you do on the right hand side will change the definition of
    ptr. It is still a pointer to void. Perhaps you meant data.ptr. If
    so, then the cast is particularly useless (as opposed to generally
    useless) since you do not change the type of the expression. See next
    comment.

    > break; // data is 'union' type
    >
    >
    > case IPL_DEPTH_8S :
    > ptr = (signed char *) rowVect->data.ptr ;


    There is an implicit conversion defined between object pointers and
    pointers to void. It is never necessary to cast one to the other on a
    simple assignment.

    > break;
    >
    >
    > case IPL_DEPTH_16S :
    > ptr = (unsigned short *) rowVect->data.ptr ;
    > break;
    >
    >
    > case IPL_DEPTH_32S :
    > ptr = (int *) rowVect->data.i ; // i is defined as an int pointer
    > break;
    >
    >
    > case IPL_DEPTH _32F :
    > ptr = (float *) rowVect->data.fl ; // fl is defined as float
    >pointer
    > break;
    >
    >
    > case IPL_DEPTH_64F :
    > ptr = (double *) rowVect->data.db ; // db is a double


    Now you introduce confusion. Every other assignment to ptr was from a
    pointer. Are you really trying to stuff the VALUE of a double into a
    void*. (I hope not. There is no guarantee it will fit. This is also
    no guarantee that such a conversion is defined). Perhaps you meant
    the comment to day "db is a double pointer" which would be consistent
    with your previous code and your for loop below.

    > break;
    >
    >
    > }


    At this point, ptr contains the address obtained from one of the
    pointers in the data union. While you were going through the switch,
    you actually determined what type of data you want to deal with.
    However, now all you have is a void* that points to something but you
    no longer know what that something is.

    >
    >
    > int i=0, k;
    > while(i<nsamples)
    > {
    > cvReshape( images, readrow, 0, 1 );
    > for(k=0; k<nfeatures; k++)
    > Data->data.db[i*(Data->width)+k] = (double) ptr[k]; // errors occur
    >here


    ptr is a pointer to void. If it were a valid expression, ptr[k] would
    be the k'th void ptr pointed to. However, void is a permanently
    incomplete type (it can never be completed). As such, an expression
    of type void is not an arithmetic value that can be converted to
    double.

    While you compiler will have no trouble distinguishing between Data
    and data, I don't think most people who would be tempted to help will
    appreciate the distinction.

    > //fill the Data matrix
    > i++;
    > }
    >
    >
    >Error : 1) 'void*' : unknown size
    > 2) 'typecast' : cannot convert from void to double
    >
    >
    >i m sorry if it is illegal to point a 3rd party library here, but it
    >has also been written in standard C. But my problem is a pure "C
    >language" problem i think. I cast a void pointer but then i cant use
    >it...


    The only place where you know the type of data that ptr points to is
    inside each switch case. That would be the logical place to process
    the data. Furthermore, it would make life so much simpler to use the
    "original" pointers (i, fl, etc) rather than try to use ptr for
    everything. For example

    case IPL_DEPTH_32S :
    {
    int i=0, k;
    while(i<nsamples)
    {
    cvReshape( images, readrow, 0, 1 );
    for(k=0; k<nfeatures; k++)
    Data->data.db[i*(Data->width)+k] = rowVect->data.i[k];
    /* Since I don't know anything about your structures, unions, or
    non-standard functions, I don't vouch for the validity of any of the
    expressions. I am only translating your code to work within the case.
    */
    i++;
    }
    }

    With the exception of the expression data.i, this same code would be
    used for all cases. That would make this a candidate for a macro.


    Remove del for email
     
    Barry Schwarz, Sep 24, 2007
    #10
  11. kkirtac

    kkirtac Guest

    On Sep 24, 3:19 am, Barry Schwarz <> wrote:
    > On Sun, 23 Sep 2007 , kkirtac <> wrote:
    > >Hi, i have a void pointer and i cast it to an appropriate known type
    > >before using.

    >
    > Unfortunately, that is not what you have. What you have is a void
    > pointer to which you assign a cast-ed value, thereby losing any
    > information the cast might have provided.
    >
    > >The types which i cast this void* to are, from the
    > >Intel's open source computer vision library. Here is my piece of non-
    > >working code:

    >
    > > CvMat *rowVect = cvCreateMat(1,nfeatures,CV_MAKETYPE(images[0]->depth,1));

    >
    > > //rowVect is a pointer to CvMat type

    >
    > > cvReshape( images[0], rowVect, 0, 1 ); //vectorize the image; readrow
    > >is a 1xN matrix(vector)

    >
    > There is no readrow. The major, perhaps only, benefit of comments is
    > help someone reading the code understand what is happening. Incorrect
    > or misleading comments perform the opposite function.
    >
    > If anyone is tempted to try to compile your code, your use of // style
    > comments makes it impractical. Line wrap is a fact of life in Usenet.
    > Use /* */ style comments and eliminate syntax errors introduced by
    > message readers.
    >
    >
    >
    > > void* ptr;

    >
    > > switch (images[0]->depth)
    > > {
    > > case IPL_DEPTH_8U :
    > > ptr = (unsigned char *) rowVect->data.ptr ; //ptr is defined as an
    > >unsigned char pointer

    >
    > Nothing you do on the right hand side will change the definition of
    > ptr. It is still a pointer to void. Perhaps you meant data.ptr. If
    > so, then the cast is particularly useless (as opposed to generally
    > useless) since you do not change the type of the expression. See next
    > comment.
    >
    > > break; // data is 'union' type

    >
    > > case IPL_DEPTH_8S :
    > > ptr = (signed char *) rowVect->data.ptr ;

    >
    > There is an implicit conversion defined between object pointers and
    > pointers to void. It is never necessary to cast one to the other on a
    > simple assignment.
    >
    >
    >
    > > break;

    >
    > > case IPL_DEPTH_16S :
    > > ptr = (unsigned short *) rowVect->data.ptr ;
    > > break;

    >
    > > case IPL_DEPTH_32S :
    > > ptr = (int *) rowVect->data.i ; // i is defined as an int pointer
    > > break;

    >
    > > case IPL_DEPTH _32F :
    > > ptr = (float *) rowVect->data.fl ; // fl is defined as float
    > >pointer
    > > break;

    >
    > > case IPL_DEPTH_64F :
    > > ptr = (double *) rowVect->data.db ; // db is a double

    >
    > Now you introduce confusion. Every other assignment to ptr was from a
    > pointer. Are you really trying to stuff the VALUE of a double into a
    > void*. (I hope not. There is no guarantee it will fit. This is also
    > no guarantee that such a conversion is defined). Perhaps you meant
    > the comment to day "db is a double pointer" which would be consistent
    > with your previous code and your for loop below.
    >
    > > break;

    >
    > > }

    >
    > At this point, ptr contains the address obtained from one of the
    > pointers in the data union. While you were going through the switch,
    > you actually determined what type of data you want to deal with.
    > However, now all you have is a void* that points to something but you
    > no longer know what that something is.
    >
    >
    >
    > > int i=0, k;
    > > while(i<nsamples)
    > > {
    > > cvReshape( images, readrow, 0, 1 );
    > > for(k=0; k<nfeatures; k++)
    > > Data->data.db[i*(Data->width)+k] = (double) ptr[k]; // errors occur
    > >here

    >
    > ptr is a pointer to void. If it were a valid expression, ptr[k] would
    > be the k'th void ptr pointed to. However, void is a permanently
    > incomplete type (it can never be completed). As such, an expression
    > of type void is not an arithmetic value that can be converted to
    > double.
    >
    > While you compiler will have no trouble distinguishing between Data
    > and data, I don't think most people who would be tempted to help will
    > appreciate the distinction.
    >
    > > //fill the Data matrix
    > > i++;
    > > }

    >
    > >Error : 1) 'void*' : unknown size
    > > 2) 'typecast' : cannot convert from void to double

    >
    > >i m sorry if it is illegal to point a 3rd party library here, but it
    > >has also been written in standard C. But my problem is a pure "C
    > >language" problem i think. I cast a void pointer but then i cant use
    > >it...

    >
    > The only place where you know the type of data that ptr points to is
    > inside each switch case. That would be the logical place to process
    > the data. Furthermore, it would make life so much simpler to use the
    > "original" pointers (i, fl, etc) rather than try to use ptr for
    > everything. For example
    >
    > case IPL_DEPTH_32S :
    > {
    > int i=0, k;
    > while(i<nsamples)
    > {
    > cvReshape( images, readrow, 0, 1 );
    > for(k=0; k<nfeatures; k++)
    > Data->data.db[i*(Data->width)+k] = rowVect->data.i[k];
    > /* Since I don't know anything about your structures, unions, or
    > non-standard functions, I don't vouch for the validity of any of the
    > expressions. I am only translating your code to work within the case.
    > */
    > i++;
    > }
    > }
    >
    > With the exception of the expression data.i, this same code would be
    > used for all cases. That would make this a candidate for a macro.
    >
    > Remove del for email


    Thank you, embedding the loop into "switch-case"s looks the best way..
    Regards
     
    kkirtac, Sep 24, 2007
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Timo Qvist
    Replies:
    2
    Views:
    2,942
    Jonathan Mcdougall
    Dec 1, 2004
  2. Pat
    Replies:
    1
    Views:
    269
    Victor Bazarov
    Feb 22, 2007
  3. praveen

    problem with a casted pointer

    praveen, Jun 29, 2007, in forum: C Programming
    Replies:
    15
    Views:
    485
    David Thompson
    Jul 22, 2007
  4. Ravi
    Replies:
    11
    Views:
    1,392
  5. Raj Pashwar

    problem with a casted pointer

    Raj Pashwar, Oct 8, 2011, in forum: C Programming
    Replies:
    4
    Views:
    339
    Morris Keesan
    Oct 10, 2011
Loading...

Share This Page