Articles - arrays

A Simple Array Program

 

It's a Small Thing

I've seen this question come up a couple of times out in the Wild Lands (tm): "Does OneWorld have array?"  Well, technically it does, but you have to write a C function to use them.  I'm afraid that I don't have any nice tricky method of creating them within Even Rules.  This will have to be another C Business Function article. 

So, I hope this proves useful to someone.  My implementation here is a bit specific to an earlier need I had at a client, but it's a good template for something more complex.

The Road Map

Arrays are very simple, really.  I won't bother writing down 'what' an array is.  If you're here and you can read this code I'm betting you already know. 

That being the case I'm going to show you how to create an array of structures.  You'll be able to write and read from it within OneWorld. 

All we need is a structure, an array of that structure, and the arrays position in memory.  We've seen before how we can use StoreDataPtr, RetrieveDataPtr, and RemoveDataPtr to save and pass memory locations as integers between ER and C code.  Right, we'll be doing it again.

The program you're about to see does one thing, it adds up the instances of Sales Order Lines.  I pass the Sales Order Detail key into the function, it searches through the array and if it doesn't find a match it adds a new entry.  If it does find a match it just exits.

I can then retrieve the count of order numbers and then free the memory pointer.  It's specific code, sure, but it should be fairly simple to extrapolate your own solution.  You could pass the subscript back and forth, for instance.

 

The Tutorial:

First is the structure definition.  Here, I want an array of the structure at the right.  I'm going to rely on the array  subscript to be my counter.  Remember, I just want to know how many unique Sales Order Lines I'm dealing with. 

/*****************************************************************************

* Structure Definitions

****************************************************************************/

typedef struct tagDSArray

{

MATH_NUMERIC mnOrderNumber;

char szOrderType[3];

char szKeyCompany[6];

MATH_NUMERIC mnLineNumber;

} DSArray, *LPDSArray;

 

 

Now, I create my interface within OneWorld.  I need to pass a mode; Add, Count, or Free.  I also pass the values I'm saving in the structure array, OneWorlds memory cross reference (look at idArrayPointer).  Lastly, I need the results of what I'm putting into the array.  This last one is really just the array subscript.

The Code:

 
JDEBFRTN (ID) JDEBFWINAPI OrderArray (LPBHVRCOM lpBhvrCom, LPVOID lpVoid, LPDSD5500010B lpDS) 
{
/************************************************************************
* Variable declarations
************************************************************************/
ID idJDBReturn = JDEDB_PASSED;
HUSER hUser = (HUSER)NULL;
int iCounter = 0;
BOOL bContinue = TRUE;
MATH_NUMERIC mnZero,mnNull;
/************************************************************************
* Declare structures
************************************************************************/
/************************************************************************
* Declare pointers
************************************************************************/
LPDSArray pArrayPointer;
/************************************************************************
* Check for NULL pointers
************************************************************************/
if ((lpBhvrCom == (LPBHVRCOM) NULL) ||
(lpVoid == (LPVOID) NULL) ||
(lpDS == (LPDSD5500010B) NULL))
{
	jdeErrorSet (lpBhvrCom, lpVoid, (ID) 0, "4363", (LPVOID) NULL);
	return ER_ERROR;
}
idJDBReturn = JDB_InitBhvr((void *)lpBhvrCom, &hUser, (char *) NULL, JDEDB_COMMIT_AUTO);
 
if(idJDBReturn == JDEDB_FAILED)
{
	jdeErrorSet (lpBhvrCom, lpVoid, (ID)0, "078S", (LPVOID)NULL);
	return ER_ERROR;
}
/************************************************************************
* Set pointers
************************************************************************/
/************************************************************************
* Main Processing
************************************************************************/
ZeroMathNumeric(&mnZero); 
memset(&mnNull,'\0',sizeof(mnNull));
switch(lpDS->cMode)
{
	case '1': /* AddCreate Array */
	if(lpDS->idArrayPointer==0)
	{	/* Assume the array doesn't exist if zero is passed in
 		   Save the array's memory location */
		pArrayPointer = (LPDSArray)jdeAlloc(COMMON_POOL, 
			MAXARRAYCOUNT * sizeof(struct tagDSArray), MEM_ZEROINIT);
		lpDS->idArrayPointer = (ID) jdeStoreDataPtr(hUser, pArrayPointer);
	}
	else
	{	/* The pointer isn't zero, so retreive the memory location */
		pArrayPointer = (LPDSArray) jdeRetrieveDataPtr(hUser, lpDS->idArrayPointer);
	}
	/* Search for the next empty entry in the array and place the new data into it. */
	while(iCounter<=MAXARRAYCOUNT && bContinue==TRUE)
	{
		if(MathCompare(&pArrayPointer[iCounter].mnOrderNumber,&mnZero)==0 || 
			MathCompare(&pArrayPointer[iCounter].mnOrderNumber,&mnNull)==0)
		{
			MathCopy( &pArrayPointer[iCounter].mnOrderNumber, 
				&lpDS->mnOrderNumber );
			MathCopy( &pArrayPointer[iCounter].mnLineNumber, 
				&lpDS->mnLineNumber );
			jdeStrcpy(pArrayPointer[iCounter].szOrderType , 
				lpDS->szOrderType, sizeof( lpDS->szOrderType ) );
			jdeStrcpy(pArrayPointer[iCounter].szKeyCompany , lpDS->szKeyCompany, 
				sizeof( lpDS->szKeyCompany ) );
			
			bContinue=FALSE;
		}
		else /* Since we found the entry again, just leave */
		{
			if((MathCompare(&pArrayPointer[iCounter].mnOrderNumber, 
				&lpDS->mnOrderNumber)==0) &&
				(MathCompare(&pArrayPointer[iCounter].mnLineNumber, 
				&lpDS->mnLineNumber)==0) &&
				(strcmp((const char*)&pArrayPointer[iCounter].szOrderType , 
				lpDS->szOrderType)==0) &&
				(strcmp((const char*)&pArrayPointer[iCounter].szKeyCompany , 
				lpDS->szKeyCompany)==0))
 
				bContinue=FALSE;
		}
		iCounter++;
	}
	break;
 
	case '2': /* CountArray - count the number of entries in the array */
	if(lpDS->idArrayPointer!=0)
	{
		pArrayPointer = (LPDSArray) jdeRetrieveDataPtr(hUser, lpDS->idArrayPointer);
		while(iCounter<=MAXARRAYCOUNT && bContinue==TRUE)
		{
			if(MathCompare(&pArrayPointer[iCounter].mnOrderNumber,&mnZero))
			{
				iCounter++;
				IntToMathNumeric(iCounter,&lpDS->mnArrayCount);
		
			}
			else
			{
				bContinue=FALSE;
			}
 
 
 
		}
	}
	break;
 
	case '3': /* FreeArray - Release the array's pointer */
	pArrayPointer = (LPDSArray) jdeRemoveDataPtr(hUser, lpDS->idArrayPointer);
	lpDS->idArrayPointer=0;
	if(pArrayPointer != (LPDSArray) NULL)
	{
		JDB_FreeBhvr(pArrayPointer) ;
	}
	break;
}
/************************************************************************
* Function Clean Up
************************************************************************/
if(hUser != (HUSER) NULL)
{
	JDB_FreeBhvr(hUser) ;
}
return (ER_SUCCESS);
}

 

Conclusion

Well, it's light on discussion, but it's a great tutorial as far as teaching goes.  But I think it reveals a lot about how to go about making arrays.  It would be quite simple to take this program and create a very generic array structure with multiple numeric and string fields.  Then, you could use the results in almost any program.

 

example graphic