/**************************************************************************/
/*                                                                        */
/*   ________                                                             */
/*   ()_______)                                                           */
/*    \:::::::\        Make your mark on open source, let people know     */
/*     \:::::::\       what you can do, profit on reputation.             */
/*     @:::::::/                                                          */
/*      ~~~~~~~                                                           */
/* ---------------------------------------------------------------------- */
/*  Scott Auge sauge@amduus.com scott_auge@yahoo.com                      */
/*  Amduus Information Works, Inc.                                        */
/*  www.amduus.com                                                 */
/*                                                                        */
/*  Initial development                                                   */
/*                                                                        */
/* ---------------------------------------------------------------------- */
/*                                                                        */
/**************************************************************************/

/* $Id: XOR.i 3 2018-24-05 10:01:10Z scott $ */
/* $URL: file:///home/scott/svn_rc/repos/trunk/src/demo/XOR.i $ */



/**************************************************************************/
/* An Exclusive OR routine(s).  When one uses two + n arguments, it XORs  */
/* between all of them that fit in a character.                           */
/* Use must chain with XOR(d,XOR(c,XOR(a,b))) for that to work ie         */
/*  a xor b xor c xor d which is different than xor(a,b,c,d).             */
/* There are examples of use in the unit testing comments at the end of   */
/* the program.                                                           */
/**************************************************************************/



/**************************************************************************/
/* Given a logical using any mnemonic, get it to a value useable by these */
/* tools.                                                                 */
/**************************************************************************/

function LogicalToString returns character (input Truth as logical):

  return if Truth then "true" else "false".

end. /* function LogicalToString */



/**************************************************************************/
/* Use this to break apart name-value pairs of the form a=b as character. */
/**************************************************************************/

function NVP returns integer (input NVPair as character,
                              output TheName as character,
                              output TheValue as character):

  define variable NumberOfEntries as integer no-undo.

  assign
  NumberOfEntries = num-entries(NVPair, "=")
  TheName = ?
  TheValue = ?
  .

  if NumberOfEntries = 2 then
    assign
    TheName = entry(1, NVPair, "=")
    TheValue = entry(2, NVPair, "=")
    .


end. /* function NVP () */



/**************************************************************************/
/* Perform an exclusive or operation as defined in                        */
/*   en.wikipedia.org/.../Exclusive_or                           */
/**************************************************************************/

function XOR returns logical (input XORString as character):

  define variable NumberOfEntries as integer no-undo.
  define variable HasTrue as logical no-undo.
  define variable CurrentEntry as integer no-undo.
  define variable EntryValue as character no-undo.

  assign
  NumberOfEntries = num-entries(XORString)
  HasTrue = false
  .

  do CurrentEntry = 1 to NumberOfEntries:

    EntryValue = entry(CurrentEntry, XORString).

    if EntryValue = "true" and HasTrue then return false.

    if EntryValue = "true" then HasTrue = true.

  end. /* do CurrentEntry = 1 to NumberOfEntries */

  return HasTrue.

end.  /* function XOR () */



/**************************************************************************/
/* Call an XOR with name value pairs seperated by commas.                 */
/**************************************************************************/

function NVPXOR returns logical (input XORString as character):

  define variable NumberOfPairs as integer no-undo.
  define variable CurrentPair as integer no-undo.
  define variable TheName as character no-undo.
  define variable TheValue as character no-undo.
  define variable ExpressionValue as character no-undo.

  NumberOfPairs = num-entries(XORString).

  ExpressionValue = "".

  do CurrentPair = 1 to NumberOfPairs:

    NVP(entry(CurrentPair, XORString), output TheName, output TheValue).

    ExpressionValue = if ExpressionValue = "" then TheValue
                      else ExpressionValue + "," + TheValue.

  end. /* do CurrentPair = 1 to NumberOfPairs */

  return XOR(ExpressionValue).

end. /* function NVPXOR () */



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

Unit Testing

{XOR.i}

disp LogicalToString(true) LogicalToString(false) LogicalToString(?)
     LogicalToString(yes) LogicalToString(no) with frame a.

define variable a as character no-undo.
define variable b as character no-undo.

NVP("name=value", output a, output b).

disp a b with frame b.

disp XOR("true,false,false") XOR("true,false,true") XOR("false,false,false") with frame c.

disp NVPXOR ("t=true,s=false,j=false")
     NVPXOR ("t=true,s=false,j=true")
     NVPXOR ("t=false,s=false,j=false")
     with frame d.


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