` Printed Icetips Article

Icetips Article



Par2: Pointer() and Position
1998-05-18 -- Sean Wilson
 
The POINTER() function is probably one of the least well understood file commands in 
the Clarion language, the presence of the POSITION() command with it's apparently 
identical functionality does little to clear the confusion. 
 The problems that arise with the use of the POINTER() function, tend to arise from 
differences in the implementation of this function between one file driver and another, 
and the assumptions that developers make based on past experience with other file 
drivers. 
 There are many implementation specific differences between file drivers. Whilst the 
drivers are designed to behave identically (where possible) for the documented use of 
a command, it is possible to write code that will work correctly with one driver but not 
with another. The POINTER() command is often misused, because the values that it 
returns exhibit highly implementation dependent characteristics. I will examine the 
characteristics of some of the drivers before drawing a conclusion. 

The Clarion File Driver 
-----------------------------------
Most Clarion developers are familiar with the Clarion File Driver which formed the basis 
for the specification of most of the file commands. The value returned by the Clarion 
File Driver for POINTER() is the number of the record in the sequence. This means that 
if POINTER(file) returns n, the next record in the file can be obtained by calling 
GET(file,n+1). Similarly, if POINTER(key) returns n, the next record in the sequence 
can be obtained by calling GET(key,n+1). 
 This behaviour is peculiar to the Clarion driver, however many developers believe that 
GET(f, POINTER(f)+1) will obtain the next record, and more particularly that GET(f, 1) 
will obtain the first record in the sequence. 

The TopSpeed File Driver 
----------------------------------------
The TopSpeed Driver returns pointers that reflect the temporal order in which records 
were added to a file. 
 The first record added to a TopSpeed file contains control information so GET(f,1) 
does not return a valid record for an applications file. 
 The pointer values are added in a contiguous sequence from 1..2^32, once a value 
has been allocated it will never be reallocated. One consequence of this is that pointers
are completely stable, a given pointer value will refer to the same record for the
lifetime 
of the table, if the record is removed the pointer will always be invalid. 
 Another consequence of this allocation mechanism affects superfiles where records 
added to different tables within a superfile take distinct values from the same sequence.

So, for example, if you add records alternately to tables A and B in the same superfile, 
table A may have pointer values 3,5,7,9,... and table B may have pointer values 
4,6,8,10. That is to say, POINTER() will return a given value for at most one table in 
a superfile. 
 It is not safe to assume that with the TopSpeed File Driver, GET(f,POINTER(f)+1) 
obtains the next record in a table. 

The xBase File Drivers 
-----------------------------------
The xBase File Drivers return pointer values that reflect the position of the record in 
the tables sequence. POINTER(file) and POINTER(key) return the same value for a 
given record. Because new records are appended to the end of the file, and deletions 
do not reorganise the data table, pointer values are stable until the table is compressed
using PACK(). What's more, GET(f,POINTER(f)+1) will return the next record in the 
file (if it exists), but may not return the subsequent record in a key sequence. 

The Paradox File Driver 
-------------------------------------
The Paradox File Driver returns pointer values that reflect the position of the record 
within the sequence. If the table has a primary key then the records within the table 
are maintained in primary key order. This means that the pointer values can be highly 
unstable. The first record in the sequence has pointer value 1, if a record with a lower 
primary key value is inserted that record will return a pointer value of 1. Calling 
GET(f,POINTER(f)+1) will obtain the next record in the table, and may be used to get 
the next record in the primary key sequence if a primary key exists. 

The DOS File Driver 
-------------------------------
The DOS File Driver returns pointer values that reflect the byte postion of the record 
within the file. For practical reasons, it is important to be able to arithmetically
change 
pointer values to access records in DOS files, so GET(f,n) will return the record starting

at the nth byte. 

POSITION() to the Rescue 
------------------------------------------
With such a variety of implementation specific semantics for one particular function, it
is
clear to see why there can be a great deal of confusion about the POINTER() function. 
The POINTER() function, clearly has it's uses, however for the purists a better 
alternative is the POSITION() function. 
 The POSITION() function offers much the same functionality as the POINTER() 
function but because of it's implementation offers less scope for misuse than the 
POINTER() function and is more portable between file drivers (all drivers support 
POSITION()/RESET() some drivers do not support POINTER()). 
 One important difference, is that the POSITION() function returns a STRING, the 
driver can therefore return a great deal more information which means that there is 
usually much more stability associated with POSITION() values. It is not possible to 
use SET() or GET() with the values returned by the POSTION() function, but identical
results can be obtained using variations with REGET(), SET(), NEXT() and PREVIOUS(). 
 One disadvantage, is that the size of the string returned by POSITION() is 
implementation dependent, and is often dependent on the sequence. However, the 
size of the string is usually documented and the Paradox File Driver even provides a 
property to determine at run-time the size of the string that needs to be allocated. 

Conclusions 
-------------------
The POINTER() function tends to cause problems as a result of confusion to do with 
the wide variety of implementation specific characteristics of the return value. The 
POSITION() function returns a much more opaque value that is less prone to misuse, 
is intended to be portable and is supported by all drivers. 
 If you choose to use POINTER() in an application remember the following: 
The return value may be the position in the sequence, the byte position in the file, the 
temporal position in the sequence or some other representation of the record location. 
The command GET(f,1) may not obtain the first record in the sequence (use SET(f);
NEXT(f) instead). 
 The pointer may not have arithmetic properties, i.e. GET(f,POINTER(f)+1) may not 
obtain the next record (use SET(...);NEXT(f) insead). 

 POSITON() is more portable.



Printed November 23, 2024, 3:39 am
This article has been viewed/printed 35201 times.