The DATA-GEN opcode generates a structured document (JSON, CSV, or any format) from an RPG variable or data structure. It is the inverse of DATA-INTO: where DATA-INTO parses a document into a data structure, DATA-GEN serializes a data structure into a document string. Like DATA-INTO, DATA-GEN has no built-in generator - you name one with %GEN, and it receives events (start, scalar value, end, etc.) and emits output text via the QrnDg* callbacks.

data-gen source %data(receiver : options) %gen(generator : genOptions);

The generator interface

A generator is a procedure that takes one parameter - the generator-info data structure (QrnDgParm_T) - and is called once per event. The generator emits output text by calling the QrnDg* callback procedures. The compiler recognizes these callbacks by name and binds them to its runtime:

dcl-ds QrnDgParm_T qualified template;
  env            pointer;      // reserved (the callback environment)
  handle         pointer;      // pass as the first argument to every callback
  event          int(10);      // event code (3=Start, 5=StartStruct, 11=ScalarValue, etc.)
  name           char(100);    // name of the current element
  valueLenChars  int(10);      // length of the value in characters
  value          pointer;      // pointer to the scalar value text
end-ds;

dcl-pr QrnDgAddText;
  handle pointer value; text pointer value; len int(10) value;
end-pr;
dcl-pr QrnDgAddTextString;
  handle pointer value; text pointer value options(*string);
end-pr;
dcl-pr QrnDgAddTextNewLine;
  handle pointer value;
end-pr;
dcl-pr QrnDgReportError;
  handle pointer value; errorCode int(10) value;
end-pr;

Event codes

Constant Value Description
QrnDgEvent_03_Start 3 Generation begins
QrnDgEvent_04_End 4 Generation ends
QrnDgEvent_05_StartStruct 5 Start of a data structure
QrnDgEvent_06_EndStruct 6 End of a data structure
QrnDgEvent_11_ScalarValue 11 Scalar subfield value

For ScalarValue events, parm.name holds the subfield name and parm.value / parm.valueLenChars hold the value pointer and length.

Example

dcl-ds info qualified;
  company char(10) inz('Acme Inc');
  city    char(10) inz('Chicago');
end-ds;
dcl-s result varchar(200);

data-gen info %data(result) %gen(kvGen);
// result = 'company=Acme Inc  ;city=Chicago   ;'

dcl-proc kvGen;
  dcl-pi *n;
    parm likeds(QrnDgParm_T);
  end-pi;
  dcl-s nm char(100);
  if parm.event = QrnDgEvent_11_ScalarValue;
    nm = parm.name;
    QrnDgAddTextString(parm.handle : %trimr(nm));
    QrnDgAddTextString(parm.handle : '=');
    QrnDgAddText(parm.handle : parm.value : parm.valueLenChars);
    QrnDgAddTextString(parm.handle : ';');
  endif;
end-proc;

The generator is called once per event. For each scalar subfield, parm.event is set to 11 (ScalarValue), parm.name holds the subfield name (preserving the original case from the RPG source), and parm.value / parm.valueLenChars hold a pointer to the text value and its character length.

Supported: a bound-procedure generator serializing a flat qualified data structure (scalar subfields). Nested data structures, arrays, and doc=file output are not supported.