ILE RPG procedures Proper-, Pascal- and CamelCase()

These procedure converts a string to Proper-, Pascal- and CamelCase.

The routines will handle exception for certain words like ‘ApS’ (Danish company type), ‘A/S’ (Danish company type, ‘LTD’ (UK/US company type), ‘GmbH’ (German company type) and others. You can extend with type you need. Further, words starting with ‘Mc’ or ‘Mac’ will also be converted correctly.

The ProperCase() procedure translates the input string to a string where all words start with a upper case letter and the remaining of the word in lower case:

tHIs sEnTence will BE TraNSlated ==> This Sentence Will Be Translated

The CamelCase() procedure translates the input string to a string where the first word is in lower case and the remaining words starts with a upper case letter and the remaining of the word in lower case. All spaces are removed:

tHIs sEnTence will BE TraNSlated ==> thisSentenceWillBeTranslated 

The PascalCase() procedure translates the input string to a string where all words start with a upper case letter and the remaining of the word in lower case. All spaces are removed:

tHIs sEnTence will BE TraNSlated ==> ThisSentenceWillBeTranslated 

No matter the ‘case’ of the input string, it will be converted correctly. As the routines relies on my LCase() and UCase() functions for translating to lower and upper case, national characters are translated correctly – and fast 😉 You can read more about the LCase() and UCase() procedures here. The procedures are written in Totally Free RPG.

Download:

  • Source members as text files: CPPCase.zip
    The zip file contains the source members. Extract the source files and transfer them to your IBM i.

To convert a string to Proper case, call the ProperCase() procedure with the parameter:

convertedstring = ProperCase(originalstring);

Where the parameter is:

  • originalstring
    A string of max 1024 characters, that must be converted to Proper case.

The procedures returns a Proper case formatted string.

To convert a string to Camel case, call the CamelCase() procedure with the parameter:

convertedstring = CamelCase(originalstring);

Where the parameter is:

  • originalstring
    A string of max 1024 characters, that must be converted to Camel case.

The procedures returns a Camel case formatted string.

To convert a sting to Pascal case, call the PascalCase() procedure with the parameter:

convertedstring = PascalCase(originalstring);

Where the parameter is:

  • original string
    A string of mac 1024 characters, that must be converted to Pascal case.

The procedure retuens a Pascal case formatted string.

Listing 1, member CPPCASE_PR, type RPGLE:

**Free
// CPPase_Pr
// ---------
// Prototype for CamelCase(), PascalCase() and ProperCase() procedures.
//
// Jesper Wachs, Version 1, June 2019.
//
// The software is delivered 'as is'.
//
// Neither Jesper Wachs nor anyone else who has been involved in
// the creation, production or delivery of this software shall be
// liable for any direct, indirect, consequential or incidental
// damages (including damages for loss of business profits,
// business interruption, loss of business information, and the
// like) arising out of the use or inability to use such software
// even if Jesper Wachs has been advised of the possibility of
// such damages.
//
// Convert a sting to Camel case. The input string must have each
// word seperated by one or more spaces. The output is a Camel cased
// string:
// 'myOwnStringInCamelCase' = CamelCase('my own string in camel case')
//
Dcl-PR CamelCase VarChar(1024);
  iString VarChar(1024) Value;
End-PR;
//
// Convert a sting to Pascal case. The input string must have each
// word seperated by one or more spaces. The output is a Pascal cased
// string:
// 'MyOwnStringInPascalCase' = PascalCase('my own string in pascal case')
//
Dcl-PR PascalCase VarChar(1024);
  iString VarChar(1024) Value;
End-PR;
//
// Convert a sting to Proper case. The input string must have each
// word seperated by one or more spaces. The output is a Pascal cased
// string:
// 'My Own String, Proper' = ProperCase('my own string, proper')
//
Dcl-PR ProperCase VarChar(1024);
  iString VarChar(1024) Value;
End-PR;

Listing 2, member CPPCASE, type RPGLE:

**Free
Ctl-Opt BndDir('QC2LE') NoMain;
//
// CPPCase
// -------
// Procedures to convert a string to Camel, Pacal and Proper (Titel)
// case.
//
// The ProperCase() procedure, which is the core coversion engine,
// looks for special words such as:
// 'A/S' - Danish code for a Inc company.
// 'ApS' - Danish code for a LTD company.
// 'IVS' - Variant of 'ApS'.
// 'GmbH' - German code for a LTD company.
// The procedure will replace them with the correct presentation (see
// CTData). Further, words starting with 'Mc*' and 'Mac*' is
// converted correctly ('mcdogan' -> 'McDogan').
//
// Jesper Wachs, Version 1, June 2019.
//
// To successful compile this module, you must have downloaded and
// compiled this procedure from my website:
// - LUCase
//
// You will find it in the 'ILE RPG Stuff' section.
//
// The software is delivered 'as is'.
//
// Neither Jesper Wachs nor anyone else who has been involved in
// the creation, production or delivery of this software shall be
// liable for any direct, indirect, consequential or incidental
// damages (including damages for loss of business profits,
// business interruption, loss of business information, and the
// like) arising out of the use or inability to use such software
// even if Jesper Wachs has been advised of the possibility of
// such damages.
//
// Copymember for exported functions.
// ----------------------------------
/copy qrpglesrc,cppcase_pr
//
// Imported functions.
// -------------------
/copy qrpglesrc,lucase_pr
//
// Prototypes for local functions.
// -------------------------------
//
Dcl-PR FindNextSep Packed(5:0);
  iString VarChar(1024);
  iStrPos Packed(5:0) Value;
End-PR;

Dcl-PR IsSpcWord Ind;
  iWord Char(25) Value;
  oWord Char(25);
End-PR;
//
// Work fields.
// ------------
//
// These two arrays are used to hold the special words in the
// the correct case (see CTData) and in uppercase for ease of
// check of special words.
//
// Extend and add your own as needed.
//
Dcl-S SpcWM Char(25) Dim(9) CTData PerRcd(1);
Dcl-S SpcWU                 Char(25) Dim(9);
//
// Exported funtions.
// ------------------
//
// CamelCase
// ---------
// Convert the input string to Camel case.
//
Dcl-Proc CamelCase Export;
  Dcl-PI CamelCase VarChar(1024);
    iString VarChar(1024) Value;
  End-PI;

  // If string is empty, quit.

  If %Len(iString) = *Zeros;
    Return '';
  EndIf;

  // Let the PascalCase() procedure do the hard work.

  iString = PascalCase(iString);

  // Then just convert the first letter to lower case.

  %SubSt(iString: 1: 1) = LCase(%SubSt(iString: 1: 1));

  Return iString;
End-Proc CamelCase;
//
// PascalCase
// ----------
// Convert the input string to Pacal case.
//
Dcl-Proc PascalCase Export;
  Dcl-PI PascalCase VarChar(1024);
    iString VarChar(1024) Value;
  End-PI;

  Dcl-PR StrTok Pointer ExtProc('strtok_r');
    iString Pointer Options(*String) Value;
    iSeps Pointer Options(*String) Value;
    oLastP Pointer;
  End-PR;

  Dcl-S OString VarChar(1024);
  Dcl-S Word VarChar(1024);
  Dcl-S PLast Pointer;
  Dcl-S PWord Pointer;

  // If string is blank, quit.

  If %Len(iString) = *Zeros;
    Return '';
  EndIf;

  // Let the ProperCase() procedure convert the string.

  iString = ProperCase(iString);

  // Then loop though the string, retrieve one word at the time and then
  // concatenate the words without spaces.

  // Start by finding the first space in the string.

  PWord = StrTok(iString: ' ': PLast);

  // Keep looping until no more spaces.

  DoW PWord <> *Null;

    // Get the word.

    Word = %Str(PWord);

    // Concatenate without space.

    oString = oString + Word;

    // Search for next space in the string.

    PWord = StrTok(*Null: ' ': PLast);

  EndDo;

  Return oString;
End-Proc PascalCase;
//
// ProperCase
// ----------
// Converts a string to Proper Case.
//
// The routine handles special words like 'A/S', 'LLC', 'GmbH'. Also
// handles words starting with 'Mc*' and 'Mac*'.
//
Dcl-Proc ProperCase Export;
  Dcl-PI ProperCase VarChar(1024);
    iString VarChar(1024) Value;
  End-PI;

  Dcl-S FirstTime Ind Inz(*On) Static;
  Dcl-S Idx Packed(5:0);
  Dcl-S IdxStart Packed(5:0);
  Dcl-S IdxEnd Packed(5:0);
  Dcl-S LowString VarChar(1024);
  Dcl-S NbrPos Packed(5:0);
  Dcl-S OWord Char(25);
  Dcl-S WWord VarChar(50);
  Dcl-S WWordLen Packed(3:0);

  // First time processing: Setup the array to use for finding special words.

  If FirstTime = *On;

    // As all the special words are in the CTData, there must be
    // a upper case counter part for quick lookup of the word.

    For Idx = 1 to %Elem(SpcWM);
      SpcWU(idx) = UCase(SpcWM(Idx));
    EndFor;

    FirstTime = *Off;
  EndIf;

  // If string is blank, quit.

  If %Len(iString) = *Zeros;
    Return '';
  EndIf;

  // To optimize for speed, we start by translating to upper and
  // lower case versions of the string.

  iString = UCase(iString);
  LowString = LCase(iString);

  IdxStart = 1;
  IdxEnd = FindNextSep(iString: IdxStart);

  DoW IdxEnd > *Zeros;

    // Calculate the number of positions between start and end.

    NbrPos = IdxEnd - IdxStart;
    WWord = %SubSt(iString: IdxStart: NbrPos);
    WWordLen = %Len(WWord);

    // Have we isolated a reserved word?

    If IsSpcWord(WWord: OWord) = *On;

      // If so, we insert the correctly spelled word into the string.

      %SubSt(iString: IdxStart: NbrPos) = oWord;
    Else;

      // Handle 'Mc*' and 'Mac*'.

      Select;
      When WWordLen > 2 And %SubSt(WWord: 1: 2) = 'MC';
        %SubSt(iString: IdxStart: 2) = 'Mc';
        IdxStart = IdxStart + 2;
        NbrPos = NbrPos - 2;

      When WWordLen > 3 And %SubSt(WWord: 1: 3) = 'MAC';
        %SubSt(iString: IdxStart: 3) = 'Mac';
        IdxStart = IdxStart + 3;
        NbrPos = NbrPos - 3;
      EndSl;

      // If the word found is longer than one letter, then translate from
      // 2 and until, incl. the seperator.

      If NbrPos > 1;
        IdxStart = IdxStart + 1;
        NbrPos = NbrPos - 1;
        %SubSt(iString: IdxStart: NbrPos) =
               %subSt(LowString: IdxStart: NbrPos);
      EndIf;
    EndIf;

    // Calculate the new start position and look for the next separator.

    IdxStart = IdxEnd + 1;
    IdxEnd = FindNextSep(iString: IdxStart);

  EndDo;

  Return iString;
End-Proc ProperCase;
//
// Internal procedures.
// --------------------
//
// FindNextSep
// -----------
// Find the next seperator character.
//
Dcl-Proc FindNextSep;
  Dcl-PI FindNextSep Packed(5:0);
    iString VarChar(1024);
    iStrPos Packed(5:0) Value;
  End-PI;

  Dcl-S Idx Packed(5:0);
  Dcl-S MaxLen Packed(5:0);
  Dcl-S TargetPos Packed(5:0) Inz(*Zeros);
  Dcl-S wChar Char(1);

  // The constant SepChars holds the characters that identify the
  // seperation of two words in the string. Change it to fix your needs.

  Dcl-C SEPCHARS Const(' ?.,:;''');

  MaxLen = %Len(iString);

  // If starting position is beyond the length of the string, then
  // we signal that we are finished looked for seperators.

  If iStrPos <= MaxLen;

    For Idx = iStrPos to MaxLen;
      wChar = %SubSt(iString: Idx: 1);
      If %Scan(wChar: SepChars) > *Zeros;
        TargetPos = Idx;
        Leave;
      EndIf;
    EndFor;

    // If TargetPos is *Zeros it means that there is no separator char
    // from the starting position and until the end of the string. So
    // we return the end position.

    If TargetPos = *Zeros;
      TargetPos = MaxLen + 1;
    EndIf;
  EndIf;

  Return TargetPos;
End-Proc FindNextSep;
//
// IsSpcWord
// ---------
// Checks if the word in input is one of the special ones, like
// company types etc.
//
Dcl-Proc IsSpcWord;
  Dcl-PI IsSpcWord Ind;
    iWord Char(25) Value;
    oWord Char(25);
  End-PI;

  Dcl-S Idx Packed(3:0);
  Dcl-S Result Ind Inz(*Off);

  oWord = *Blanks;
  Idx = %LookUp(iWord: SpcWU);
  If Idx > *Zeros;

    // It is a special word. We take the correct spelling (see CTData)
    // and return that to the caller.

    oWord = SpcWM(Idx);
    Result = *On;
  EndIf;

  Return Result;
End-Proc IsSpcWord;
**
ApS
A/S
C/O
CO
IVS
AMBA
LLC
PLC
GmbH

Listing 3, member CPPCASE_EX, type RPGLE:

**Free
Ctl-Opt BndDir('QC2LE');
//
// CPPCase_Ex
// ----------
// Example program for the CamelCase(), PascalCase() and ProperCase()
// procedures.
//
// Jesper Wachs, Version 1, June 2019.
//
// The source member are delivered 'as is'.
//
// Neither Jesper Wachs nor anyone else who has been involved in
// the creation, production or delivery of this software shall be
// liable for any direct, indirect, consequential or incidental
// damages (including damages for loss of business profits,
// business interruption, loss of business information, and the
// like) arising out of the use or inability to use such software
// even if Jesper Wachs has been advised of the possibility of
// such damages.
//
// Copymember for imported functions.
// ----------------------------------
/copy qrpglesrc,CPPCase_Pr
//
// Imported functions.
// -------------------
Dcl-PR PutS Int(10:0) ExtProc('puts');
  oString Pointer Options(*String) Value;
End-PR;

Dcl-PR GetS Pointer ExtProc('gets');
  Buffer Char(1024);
End-PR;
//
// Prototypes for local functions.
// -------------------------------
//
Dcl-PR WriteConv;
  iString VarChar(1024) Value;
End-PR;
//
// Work fields.
// ------------
//
Dcl-S DummyInput Char(1024);
Dcl-S InputString VarChar(1024);
Dcl-S Message VarChar(78);
Dcl-S pDummyInput Pointer Inz(%Addr(DummyInput));
//
// Main line of program.
// ---------------------
//
Message = 'Demo of CamelCase(), PascalCase() and ProperCase() procedures.';
PutS(Message);
Message = '--------------------------------------------------------------';
PutS(Message);

Message = 'JAMES BOND, PETER O''CONNELL';
WriteConv(Message);

Message = 'SEAN MCDONALD, JEFF MACDONALD';
WriteConv(Message);

Message = 'this is a tEXT.it has companycode iNc or was it plc?';
WriteConv(Message);

Message = '';
PutS(Message);

Message = 'Type a sentence and press ENTER to convert it to Proper case.';
Puts(Message);
Message = 'Press ENTER on an empty line to end';
Puts(Message);

GetS(DummyInput);
InputString = %Str(pDummyInput);

DoW InputString <> *Blanks;

  PutS('');
  WriteConv(InputString);

  GetS(DummyInput);
  InputString = %Str(pDummyInput);

EndDo;

*InLR = *On;
Return;
//
// Procedure to write the string in vaious formats.
//
Dcl-Proc WriteConv;
  Dcl-PI WriteConv;
    iString VarChar(1024) Value;
  End-PI;

  PutS('Input string: ' + iString);
  PutS('ProperCase(): ' + ProperCase(iString));
  PutS('CamelCase().: ' + CamelCase(iString));
  PutS('PascalCase(): ' + PascalCase(iString));
  Return;
End-Proc WriteConv;

Listing 4, member CPPCASE_MK, type TXT:

;
; CPPCase_Mk
; ----------
; MAKE member for ProperCase(), CamelCase() and PascalCase() module.
;
; Jesper Wachs, June 2019.
;
;
; Variables defined once and used though out make member.
;
v &lib    jwtools
v &srclib jwtools
v &debug  *source
;
; Check and possibly build PCase module.
;
v &mod cppcase
o &srclib &mod *module
u &srclib qrpglesrc *file &mod
ci dltmod &srclib/&mod
c crtrpgmod &srclib/&mod srcfile(&srclib/qrpglesrc) dbgview(&debug)
;
; Check and possibly build CPPCase_Ex module.
;
v &mod cppcase_ex
o &srclib &mod *module
u &srclib qrpglesrc *file &mod
ci dltmod &srclib/&mod
c crtrpgmod &srclib/&mod srcfile(&srclib/qrpglesrc) dbgview(&debug)
;
; Build main program.
;
v &pgm cppcase_ex
o &lib &pgm *pgm
u &srclib cppcase    *module
u &srclib cppcase_ex *module
u &srclib lucase    *module
ci DltPgm &lib/&pgm
c CrtPgm &lib/&pgm module(&srclib/&pgm &srclib/cppcase +
  &srclib/lucase)