A Bevy Of BIFs: Updates
October 8, 2014 Jon Paris
In my last tip I returned to the “Bevy” series to tell you about the latest addition to the family: %ScanRpl. Shortly after completing that tip I realized that there have been a number of more recent BIFs such as %SubArr and some enhancements to existing BIFs like %Trimx that seem to have escaped people’s notice. In this tip I attempt to fill those omissions.
%Trim: Specify Characters to Trim
Let’s start with a BIF that hopefully you are all familiar with: %Trim. Before going any further I should point out that when I say %Trim, I am referring to the entire Trim family, i.e., %Trim, %TrimL, and %TrimR.
What you might have missed though is that since V5R3, %Trim has offered an op-tional second parameter that allows you to specify exactly which character(s) you want to trim off. This can be really useful when processing data from CSV files or Web ser-vices where you will sometimes find numeric values with leading asterisks and/or a cur-rency symbol. For example $250.95 or ***125. The sample code below shows how this new option would allow you to handle this situation. Running it will result in the field tar-get receiving the value 123.45 and having a length of six, at this point it is “clean” enough to be processed by %Dec() for subsequent use in numeric calculations.
dcl-s charAmt2 char(20) Inz('***$123.45'); dcl-s target varchar(20); target = %Trim(charAmt2: ' *$');
Note that in order to have blanks removed (trailing blanks in the example) I had to in-clude a space in the string of characters to be removed. This would not have been needed if the intent is simply to use the resulting value with %Dec() since this BIF will automatically ignore leading and trailing spaces.
%Addr: *Data Option
This is one that I’m sure a lot of people missed, judging from the number of examples I see posted in online forums that do not make use of it.
Introduced in V5R4, the *Data option of the %Addr BIF returns the address of the data portion of a varying-length field, automatically bypassing the two- or four-byte count header portion. I make a lot of use of this capability in programs that build a string iteratively. For example, records to be written to CSV files, HTML and XML, etc. These sorts of strings are much more efficiently built in varying-length fields than in fixed length, but until this option was introduced it was necessary to manually add two (or four) to the address before passing it to an API.
This is the kind of code you may encounter that can be simplified by this new option:
pParmData = %Addr(ParmData) + 2;
The new option allows you to code it this way:
pParmData = %Addr(ParmData: *Data);
Not only is this code simpler and more obvious to anyone who has to maintain the code in the future, but it is also much safer.
Why so? Suppose that ParmData was originally 50,000 bytes long, but we subsequently need to increase the size to 100,000 bytes. At this point we have to hope that the pro-grammer tasked with making this change is aware that a varying length field of 100,000 bytes requires a 4-byte header, not a 2-byte. As a result, simply changing the field length is not enough. They must also change the “+ 2” to “+ 4” or the address created will be incorrect. Had the original programmer used the *Data option then this could never have become a problem since the compiler would have automatically calculated the correct address.
Ever since I started coding in PHP, where arrays are a way of life, I realized that RPGers don’t use arrays as much as they should. But even among those who do make use of them, the V5R3 BIF %SubArr seems to have slipped by unnoticed. While RPG still lacks the ability to use dynamic arrays in the sense that languages like PHP do, %SubArr allows us to come a little closer.
For those unfamiliar with it, %SubArr allows you to specify that an operation, such as a SORTA, is to take place on only a portion of the array. So, for example, if we kept track of the number of active elements in a dynamically built array in the field count:
SORTA %SubArr( myArray : 1 : count );
As you can see, this allows us to sort only the active portion of the array. Not only is this faster, but it also avoids the need to have previously loaded all of the array elements with high (or low) values to “keep them out of the way” after the sort.
%SubArr() can also be used to assign one portion of an array to another. Similar in some ways to the way in which the old MOVEA operation could be used.
While on the subject of arrays, it may have slipped past you that in V7.1 we finally got the ability to perform lookup operations on Data Structure arrays. We have had the ar-rays themselves since V5R2, but to in order to search them we had to resort to APIs such as bsearch(). No longer. As of V7.1 we can perform lookups directly on DS arrays, like so:
dcl-s element int(5); dcl-s product char(7); dcl-ds productInfo Dim(999) Qualified; productCode Like(product); description Varchar(60); price Packed(7:2); cost Packed(7:2); end-ds; element = %LookUp( product: productInfo(*).productCode );
That’s a whole lot easier.
The End: For Now
That brings us pretty much up to date in the world of RPG BIFs. I will return to this series in the future as and when IBM makes changes in the future.
Jon Paris is one of the world’s most knowledgeable experts on programming on the System i platform. Paris cut his teeth on the System/38 way back when, and in 1987 he joined IBM’s Toronto software lab to work on the COBOL compilers for the System/38 and System/36. He also worked on the creation of the COBOL/400 compilers for the original AS/400s back in 1988, and was one of the key developers behind RPG IV and the CODE/400 development tool. In 1998, he left IBM to start his own education and training firm, a job he does to this day with his wife, Susan Gantner–also an expert in System i programming. Paris and Gantner, along with Paul Tuohy and Skip Marchesani, are co-founders of System i Developer, which hosts the new RPG & DB2 Summit conference. Send your questions or comments for Jon to Ted Holt via the IT Jungle Contact page.