[GRASS-dev] Re: About the vector changes
Glynn Clements
glynn at gclements.plus.com
Mon Aug 10 17:30:25 EDT 2009
Markus Metz wrote:
> > [...] An integer literal without a
> > trailing suffix is an "int". Using a larger type to hold the value
> > where necessary is a gcc extension. Other compilers may simply
> > truncate the value to an int, even if off_t is 64 bits.
> >
> > The latest change:
> >
> > #define OFF_T_TEST 0x0102030405060708LL
> >
> > will fail to compile with a compiler which doesn't have long long int.
> > Both the definition and use of OFF_T_TEST need to be conditionalised
> > with "#ifdef HAVE_LONG_LONG_INT".
>
> OK. But on Linux 32 without LFS I get
>
> port_init.c:217: warning: overflow in implicit constant conversion
>
> at compile time because long long int is available but sizeof(off_t) =
> 4. Portability and its test is ok because OFF_T_TEST is not used in this
> case.
Making the conversion explicit would eliminate the warning:
u_o = (off_t) OFF_T_TEST;
> To avoid this warning I could use in port_init()
>
> #ifdef HAVE_LONG_LONG_INT
> #ifdef HAVE_LARGEFILES
> u_o = OFF_T_TEST;
> #else
> u_o = LONG_TEST;
> #endif
> #else
> u_o = LONG_TEST;
> #endif
I suggest:
1. Remove OFF_T_TEST.
2. Add:
#ifdef HAVE_LONG_LONG_INT
#define LONG_LONG_TEST 0x0102030405060708LL
#endif
3. Change the initialisation of u_o to e.g.:
if (nat_off_t == 8)
#ifdef HAVE_LONG_LONG_INT
u_o = (off_t) LONG_LONG_TEST;
#else
G_fatal_error("Internal error: can't construct an off_t literal");
#endif
else
u_o = (off_t) LONG_TEST;
Actually, that's not ideal. A 64-bit system might have a 64-bit off_t
but no "long long" type. We really need to have autoconf use define
SIZEOF_LONG etc in config.h (AC_CHECK_SIZEOF macro), so that we can
use e.g.:
#if SIZEOF_LONG == 8
#define LONG_LONG_TEST 0x0102030405060708L
#elif defined(HAVE_LONG_LONG_INT)
#define LONG_LONG_TEST 0x0102030405060708LL
#endif
> but I am not sure if HAVE_LARGEFILES is always set on 64bit systems also
> without --enable-largefile.
It won't be set if --enable-largefile isn't used.
> > I still see:
> >
> > 719: s[top].sn.branch[j].child.id =
> > 720: (int)s[top].childpos[j];
> >
> > 754: s[top].sn.branch[j].child.id =
> > 755: (int)s[top].childpos[j];
> >
> > Also:
> >
> > 1011: if (!shcb((int)s[top].sn.branch[i].child, cbarg)) {
> >
> > A narrowing cast always brings up the question of "what if the value
> > won't fit in the destination type"?
> >
> > Am I missing something, or is childpos[j] *always* an "int"?
>
> On level 0, it is always an int. It's the ID of the rectangle passed to
> int RTreeInsertRect(struct Rect *r, int tid, struct RTree *t)
> as tid. That applies to all three cases above.
>
> I am writing out the rectangle ID as off_t although it is int and have
> to read it as off_t then cast it to int again when loading the sidx file
> to memory for updating. Of course I could also write the ID as int and
> read it as int, then there would be no type casting, at the cost of one
> more if ... else ... .
>
> > If so,
> > why is it stored in the file as an off_t?
>
> On higher levels (RTree internal nodes), it is the position in file of
> the child nodes of a node. For large sidx files, off_t is needed. The
> corresponding line in spindex_rw.c is
>
> 668 s[top].pos[s[top].branch_id - 1] = nextfreepos;
>
> where I set the node positions in file as off_t.
>
> This is related to the use of union Child: on level 0, int id is used,
> on higher levels, struct Node *ptr is used.
So it's a case of simplifying the sidx file I/O?
That's reasonable enough. But, personally, I would:
1. Make the pos and childpos fields unions (int/off_t).
2. Add an explicit range check before casting the off_t read from the
file to an int. An assert() would suffice; the main purpose is to
answer the "what if it doesn't fit in an int?" question for the
benefit of anyone trying to read that code.
--
Glynn Clements <glynn at gclements.plus.com>
More information about the grass-dev
mailing list