json 42755 2763 0 0 11517625602 7344 5 ustar 00MSCHMIDT json/json_chk_h.rpgle 100666 2763 0 4157 11515400046 12660 0 ustar 00MSCHMIDT /if not defined (JSON_CHK)
/define JSON_CHK
/*
* Copyright (c) 2007-2009 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*/
*------------------------------------------------------------------------
* RPG Protypes for C Procedures
*------------------------------------------------------------------------
D json_new_checker...
D PR * extproc(*CWIDEN:'json_new_checker')
D depth 10I 0 value
D json_checker_done...
D PR 10I 0 extproc(*CWIDEN:'json_checker_done')
D checker * value
D json_checker_char...
D PR 10I 0 extproc(*CWIDEN:'json_checker_char')
D checker * value
D char 10U 0 value
*------------------------------------------------------------------------
* Data structures
*------------------------------------------------------------------------
D tmpl_json_checker...
D DS qualified align based(nullPointer)
D state 10I 0
D depth 10I 0
D top 10I 0
D stack 10I 0 dim(20)
/endif
json/json_par_h.rpgle 100666 2763 0 2455 11515400052 12671 0 ustar 00MSCHMIDT /if not defined (JSON_PAR)
/define JSON_PAR
/*
* Copyright (c) 2007-2009 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*/
*---------------------------------------------------------------
* Prototypes
*---------------------------------------------------------------
D json_parse PR * extproc('json_parse')
D json_string * const options(*omit)
D ptrHeader * const options(*nopass)
/endif
json/json_par.rpgle 100666 2763 0 57601 11515400052 12405 0 ustar 00MSCHMIDT /**
* \brief JSON Parser
*
* A utility module for parsing JSON strings.
*
*
*
* The parser string should be a valid JSON string or else and escape
* message will be sent to the caller.
*
*
*
* The parser also accepts the equal sign (=) as a separator for the key
* and the value. The parser also supports the ; instead of the , for
* separating pairs of values or values in an array. Strings may be
* enclosed in single or double quotes. Arrays can either be enclosed in
* curly braces () or in brackets []. Empty objects and arrays are supported.
* Unicode representation of a character is not supported like \u00CF.
*
* \author Mihael Schmidt
* \date 2009-03-07
*
* \link http://www.json.org JSON.org
*
* \info The JSON syntax is not fully supported at the moment.
*/
*-------------------------------------------------------------------------
* Copyright (c) 2007-2009 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*-------------------------------------------------------------------------
H nomain
H bnddir('QC2LE')
H copyright('Copyright (c) 2007-2009 Mihael Schmidt. All rights reserved.')
*---------------------------------------------------------------
* Constants
*---------------------------------------------------------------
D CR C const(x'0d')
D LF C const(x'25')
D NULL C const(x'00')
D TYPE_NO_VALUE C const(-1)
*
/copy 'json_c.rpgle'
/copy 'unicode_c.rpgle'
*---------------------------------------------------------------
* Prototypes
*---------------------------------------------------------------
D nextValue PR
D retValPtr * const
D header *
D dataType 10I 0
*
D nextCleanChar PR 1A
D header *
*
D nextString PR 10000A
D header *
D quote 1A const
*
D nextArray PR *
D header *
*
D next PR 1A
D header *
*
D back PR
D header *
*
D more PR N
D header *
*
D abortParsing PR
D header *
D message 1000A const
*
D strlen PR 10I 0 extproc('strlen')
D buffer1 * value
*
D strcasecmp PR 10I 0 extproc('strcasecmp')
D buffer1 * value
D buffer2 * value
*
D convertChar PR extproc('cvtch')
D target1byte * value
D source2byte * value options(*string)
D sourceBytes 10I 0 value
*
/copy 'json_h.rpgle'
*---------------------------------------------------------------
* Data structures
*---------------------------------------------------------------
D tmpl_parser_ds DS qualified based(nullPointer)
D json_string_ptr...
D *
D index_pos 10I 0
*
D tmpl_return_value_ds...
D DS qualified based(nullPointer)
D text 65535A
D boolean N overlay(text : 1)
D integer 10I 0 overlay(text : 1)
D long 20I 0 overlay(text : 1)
D double 8F overlay(text : 1)
D pointer * overlay(text : 1)
/**
* \brief Parse JSON string
*
* Creates a JSON object from the passed string. If the passed
* string is not a valid JSON string an escape message will be
* sent. The string must be null terminated.
*
* \param Pointer to JSON string
* \param Pointer to parser header (only for internal use)
*
* \return Pointer to JSON object
*/
P json_parse B export
D PI *
D string * const options(*omit)
D ptrHeader * const options(*nopass)
*
D json S *
D key S 10000A
*
D ptr S *
D header DS likeds(tmpl_parser_ds) based(ptr)
*
D retValDs DS likeds(tmpl_return_value_ds)
D dataType S 10I 0
D data S 1A
D keepLooping S N inz(*on)
/free
json = json_create();
if (%parms() = 2);
// nested json object
ptr = ptrHeader;
data = UNICODE_LEFT_CURLY_BRACE;
else;
// first json object (top-level)
ptr = %alloc(%size(tmpl_parser_ds));
// init header ds
header.json_string_ptr = string;
header.index_pos = -1;
data = nextCleanChar(ptr);
endif;
if (data = UNICODE_LEFT_CURLY_BRACE);
dow (keepLooping);
data = nextCleanChar(ptr);
if (data = NULL);
abortParsing(ptr : 'A JSON object text must end with ' +
%char(UNICODE_RIGHT_CURLY_BRACE));
elseif (data = UNICODE_RIGHT_CURLY_BRACE);
leave;
else;
// should be a key
back(ptr);
nextValue(%addr(retValDs) : ptr : dataType);
if (dataType <> JSON_TYPE_STRING);
abortParsing(ptr : 'Key is not of type string');
endif;
key = retValDs.text;
// The key is followed by ':'. We will also tolerate '='.
data = nextCleanChar(ptr);
if (data <> UNICODE_COLON and data <> UNICODE_EQUAL);
abortParsing(ptr : 'Expected a colon after a key');
endif;
// A value should be following
nextValue(%addr(retValDs) : ptr : dataType);
if (dataType = JSON_TYPE_STRING);
json_putString(json : %trimr(key) : %trimr(retValDs.text));
elseif (dataType = JSON_TYPE_BOOLEAN);
json_putBoolean(json : %trimr(key) : retValDs.boolean);
elseif (dataType = JSON_TYPE_NULL);
json_putNull(json : %trimr(key));
elseif (dataType = JSON_TYPE_INT);
json_putInt(json : %trimr(key) : retValDs.integer);
elseif (dataType = JSON_TYPE_LONG);
json_putLong(json : %trimr(key) : retValDs.long);
elseif (dataType = JSON_TYPE_DOUBLE);
json_putDouble(json : %trimr(key) : retValDs.double);
elseif (dataType = JSON_TYPE_OBJECT);
json_putObject(json : %trimr(key) : retValDs.pointer);
elseif (dataType = JSON_TYPE_ARRAY);
json_putArray(json : %trimr(key) : retValDs.pointer);
endif;
// Pairs are separated by ','. We will also tolerate ';'.
data = nextCleanChar(ptr);
if (data = UNICODE_COMMA);
// everything ok
elseif (data = UNICODE_SEMICOLON);
// everything ok
elseif (data = UNICODE_RIGHT_CURLY_BRACE); // end of object
leave;
abortParsing(ptr : 'Expected a comma or right curly brace ' +
'after value');
endif;
// next iteration => next key/value pair
endif;
enddo;
else;
abortParsing(ptr : 'String is no JSON object string');
endif;
// deallocate memory
if (%parms() = 1 and ptr <> *null);
dealloc ptr;
endif;
return json;
/end-free
P E
/**
* \brief Next value
*
* Returns the next value. The parser is moved after the next value.
* The returned value can be any supported JSON data type including array
* and object.
*
* \param Pointer to the return value data structure
* \param Pointer to the JSON string
* \param JSON data type of the return value
*/
P nextValue B
D PI
D retValPtr * const
D ptr *
D dataType 10I 0
*
D retValDs DS likeds(tmpl_return_value_ds)
D based(retValPtr)
D data S 1A
D backupData S 1A
D tmp S 65535A
D unquotedTextEnd...
D S 13A
*
D STRING_TRUE S 5A
D STRING_FALSE S 6A
D STRING_NULL S 5A
D numbers S 14A
/free
// ,:]}/\''"[{;=#
unquotedTextEnd =u'002C003A005D007D002F005C00270022005B007B003B003D0023';
// 0123456789.,+-
numbers = u'0030003100320033003400350036003700380039002E002C002B002D';
STRING_TRUE = 'true' + NULL;
STRING_FALSE = 'false' + NULL;
STRING_NULL = 'null' + NULL;
data = nextCleanChar(ptr);
if (data = UNICODE_DOUBLE_QUOTE or data = UNICODE_APOSTROPHE);
// string
retValDs.text = nextString(ptr : data);
dataType = JSON_TYPE_STRING;
return;
elseif (data = UNICODE_LEFT_CURLY_BRACE);
// json object
retValDs.pointer = json_parse(*omit : ptr);
dataType = JSON_TYPE_OBJECT;
return;
elseif (data = UNICODE_LEFT_BRACKET or data = UNICODE_LEFT_BRACE);
// json array
retValDs.pointer = nextArray(ptr);
dataType = JSON_TYPE_ARRAY;
return;
elseif (data = UNICODE_RIGHT_BRACKET or data = UNICODE_RIGHT_BRACE);
dataType = TYPE_NO_VALUE;
return;
elseif (data = UNICODE_RIGHT_CURLY_BRACE);
dataType = TYPE_NO_VALUE;
return;
else;
//
// Handle unquoted text. This could be the values true, false, or
// null, or it can be a number. An implementation (such as this one)
// is allowed to also accept non-standard forms.
//
// Accumulate characters until we reach the end of the text or a
// formatting character.
//
backupData = data;
dow (%scan(data : unquotedTextEnd) = 0);
tmp = %trimr(tmp) + data;
data = next(ptr);
enddo;
back(ptr);
//
// If it is true, false, or null, return the proper value.
//
// add null for string compare
tmp = %trimr(tmp) + NULL;
if (strcasecmp(%addr(tmp) : %addr(STRING_TRUE)) = 0);
dataType = JSON_TYPE_BOOLEAN;
retValDs.boolean = *on;
return;
elseif (strcasecmp(%addr(tmp) : %addr(STRING_FALSE)) = 0);
dataType = JSON_TYPE_BOOLEAN;
retValDs.boolean = *off;
return;
elseif (strcasecmp(%addr(tmp) : %addr(STRING_NULL)) = 0);
dataType = JSON_TYPE_NULL;
return;
endif;
// remove null from tmp
tmp = %str(%addr(tmp));
//
// It should be a number
//
if (%scan(backupData : numbers) > 0);
// determine if integer or double
if (%scan('.' : tmp) > 0);
// is double
monitor;
dataType = JSON_TYPE_DOUBLE;
retValDs.double = %float(tmp);
return;
on-error *all;
// do nothing => value should be returned as string;
endmon;
else;
monitor;
dataType = JSON_TYPE_INT;
retValDs.integer = %int(tmp);
return;
on-error 0103;
monitor;
dataType = JSON_TYPE_LONG;
retValDs.long = %int(tmp);
return;
on-error *all;
// do nothing => value should be returned as string
// because it ain't parsable as number
endmon;
on-error 0202;
// do nothing => value should be returned as string
endmon;
endif;
endif;
//
// Ain't a number => return value as string
//
dataType = JSON_TYPE_STRING;
retValDs.text = tmp;
endif;
/end-free
P E
/**
* \brief Next clean character
*
* Moves the parser to the position on the next clean character and
* returns it to the caller. Character like carriage return, linefeed and
* blanks are ignored. On a null character an escape message will be sent.
*
* \param Pointer to the parser header structure
*
* \return next clean character
*/
P nextCleanChar B
D PI 1A
D ptr *
*
D header DS likeds(tmpl_parser_ds) based(ptr)
D data S 1A
D retVal S 1A
D keepLooping S N inz(*on)
/free
dow (keepLooping);
data = next(ptr);
if (data = *blank);
// loop
elseif (data = CR);
// loop
elseif (data = LF);
// loop
elseif (data = NULL);
abortParsing(ptr : 'Unexpected ending of JSON string');
else;
keepLooping = *off;
endif;
enddo;
retVal = data;
return retVal;
/end-free
P E
/**
* \brief Next string
*
* Returns the next string from the current parser position on and moves
* the parser to the position behind the returned string.
*
* \param Pointer to the parser header structure
* \param Open quote character of the string (' or ")
*
* \return next JSON string
*/
P nextString B
D PI 10000A
D ptr *
D quote 1A const
*
D header DS likeds(tmpl_parser_ds) based(ptr)
D data S 1A
D keepLooping S N inz(*on)
D retVal S 10000A varying
D unicode S 1C
D unicodeCharRep S 4A
D allowedChars C 'ABCDEFabcdef0123456789'
/free
dow (keepLooping);
data = next(ptr);
if (data = CR);
// throw esc message (unterminated end)
abortParsing(ptr : 'Unterminated string (cr)');
elseif (data = LF);
// throw esc message (unterminated end)
abortParsing(ptr : 'Unterminated string (linefeed)');
elseif (data = NULL);
// throw esc message (unterminated end)
abortParsing(ptr : 'Unterminated string (null)');
elseif (data = quote); // end of string
keepLooping = *off;
elseif (data = UNICODE_BACKSLASH);
// check if we have an escape sequence
data = next(ptr);
if (data = UNICODE_DOUBLE_QUOTE);
retVal += %char(UNICODE_DOUBLE_QUOTE);
elseif (data = UNICODE_BACKSLASH);
retVal += %char(UNICODE_BACKSLASH);
elseif (data = UNICODE_SLASH);
retVal += %char(UNICODE_SLASH);
elseif (data = 'b');
retVal += x'16'; // backspace
elseif (data = 'f');
retVal += x'0c'; // form feed
elseif (data = 'n');
retVal += x'25'; // new line / line feed
elseif (data = 'r');
retVal += x'0d'; // carriage return
elseif (data = 't');
retVal += x'05'; // tab (horizontal)
elseif (data = 'u');
// add the next 4 character to the unicode char representation
unicodeCharRep = next(ptr) + next(ptr) + next(ptr) + next(ptr);
if (%check(allowedChars : unicodeCharRep) > 0);
abortParsing(ptr :'Incomplete unicode character representation');
endif;
convertChar(%addr(unicode) : %addr(unicodeCharRep) : 4);
retVal += %char(unicode);
else;
abortParsing(ptr : 'Invalid escape sequence \' + data);
endif;
else;
retVal += data;
endif;
enddo;
return retVal;
/end-free
P E
/**
* \brief Next JSON array
*
* Returns the JSON array which is at the next position in the JSON
* string. This procedure expects the position of the parser to be on
* the opening bracket of the array ( [ ). If there is no JSON array
* array at the current position an escape message will be sent.
*
*
*
* Empty arrays are also supported.
*
* \param Pointer to the parser header structure
*
* \return Pointer to JSON array
*/
P nextArray B
D PI *
D ptr *
*
D header DS likeds(tmpl_parser_ds) based(ptr)
D array S *
D retValDs DS likeds(tmpl_return_value_ds)
D dataType S 10I 0
D data S 1A inz
D keepLooping S N inz(*on)
/free
array = jsona_create();
dow (keepLooping);
// Values are separated by ','. We will also tolerate ';'.
if (data = NULL);
abortParsing(ptr : 'A JSON array text must end with "]"');
elseif (data = UNICODE_RIGHT_BRACKET);
// end of array
leave;
elseif (data = UNICODE_COMMA);
// everything ok
elseif (data = UNICODE_SEMICOLON);
// everything ok
endif;
// arrays consists of values only
nextValue(%addr(retValDs) : ptr : dataType);
if (dataType = JSON_TYPE_STRING);
jsona_putString(array : %trimr(retValDs.text));
elseif (dataType = JSON_TYPE_BOOLEAN);
jsona_putBoolean(array : retValDs.boolean);
elseif (dataType = JSON_TYPE_NULL);
jsona_putNull(array);
elseif (dataType = JSON_TYPE_INT);
jsona_putInt(array : retValDs.integer);
elseif (dataType = JSON_TYPE_LONG);
jsona_putLong(array : retValDs.long);
elseif (dataType = JSON_TYPE_DOUBLE);
jsona_putDouble(array : retValDs.double);
elseif (dataType = JSON_TYPE_OBJECT);
jsona_putObject(array : retValDs.pointer);
elseif (dataType = JSON_TYPE_ARRAY);
jsona_putArray(array : retValDs.pointer);
elseif (dataType = TYPE_NO_VALUE);
leave;
endif;
// get next char
data = nextCleanChar(ptr);
// next iteration
enddo;
return array;
/end-free
P E
/**
* \brief Next character
*
* Returns the next character in the JSON string and moves the parser
* forward by one position.
*
* \param Pointer to parser header structure
*
* \return next character or null if there are no more characters
*/
P next B
D PI 1A
D ptrHead *
*
D header DS likeds(tmpl_parser_ds) based(ptrHead)
D ptr S *
D data S 1A based(ptr)
D retVal S 1A
/free
if (more(ptrHead));
ptr = header.json_string_ptr + header.index_pos + 1;
retVal = data;
header.index_pos += 1;
else;
retVal = NULL;
endif;
return retVal;
/end-free
P E
/**
* \brief Move parser back
*
* Moves the position of the parser back by one position.
*
* \param Pointer to parser header structure
*/
P back B
D PI
D ptr *
*
D header DS likeds(tmpl_parser_ds) based(ptr)
/free
header.index_pos -= 1;
/end-free
P E
/**
* \brief Checks for more characters in string
*
* Checks if there are still more characters to parse in the given string.
*
* \param Pointer to the rest of the JSON string to be parsed
*/
P more B
D PI N
D ptr *
/free
if (strlen(ptr) = 0);
return *off;
else;
return *on;
endif;
/end-free
P E
/**
* \brief Abort parsing
*
* The memory of the parser header is deallocated (freed) and an
* escape message is sent to the previous call stack entry with the
* passed message text.
*
* \param Pointer to parser header
* \param Message text
*/
P abortParsing B
D PI
D ptr *
D message 1000A const
*
D sendProgramMessage...
D PR extpgm('QMHSNDPM')
D szMsgID 7A const
D szMsgFile 20A const
D szMsgData 6000A const options(*varsize)
D nMsgDataLen 10I 0 const
D szMsgType 10A const
D szCallStkEntry...
D 10A const
D nRelativeCallStkEntry...
D 10I 0 const
D szRtnMsgKey 4A
D error 265A options(*varsize)
*
D msgdata S 512A
D msgkey S 4A
D apiError S 265A
/free
// dispose header
dealloc(n) ptr;
// set message data
msgdata = message;
// send escape message
sendProgramMessage('CPF9898' :
'QCPFMSG *LIBL ' :
%trimr(msgdata) :
%len(%trimr(msgdata)) :
'*ESCAPE ' :
'*' :
1 :
msgkey :
apiError);
/end-free
P E
json/unittest 42755 2763 0 0 11516372107 11221 5 ustar 00MSCHMIDT json/unittest/json_ut_01.rpgle 100755 2763 0 2507 11526177151 14421 0 ustar 00MSCHMIDT /**
* \brief JSON : Unit Test
*
* \author Mihael Schmidt
* \date 21.01.2011
*/
H nomain
*-------------------------------------------------------------------------
* Prototypes
*-------------------------------------------------------------------------
D test_basics...
D PR
/copy RPGUNIT1,TESTCASE
/copy 'json/json_h.rpgle'
/copy 'message_h.rpgle'
P test_basics...
P B export
*
D json S *
/free
json = json_create();
assert(json <> *null : 'Newly created json object mustn''t be null.');
json_putBoolean(json : 'bool' : *on);
iEqual(json_size(json) : 1);
assert(json_getBoolean(json : 'bool') = *on :
'Wrong value for added boolean value.');
json_remove(json : 'bool');
iEqual(json_size(json) : 0);
assert(json_isEmpty(json) : 'JSON object should be empty.');
json_putInt(json : 'Integer' : 358);
iEqual(json_getInt(json : 'Integer') : 358);
json_putString(json : 'String' : 'Mihael');
aEqual(%str(json_getString(json : 'String')) : 'Mihael');
json_dispose(json);
/end-free
P E
json/unittest/Makefile 100666 2763 0 2250 11526177266 13050 0 ustar 00MSCHMIDT #
# Makefile for JSON Unit Tests
#
#-----------------------------------------------------------
# User-defined part start
#
# BIN_LIB is the destination library for the service program.
# the rpg modules and the binder source file are also created in BIN_LIB.
# binder source file and rpg module can be remove with the clean step (make clean)
BIN_LIB=QGPL
# to this library the prototype source file (copy book) is copied in the install step
INCLUDE=/usr/local/include
# CFLAGS = RPG compile parameter
CFLAGS=DBGVIEW(*LIST)
# LFLAGS = binding parameter
# (make sure modules and service programs are in library list)
LFLAGS=BNDDIR(QC2LE) BNDSRVPGM(JSON LLIST)
FROM_CCSID=37
#
# User-defined part end
#-----------------------------------------------------------
MODULES = json_ut_01
OBJECTS = $(BIN_LIB)/json_ut_01
.SUFFIXES: .rpgle .c .cpp
# suffix rules
.rpgle:
system "CRTRPGMOD $(BIN_LIB)/$@ SRCSTMF('$<') $(CFLAGS)"
system "crtsrvpgm $(BIN_LIB)/json_ut_01 MODULE($(BIN_LIB)/JSON_UT_01) export(*all) bndsrvpgm(rutestcase json)"
all: build
.PHONY:
json_ut_01:
build: $(MODULES)
clean:
-system "DLTMOD $(BIN_LIB)/JSON_UT_01"
-system "DLTSRVPGM $(BIN_LIB)/JSON_UT_01"
json/libc_h.rpgle 100666 2763 0 11734 11515400055 12012 0 ustar 00MSCHMIDT *-------------------------------------------------------------------------
* Prototypes for C functions
*-------------------------------------------------------------------------
/if not defined(QUSEC)
/define QUSEC
/include QSYSINC/QRPGLESRC,QUSEC
/endif
*
* strings
*
D strtok PR * extproc('strtok')
D i_string * value options(*string)
D i_token * value options(*string)
*
D strlen PR 10U 0 extproc('strlen')
D string * value
*
D requestControlBlockLower...
D DS qualified
D type 10I 0 inz(0)
D ccsid 10I 0 inz(0)
D case 10I 0 inz(0)
D res1 10A inz(*ALLX'00')
*
D requestControlBlockUpper...
D DS qualified
D type 10I 0 inz(1)
D ccsid 10I 0 inz(0)
D case 10I 0 inz(0)
D res1 10A inz(*ALLX'00')
*
D caseConvert PR extproc('QlgConvertCase')
D reqContBlock const
D likeds(requestControlBlockUpper)
D input 1024A const options(*varsize)
D output 1024A options(*varsize)
D len 10I 0 const
D errorcode likeds(QUSEC) options(*varsize)
*
* memory handling
*
D memcpy PR * extproc('memcpy')
D dest * value
D source * value
D count 10U 0 value
*
D memset PR * extproc('memset')
D i_pDest * value
D i_char 10I 0 value
D i_count 10U 0 value
*
D memmove PR * extproc('memmove')
D pMemDest * value
D pMemSrc * value
D memSize 10U 0 value
*
D memcmp PR 10I 0 extproc('memcmp')
D pBuf1 * value
D pBuf2 * value
D count 10U 0 value
*
D memicmp PR 10I 0 extproc('__memicmp')
D pBuf1 * value
D pBuf2 * value
D count 10U 0 value
*
* Math
*
D ceil PR 8F extproc('ceil')
D value 8F value
*
D floor PR 8F extproc('floor')
D value 8F value
*
* Date and time
*
D time PR 10I 0 extproc('time')
D timeptr * value
*
D time_ds DS qualified based(nullPointer)
D seconds 10I 0
D minutes 10I 0
D hours 10I 0
D day 10I 0
D month 10I 0
D year 10I 0
D weekday 10I 0
D dayOfYear 10I 0
D isDST 10I 0
*
* Misc
*
D tmpnam PR * extproc('tmpnam')
D buffer 39A options(*omit)
*
D tmpnamIFS PR * extproc('_C_IFS_tmpnam')
D buffer 39A options(*omit)
*
D system PR 10I 0 extproc('system')
D command * value options(*string)
*
D sleep PR 10U 0 extproc('sleep')
D seconds 10U 0 value
*
D srand PR extproc('srand')
D i_seed 10U 0 value
*
D rand PR 10I 0 extproc('rand')
*
D qsort PR * extproc('qsort')
D memPtr * value
D numElem 10U 0 value
D width 10U 0 value
D pSortFunc * value procptr
*
D bsearch PR * extproc('bsearch')
D keyPtr * value
D memPtr * value
D numElem 10U 0 value
D width 10U 0 value
D pSearchFnc * value procptr
json/json_cut_h.rpgle 100666 2763 0 3110 11515400047 12673 0 ustar 00MSCHMIDT /if not defined (JSON_CUTIL)
/define JSON_CUTIL
/*
* Copyright (c) 2007-2009 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*/
*------------------------------------------------------------------------
* Prototypes
*------------------------------------------------------------------------
D json_validate PR N extproc('json_validate') opdesc
D json_string 65535A const options(*varsize)
D ccsid 10I 0 const options(*nopass)
*
D json_validateFile...
D PR N extproc('json_validateFile') opdesc
D path 65535A const options(*varsize)
D ccsid 10I 0 const options(*nopass)
/endif
json/llist_h.rpgle 100666 2763 0 27506 11515400056 12235 0 ustar 00MSCHMIDT /if not defined(LLIST)
/define LLIST
*------------------------------------------------------------------------
*
* Copyright (c) 2007-2009 Mihael Schmidt
* All rights reserved.
*
* This file is part of the LLIST service program.
*
* LLIST is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* LLIST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with LLIST. If not, see http://www.gnu.org/licenses/.
*
*------------------------------------------------------------------------
*-------------------------------------------------------------------------
* Prototypes for Linked List
*-------------------------------------------------------------------------
D list_create PR * extproc('list_create')
*
D list_dispose PR extproc('list_dispose')
D listPtr *
*
D list_add PR N extproc('list_add')
D listPtr * const
D ptrValue * const
D length 10U 0 const
D pos 10U 0 const options(*nopass)
*
D list_addFirst PR N extproc('list_addFirst')
D listPtr *
D valuePtr * const
D length 10U 0 const
*
D list_addLast PR N extproc('list_addLast')
D listPtr * const
D valuePtr * const
D length 10U 0 const
*
D list_addAll PR N extproc('list_addAll')
D listPtr * const
D srcListPtr * const
*
D list_remove PR N extproc('list_remove')
D listPtr * const
D index 10U 0 const
*
D list_removeFirst...
D PR N extproc('list_removeFirst')
D listPtr * const
*
D list_removeLast...
D PR N extproc('list_removeLast')
D listPtr * const
*
D list_clear PR N extproc('list_clear')
D listPtr * const
*
D list_isEmpty PR N extproc('list_isEmpty')
D listPtr * const
*
D list_replace PR N extproc('list_replace')
D listPtr * const
D ptrValue * const
D lengthValue 10U 0 const
D index 10U 0 const
*
D list_get PR * extproc('list_get')
D listPtr * const
D index 10U 0 const
*
D list_getFirst PR * extproc('list_getFirst')
D listPtr * const
*
D list_getLast PR * extproc('list_getLast')
D listPtr * const
*
D list_getNext PR * extproc('list_getNext')
D listPtr * const
*
D list_getPrev PR * extproc('list_getPrev')
D listPtr * const
*
D list_abortIteration...
D PR extproc('list_abortIteration')
D listPtr * const
*
D list_contains PR N extproc('list_contains')
D listPtr * const
D valuePtr * const
D valueLength 10U 0 const
*
D list_indexOf PR 10I 0 extproc('list_indexOf')
D listPtr * const
D valuePtr * const
D valueLength 10U 0 const
*
D list_lastIndexOf...
D PR 10I 0 extproc('list_lastIndexOf')
D listPtr * const
D valuePtr * const
D valueLength 10U 0 const
*
D list_toCharArray...
D PR extproc('list_toCharArray')
D listPtr * const
D arrayPtr * const
D count 10U 0 const
D length 10U 0 const
*
D list_size PR 10U 0 extproc('list_size')
D listPtr * const
*
D list_sublist PR * extproc('list_sublist')
D listPtr * const
D startIndex 10U 0 const
D length 10U 0 const options(*nopass)
*
D list_rotate PR extproc('list_rotate')
D listPtr * const
D rotatePos 10I 0 const
*
D list_swap PR N extproc('list_swap')
D listPtr * const
D itemPos1 10U 0 const
D itemPos2 10U 0 const
*
D list_foreach...
D PR extproc('list_foreach')
D listPtr * const
D procPtr * const procptr
D userData * const
*
D list_toString PR 65535A varying extproc('list_toString')
D listPtr * const
D separator 1A const varying options(*omit:*nopass)
D enclosing 100A const varying options(*nopass)
D enclosingEnd 100A const varying options(*nopass)
*
D list_split PR * extproc('list_split') opdesc
D string 65535A const options(*varsize)
D separator 1A const options(*nopass)
*
D list_reverse PR extproc('list_reverse')
D listPtr * const
*
D list_copy PR * extproc('list_copy')
D listPtr * const
*
D list_frequency...
D PR 10U 0 extproc('list_frequency')
D listPtr * const
D valuePtr * const
D valueLength 10U 0 const
*
D list_addString...
D PR N extproc('list_addString') opdesc
D listPtr * const
D value 65535A const options(*varsize)
D index 10U 0 const options(*nopass)
*
D list_addInteger...
D PR N extproc('list_addInteger')
D listPtr * const
D value 10I 0 const
D index 10U 0 const options(*nopass)
*
D list_addLong...
D PR N extproc('list_addLong')
D listPtr * const
D value 20I 0 const
D index 10U 0 const options(*nopass)
*
D list_addShort...
D PR N extproc('list_addShort')
D listPtr * const
D value 5I 0 const
D index 10U 0 const options(*nopass)
*
D list_addFloat...
D PR N extproc('list_addFloat')
D listPtr * const
D value 4F const
D index 10U 0 const options(*nopass)
*
D list_addDouble...
D PR N extproc('list_addDouble')
D listPtr * const
D value 8F const
D index 10U 0 const options(*nopass)
*
D list_addBoolean...
D PR N extproc('list_addBoolean')
D listPtr * const
D value N const
D index 10U 0 const options(*nopass)
*
D list_addDecimal...
D PR N extproc('list_addDecimal')
D listPtr * const
D value 15P 5 const
D index 10U 0 const options(*nopass)
*
D list_addDate...
D PR N extproc('list_addDate')
D listPtr * const
D value D const
D index 10U 0 const options(*nopass)
*
D list_getString...
D PR 65535A extproc('list_getString')
D listPtr * const
D index 10U 0 const
*
D list_getInteger...
D PR 10I 0 extproc('list_getInteger')
D listPtr * const
D index 10U 0 const
*
D list_getShort...
D PR 5I 0 extproc('list_getShort')
D listPtr * const
D index 10U 0 const
*
D list_getLong...
D PR 20I 0 extproc('list_getLong')
D listPtr * const
D index 10U 0 const
*
D list_getFloat...
D PR 4F extproc('list_getFloat')
D listPtr * const
D index 10U 0 const
*
D list_getDouble...
D PR 8F extproc('list_getDouble')
D listPtr * const
D index 10U 0 const
*
D list_getBoolean...
D PR N extproc('list_getBoolean')
D listPtr * const
D index 10U 0 const
*
D list_getDecimal...
D PR 15P 5 extproc('list_getDecimal')
D listPtr * const
D index 10U 0 const
*
D list_getDate...
D PR D extproc('list_getDate')
D listPtr * const
D index 10U 0 const
*
D list_sort PR extproc('list_sort')
D listPtr * const
D sortAlgo * const procptr
*
D list_removeRange...
D PR extproc('list_removeRange')
D listPtr * const
D index 10U 0 const
D numberElements...
D 10U 0 const
*
D list_merge...
D PR extproc('list_merge')
D destList * const
D sourceList * const
/endif
json/json_h.rpgle 100666 2763 0 20001 11515400050 12030 0 ustar 00MSCHMIDT /if not defined (JSON)
/define JSON
/*
* Copyright (c) 2007-2009 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*/
*-------------------------------------------------------------------------
* Prototypes
*-------------------------------------------------------------------------
D json_create PR * extproc('json_create')
*
D json_dispose PR extproc('json_dispose')
D jsonPtr *
*
D json_remove PR extproc('json_remove') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D json_clear PR extproc('json_clear')
D jsonPtr * const
*
D json_getNext PR * extproc('json_getNext')
D jsonPtr * const
*
D json_abortIteration...
D PR extproc('json_abortIteration')
D jsonPtr * const
*
D json_contains...
D PR N extproc('json_contains') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D json_isEmpty PR N extproc('json_isEmpty')
D jsonPtr * const
*
D json_size PR 10I 0 extproc('json_size')
D jsonPtr * const
*
D json_putString PR extproc('json_putString') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value 65535A const options(*varsize)
*
D json_putBoolean...
D PR extproc('json_putBoolean') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value N const
*
D json_putInt...
D PR extproc('json_putInt') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value 10I 0 const
*
D json_putLong...
D PR extproc('json_putLong') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value 20I 0 const
*
D json_putDouble...
D PR extproc('json_putDouble') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value 8F const
*
D json_putArray...
D PR extproc('json_putArray') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D array * const
*
D json_get PR * extproc('json_get') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D json_getString PR * extproc('json_getString') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D json_getBoolean...
D PR N extproc('json_getBoolean') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D json_getInt...
D PR 10I 0 extproc('json_getInt') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D json_getLong...
D PR 20I 0 extproc('json_getLong') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D json_getDouble...
D PR 8F extproc('json_getDouble') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D json_getArray...
D PR * extproc('json_getArray') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D json_toString PR * extproc('json_toString')
D jsonPtr * const
D pOutputFormat...
D 10I 0 const options(*nopass)
D pPrettyPrintFormat...
D likeds(json_prettyPrintFormat)
D const options(*nopass)
D pIndentationLevel...
D 10I 0 options(*nopass)
*
D json_putNull PR extproc('json_putNull') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D json_putObject...
D PR extproc('json_putObject') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D objPtr * const
*
D json_getObject...
D PR * extproc('json_getObject') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D json_getEntryType...
D PR 10I 0 extproc('json_getEntryType') opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*-------------------------------------------------------------------------
* Data structures
*-------------------------------------------------------------------------
D json_prettyPrintFormat...
D DS qualified based(template)
D useTabs N
D numberWhitespace...
D 5U 0
D breakAfterElement...
D N
D breakAfterObjectBrace...
D N
D breakBeforeArrayBrace...
D N
D breakAfterArrayBrace...
D N
*
* include the prototypes from the json array module
*
/copy 'json_arr_h.rpgle'
*
* include the prototypes from the json parser module
*
/copy 'json_par_h.rpgle'
*
* include the prototypes from the json checker module
*
/copy 'json_chk_h.rpgle'
*
* include the prototypes from the json checker utilities module
*
/copy 'json_cut_h.rpgle'
*
* include the prototypes from the json utilities module
*
/copy 'json_util_h.rpgle'
/endif
json/json_chk.h 100666 2763 0 2316 11515400047 11463 0 ustar 00MSCHMIDT /*
* Copyright (c) 2007-2009 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*/
/* JSON_CHK_H.RPGLE */
typedef struct json_checker_struct {
int state;
int depth;
int top;
int* stack;
} * JSON_checker;
extern JSON_checker json_new_checker(int depth);
extern int json_checker_char(JSON_checker jc, int next_char);
extern int json_checker_done(JSON_checker jc);
json/json.rpgle 100666 2763 0 227465 11526200015 11571 0 ustar 00MSCHMIDT /**
* \brief JSON Service program
*
* From the main web site:
*
*
* JSON (JavaScript Object Notation) is a lightweight data-interchange
* format. It is easy for humans to read and write. It is easy for
* machines to parse and generate. It is based on a subset of the
* JavaScript Programming Language, Standard ECMA-262 3rd Edition -
* December 1999. JSON is a text format that is completely language
* independent but uses conventions that are familiar to programmers
* of the C-family of languages, including C, C++, C#, Java, JavaScript,
* Perl, Python, and many others. These properties make JSON an ideal
* data-interchange language.
*
*
* JSON is built on two structures:
*
*
* - A collection of name/value pairs. In various languages, this is
* realized as an object, record, struct, dictionary, hash table,
* keyed list, or associative array.
*
* -
* An ordered list of values. In most languages, this is realized as
* an array, vector, list, or sequence.
*
*
*
*
* These are universal data structures. Virtually all modern programming
* languages support them in one form or another. It makes sense that a
* data format that is interchangable with programming languages also be
* based on these structures.
*
*
* In JSON, they take on these forms:
*
*
* An object is an unordered set of name/value pairs. An object begins
* with { (left brace) and ends with } (right brace). Each name is followed
* by : (colon) and the name/value pairs are separated by , (comma).
*
*
* Concerning this implementation:
*
*
*
* The pointer to the JSON object will be check on every procedure call.
* If the pointer does not point to a JSON object an escape message will
* be send to the next level of the call stack.
*
*
*
* If the JSON obect is queried for an entry of a specific type and the
* type does not match with the expectation of the procedure an escape
* message will be send to the next level of the call stack.
*
*
*
* All the allocated memory of the JSON object and its entries is managed
* by this service program and will be freed with the call of the
* procedure dispose. No manual deallocation must be done.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \link http://www.json.org JSON
*
* \rev 27.01.2010 Mihael Schmidt
* Added support for getting numbers with procedures json_getInt,
* json_getLong, json_getDouble no matter what the original type was
* (f. e. double value will be cast to int with json_getInt).
*
* \rev 13.02.2011 Mihael Schmidt
* Fixed bug in remove procedure. Replaced string and hex constants
* with unicode constants.
*/
*-------------------------------------------------------------------------
* Copyright (c) 2007-2011 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*-------------------------------------------------------------------------
H nomain
H bnddir('QC2LE')
H copyright('Copyright (c) 2007-2010 Mihael Schmidt. All rights reserved.')
*-------------------------------------------------------------------------
* Prototypes
*-------------------------------------------------------------------------
D json_srvpgm_init...
D PR 10I 0 extproc('json_srvpgm_init')
*
/copy 'json_h.rpgle'
/copy 'json_int_h.rpgle'
/copy 'ceeapi_h.rpgle'
/copy 'llist_h.rpgle'
/copy 'libc_h.rpgle'
/if not defined (QUSEC)
/define QUSEC
/copy QSYSINC/QRPGLESRC,QUSEC
/endif
*-------------------------------------------------------------------------
* Constants
*-------------------------------------------------------------------------
D HEX_NULL C x'00'
D JSON_ID C 'JSON_IMPLEMENTATION'
/copy 'json_c.rpgle'
/copy 'unicode_c.rpgle'
*-------------------------------------------------------------------------
* Global Variables
*-------------------------------------------------------------------------
*
* Parameters passed to CEEDOD
*
D descType S 10I 0
D dataType S 10I 0
D descInfo1 S 10I 0
D descInfo2 S 10I 0
D length S 10I 0
*
D chars DS likeds(tmpl_chars)
D chars_compact DS likeds(tmpl_chars)
*
D hexNull S 1A inz(HEX_NULL)
*-------------------------------------------------------------------------
* Procedures
*-------------------------------------------------------------------------
/**
* \brief Service program initialization
*
* String formattings are preloaded.
*/
P json_srvpgm_init...
P B export
D PI 10I 0
/free
chars.d_quote = %char(UNICODE_DOUBLE_QUOTE) + x'00';
chars.l_brace = ' ' + %char(UNICODE_LEFT_CURLY_BRACE) + ' ' + x'00';
chars.r_brace = ' ' + %char(UNICODE_RIGHT_CURLY_BRACE) + ' ' + x'00';
chars.l_bracket = ' ' + %char(UNICODE_LEFT_BRACKET) + ' ' + x'00';
chars.r_bracket = ' ' + %char(UNICODE_RIGHT_BRACKET) + ' ' + x'00';
chars.comma = ' ' + %char(UNICODE_COMMA) + ' ' + x'00';
chars.colon = ' ' + %char(UNICODE_COLON) + ' ' + x'00';
chars.true = 'true' + x'00';
chars.false = 'false' + x'00';
chars.null_str = 'null' + x'00';
chars.size_d_quote = 1;
chars.size_l_brace = 3;
chars.size_r_brace = 3;
chars.size_l_bracket = 3;
chars.size_r_bracket = 3;
chars.size_comma = 3;
chars.size_colon = 3;
chars.size_true = 4;
chars.size_false = 5;
chars.size_null_str = 4;
chars_compact.d_quote = %char(UNICODE_DOUBLE_QUOTE) + x'00';
chars_compact.l_brace = %char(UNICODE_LEFT_CURLY_BRACE) + x'00';
chars_compact.r_brace = %char(UNICODE_RIGHT_CURLY_BRACE) + x'00';
chars_compact.l_bracket = %char(UNICODE_LEFT_BRACKET) + x'00';
chars_compact.r_bracket = %char(UNICODE_RIGHT_BRACKET) + x'00';
chars_compact.comma = %char(UNICODE_COMMA) + x'00';
chars_compact.colon = %char(UNICODE_COLON) + x'00';
chars_compact.true = 'true' + x'00';
chars_compact.false = 'false' + x'00';
chars_compact.null_str = 'null' + x'00';
chars_compact.size_d_quote = 1;
chars_compact.size_l_brace = 1;
chars_compact.size_r_brace = 1;
chars_compact.size_l_bracket = 1;
chars_compact.size_r_bracket = 1;
chars_compact.size_comma = 1;
chars_compact.size_colon = 1;
chars_compact.size_true = 4;
chars_compact.size_false = 5;
chars_compact.size_null_str = 4;
return 0;
/end-free
P E
/**
* \brief Create JSON Object
*
* Creates a JSON Object.
*
*
*
* The memory allocated for this object must be deallocated with the
* dispose procedure when finished.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \return Pointer to the JSON object
*/
P json_create B export
D PI *
*
D jsonPtr S *
D header DS likeds(tmpl_header) based(jsonPtr)
/free
jsonPtr = %alloc(%size(tmpl_header));
header.id = JSON_ID;
header.size = 0;
header.firstEntry = *null;
header.lastEntry = *null;
header.iteration = -1;
header.iterNextEntry = *null;
header.iterPrevEntry = *null;
header.disposeList = list_create();
return jsonPtr;
/end-free
P E
/**
* \brief Deallocate JSON object
*
* The memory for the JSON Object will be deallocated and the passed
* pointer will be set to *null.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
*/
P json_dispose B export
D PI
D jsonPtr *
*
D header DS likeds(tmpl_header) based(jsonPtr)
D ptr S *
D ptrDisposeElement...
D S * based(ptr)
/free
if (jsonPtr <> *null);
isJSONImpl(jsonPtr);
// deallocate all temporary allocated memory from the dispose list
ptr = list_getNext(header.disposeList);
dow (ptr <> *null);
dealloc ptrDisposeElement;
ptr = list_getNext(header.disposeList);
enddo;
list_dispose(header.disposeList);
json_clear(jsonPtr);
dealloc(n) jsonPtr;
endif;
/end-free
P E
/**
* \brief Remove entry
*
* If the JSON object contains such an entry it will be removed.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Entry key
*
*/
P json_remove B export
D PI opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D header DS likeds(tmpl_header) based(jsonPtr)
D ptr S *
D entry DS likeds(tmpl_entry) based(ptr)
D nextEntryPtr S *
D nextEntry DS likeds(tmpl_entry)
D based(nextEntryPtr)
D prevEntryPtr S *
D prevEntry DS likeds(tmpl_entry)
D based(prevEntryPtr)
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
ptr = getJSONEntry(jsonPtr : %addr(tmpKey) : length);
// check if entry was found
if (ptr <> *null);
// update header
if (header.firstEntry = ptr);
header.firstEntry = entry.next;
endif;
if (header.lastEntry = ptr);
header.lastEntry = entry.prev;
endif;
// update previous and next (if exist)
if (entry.prev <> *null);
prevEntryPtr = entry.prev;
prevEntry.next = entry.next;
endif;
if (entry.next <> *null);
nextEntryPtr = entry.next;
nextEntry.prev = entry.prev;
endif;
// release memory of entry value
disposeEntryValue(ptr);
dealloc(n) entry.key;
dealloc(n) ptr;
header.size -= 1;
endif;
/end-free
P E
/**
* \brief Clear JSON object
*
* Removes all entries from the JSON object.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
*
*/
P json_clear B export
D PI
D jsonPtr * const
*
D header DS likeds(tmpl_header) based(jsonPtr)
D tmpPtr S *
D ptr S *
D entry DS likeds(tmpl_entry) based(ptr)
/free
isJSONImpl(jsonPtr);
ptr = header.lastEntry;
dow (ptr <> *null);
tmpPtr = entry.prev;
// dispose/dealloc old value
disposeEntryValue(ptr);
dealloc(n) entry.key;
dealloc(n) ptr;
ptr = tmpPtr;
enddo;
// update header
header.size = 0;
header.firstEntry = *null;
header.lastEntry = *null;
header.iteration = -1;
header.iterNextEntry = *null;
header.iterPrevEntry = *null;
/end-free
P E
/**
* \brief Get next entry
*
* Iterates through all JSON entries and returns a pointer to the key of
* the next entry.
*
*
*
* If the iteration ends with the last key *null will be returned.
*
*
*
* If the iteration is aborted the calling program should use the
* abortIteration procedure to reset the iteration.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
*
* \return Pointer to the key of the next entry or *null if there are no
* more entries
*/
P json_getNext B export
D PI *
D jsonPtr * const
*
D header DS likeds(tmpl_header) based(jsonPtr)
D entryPtr S *
D entry DS likeds(tmpl_entry) based(entryPtr)
D retVal S *
/free
isJSONImpl(jsonPtr);
if (header.iteration = header.size-1 or
header.iteration < -1);
header.iteration = -1;
retVal = *null;
else;
if (header.iterNextEntry = *null);
entryPtr = header.firstEntry;
else;
entryPtr = header.iterNextEntry;
endif;
header.iteration += 1;
header.iterNextEntry = entry.next;
retVal = entry.key;
endif;
return retVal;
/end-free
P E
/**
* \brief Abort iteration
*
* Resets the iteration of the JSON Object.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
*/
P json_abortIteration...
P B export
D PI
D jsonPtr * const
*
D header DS likeds(tmpl_header) based(jsonPtr)
/free
isJSONImpl(jsonPtr);
header.iteration = -1;
header.iterNextEntry = *null;
header.iterPrevEntry = *null;
/end-free
P E
/**
* \brief Contains key
*
* Checks if the JSON object contains an entry with the passed key.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Entry key
*
* \return *on = JSON object contains key
* *off = JSON object does not contain key
*/
P json_contains...
P B export
D PI N opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D entryPtr S *
D retVal S N
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
entryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : length);
if (entryPtr = *null);
retVal = *off;
else;
retVal = *on;
endif;
return retVal;
/end-free
P E
/**
* \brief Is JSON object empty
*
* Checks if the JSON object contains no entries at all.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
*
* \return *on = JSON object is empty
* *off = JSON object is not empty
*/
P json_isEmpty B export
D PI N
D jsonPtr * const
*
D header DS likeds(tmpl_header) based(jsonPtr)
D retVal S N
/free
isJSONImpl(jsonPtr);
if (header.size = 0);
retVal = *on;
else;
retVal = *off;
endif;
return retVal;
/end-free
P E
/**
* \brief Count JSON object entries
*
* Returns the number of entries in the JSON object. The keys of the
* entries are counted. If the JSON object contains arrays the elements
* of the arrays are ignored.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
*
* \return number of entries in the JSON object
*/
P json_size B export
D PI 10I 0
D jsonPtr * const
*
D header DS likeds(tmpl_header) based(jsonPtr)
/free
isJSONImpl(jsonPtr);
return header.size;
/end-free
P E
/**
* \brief Add character entry
*
* Adds an entry of type character.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
* \param Value
*/
P json_putString B export
D PI opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value 65535A const options(*varsize)
*
D header DS likeds(tmpl_header) based(jsonPtr)
D prevEntryPtr S *
D prevEntry DS likeds(tmpl_entry)
D based(prevEntryPtr)
D newEntryPtr S *
D newEntry DS likeds(tmpl_entry)
D based(newEntryPtr)
D tmpPtr S *
D tmpKey S 65535A
D tmpValue S 65535A
D keyLength S 10I 0
D valueLength S 10I 0
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
keyLength = length;
tmpKey = %subst(key : 1 : keyLength);
cee_getOpDescInfo(3 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
valueLength = length;
tmpValue = %subst(value : 1 : valueLength);
// check if key is in already in the map
newEntryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : keyLength);
if (newEntryPtr = *null); // entry not in json object
// create new entry
newEntryPtr = %alloc(%size(tmpl_entry));
newEntry.type = JSON_TYPE_STRING;
newEntry.keyLength = keyLength + 1; // +1 for the null byte
newEntry.key = %alloc(keyLength + 1); // +1 for the null byte
newEntry.valueLength = valueLength;
newEntry.value = %alloc(valueLength + 1); // +1 for the null byte
newEntry.next = *null;
newEntry.prev = *null;
// update header
header.size += 1;
if (header.firstEntry = *null);
header.firstEntry = newEntryPtr;
else;
prevEntryPtr = header.lastEntry;
prevEntry.next = newEntryPtr;
newEntry.prev = prevEntryPtr;
endif;
header.lastEntry = newEntryPtr;
else;
// entry needs to be resized
newEntry.type = JSON_TYPE_STRING;
newEntry.keyLength = keyLength + 1;
newEntry.key = %realloc(newEntry.key : keyLength + 1);
newEntry.valueLength = valueLength;
// dispose/dealloc old value
disposeEntryValue(newEntryPtr);
endif;
// copy value to the list entry
memcpy(newEntry.key : %addr(tmpKey) : keyLength);
memcpy(newEntry.value : %addr(tmpValue) : valueLength);
// set null to the last byte
memcpy(newEntry.key + keyLength : %addr(hexNull) : 1);
memcpy(newEntry.value + valueLength : %addr(hexNull) : 1);
/end-free
P E
/**
* \brief Add boolean entry
*
* Adds an entry of type boolean.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
* \param Value
*/
P json_putBoolean...
P B export
D PI opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value N const
*
D header DS likeds(tmpl_header) based(jsonPtr)
D prevEntryPtr S *
D prevEntry DS likeds(tmpl_entry)
D based(prevEntryPtr)
D newEntryPtr S *
D newEntry DS likeds(tmpl_entry)
D based(newEntryPtr)
D tmpPtr S *
D tmpKey S 65535A
D keyLength S 10I 0
D tmpValue S N based(newEntry.value)
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
keyLength = length;
tmpKey = %subst(key : 1 : keyLength);
// check if key is in already in the map
newEntryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : keyLength);
if (newEntryPtr = *null); // entry not in json object
// create new entry
newEntryPtr = %alloc(%size(tmpl_entry));
newEntry.type = JSON_TYPE_BOOLEAN;
newEntry.keyLength = keyLength + 1; // +1 for the null byte
newEntry.key = %alloc(keyLength + 1); // +1 for the null byte
newEntry.valueLength = 1;
newEntry.value = %alloc(1);
newEntry.next = *null;
newEntry.prev = *null;
// update header
header.size += 1;
if (header.firstEntry = *null);
header.firstEntry = newEntryPtr;
else;
prevEntryPtr = header.lastEntry;
prevEntry.next = newEntryPtr;
newEntry.prev = prevEntryPtr;
endif;
header.lastEntry = newEntryPtr;
else;
// entry needs to be resized
newEntry.type = JSON_TYPE_BOOLEAN;
newEntry.keyLength = keyLength + 1;
newEntry.key = %realloc(newEntry.key : keyLength + 1);
newEntry.valueLength = 1;
// dispose/dealloc old value
disposeEntryValue(newEntryPtr);
endif;
// copy key/value to the list entry
memcpy(newEntry.key : %addr(tmpKey) : keyLength);
tmpValue = value;
// set null to the last byte
memcpy(newEntry.key + keyLength : %addr(hexNull) : 1);
/end-free
P E
/**
* \brief Add integer entry
*
* Adds an entry of type integer.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
* \param Value
*/
P json_putInt...
P B export
D PI opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value 10I 0 const
*
D header DS likeds(tmpl_header) based(jsonPtr)
D prevEntryPtr S *
D prevEntry DS likeds(tmpl_entry)
D based(prevEntryPtr)
D newEntryPtr S *
D newEntry DS likeds(tmpl_entry)
D based(newEntryPtr)
D tmpPtr S *
D tmpKey S 65535A
D keyLength S 10I 0
D tmpValue S 10I 0 based(newEntry.value)
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
keyLength = length;
tmpKey = %subst(key : 1 : keyLength);
// check if key is in already in the map
newEntryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : keyLength);
if (newEntryPtr = *null); // entry not in json object
// create new entry
newEntryPtr = %alloc(%size(tmpl_entry));
newEntry.type = JSON_TYPE_INT;
newEntry.keyLength = keyLength + 1; // +1 for the null byte
newEntry.key = %alloc(keyLength + 1); // +1 for the null byte
newEntry.valueLength = %size(tmpValue);
newEntry.value = %alloc(%size(tmpValue));
newEntry.next = *null;
newEntry.prev = *null;
// update header
header.size += 1;
if (header.firstEntry = *null);
header.firstEntry = newEntryPtr;
else;
prevEntryPtr = header.lastEntry;
prevEntry.next = newEntryPtr;
newEntry.prev = prevEntryPtr;
endif;
header.lastEntry = newEntryPtr;
else;
// entry needs to be resized
newEntry.type = JSON_TYPE_INT;
newEntry.keyLength = keyLength + 1;
newEntry.key = %realloc(newEntry.key : keyLength + 1);
newEntry.valueLength = %size(tmpValue);
// dispose/dealloc old value
disposeEntryValue(newEntryPtr);
endif;
// copy value to the list entry
memcpy(newEntry.key : %addr(tmpKey) : keyLength);
tmpValue = value;
// set null to the last byte
memcpy(newEntry.key + keyLength : %addr(hexNull) : 1);
/end-free
P E
/**
* \brief Add long entry
*
* Adds an entry of type long.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
* \param Value
*/
P json_putLong...
P B export
D PI opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value 20I 0 const
*
D header DS likeds(tmpl_header) based(jsonPtr)
D prevEntryPtr S *
D prevEntry DS likeds(tmpl_entry)
D based(prevEntryPtr)
D newEntryPtr S *
D newEntry DS likeds(tmpl_entry)
D based(newEntryPtr)
D tmpPtr S *
D tmpKey S 65535A
D keyLength S 10I 0
D tmpValue S 20I 0 based(newEntry.value)
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
keyLength = length;
tmpKey = %subst(key : 1 : keyLength);
// check if key is in already in the map
newEntryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : keyLength);
if (newEntryPtr = *null); // entry not in json object
// create new entry
newEntryPtr = %alloc(%size(tmpl_entry));
newEntry.type = JSON_TYPE_LONG;
newEntry.keyLength = keyLength + 1; // +1 for the null byte
newEntry.key = %alloc(keyLength + 1); // +1 for the null byte
newEntry.valueLength = %size(tmpValue);
newEntry.value = %alloc(%size(tmpValue));
newEntry.next = *null;
newEntry.prev = *null;
// update header
header.size += 1;
if (header.firstEntry = *null);
header.firstEntry = newEntryPtr;
else;
prevEntryPtr = header.lastEntry;
prevEntry.next = newEntryPtr;
newEntry.prev = prevEntryPtr;
endif;
header.lastEntry = newEntryPtr;
else;
// entry needs to be resized
newEntry.type = JSON_TYPE_LONG;
newEntry.keyLength = keyLength + 1;
newEntry.key = %realloc(newEntry.key : keyLength + 1);
newEntry.valueLength = %size(tmpValue);
// dispose/dealloc old value
disposeEntryValue(newEntryPtr);
endif;
// copy value to the list entry
memcpy(newEntry.key : %addr(tmpKey) : keyLength);
tmpValue = value;
// set null to the last byte
memcpy(newEntry.key + keyLength : %addr(hexNull) : 1);
/end-free
P E
/**
* \brief Add double entry
*
* Adds an entry of type double.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
* \param Value
*/
P json_putDouble...
P B export
D PI opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value 8F const
*
D header DS likeds(tmpl_header) based(jsonPtr)
D prevEntryPtr S *
D prevEntry DS likeds(tmpl_entry)
D based(prevEntryPtr)
D newEntryPtr S *
D newEntry DS likeds(tmpl_entry)
D based(newEntryPtr)
D tmpPtr S *
D tmpKey S 65535A
D keyLength S 10I 0
D tmpValue S 8F based(newEntry.value)
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
keyLength = length;
tmpKey = %subst(key : 1 : keyLength);
// check if key is in already in the map
newEntryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : keyLength);
if (newEntryPtr = *null); // entry not in json object
// create new entry
newEntryPtr = %alloc(%size(tmpl_entry));
newEntry.type = JSON_TYPE_DOUBLE;
newEntry.keyLength = keyLength + 1; // +1 for the null byte
newEntry.key = %alloc(keyLength + 1); // +1 for the null byte
newEntry.valueLength = %size(tmpValue);
newEntry.value = %alloc(%size(tmpValue));
newEntry.next = *null;
newEntry.prev = *null;
// update header
header.size += 1;
if (header.firstEntry = *null);
header.firstEntry = newEntryPtr;
else;
prevEntryPtr = header.lastEntry;
prevEntry.next = newEntryPtr;
newEntry.prev = prevEntryPtr;
endif;
header.lastEntry = newEntryPtr;
else;
// entry needs to be resized
newEntry.type = JSON_TYPE_DOUBLE;
newEntry.keyLength = keyLength + 1;
newEntry.key = %realloc(newEntry.key : keyLength + 1);
newEntry.valueLength = %size(tmpValue);
// dispose/dealloc old value
disposeEntryValue(newEntryPtr);
endif;
// copy value to the list entry
memcpy(newEntry.key : %addr(tmpKey) : keyLength);
tmpValue = value;
// set null to the last byte
memcpy(newEntry.key + keyLength : %addr(hexNull) : 1);
/end-free
P E
/**
* \brief Add array entry
*
* Adds an entry of type array.
*
* \author Mihael Schmidt
* \date 19.04.2008
*
* \param Pointer to the JSON object
* \param Key
* \param Array
*/
P json_putArray...
P B export
D PI opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value * const
*
D header DS likeds(tmpl_header) based(jsonPtr)
D prevEntryPtr S *
D prevEntry DS likeds(tmpl_entry)
D based(prevEntryPtr)
D newEntryPtr S *
D newEntry DS likeds(tmpl_entry)
D based(newEntryPtr)
D tmpKey S 65535A
D keyLength S 10I 0
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
keyLength = length;
tmpKey = %subst(key : 1 : keyLength);
// check if key is in already in the map
newEntryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : keyLength);
if (newEntryPtr = *null); // entry not in json object
// create new entry
newEntryPtr = %alloc(%size(tmpl_entry));
newEntry.type = JSON_TYPE_ARRAY;
newEntry.keyLength = keyLength + 1; // +1 for the null byte
newEntry.key = %alloc(keyLength + 1); // +1 for the null byte
newEntry.valueLength = 0;
newEntry.value = *null;
newEntry.next = *null;
newEntry.prev = *null;
// update header
header.size += 1;
if (header.firstEntry = *null);
header.firstEntry = newEntryPtr;
else;
prevEntryPtr = header.lastEntry;
prevEntry.next = newEntryPtr;
newEntry.prev = prevEntryPtr;
endif;
header.lastEntry = newEntryPtr;
else;
// entry needs to be resized
newEntry.type = JSON_TYPE_ARRAY;
newEntry.keyLength = keyLength + 1;
newEntry.key = %realloc(newEntry.key : keyLength + 1);
newEntry.valueLength = 0;
// dispose/dealloc old value
disposeEntryValue(newEntryPtr);
endif;
// copy key and value to entry
memcpy(newEntry.key : %addr(tmpKey) : keyLength);
newEntry.value = value;
// set null to the last byte
memcpy(newEntry.key + keyLength : %addr(hexNull) : 1);
/end-free
P E
/**
* \brief Get entry
*
* Gets the value of entry in the JSON object as a string.
*
*
*
* The return value is a pointer to a null terminated string so that it
* can be easily processed with the %str BIF.
*
*
*
* The memory for the return value was allocated will be managed by
* the JSON object and will be disposed with the dispose
* procedure. The calling program does not need to deallocate the
* the memory by itself.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
*
* \return Pointer to a null terminated string or *null if JSON object
* does not contain the passed key
*/
P json_get B export
D PI * opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D header DS likeds(tmpl_header) based(jsonPtr)
D entryPtr S *
D entry DS likeds(tmpl_entry) based(entryPtr)
D retVal S * inz(*null)
*
D tmpPtr S *
D tmpDs DS based(tmpPtr)
D tmpBoolean N overlay(tmpDs)
D tmpInt 10I 0 overlay(tmpDs)
D tmpLong 20I 0 overlay(tmpDs)
D tmpDouble 8F overlay(tmpDs)
D tmpString S 310A
D tmpLength S 10I 0
D hex_null S 1A inz(x'00')
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
entryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : length);
if (entryPtr <> *null);
select;
when (entry.type = JSON_TYPE_STRING);
retVal = %alloc(entry.valueLength + 1); // + 1 byte for the null value
// +1 because the null byte was already added to the string during putString
memcpy(retVal : entry.value : entry.valueLength + 1);
when (entry.type = JSON_TYPE_INT);
tmpPtr = entry.value;
tmpString = %char(tmpInt);
tmpLength = %len(%trimr(tmpString));
retVal = %alloc(tmpLength);
memcpy(retVal : %addr(tmpString) : tmpLength);
memcpy(retVal + tmplength : %addr(hex_null) : 1);
when (entry.type = JSON_TYPE_LONG);
tmpPtr = entry.value;
tmpString = %char(tmpLong);
tmpLength = %len(%trimr(tmpString));
retVal = %alloc(tmpLength);
memcpy(retVal : %addr(tmpString) : tmpLength);
memcpy(retVal + tmplength : %addr(hex_null) : 1);
when (entry.type = JSON_TYPE_DOUBLE);
tmpPtr = entry.value;
tmpString = %char(tmpDouble);
tmpLength = %len(%trimr(tmpString));
retVal = %alloc(tmpLength);
memcpy(retVal : %addr(tmpString) : tmpLength);
memcpy(retVal + tmplength : %addr(hex_null) : 1);
when (entry.type = JSON_TYPE_BOOLEAN);
tmpPtr = entry.value;
retVal = %alloc(%size(tmpBoolean));
memcpy(retVal : %addr(tmpDs) : %size(tmpBoolean));
memcpy(retVal + 1 : %addr(hex_null) : 1);
when (entry.type = JSON_TYPE_ARRAY);
retVal = jsona_toString(entry.value);
when (entry.type = JSON_TYPE_OBJECT);
retVal = json_toString(entry.value);
endsl;
endif;
// register this pointer to the dispose list so that the memory will be managed
if (retVal <> *null);
list_add(header.disposeList : retVal : 16);
endif;
return retVal;
/end-free
P E
/**
* \brief Get string entry
*
* Returns a pointer to the value of the entry for the passed key.
* The value is null terminated and can be processed with the %str BIF.
*
*
*
* If the entry is not of type string an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
*
* \return Pointer to a null-terminated string
*/
P json_getString B export
D PI * opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D header DS likeds(tmpl_header) based(jsonPtr)
D entryPtr S *
D entry DS likeds(tmpl_entry) based(entryPtr)
D retVal S * inz(*null)
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
entryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : length);
if (entryPtr <> *null);
if (entry.type = JSON_TYPE_STRING);
retVal = entry.value;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
endif;
return retVal;
/end-free
P E
/**
* \brief Get boolean entry
*
* Returns the boolean value of the entry.
*
*
*
* If the entry is not of type boolean an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
*
* \return Boolean value of the entry
*/
P json_getBoolean...
P B export
D PI N opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D header DS likeds(tmpl_header) based(jsonPtr)
D entryPtr S *
D entry DS likeds(tmpl_entry) based(entryPtr)
D value S N based(entry.value)
D retVal S N
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
entryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : length);
if (entryPtr <> *null);
if (entry.type = JSON_TYPE_BOOLEAN);
retVal = value;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
endif;
return retVal;
/end-free
P E
/**
* \brief Get integer entry
*
* Returns the integer value of the entry.
*
*
*
* If the entry is not of type integer an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
*
* \return Integer value of the entry
*/
P json_getInt...
P B export
D PI 10I 0 opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D header DS likeds(tmpl_header) based(jsonPtr)
D entryPtr S *
D entry DS likeds(tmpl_entry) based(entryPtr)
D valueInt S 10I 0 based(entry.value)
D valueLong S 20I 0 based(entry.value)
D valueDouble S 8F based(entry.value)
D retVal S 10I 0
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
entryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : length);
if (entryPtr <> *null);
if (entry.type = JSON_TYPE_INT);
retVal = valueInt;
elseif (entry.type = JSON_TYPE_LONG);
monitor;
retVal = valueLong;
on-error *all;
sendEscapeMessage(MSG_TYPE_CAST_EXCEPTION);
endmon;
elseif (entry.type = JSON_TYPE_DOUBLE);
monitor;
retVal = %int(valueDouble);
on-error *all;
sendEscapeMessage(MSG_TYPE_CAST_EXCEPTION);
endmon;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
endif;
return retVal;
/end-free
P E
/**
* \brief Get long entry
*
* Returns the long value of the entry.
*
*
*
* If the entry is not of type long an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
*
* \return Long value of the entry
*/
P json_getLong...
P B export
D PI 20I 0 opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D header DS likeds(tmpl_header) based(jsonPtr)
D entryPtr S *
D entry DS likeds(tmpl_entry) based(entryPtr)
D valueInt S 10I 0 based(entry.value)
D valueLong S 20I 0 based(entry.value)
D valueDouble S 8F based(entry.value)
D retVal S 20I 0
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
entryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : length);
if (entryPtr <> *null);
if (entry.type = JSON_TYPE_LONG);
retVal = valueLong;
elseif (entry.type = JSON_TYPE_INT);
retVal = valueInt;
elseif (entry.type = JSON_TYPE_DOUBLE);
monitor;
retVal = %int(valueDouble);
on-error *all;
sendEscapeMessage(MSG_TYPE_CAST_EXCEPTION);
endmon;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
endif;
return retVal;
/end-free
P E
/**
* \brief Get double entry
*
* Returns the double value of the entry.
*
*
*
* If the entry is not of type double an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
*
* \return Double value of the entry
*/
P json_getDouble...
P B export
D PI 8F opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D header DS likeds(tmpl_header) based(jsonPtr)
D entryPtr S *
D entry DS likeds(tmpl_entry) based(entryPtr)
D valueInt S 10I 0 based(entry.value)
D valueLong S 20I 0 based(entry.value)
D valueDouble S 8F based(entry.value)
D retVal S 8F
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
entryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : length);
if (entryPtr <> *null);
if (entry.type = JSON_TYPE_DOUBLE);
retVal = valueDouble;
elseif (entry.type = JSON_TYPE_INT);
retVal = %float(valueInt);
elseif (entry.type = JSON_TYPE_LONG);
monitor;
retVal = %float(valueLong);
on-error *all;
sendEscapeMessage(MSG_TYPE_CAST_EXCEPTION);
endmon;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
endif;
return retVal;
/end-free
P E
/**
* \brief Get array entry
*
* Returns the array value of the entry.
*
*
*
* If the entry is not of type array an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
* \param Key
*
* \return Pointer to the JSON array
*/
P json_getArray...
P B export
D PI * opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D header DS likeds(tmpl_header) based(jsonPtr)
D entryPtr S *
D entry DS likeds(tmpl_entry) based(entryPtr)
D retVal S *
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
entryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : length);
if (entryPtr <> *null);
if (entry.type = JSON_TYPE_ARRAY);
retVal = entry.value;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
endif;
return retVal;
/end-free
P E
/**
* \brief String representation of the JSON object in JSON syntax
*
* Creates a null terminated string representation of the JSON object in
* JSON syntax.
*
*
*
* For entries of type string double quotes and backslashes will be escaped
* (" => \" and \ => \\).
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
*/
P json_toString B export
D PI *
D jsonPtr * const
D pOutputFormat...
D 10I 0 const options(*nopass)
D pPrettyPrintFormat...
D likeds(json_prettyPrintFormat)
D const options(*nopass)
D pIndentationLevel...
D 10I 0 options(*nopass)
*
D outputFormat S 10I 0
D prettyPrintOption...
D S N inz(*off)
D prettyPrintFormat...
D DS likeds(json_prettyPrintFormat) inz
D indentationLevel...
D S 10I 0 inz(0)
*
D l_chars DS likeds(tmpl_chars) inz
*
D json_string_ptr...
D S *
D json_string_length...
D S 10I 0
D tokenList S *
*
D tmpDs DS based(entry.value)
D tmpBoolean N overlay(tmpDs)
D tmpInt 10I 0 overlay(tmpDs)
D tmpLong 20I 0 overlay(tmpDs)
D tmpDouble 8F overlay(tmpDs)
D tmpArray * overlay(tmpDs)
D tmpString S 310A
D tmpLength S 10I 0
D hex_null S 1A inz(x'00')
D newline S 2A inz(x'0D25')
*
D header DS likeds(tmpl_header) based(jsonPtr)
D entryPtr S *
D entry DS likeds(tmpl_entry) based(entryPtr)
*
D ptr S *
D x S 10I 0
/free
isJSONImpl(jsonPtr);
if (%parms() = 2);
outputFormat = pOutputFormat;
prettyPrintFormat.useTabs = *off;
prettyPrintFormat.numberWhitespace = 4;
prettyPrintFormat.breakAfterElement = *on;
prettyPrintFormat.breakAfterObjectBrace = *on;
prettyPrintFormat.breakBeforeArrayBrace = *on;
prettyPrintFormat.breakAfterArrayBrace = *on;
elseif (%parms() = 3);
outputFormat = pOutputFormat;
prettyPrintFormat = pPrettyPrintFormat;
elseif (%parms() = 4);
outputFormat = pOutputFormat;
prettyPrintFormat = pPrettyPrintFormat;
indentationLevel = pIndentationLevel;
endif;
if (outputFormat = JSON_OUTPUT_PRETTY_PRINT);
prettyPrintOption = *on;
endif;
exsr init;
// initialisierung
// - anfangszeichen schreiben
// - tokenlist initialisieren
tokenList = list_create();
list_add(tokenList : %addr(l_chars.l_brace):%size(l_chars.size_l_brace));
if (prettyPrintOption);
if (prettyPrintFormat.breakAfterObjectBrace);
indentationLevel += 1;
list_add(tokenList : %addr(newline) : %size(newline));
endif;
endif;
// einträge verarbeiten
entryPtr = header.firstEntry;
dow (entryPtr <> *null);
if (prettyPrintOption);
prettyPrint(tokenList : prettyPrintFormat : indentationLevel);
endif;
// add key as token to token list
list_add(tokenList : %addr(l_chars.d_quote) : l_chars.size_d_quote);
list_add(tokenList : entry.key : entry.keyLength -1);
list_add(tokenList : %addr(l_chars.d_quote) : l_chars.size_d_quote);
// add key/value separator
list_add(tokenList : %addr(l_chars.colon) : l_chars.size_colon);
select;
when (entry.type = JSON_TYPE_STRING);
list_add(tokenList : %addr(l_chars.d_quote):l_chars.size_d_quote);
// +1 weil das null byte schon beim hinzufügen des wertes hinzugefügt wurde
list_add(tokenList : entry.value : entry.valueLength + 1);
escapeLastToken(tokenList);
list_add(tokenList : %addr(l_chars.d_quote):l_chars.size_d_quote);
when (entry.type = JSON_TYPE_INT);
tmpString = %char(tmpInt);
tmpLength = %len(%trimr(tmpString));
list_add(tokenList : %addr(tmpString) : tmpLength);
when (entry.type = JSON_TYPE_LONG);
tmpString = %char(tmpLong);
tmpLength = %len(%trimr(tmpString));
list_add(tokenList : %addr(tmpString) : tmpLength);
when (entry.type = JSON_TYPE_DOUBLE);
tmpString = %char(tmpDouble);
tmpLength = %len(%trimr(tmpString));
// JSON Syntax erwartet immer ein . als Trennzeichen (und kein ,)
tmpString = %xlate(',' : '.' : tmpString);
list_add(tokenList : %addr(tmpString) : tmpLength);
when (entry.type = JSON_TYPE_BOOLEAN);
if (tmpBoolean);
list_add(tokenList : %addr(l_chars.true) : l_chars.size_true);
else;
list_add(tokenList : %addr(l_chars.false) : l_chars.size_false);
endif;
when (entry.type = JSON_TYPE_ARRAY);
ptr = jsona_toString(entry.value : outputFormat:prettyPrintFormat:
indentationLevel);
list_add(tokenList : ptr : strlen(ptr));
dealloc(n) ptr;
when (entry.type = JSON_TYPE_OBJECT);
ptr = json_toString(entry.value : outputFormat : prettyPrintFormat:
indentationLevel);
list_add(tokenList : ptr : strlen(ptr));
dealloc(n) ptr;
when (entry.type = JSON_TYPE_NULL);
list_add(tokenList : %addr(l_chars.null_str) :
l_chars.size_null_str);
endsl;
// komma hinzufügen falls es nicht der letzte eintrag ist
if (entryPtr <> header.lastEntry);
list_add(tokenList : %addr(l_chars.comma) : l_chars.size_comma);
if (prettyPrintOption and prettyPrintFormat.breakAfterElement);
list_add(tokenList : %addr(newline) : %size(newline));
endif;
endif;
// nächsten eintrag
entryPtr = entry.next;
enddo;
if (prettyPrintOption);
if (prettyPrintFormat.breakAfterObjectBrace);
list_add(tokenList : %addr(newline) : %size(newline));
indentationLevel -= 1;
endif;
prettyPrint(tokenList : prettyPrintFormat : indentationLevel);
endif;
// endezeichen schreiben falls einträge vorhanden
list_add(tokenList : %addr(l_chars.r_brace) : l_chars.size_r_brace);
// json string länge ermitteln
ptr = list_getNext(tokenList);
dow (ptr <> *null);
json_string_length += strlen(ptr);
ptr = list_getNext(tokenList);
enddo;
// +1 für hex Null
json_string_length += 1;
// speicher für json string reservieren
json_string_ptr = %alloc(json_string_length);
// json string zusammenbauen
ptr = list_getNext(tokenList);
dow (ptr <> *null);
tmpLength = strlen(ptr);
memcpy(json_string_ptr + x : ptr : tmpLength);
x += tmpLength;
ptr = list_getNext(tokenList);
enddo;
// hex Null anhängen
memcpy(json_string_ptr + x : %addr(hexNull) : 1);
// aufräumen
if (tokenList <> *null);
list_dispose(tokenList);
endif;
// register allocated memory at the dispose list
if (json_string_ptr <> *null);
list_add(header.disposeList : json_string_ptr : 16);
endif;
return json_string_ptr;
begsr init;
if (outputFormat = JSON_OUTPUT_COMPACT);
l_chars = chars_compact;
else;
l_chars = chars;
endif;
endsr;
/end-free
P E
/**
* \brief Add null value entry
*
* Adds an entry of type null to the array.
*
* \author Mihael Schmidt
* \date 11.05.2008
*
* \param Pointer to the JSON array
* \param Key
*/
P json_putNull B export
D PI opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D header DS likeds(tmpl_header) based(jsonPtr)
D prevEntryPtr S *
D prevEntry DS likeds(tmpl_entry)
D based(prevEntryPtr)
D newEntryPtr S *
D newEntry DS likeds(tmpl_entry)
D based(newEntryPtr)
D tmpPtr S *
D tmpKey S 65535A
D keyLength S 10I 0
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
keyLength = length;
tmpKey = %subst(key : 1 : keyLength);
// check if key is in already in the map
newEntryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : keyLength);
if (newEntryPtr = *null); // entry not in json object
// create new entry
newEntryPtr = %alloc(%size(tmpl_entry));
newEntry.type = JSON_TYPE_NULL;
newEntry.keyLength = keyLength + 1; // +1 for the null byte
newEntry.key = %alloc(keyLength + 1); // +1 for the null byte
newEntry.valueLength = 0;
newEntry.value = *null;
newEntry.next = *null;
newEntry.prev = *null;
// update header
header.size += 1;
if (header.firstEntry = *null);
header.firstEntry = newEntryPtr;
else;
prevEntryPtr = header.lastEntry;
prevEntry.next = newEntryPtr;
newEntry.prev = prevEntryPtr;
endif;
header.lastEntry = newEntryPtr;
else;
// entry needs to be resized
newEntry.type = JSON_TYPE_NULL;
newEntry.keyLength = keyLength + 1;
newEntry.key = %realloc(newEntry.key : keyLength + 1);
newEntry.valueLength = 0;
// dispose/dealloc old value
disposeEntryValue(newEntryPtr);
endif;
// copy key/value to the list entry
memcpy(newEntry.key : %addr(tmpKey) : keyLength);
// set null to the last byte
memcpy(newEntry.key + keyLength : %addr(hexNull) : 1);
/end-free
P E
/**
* \brief Add JSON object entry
*
* Adds an entry of type object to the array.
*
* \author Mihael Schmidt
* \date 11.05.2008
*
* \param Pointer to the JSON array
* \param Key
* \param Pointer to the JSON object
*/
P json_putObject...
P B export
D PI opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D objPtr * const
*
D header DS likeds(tmpl_header) based(jsonPtr)
D prevEntryPtr S *
D prevEntry DS likeds(tmpl_entry)
D based(prevEntryPtr)
D newEntryPtr S *
D newEntry DS likeds(tmpl_entry)
D based(newEntryPtr)
D tmpKey S 65535A
D keyLength S 10I 0
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
keyLength = length;
tmpKey = %subst(key : 1 : keyLength);
// check if key is in already in the map
newEntryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : keyLength);
if (newEntryPtr = *null); // entry not in json object
// create new entry
newEntryPtr = %alloc(%size(tmpl_entry));
newEntry.type = JSON_TYPE_OBJECT;
newEntry.keyLength = keyLength + 1; // +1 for the null byte
newEntry.key = %alloc(keyLength + 1); // +1 for the null byte
newEntry.valueLength = 0;
newEntry.value = *null;
newEntry.next = *null;
newEntry.prev = *null;
// update header
header.size += 1;
if (header.firstEntry = *null);
header.firstEntry = newEntryPtr;
else;
prevEntryPtr = header.lastEntry;
prevEntry.next = newEntryPtr;
newEntry.prev = prevEntryPtr;
endif;
header.lastEntry = newEntryPtr;
else;
// entry needs to be resized
newEntry.type = JSON_TYPE_OBJECT;
newEntry.keyLength = keyLength + 1;
newEntry.key = %realloc(newEntry.key : keyLength + 1);
newEntry.valueLength = 0;
// dispose/dealloc old value
disposeEntryValue(newEntryPtr);
endif;
// copy key and value to entry
memcpy(newEntry.key : %addr(tmpKey) : keyLength);
newEntry.value = objPtr;
// set null to the last byte
memcpy(newEntry.key + keyLength : %addr(hexNull) : 1);
/end-free
P E
/**
* \brief Get object entry
*
* Returns a pointer to the object.
*
*
*
* If the entry is not of type object an escape message will be send.
*
* \author Mihael Schmidt
* \date 11.05.2008
*
* \param Pointer to the JSON array
* \param Index
*
* \return Pointer to the JSON object
*/
P json_getObject...
P B export
D PI * opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D header DS likeds(tmpl_header) based(jsonPtr)
D entryPtr S *
D entry DS likeds(tmpl_entry) based(entryPtr)
D retVal S *
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
entryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : length);
if (entryPtr <> *null);
if (entry.type = JSON_TYPE_OBJECT);
retVal = entry.value;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
endif;
return retVal;
/end-free
P E
/**
* \brief Get entry type
*
* Returns the type of the entry.
*
* \param Pointer to the JSON object
* \param Key
*
* \return Entry type
*/
P json_getEntryType...
P B export
D PI 10I 0 opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D header DS likeds(tmpl_header) based(jsonPtr)
D entry DS likeds(tmpl_entry) based(entryPtr)
D type S 10I 0
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
entryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : length);
if (entryPtr <> *null);
type = entry.type;
else;
sendEscapeMessage(MSG_ENTRY_NOT_FOUND);
endif;
return type;
/end-free
P E
/**
* \brief Check for JSON object
*
* Checks if the passed pointer points to a JSON object.
*
*
*
* If the pointer does not point to a JSON object and escape message will
* be send to the next entry in the call stack.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON object
*/
P isJSONImpl...
P B export
D PI
D jsonPtr * const
*
D header DS likeds(tmpl_header) based(jsonPtr)
/free
monitor;
if (header.id <> JSON_ID);
sendEscapeMessage(MSG_NO_JSON_OBJECT);
endif;
on-error *all;
sendEscapeMessage(MSG_NO_JSON_OBJECT);
endmon;
/end-free
P E
/**
* \brief Send escape message
*
* A wrapper for the i5/OS API QMHSNDPM.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Message id
*/
P sendEscapeMessage...
P B export
D PI
D id 10I 0 const
*
D sendProgramMessage...
D PR extpgm('QMHSNDPM')
D szMsgID 7A const
D szMsgFile 20A const
D szMsgData 6000A const options(*varsize)
D nMsgDataLen 10I 0 const
D szMsgType 10A const
D szCallStkEntry...
D 10A const
D nRelativeCallStkEntry...
D 10I 0 const
D szRtnMsgKey 4A
D error 265A options(*varsize)
*
D msgdata S 512A
D msgkey S 4A
/free
if (id = MSG_NO_JSON_OBJECT);
msgdata = 'The pointer does not point to a JSON object data structure';
elseif (id = MSG_ENTRY_TYPE_MISMATCH);
msgdata = 'The entry type does not match with the expected type.';
elseif (id = MSG_ARRAY_ELEMENT_NOT_FOUND);
msgdata = 'The specified array element was not found in the array.';
elseif (id = MSG_TYPE_CAST_EXCEPTION);
msgdata = 'The specified entry could not be cast to the requested ' +
'type.';
else;
return;
endif;
clear QUSEC;
QUSBPRV = 0;
sendProgramMessage('CPF9898' :
'QCPFMSG *LIBL ' :
%trimr(msgdata) :
%len(%trimr(msgdata)) :
'*ESCAPE ' :
'*PGMBDY' :
0 :
msgkey :
QUSEC);
/end-free
P E
/**
* \brief Get entry by key
*
* Returns a pointer to the entry data structure for the passed key.
*
* \param Pointer to the JSON object
* \param Pointer to the key
* \param Key length
*
* \return Pointer to the entry or *null if no such entry exists in this
* JSON object.
*/
P getJSONEntry B export
D PI *
D jsonPtr * const
D keyPtr * const
D keyLength 10U 0 const
*
D header DS likeds(tmpl_header) based(jsonPtr)
D entryPtr S *
D entry DS likeds(tmpl_entry) based(entryPtr)
D retVal S * inz(*null)
/free
entryPtr = header.firstEntry;
dow (entryPtr <> *null);
if (keyLength = entry.keyLength - 1 and
memcmp(keyPtr : entry.key : keyLength) = 0); // dont include the null
retVal = entryPtr;
leave;
endif;
entryPtr = entry.next;
enddo;
return retVal;
/end-free
P E
/**
* \brief Escape characters
*
* Double quotes and backslashes must be escape in string values to
* comply to the JSON specs.
*
*
*
* The last element of the token list will be checked for characters
* which need to be escaped.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to token list
*/
P escapeLastToken...
P B export
D PI
D tokenList *
*
D ptr S *
D length S 10I 0
D backslash S 1A inz('\')
D newPtr S *
D newLength S 10I 0
D newCurLength S 10I 0
D i S 10I 0
D x S 10I 0
D iPtr S *
D char S 1A based(iPtr)
/free
ptr = list_getLast(tokenList);
length = strlen(ptr);
newLength = length;
// number of character to be escaped
for i = 0 to length - 1;
iPtr = ptr + i;
if (char = '\' or char = '"');
newLength += 1;
endif;
endfor;
// check if there are any characters which need to be escaped
if (newLength <> length);
newPtr = %alloc(newLength);
for i = 0 to length - 1;
iPtr = ptr + i;
if (char = '\' or char = '"');
memcpy(newPtr + newCurLength : ptr + x : i - x);
newCurLength += i - x;
// copy escape character
memcpy(newPtr + newCurLength : %addr(backslash) : 1);
newCurLength += 1;
x = i; // save last position
endif;
endfor;
// copy the rest of the string
memcpy(newPtr + newCurLength : ptr + x : i - x + 1);
newCurLength += i - x;
// replace value in token list
list_removeLast(tokenList);
list_add(tokenList : newPtr : newCurLength);
dealloc(n) newPtr;
endif;
/end-free
P E
/**
* \brief Dealloc entry value
*
* The value of an entry is deallocated. If the entry is of
* type object or array it must be disposed.
*
* \author Mihael Schmidt
* \date 14.05.2008
*
* \param Pointer to an entry
*/
P disposeEntryValue...
P B export
D PI
D entryPtr *
*
D entry DS likeds(tmpl_entry) based(entryPtr)
/free
if (entry.type = JSON_TYPE_ARRAY);
jsona_dispose(entry.value);
elseif (entry.type = JSON_TYPE_OBJECT);
json_dispose(entry.value);
elseif (entry.type = JSON_TYPE_NULL);
// do nothing, entry is already *null
elseif (entry.value <> *null);
dealloc(n) entry.value;
endif;
/end-free
P E
/**
* \brief Send diagnostic message
*
* Sends a diagnostic message to the call stack
* (one level above this one).
*
* \author Mihael Schmidt
* \date 07.03.2009
*
* \param Message
*/
P sendDiagnosticMessage...
P B export
D PI
D message 200A const
*
D sendProgramMessage...
D PR extpgm('QMHSNDPM')
D szMsgID 7A const
D szMsgFile 20A const
D szMsgData 6000A const options(*varsize)
D nMsgDataLen 10I 0 const
D szMsgType 10A const
D szCallStkEntry...
D 10A const
D nRelativeCallStkEntry...
D 10I 0 const
D szRtnMsgKey 4A
D error 265A options(*varsize)
*
D msgdata S 512A
D msgkey S 4A
/free
msgdata = message;
clear QUSEC;
QUSBPRV = 0;
sendProgramMessage(*blank :
*blank :
%trimr(msgdata) :
%len(%trimr(msgdata)) :
'*DIAG' :
'*PGMBDY' :
0 :
msgkey :
QUSEC);
/end-free
P E
P prettyPrint B export
D PI
D tokenList * const
D printFormat const likeds(json_prettyPrintFormat)
D indentationLevel...
D 10I 0 const
*
D indentSpace S 1000A static inz
D indentTab S 1000A static inz(*ALLx'05')
/free
if (printFormat.useTabs);
list_add(tokenList : %addr(indentTab) :
indentationLevel * printFormat.numberWhitespace);
else;
list_add(tokenList : %addr(indentSpace) :
indentationLevel * printFormat.numberWhitespace);
endif;
/end-free
P E
json/json.bnd 100666 2763 0 32000 11526177355 11202 0 ustar 00MSCHMIDT /*
Copyright (c) 2007-2011 Mihael Schmidt
All rights reserved.
This file is part of the JSON service program.
JSON service program is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
JSON service program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*/
STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('JSON 1.3.0')
/*
Module JSON
*/
EXPORT SYMBOL('json_create')
EXPORT SYMBOL('json_dispose')
EXPORT SYMBOL('json_remove')
EXPORT SYMBOL('json_clear')
EXPORT SYMBOL('json_getNext')
EXPORT SYMBOL('json_abortIteration')
EXPORT SYMBOL('json_contains')
EXPORT SYMBOL('json_isEmpty')
EXPORT SYMBOL('json_size')
EXPORT SYMBOL('json_putString')
EXPORT SYMBOL('json_putBoolean')
EXPORT SYMBOL('json_putInt')
EXPORT SYMBOL('json_putLong')
EXPORT SYMBOL('json_putDouble')
EXPORT SYMBOL('json_putArray')
EXPORT SYMBOL('json_get')
EXPORT SYMBOL('json_getString')
EXPORT SYMBOL('json_getBoolean')
EXPORT SYMBOL('json_getInt')
EXPORT SYMBOL('json_getLong')
EXPORT SYMBOL('json_getDouble')
EXPORT SYMBOL('json_getArray')
EXPORT SYMBOL('json_toString')
EXPORT SYMBOL('json_putNull')
EXPORT SYMBOL('json_putObject')
EXPORT SYMBOL('json_getObject')
/*
Moduel JSON Array (JSON_ARR)
*/
EXPORT SYMBOL('jsona_create')
EXPORT SYMBOL('jsona_dispose')
EXPORT SYMBOL('jsona_remove')
EXPORT SYMBOL('jsona_clear')
EXPORT SYMBOL('jsona_putString')
EXPORT SYMBOL('jsona_putBoolean')
EXPORT SYMBOL('jsona_putInt')
EXPORT SYMBOL('jsona_putLong')
EXPORT SYMBOL('jsona_putDouble')
EXPORT SYMBOL('jsona_putArray')
EXPORT SYMBOL('jsona_getString')
EXPORT SYMBOL('jsona_getBoolean')
EXPORT SYMBOL('jsona_getInt')
EXPORT SYMBOL('jsona_getLong')
EXPORT SYMBOL('jsona_getArray')
EXPORT SYMBOL('jsona_toString')
EXPORT SYMBOL('jsona_putNull')
EXPORT SYMBOL('jsona_putObject')
EXPORT SYMBOL('jsona_getObject')
EXPORT SYMBOL('jsona_size')
/*
Module JSON Parser (JSON_PAR)
*/
EXPORT SYMBOL('json_parse')
/*
Module JSON Checker (JSON_CHK)
*/
EXPORT SYMBOL('json_checker_char')
EXPORT SYMBOL('json_checker_done')
/*
Module JSON Checker Utilities (JSON_CUTIL)
*/
EXPORT SYMBOL('json_validate')
EXPORT SYMBOL('json_validateFile')
/*
Forgotten Procedure from JSON Array
*/
EXPORT SYMBOL('jsona_getDouble')
/*
Utilities Procedures from JSON_UTIL
*/
EXPORT SYMBOL('json_util_toFile')
EXPORT SYMBOL('json_util_fromFile')
EXPORT SYMBOL('json_util_getDate')
EXPORT SYMBOL('json_util_putDate')
EXPORT SYMBOL('jsona_util_getDate')
EXPORT SYMBOL('jsona_util_putDate')
EXPORT SYMBOL('json_getEntryType')
EXPORT SYMBOL('jsona_getEntryType')
ENDPGMEXP
STRPGMEXP PGMLVL(*PRV) SIGNATURE('JSON 1.2.2')
/*
Module JSON
*/
EXPORT SYMBOL('json_create')
EXPORT SYMBOL('json_dispose')
EXPORT SYMBOL('json_remove')
EXPORT SYMBOL('json_clear')
EXPORT SYMBOL('json_getNext')
EXPORT SYMBOL('json_abortIteration')
EXPORT SYMBOL('json_contains')
EXPORT SYMBOL('json_isEmpty')
EXPORT SYMBOL('json_size')
EXPORT SYMBOL('json_putString')
EXPORT SYMBOL('json_putBoolean')
EXPORT SYMBOL('json_putInt')
EXPORT SYMBOL('json_putLong')
EXPORT SYMBOL('json_putDouble')
EXPORT SYMBOL('json_putArray')
EXPORT SYMBOL('json_get')
EXPORT SYMBOL('json_getString')
EXPORT SYMBOL('json_getBoolean')
EXPORT SYMBOL('json_getInt')
EXPORT SYMBOL('json_getLong')
EXPORT SYMBOL('json_getDouble')
EXPORT SYMBOL('json_getArray')
EXPORT SYMBOL('json_toString')
EXPORT SYMBOL('json_putNull')
EXPORT SYMBOL('json_putObject')
EXPORT SYMBOL('json_getObject')
/*
Moduel JSON Array (JSON_ARR)
*/
EXPORT SYMBOL('jsona_create')
EXPORT SYMBOL('jsona_dispose')
EXPORT SYMBOL('jsona_remove')
EXPORT SYMBOL('jsona_clear')
EXPORT SYMBOL('jsona_putString')
EXPORT SYMBOL('jsona_putBoolean')
EXPORT SYMBOL('jsona_putInt')
EXPORT SYMBOL('jsona_putLong')
EXPORT SYMBOL('jsona_putDouble')
EXPORT SYMBOL('jsona_putArray')
EXPORT SYMBOL('jsona_getString')
EXPORT SYMBOL('jsona_getBoolean')
EXPORT SYMBOL('jsona_getInt')
EXPORT SYMBOL('jsona_getLong')
EXPORT SYMBOL('jsona_getArray')
EXPORT SYMBOL('jsona_toString')
EXPORT SYMBOL('jsona_putNull')
EXPORT SYMBOL('jsona_putObject')
EXPORT SYMBOL('jsona_getObject')
EXPORT SYMBOL('jsona_size')
/*
Module JSON Parser (JSON_PAR)
*/
EXPORT SYMBOL('json_parse')
/*
Module JSON Checker (JSON_CHK)
*/
EXPORT SYMBOL('json_checker_char')
EXPORT SYMBOL('json_checker_done')
/*
Module JSON Checker Utilities (JSON_CUTIL)
*/
EXPORT SYMBOL('json_validate')
EXPORT SYMBOL('json_validateFile')
/*
Forgotten Procedure from JSON Array
*/
EXPORT SYMBOL('jsona_getDouble')
ENDPGMEXP
STRPGMEXP PGMLVL(*PRV) SIGNATURE('JSON 1.2.1')
/*
Module JSON
*/
EXPORT SYMBOL('json_create')
EXPORT SYMBOL('json_dispose')
EXPORT SYMBOL('json_remove')
EXPORT SYMBOL('json_clear')
EXPORT SYMBOL('json_getNext')
EXPORT SYMBOL('json_abortIteration')
EXPORT SYMBOL('json_contains')
EXPORT SYMBOL('json_isEmpty')
EXPORT SYMBOL('json_size')
EXPORT SYMBOL('json_putString')
EXPORT SYMBOL('json_putBoolean')
EXPORT SYMBOL('json_putInt')
EXPORT SYMBOL('json_putLong')
EXPORT SYMBOL('json_putDouble')
EXPORT SYMBOL('json_putArray')
EXPORT SYMBOL('json_get')
EXPORT SYMBOL('json_getString')
EXPORT SYMBOL('json_getBoolean')
EXPORT SYMBOL('json_getInt')
EXPORT SYMBOL('json_getLong')
EXPORT SYMBOL('json_getDouble')
EXPORT SYMBOL('json_getArray')
EXPORT SYMBOL('json_toString')
EXPORT SYMBOL('json_putNull')
EXPORT SYMBOL('json_putObject')
EXPORT SYMBOL('json_getObject')
/*
Moduel JSON Array (JSON_ARR)
*/
EXPORT SYMBOL('jsona_create')
EXPORT SYMBOL('jsona_dispose')
EXPORT SYMBOL('jsona_remove')
EXPORT SYMBOL('jsona_clear')
EXPORT SYMBOL('jsona_putString')
EXPORT SYMBOL('jsona_putBoolean')
EXPORT SYMBOL('jsona_putInt')
EXPORT SYMBOL('jsona_putLong')
EXPORT SYMBOL('jsona_putDouble')
EXPORT SYMBOL('jsona_putArray')
EXPORT SYMBOL('jsona_getString')
EXPORT SYMBOL('jsona_getBoolean')
EXPORT SYMBOL('jsona_getInt')
EXPORT SYMBOL('jsona_getLong')
EXPORT SYMBOL('jsona_getArray')
EXPORT SYMBOL('jsona_toString')
EXPORT SYMBOL('jsona_putNull')
EXPORT SYMBOL('jsona_putObject')
EXPORT SYMBOL('jsona_getObject')
EXPORT SYMBOL('jsona_size')
/*
Module JSON Parser (JSON_PAR)
*/
EXPORT SYMBOL('json_parse')
/*
Module JSON Checker (JSON_CHK)
*/
EXPORT SYMBOL('json_checker_char')
EXPORT SYMBOL('json_checker_done')
/*
Module JSON Checker Utilities (JSON_CUTIL)
*/
EXPORT SYMBOL('json_validate')
EXPORT SYMBOL('json_validateFile')
/*
Forgotten Procedure from JSON Array
*/
EXPORT SYMBOL('jsona_getDouble')
ENDPGMEXP
STRPGMEXP PGMLVL(*PRV) SIGNATURE('JSON 1.2.0')
/*
Module JSON
*/
EXPORT SYMBOL('json_create')
EXPORT SYMBOL('json_dispose')
EXPORT SYMBOL('json_remove')
EXPORT SYMBOL('json_clear')
EXPORT SYMBOL('json_getNext')
EXPORT SYMBOL('json_abortIteration')
EXPORT SYMBOL('json_contains')
EXPORT SYMBOL('json_isEmpty')
EXPORT SYMBOL('json_size')
EXPORT SYMBOL('json_putString')
EXPORT SYMBOL('json_putBoolean')
EXPORT SYMBOL('json_putInt')
EXPORT SYMBOL('json_putLong')
EXPORT SYMBOL('json_putDouble')
EXPORT SYMBOL('json_putArray')
EXPORT SYMBOL('json_get')
EXPORT SYMBOL('json_getString')
EXPORT SYMBOL('json_getBoolean')
EXPORT SYMBOL('json_getInt')
EXPORT SYMBOL('json_getLong')
EXPORT SYMBOL('json_getDouble')
EXPORT SYMBOL('json_getArray')
EXPORT SYMBOL('json_toString')
EXPORT SYMBOL('json_putNull')
EXPORT SYMBOL('json_putObject')
EXPORT SYMBOL('json_getObject')
/*
Moduel JSON Array (JSON_ARR)
*/
EXPORT SYMBOL('jsona_create')
EXPORT SYMBOL('jsona_dispose')
EXPORT SYMBOL('jsona_remove')
EXPORT SYMBOL('jsona_clear')
EXPORT SYMBOL('jsona_putString')
EXPORT SYMBOL('jsona_putBoolean')
EXPORT SYMBOL('jsona_putInt')
EXPORT SYMBOL('jsona_putLong')
EXPORT SYMBOL('jsona_putDouble')
EXPORT SYMBOL('jsona_putArray')
EXPORT SYMBOL('jsona_getString')
EXPORT SYMBOL('jsona_getBoolean')
EXPORT SYMBOL('jsona_getInt')
EXPORT SYMBOL('jsona_getLong')
EXPORT SYMBOL('jsona_getArray')
EXPORT SYMBOL('jsona_toString')
EXPORT SYMBOL('jsona_putNull')
EXPORT SYMBOL('jsona_putObject')
EXPORT SYMBOL('jsona_getObject')
EXPORT SYMBOL('jsona_size')
/*
Module JSON Parser (JSON_PAR)
*/
EXPORT SYMBOL('json_parse')
/*
Module JSON Checker (JSON_CHK)
*/
EXPORT SYMBOL('json_checker_char')
EXPORT SYMBOL('json_checker_done')
/*
Module JSON Checker Utilities (JSON_CUTIL)
*/
EXPORT SYMBOL('json_validate')
EXPORT SYMBOL('json_validateFile')
ENDPGMEXP
STRPGMEXP PGMLVL(*PRV) SIGNATURE('JSON 1.1.0')
/*
Module JSON
*/
EXPORT SYMBOL('json_create')
EXPORT SYMBOL('json_dispose')
EXPORT SYMBOL('json_remove')
EXPORT SYMBOL('json_clear')
EXPORT SYMBOL('json_getNext')
EXPORT SYMBOL('json_abortIteration')
EXPORT SYMBOL('json_contains')
EXPORT SYMBOL('json_isEmpty')
EXPORT SYMBOL('json_size')
EXPORT SYMBOL('json_putString')
EXPORT SYMBOL('json_putBoolean')
EXPORT SYMBOL('json_putInt')
EXPORT SYMBOL('json_putLong')
EXPORT SYMBOL('json_putDouble')
EXPORT SYMBOL('json_putArray')
EXPORT SYMBOL('json_get')
EXPORT SYMBOL('json_getString')
EXPORT SYMBOL('json_getBoolean')
EXPORT SYMBOL('json_getInt')
EXPORT SYMBOL('json_getLong')
EXPORT SYMBOL('json_getArray')
EXPORT SYMBOL('json_toString')
EXPORT SYMBOL('json_putNull')
EXPORT SYMBOL('json_putObject')
EXPORT SYMBOL('json_getObject')
EXPORT SYMBOL('json_private_sendEscapeMessage')
EXPORT SYMBOL('json_private_escapeLastToken')
/*
Moduel JSON Array
*/
EXPORT SYMBOL('jsona_create')
EXPORT SYMBOL('jsona_dispose')
EXPORT SYMBOL('jsona_remove')
EXPORT SYMBOL('jsona_clear')
EXPORT SYMBOL('jsona_putString')
EXPORT SYMBOL('jsona_putBoolean')
EXPORT SYMBOL('jsona_putInt')
EXPORT SYMBOL('jsona_putLong')
EXPORT SYMBOL('jsona_putDouble')
EXPORT SYMBOL('jsona_putArray')
EXPORT SYMBOL('jsona_getString')
EXPORT SYMBOL('jsona_getBoolean')
EXPORT SYMBOL('jsona_getInt')
EXPORT SYMBOL('jsona_getLong')
EXPORT SYMBOL('jsona_getArray')
EXPORT SYMBOL('jsona_toString')
EXPORT SYMBOL('jsona_putNull')
EXPORT SYMBOL('jsona_putObject')
EXPORT SYMBOL('jsona_getObject')
ENDPGMEXP
STRPGMEXP PGMLVL(*PRV) SIGNATURE('JSON 1.0.0')
/*
Module JSON
*/
EXPORT SYMBOL('json_create')
EXPORT SYMBOL('json_dispose')
EXPORT SYMBOL('json_remove')
EXPORT SYMBOL('json_clear')
EXPORT SYMBOL('json_getNext')
EXPORT SYMBOL('json_abortIteration')
EXPORT SYMBOL('json_contains')
EXPORT SYMBOL('json_isEmpty')
EXPORT SYMBOL('json_size')
EXPORT SYMBOL('json_putString')
EXPORT SYMBOL('json_putBoolean')
EXPORT SYMBOL('json_putInt')
EXPORT SYMBOL('json_putLong')
EXPORT SYMBOL('json_putDouble')
EXPORT SYMBOL('json_putArray')
EXPORT SYMBOL('json_get')
EXPORT SYMBOL('json_getString')
EXPORT SYMBOL('json_getBoolean')
EXPORT SYMBOL('json_getInt')
EXPORT SYMBOL('json_getLong')
EXPORT SYMBOL('json_getArray')
EXPORT SYMBOL('json_toString')
EXPORT SYMBOL('json_private_sendEscapeMessage')
EXPORT SYMBOL('json_private_escapeLastToken')
/*
Moduel JSON Array
*/
EXPORT SYMBOL('jsona_create')
EXPORT SYMBOL('jsona_dispose')
EXPORT SYMBOL('jsona_remove')
EXPORT SYMBOL('jsona_clear')
EXPORT SYMBOL('jsona_putString')
EXPORT SYMBOL('jsona_putBoolean')
EXPORT SYMBOL('jsona_putInt')
EXPORT SYMBOL('jsona_putLong')
EXPORT SYMBOL('jsona_putDouble')
EXPORT SYMBOL('jsona_putArray')
EXPORT SYMBOL('jsona_getString')
EXPORT SYMBOL('jsona_getBoolean')
EXPORT SYMBOL('jsona_getInt')
EXPORT SYMBOL('jsona_getLong')
EXPORT SYMBOL('jsona_getArray')
EXPORT SYMBOL('jsona_toString')
ENDPGMEXP
json/json_cutil.rpgle 100666 2763 0 24173 11515400050 12737 0 ustar 00MSCHMIDT /**
* \brief JSON : Checker Utilities
*
* Utility module for validating string for the JSON syntax.
* The strings are converted from the passed or Job ccsid to
* ASCII (ccsid 819). Comments before, inline and after the JSON
* string are not supported.
*
* \author Mihael Schmidt
* \date 2009-02-28
*
* \link http://www.json.org/JSON_checker/ JSON Checker
*/
*-------------------------------------------------------------------------
* And thanks to Scott Klement for his excellent tutorials about IFS and
* iconv() at http://www.scottklement.com .
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
* Copyright (c) 2007-2009 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*-------------------------------------------------------------------------
H nomain
H bnddir('QC2LE')
H copyright('Copyright (c) 2007-2009 Mihael Schmidt. All rights reserved.')
*------------------------------------------------------------------------
* Prototypes
*------------------------------------------------------------------------
/copy 'json_h.rpgle'
/copy 'json_int_h.rpgle'
/copy 'iconv_h.rpgle'
/copy 'ifsio_h.rpgle'
/copy 'libc_h.rpgle'
/copy 'ceeapi_h.rpgle'
*-------------------------------------------------------------------------
* Global Variables
*-------------------------------------------------------------------------
*
* Parameters passed to CEEDOD
*
D cee_descType S 10I 0
D cee_dataType S 10I 0
D cee_descInfo1 S 10I 0
D cee_descInfo2 S 10I 0
D cee_length S 10I 0
*
D true S 10I 0 inz(1)
D false S 10I 0 inz(0)
*------------------------------------------------------------------------
* Procedures
*------------------------------------------------------------------------
/**
* \brief Validate JSON string
*
* Validates the passed JSON string.
*
* \author Mihael Schmidt
*
* \param JSON string
* \param CCSID from the source string (default: 0 = Job CCSID)
*
* \return *on = valid JSON string
* *off = invalid JSON string
*/
P json_validate B export
D PI N opdesc
D string 65535A const options(*varsize)
D ccsid 10I 0 const options(*nopass)
*
D iconv_table DS likeds(iconv_t)
D json_string_ptr...
D S *
D json_string S 65535A
D json_string_length...
D S 10U 0
D json_checker_ptr...
D S *
D json_checker DS likeds(tmpl_json_checker)
D based(json_checker_ptr)
*
D conv_ds DS
D unsInt 10U 0 inz(0)
D char 1A overlay(unsInt : 4)
*
D tmpLength S 10U 0
D i S 10I 0
D valid S N inz(*on)
/free
cee_getOpDescInfo(1 : cee_descType : cee_dataType : cee_descInfo1 :
cee_descInfo2 : cee_length : *omit);
json_string = %trim(%subst(string : 1 : cee_length)) + x'00';
json_string_ptr = %addr(json_string);
json_string_length = strlen(json_string_ptr);
tmpLength = json_string_length;
if (%parms() = 2);
iconv_from.ccsid = ccsid;
else;
iconv_from.ccsid = 0;
endif;
//
// translate the string from the current job ccsid (or passed ccsid)
// to ascii (819) because the checker only understands ascii
//
iconv_table = iconv_open(iconv_to : iconv_from);
if (iconv_table.return_value <> -1);
if (iconv(iconv_table :
json_string_ptr : tmpLength :
json_string_ptr : tmpLength) <> -1);
// create json checker
json_checker_ptr = json_new_checker(99);
// check string char by char
for i = 1 to json_string_length;
char = %subst(json_string : i : 1);
if (json_checker_char(json_checker_ptr : unsInt) = false);
sendDiagnosticMessage('JSON checker aborted at position ' +
%char(i) + '.');
valid = *off;
leave;
endif;
endfor;
// free memory
if (valid and json_checker_done(json_checker_ptr) = true);
valid = *on;
endif;
else;
sendDiagnosticMessage('Could not translate buffer from ccsid ' +
%char(iconv_from.ccsid) + ' to ccsid ' +
%char(iconv_to.ccsid) + '.');
valid = *off;
endif;
// cleanup
iconv_close(iconv_table);
else;
sendDiagnosticMessage('Could not init iconv.');
valid = *off;
endif;
return valid;
/end-free
P E
/**
* \brief Validate JSON file
*
* Validates the JSON string in the passed file. The file should only
* contain the JSON string. Comments are not supported.
*
* \author Mihael Schmidt
*
* \param IFS file path
* \param CCSID from the source string (default: 0 = Job CCSID)
*
* \return *on = valid JSON string
* *off = invalid JSON string
*/
P json_validateFile...
P B export
D PI N opdesc
D path 65535A const options(*varsize)
D ccsid 10I 0 const options(*nopass)
*
* file stuff
*
D filePath S 65535A
D fd S 10I 0
D dataPtr S *
D data S 1024A inz
D length S 10I 0
*
* translation stuff
*
D iconv_table DS likeds(iconv_t)
D json_string_ptr...
D S *
D json_string S 65535A
D json_checker_ptr...
D S *
D json_checker DS likeds(tmpl_json_checker)
D based(json_checker_ptr)
*
D conv_ds DS
D unsInt 10U 0 inz(0)
D char 1A overlay(unsInt : 4)
*
D tmpLength S 10U 0
D i S 10I 0
D valid S N inz(*on)
/free
cee_getOpDescInfo(1 : cee_descType : cee_dataType : cee_descInfo1 :
cee_descInfo2 : cee_length : *omit);
filePath = %trim(%subst(path : 1 : cee_length)) + x'00';
json_string_ptr = %addr(json_string);
dataPtr = %addr(data);
fd = open(filePath : O_RDONLY + O_TEXTDATA);
if (fd >= 0);
if (%parms() = 2);
iconv_from.ccsid = ccsid;
else;
iconv_from.ccsid = 0;
endif;
// create json checker
json_checker_ptr = json_new_checker(99);
//
// translate the string from the current job ccsid (or passed ccsid)
// to ascii (819) because the checker only understands ascii
//
iconv_table = iconv_open(iconv_to : iconv_from);
if (iconv_table.return_value <> -1);
length = read(fd : dataPtr : %size(data));
dow (length >= 1 and valid);
tmpLength = length;
if (iconv(iconv_table :
dataPtr : tmpLength :
json_string_ptr : tmpLength) <> -1);
// check string char by char
for i = 1 to length;
char = %subst(json_string : i : 1);
if (json_checker_char(json_checker_ptr : unsInt) = false);
sendDiagnosticMessage('JSON checker aborted at position ' +
%char(i) + '.');
valid = *off;
leave;
endif;
endfor;
else;
sendDiagnosticMessage('Could not translate buffer from ccsid ' +
%char(iconv_from.ccsid) + ' to ccsid ' +
%char(iconv_to.ccsid) + '.');
valid = *off;
endif;
length = read(fd : dataPtr : %size(data));
enddo;
else;
sendDiagnosticMessage('Could not init iconv.');
valid = *off;
endif;
// free memory
if (not valid or json_checker_done(json_checker_ptr) = false);
valid = *off;
endif;
// cleanup
iconv_close(iconv_table);
callp close(fd);
else;
sendDiagnosticMessage('Could not open file ' + %trim(filePath) + '.');
valid = *off;
endif;
return valid;
/end-free
P E
json/json_inz.cpp 100666 2763 0 132 11515400052 12017 0 ustar 00MSCHMIDT extern "C" { int json_srvpgm_init(void); }
static int dummyInitVar = json_srvpgm_init();
json/ifsio_h.rpgle 100666 2763 0 160511 11515400044 12226 0 ustar 00MSCHMIDT D/if defined(IFSIO_H)
D/eof
D/endif
D/define IFSIO_H
**********************************************************************
* Some CCSID definitions that I've found useful
**********************************************************************
D CP_MSDOS C 437
D CP_ISO8859_1 C 819
D CP_WINDOWS C 1252
D CP_UTF8 C 1208
D CP_UCS2 C 1200
D CP_CURJOB C 0
**********************************************************************
* Flags for use in open()
*
* More than one can be used -- add them together.
**********************************************************************
* 00000000000000000000000000000001 Reading Only
D O_RDONLY C 1
* 00000000000000000000000000000010 Writing Only
D O_WRONLY C 2
* 00000000000000000000000000000100 Reading & Writing
D O_RDWR C 4
* 00000000000000000000000000001000 Create File if needed
D O_CREAT C 8
* 00000000000000000000000000010000 Exclusively create --
* open will fail if it
* already exists.
D O_EXCL C 16
* 00000000000000000000000000100000 Assign a CCSID to new
* file.
D O_CCSID C 32
* 00000000000000000000000001000000 Truncate file to 0 bytes
D O_TRUNC C 64
* 00000000000000000000000100000000 Append to file
* (write data at end only)
D O_APPEND C 256
* 00000000000000000000010000000000 Synchronous write
D O_SYNC C 1024
* 00000000000000000000100000000000 Sync write, data only
D O_DSYNC C 2048
* 00000000000000000001000000000000 Sync read
D O_RSYNC C 4096
* 00000000000000001000000000000000 No controlling terminal
D O_NOCTTY C 32768
* 00000000000000010000000000000000 Share with readers only
D O_SHARE_RDONLY C 65536
* 00000000000000100000000000000000 Share with writers only
D O_SHARE_WRONLY C 131072
* 00000000000001000000000000000000 Share with read & write
D O_SHARE_RDWR C 262144
* 00000000000010000000000000000000 Share with nobody.
D O_SHARE_NONE C 524288
* 00000000100000000000000000000000 Assign a code page
D O_CODEPAGE C 8388608
* 00000001000000000000000000000000 Open in text-mode
D O_TEXTDATA C 16777216
/if defined(*V5R2M0)
* 00000010000000000000000000000000 Allow text translation
* on newly created file.
* Note: O_TEXT_CREAT requires all of the following flags to work:
* O_CREAT+O_TEXTDATA+(O_CODEPAGE or O_CCSID)
D O_TEXT_CREAT C 33554432
/endif
* 00001000000000000000000000000000 Inherit mode from dir
D O_INHERITMODE C 134217728
* 00100000000000000000000000000000 Large file access
* (for >2GB files)
D O_LARGEFILE C 536870912
**********************************************************************
* Access mode flags for access() and accessx()
*
* F_OK = File Exists
* R_OK = Read Access
* W_OK = Write Access
* X_OK = Execute or Search
**********************************************************************
D F_OK C 0
D R_OK C 4
D W_OK C 2
D X_OK C 1
**********************************************************************
* class of users flags for accessx()
*
* ACC_SELF = Check access based on effective uid/gid
* ACC_INVOKER = Check access based on real uid/gid
* ( this is equvalent to calling access() )
* ACC_OTHERS = Check access of someone not the owner
* ACC_ALL = Check access of all users
**********************************************************************
D ACC_SELF C 0
D ACC_INVOKER C 1
D ACC_OTHERS C 8
D ACC_ALL C 32
**********************************************************************
* Mode Flags.
* basically, the mode parm of open(), creat(), chmod(),etc
* uses 9 least significant bits to determine the
* file's mode. (peoples access rights to the file)
*
* user: owner group other
* access: R W X R W X R W X
* bit: 8 7 6 5 4 3 2 1 0
*
* (This is accomplished by adding the flags below to get the mode)
**********************************************************************
* owner authority
D S_IRUSR C 256
D S_IWUSR C 128
D S_IXUSR C 64
D S_IRWXU C 448
* group authority
D S_IRGRP C 32
D S_IWGRP C 16
D S_IXGRP C 8
D S_IRWXG C 56
* other people
D S_IROTH C 4
D S_IWOTH C 2
D S_IXOTH C 1
D S_IRWXO C 7
* special modes:
* Set effective GID
D S_ISGID C 1024
* Set effective UID
D S_ISUID C 2048
**********************************************************************
* My own special MODE shortcuts for open() (instead of those above)
**********************************************************************
D M_RDONLY C const(292)
D M_RDWR C const(438)
D M_RWX C const(511)
**********************************************************************
* "whence" constants for use with seek(), lseek() and others
**********************************************************************
D SEEK_SET C CONST(0)
D SEEK_CUR C CONST(1)
D SEEK_END C CONST(2)
**********************************************************************
* flags specified in the f_flags element of the ds_statvfs
* data structure used by the statvfs() API
**********************************************************************
D ST_RDONLY...
D C CONST(1)
D ST_NOSUID...
D C CONST(2)
D ST_CASE_SENSITITIVE...
D C CONST(4)
D ST_CHOWN_RESTRICTED...
D C CONST(8)
D ST_THREAD_SAFE...
D C CONST(16)
D ST_DYNAMIC_MOUNT...
D C CONST(32)
D ST_NO_MOUNT_OVER...
D C CONST(64)
D ST_NO_EXPORTS...
D C CONST(128)
D ST_SYNCHRONOUS...
D C CONST(256)
**********************************************************************
* Constants used by pathconf() API
**********************************************************************
D PC_CHOWN_RESTRICTED...
D C 0
D PC_LINK_MAX...
D C 1
D PC_MAX_CANON...
D C 2
D PC_MAX_INPUT...
D C 3
D PC_NAME_MAX...
D C 4
D PC_NO_TRUNC...
D C 5
D PC_PATH_MAX...
D C 6
D PC_PIPE_BUF...
D C 7
D PC_VDISABLE...
D C 8
D PC_THREAD_SAFE...
D C 9
**********************************************************************
* Constants used by sysconf() API
**********************************************************************
D SC_CLK_TCK...
D C 2
D SC_NGROUPS_MAX...
D C 3
D SC_OPEN_MAX...
D C 4
D SC_STREAM_MAX...
D C 5
D SC_CCSID...
D C 10
D SC_PAGE_SIZE...
D C 11
D SC_PAGESIZE...
D C 12
**********************************************************************
* File Information Structure (stat)
* struct stat {
* mode_t st_mode; /* File mode */
* ino_t st_ino; /* File serial number */
* nlink_t st_nlink; /* Number of links */
* unsigned short st_reserved2; /* Reserved @B4A*/
* uid_t st_uid; /* User ID of the owner of file */
* gid_t st_gid; /* Group ID of the group of file */
* off_t st_size; /* For regular files, the file
* size in bytes */
* time_t st_atime; /* Time of last access */
* time_t st_mtime; /* Time of last data modification */
* time_t st_ctime; /* Time of last file status change */
* dev_t st_dev; /* ID of device containing file */
* size_t st_blksize; /* Size of a block of the file */
* unsigned long st_allocsize; /* Allocation size of the file */
* qp0l_objtype_t st_objtype; /* AS/400 object type */
* char st_reserved3; /* Reserved @B4A*/
* unsigned short st_codepage; /* Object data codepage */
* unsigned short st_ccsid; /* Object data ccsid @AAA*/
* dev_t st_rdev; /* Device ID (if character special */
* /* or block special file) @B4A*/
* nlink32_t st_nlink32; /* Number of links-32 bit @B5C*/
* dev64_t st_rdev64; /* Device ID - 64 bit form @B4A*/
* dev64_t st_dev64; /* ID of device containing file - */
* /* 64 bit form. @B4A*/
* char st_reserved1[36]; /* Reserved @B4A*/
* unsigned int st_ino_gen_id; /* File serial number generation id
* };
* @A2A*/
**********************************************************************
D statds DS qualified
D BASED(Template)
D st_mode 10U 0
D st_ino 10U 0
D st_nlink 5U 0
D st_reserved2 5U 0
D st_uid 10U 0
D st_gid 10U 0
D st_size 10I 0
D st_atime 10I 0
D st_mtime 10I 0
D st_ctime 10I 0
D st_dev 10U 0
D st_blksize 10U 0
D st_allocsize 10U 0
D st_objtype 11A
D st_reserved3 1A
D st_codepage 5U 0
D st_ccsid 5U 0
D st_rdev 10U 0
D st_nlink32 10U 0
D st_rdev64 20U 0
D st_dev64 20U 0
D st_reserved1 36A
D st_ino_gen_id 10U 0
**********************************************************************
* File Information Structure, Large File Enabled (stat64)
* struct stat64 { */
* mode_t st_mode; /* File mode */
* ino_t st_ino; /* File serial number */
* uid_t st_uid; /* User ID of the owner of file */
* gid_t st_gid; /* Group ID of the group of fileA2A*/
* off64_t st_size; /* For regular files, the file */
* size in bytes */
* time_t st_atime; /* Time of last access */
* time_t st_mtime; /* Time of last data modification2A*/
* time_t st_ctime; /* Time of last file status changeA*/
* dev_t st_dev; /* ID of device containing file */
* size_t st_blksize; /* Size of a block of the file */
* nlink_t st_nlink; /* Number of links */
* unsigned short st_codepage; /* Object data codepage */
* unsigned long long st_allocsize; /* Allocation size of the file2A*/
* unsigned int st_ino_gen_id; /* File serial number generationAid*/
* */
* qp0l_objtype_t st_objtype; /* AS/400 object type */
* char st_reserved2[5]; /* Reserved @B4A*/
* dev_t st_rdev; /* Device ID (if character specialA*/
* /* or block special file) @B4A*/
* dev64_t st_rdev64; /* Device ID - 64 bit form @B4A*/
* dev64_t st_dev64; /* ID of device containing file@-2A*/
* /* 64 bit form. @B4A*/
* nlink32_t st_nlink32; /* Number of links-32 bit @B5A*/
* char st_reserved1[26]; /* Reserved @B4A @B5C*/
* unsigned short st_ccsid; /* Object data ccsid @AAA*/
* }; */
*
**********************************************************************
D statds64 DS qualified
D BASED(Template)
D st_mode 10U 0
D st_ino 10U 0
D st_uid 10U 0
D st_gid 10U 0
D st_size 20I 0
D st_atime 10I 0
D st_mtime 10I 0
D st_ctime 10I 0
D st_dev 10U 0
D st_blksize 10U 0
D st_nlink 5U 0
D st_codepage 5U 0
D st_allocsize 20U 0
D st_ino_gen_id 10U 0
D st_objtype 11A
D st_reserved2 5A
D st_rdev 10U 0
D st_rdev64 20U 0
D st_dev64 20U 0
D st_nlink32 10U 0
D st_reserved1 26A
D st_ccsid 5U 0
**********************************************************************
* ds_statvfs - data structure to receive file system info
*
* f_bsize = file system block size (in bytes)
* f_frsize = fundamental block size in bytes.
* if this is zero, f_blocks, f_bfree and f_bavail
* are undefined.
* f_blocks = total number of blocks (in f_frsize)
* f_bfree = total free blocks in filesystem (in f_frsize)
* f_bavail = total blocks available to users (in f_frsize)
* f_files = total number of file serial numbers
* f_ffree = total number of unused file serial numbers
* f_favail = number of available file serial numbers to users
* f_fsid = filesystem ID. This will be 4294967295 if it's
* too large for a 10U 0 field. (see f_fsid64)
* f_flag = file system flags (see below)
* f_namemax = max filename length. May be 4294967295 to
* indicate that there is no maximum.
* f_pathmax = max pathname legnth. May be 4294967295 to
* indicate that there is no maximum.
* f_objlinkmax = maximum number of hard-links for objects
* other than directories
* f_dirlinkmax = maximum number of hard-links for directories
* f_fsid64 = filesystem id (in a 64-bit integer)
* f_basetype = null-terminated string containing the file
* system type name. For example, this might
* be "root" or "Network File System (NFS)"
*
* Since f_basetype is null-terminated, you should read it
* in ILE RPG with:
* myString = %str(%addr(ds_statvfs.f_basetype))
**********************************************************************
D ds_statvfs DS qualified
D BASED(Template)
D f_bsize 10U 0
D f_frsize 10U 0
D f_blocks 20U 0
D f_bfree 20U 0
D f_bavail 20U 0
D f_files 10U 0
D f_ffree 10U 0
D f_favail 10U 0
D f_fsid 10U 0
D f_flag 10U 0
D f_namemax 10U 0
D f_pathmax 10U 0
D f_objlinkmax 10I 0
D f_dirlinkmax 10I 0
D f_reserved1 4A
D f_fsid64 20U 0
D f_basetype 80A
**********************************************************************
* Group Information Structure (group)
*
* struct group {
* char *gr_name; /* Group name. */
* gid_t gr_gid; /* Group id. */
* char **gr_mem; /* A null-terminated list of pointers
* to the individual member names. */
* };
*
**********************************************************************
D group DS qualified
D BASED(Template)
D gr_name *
D gr_gid 10U 0
D gr_mem * DIM(256)
**********************************************************************
* User Information Structure (passwd)
*
* (Don't let the name fool you, this structure does not contain
* any password information. Its named after the UNIX file that
* contains all of the user info. That file is "passwd")
*
* struct passwd {
* char *pw_name; /* User name. */
* uid_t pw_uid; /* User ID number. */
* gid_t pw_gid; /* Group ID number. */
* char *pw_dir; /* Initial working directory. */
* char *pw_shell; /* Initial user program. */
* };
*
**********************************************************************
D passwd DS qualified
D BASED(Template)
D pw_name *
D pw_uid 10U 0
D pw_gid 10U 0
D pw_dir *
D pw_shell *
**********************************************************************
* File Time Structure (utimbuf)
*
* struct utimbuf {
* time_t actime; /* access time */
* time_t modtime; /* modification time */
* };
*
**********************************************************************
D utimbuf DS qualified
D BASED(Template)
D actime 10I 0
D modtime 10I 0
**********************************************************************
* Directory Entry Structure (dirent)
*
* struct dirent {
* char d_reserved1[16]; /* Reserved */
* unsigned int d_fileno_gen_id /* File number generation ID @A1C*/
* ino_t d_fileno; /* The file number of the file */
* unsigned int d_reclen; /* Length of this directory entry
* * in bytes */
* int d_reserved3; /* Reserved */
* char d_reserved4[8]; /* Reserved */
* qlg_nls_t d_nlsinfo; /* National Language Information
* * about d_name */
* unsigned int d_namelen; /* Length of the name, in bytes
* * excluding NULL terminator */
* char d_name[_QP0L_DIR_NAME]; /* Name...null terminated */
*
* };
**********************************************************************
D dirent ds qualified
D BASED(Template)
D d_reserv1 16A
D d_fileno_gen_id...
D 10U 0
D d_fileno 10U 0
D d_reclen 10U 0
D d_reserv3 10I 0
D d_reserv4 8A
D d_nlsinfo 12A
D d_nls_ccsid 10I 0 OVERLAY(d_nlsinfo:1)
D d_nls_cntry 2A OVERLAY(d_nlsinfo:5)
D d_nls_lang 3A OVERLAY(d_nlsinfo:7)
D d_namelen 10U 0
D d_name 640A
**********************************************************************
* I/O Vector Structure
*
* struct iovec {
* void *iov_base;
* size_t iov_len;
* }
**********************************************************************
D iovec DS qualified
D BASED(Template)
D iov_base *
D iov_len 10U 0
*--------------------------------------------------------------------
* Determine file accessibility
*
* int access(const char *path, int amode)
*
*--------------------------------------------------------------------
D access PR 10I 0 ExtProc('access')
D Path * Value Options(*string)
D amode 10I 0 Value
*--------------------------------------------------------------------
* Determine file accessibility for a class of users
*
* int accessx(const char *path, int amode, int who);
*
*--------------------------------------------------------------------
/if defined(*V5R2M0)
D accessx PR 10I 0 ExtProc('accessx')
D Path * Value Options(*string)
D amode 10I 0 Value
D who 10I 0 value
/endif
*--------------------------------------------------------------------
* Change Directory
*
* int chdir(const char *path)
*--------------------------------------------------------------------
D chdir PR 10I 0 ExtProc('chdir')
D path * Value Options(*string)
*--------------------------------------------------------------------
* Change file authorizations
*
* int chmod(const char *path, mode_t mode)
*--------------------------------------------------------------------
D chmod PR 10I 0 ExtProc('chmod')
D path * Value options(*string)
D mode 10U 0 Value
*--------------------------------------------------------------------
* Change Owner/Group of File
*
* int chown(const char *path, uid_t owner, gid_t group)
*--------------------------------------------------------------------
D chown PR 10I 0 ExtProc('chown')
D path * Value options(*string)
D owner 10U 0 Value
D group 10U 0 Value
*--------------------------------------------------------------------
* Close a file
*
* int close(int fildes)
*
* Note: Because the same close() API is used for IFS, sockets,
* and pipes, it's conditionally defined here. If it's
* done the same in the sockets & pipe /copy members,
* there will be no conflict.
*--------------------------------------------------------------------
D/if not defined(CLOSE_PROTOTYPE)
D close PR 10I 0 ExtProc('close')
D fildes 10I 0 value
D/define CLOSE_PROTOTYPE
D/endif
*--------------------------------------------------------------------
* Close a directory
*
* int closedir(DIR *dirp)
*--------------------------------------------------------------------
D closedir PR 10I 0 EXTPROC('closedir')
D dirp * VALUE
*--------------------------------------------------------------------
* Create or Rewrite File
*
* int creat(const char *path, mode_t mode)
*
* DEPRECATED: Use open() instead.
*--------------------------------------------------------------------
D creat PR 10I 0 ExtProc('creat')
D path * Value options(*string)
D mode 10U 0 Value
*--------------------------------------------------------------------
* Duplicate open file descriptor
*
* int dup(int fildes)
*--------------------------------------------------------------------
D dup PR 10I 0 ExtProc('dup')
D fildes 10I 0 Value
*--------------------------------------------------------------------
* Duplicate open file descriptor to another descriptor
*
* int dup2(int fildes, int fildes2)
*--------------------------------------------------------------------
D dup2 PR 10I 0 ExtProc('dup2')
D fildes 10I 0 Value
D fildes2 10I 0 Value
*--------------------------------------------------------------------
* Determine file accessibility for a class of users by descriptor
*
* int faccessx(int filedes, int amode, int who)
*--------------------------------------------------------------------
/if defined(*V5R2M0)
D faccessx PR 10I 0 ExtProc('faccessx')
D fildes 10I 0 Value
D amode 10I 0 Value
D who 10I 0 Value
/endif
*--------------------------------------------------------------------
* Change Current Directory by Descriptor
*
* int fchdir(int fildes)
*--------------------------------------------------------------------
/if defined(*V5R2M0)
D fchdir PR 10I 0 ExtProc('fchdir')
D fildes 10I 0 value
/endif
*--------------------------------------------------------------------
* Change file authorizations by descriptor
*
* int fchmod(int fildes, mode_t mode)
*--------------------------------------------------------------------
D fchmod PR 10I 0 ExtProc('fchmod')
D fildes 10I 0 Value
D mode 10U 0 Value
*--------------------------------------------------------------------
* Change Owner and Group of File by Descriptor
*
* int fchown(int fildes, uid_t owner, gid_t group)
*--------------------------------------------------------------------
D fchown PR 10I 0 ExtProc('fchown')
D fildes 10I 0 Value
D owner 10U 0 Value
D group 10U 0 Value
*--------------------------------------------------------------------
* Perform File Control
*
* int fcntl(int fildes, int cmd, . . .)
*
* Note: Because the same fcntl() API is used for IFS and sockets,
* it's conditionally defined here. If it's defined with
* the same conditions in the sockets /copy member, there
* will be no conflict.
*--------------------------------------------------------------------
D/if not defined(FCNTL_PROTOTYPE)
D fcntl PR 10I 0 ExtProc('fcntl')
D fildes 10I 0 Value
D cmd 10I 0 Value
D arg 10I 0 Value options(*nopass)
D/define FCNTL_PROTOTYPE
D/endif
*--------------------------------------------------------------------
* Get configurable path name variables by descriptor
*
* long fpathconf(int fildes, int name)
*--------------------------------------------------------------------
D fpathconf PR 10I 0 ExtProc('fpathconf')
D fildes 10I 0 Value
D name 10I 0 Value
*--------------------------------------------------------------------
* Get File Information by Descriptor
*
* int fstat(int fildes, struct stat *buf)
*--------------------------------------------------------------------
D fstat PR 10I 0 ExtProc('fstat')
D fildes 10I 0 Value
D buf likeds(statds)
*--------------------------------------------------------------------
* Get File Information by Descriptor, Large File Enabled
*
* int fstat64(int fildes, struct stat *buf)
*--------------------------------------------------------------------
D fstat64 PR 10I 0 ExtProc('fstat64')
D fildes 10I 0 Value
D buf likeds(statds64)
*--------------------------------------------------------------------
* fstatvfs() -- Get file system status by descriptor
*
* fildes = (input) file descriptor to use to locate file system
* buf = (output) data structure containing file system info
*
* Returns 0 if successful, -1 upon error.
* (error information is returned via the "errno" variable)
*--------------------------------------------------------------------
D fstatvfs PR 10I 0 ExtProc('fstatvfs64')
D fildes 10I 0 value
D buf like(ds_statvfs)
*--------------------------------------------------------------------
* Synchronize Changes to file
*
* int fsync(int fildes)
*--------------------------------------------------------------------
D fsync PR 10I 0 ExtProc('fsync')
D fildes 10I 0 Value
*--------------------------------------------------------------------
* Truncate file
*
* int ftruncate(int fildes, off_t length)
*--------------------------------------------------------------------
D ftruncate PR 10I 0 ExtProc('ftruncate')
D fildes 10I 0 Value
D length 10I 0 Value
*--------------------------------------------------------------------
* Truncate file, large file enabled
*
* int ftruncate64(int fildes, off64_t length)
*--------------------------------------------------------------------
D ftruncate64 PR 10I 0 ExtProc('ftruncate64')
D fildes 10I 0 Value
D length 20I 0 Value
*--------------------------------------------------------------------
* Get current working directory
*
* char *getcwd(char *buf, size_t size)
*--------------------------------------------------------------------
D getcwd PR * ExtProc('getcwd')
D buf * Value
D size 10U 0 Value
*--------------------------------------------------------------------
* Get effective group ID
*
* gid_t getegid(void)
*--------------------------------------------------------------------
D getegid PR 10U 0 ExtProc('getegid')
*--------------------------------------------------------------------
* Get effective user ID
*
* uid_t geteuid(void)
*--------------------------------------------------------------------
D geteuid PR 10U 0 ExtProc('geteuid')
*--------------------------------------------------------------------
* Get Real Group ID
*
* gid_t getgid(void)
*--------------------------------------------------------------------
D getgid PR 10U 0 ExtProc('getgid')
*--------------------------------------------------------------------
* Get group information from group ID
*
* struct group *getgrgid(gid_t gid)
*--------------------------------------------------------------------
D getgrgid PR * ExtProc('getgrgid')
D gid 10U 0 VALUE
*--------------------------------------------------------------------
* Get group info using group name
*
* struct group *getgrnam(const char *name)
*--------------------------------------------------------------------
D getgrnam PR * ExtProc('getgrnam')
D name * VALUE
*--------------------------------------------------------------------
* Get group IDs
*
* int getgroups(int gidsetsize, gid_t grouplist[])
*--------------------------------------------------------------------
D getgroups PR * ExtProc('getgroups')
D gidsetsize 10I 0 value
D grouplist 10U 0 dim(256) options(*varsize)
*--------------------------------------------------------------------
* Get user information by user-name
*
* (Don't let the name mislead you, this does not return the password,
* the user info database on unix systems is called "passwd",
* therefore, getting the user info is called "getpw")
*
* struct passwd *getpwnam(const char *name)
*--------------------------------------------------------------------
D getpwnam PR * ExtProc('getpwnam')
D name * Value options(*string)
*--------------------------------------------------------------------
* Get user information by user-id number
*
* (Don't let the name mislead you, this does not return the password,
* the user info database on unix systems is called "passwd",
* therefore, getting the user info is called "getpw")
*
* struct passwd *getpwuid(uid_t uid)
*--------------------------------------------------------------------
D getpwuid PR * extproc('getpwuid')
D uid 10U 0 Value
*--------------------------------------------------------------------
* Get Real User-ID
*
* uid_t getuid(void)
*--------------------------------------------------------------------
D getuid PR 10U 0 ExtProc('getuid')
*--------------------------------------------------------------------
* Perform I/O Control Request
*
* int ioctl(int fildes, unsigned long req, ...)
*--------------------------------------------------------------------
D ioctl PR 10I 0 ExtProc('ioctl')
D fildes 10I 0 Value
D req 10U 0 Value
D arg * Value
*--------------------------------------------------------------------
* Change Owner/Group of symbolic link
*
* int lchown(const char *path, uid_t owner, gid_t group)
*
* NOTE: for non-symlinks, this behaves identically to chown().
* for symlinks, this changes ownership of the link, whereas
* chown() changes ownership of the file the link points to.
*--------------------------------------------------------------------
D lchown PR 10I 0 ExtProc('lchown')
D path * Value options(*string)
D owner 10U 0 Value
D group 10U 0 Value
*--------------------------------------------------------------------
* Create Hard Link to File
*
* int link(const char *existing, const char *new)
*--------------------------------------------------------------------
D link PR 10I 0 ExtProc('link')
D existing * Value options(*string)
D new * Value options(*string)
*--------------------------------------------------------------------
* Set File Read/Write Offset
*
* off_t lseek(int fildes, off_t offset, int whence)
*--------------------------------------------------------------------
D lseek PR 10I 0 ExtProc('lseek')
D fildes 10I 0 value
D offset 10I 0 value
D whence 10I 0 value
*--------------------------------------------------------------------
* Set File Read/Write Offset, Large File Enabled
*
* off64_t lseek64(int fildes, off64_t offset, int whence)
*--------------------------------------------------------------------
D lseek64 PR 20I 0 ExtProc('lseek64')
D fildes 10I 0 value
D offset 20I 0 value
D whence 10I 0 value
*--------------------------------------------------------------------
* Get File or Link Information
*
* int lstat(const char *path, struct stat *buf)
*
* NOTE: for non-symlinks, this behaves identically to stat().
* for symlinks, this gets information about the link, whereas
* stat() gets information about the file the link points to.
*--------------------------------------------------------------------
D lstat PR 10I 0 ExtProc('lstat')
D path * Value options(*string)
D buf likeds(statds)
*--------------------------------------------------------------------
* Get File or Link Information, Large File Enabled
*
* int lstat64(const char *path, struct stat64 *buf)
*
* NOTE: for non-symlinks, this behaves identically to stat().
* for symlinks, this gets information about the link, whereas
* stat() gets information about the file the link points to.
*--------------------------------------------------------------------
D lstat64 PR 10I 0 ExtProc('lstat64')
D path * Value options(*string)
D buf likeds(statds64)
*--------------------------------------------------------------------
* Make Directory
*
* int mkdir(const char *path, mode_t mode)
*--------------------------------------------------------------------
D mkdir PR 10I 0 ExtProc('mkdir')
D path * Value options(*string)
D mode 10U 0 Value
*--------------------------------------------------------------------
* Make FIFO Special File
*
* int mkfifo(const char *path, mode_t mode)
*--------------------------------------------------------------------
/if defined(*V5R1M0)
D mkfifo PR 10I 0 ExtProc('mkfifo')
D path * Value options(*string)
D mode 10U 0 Value
/endif
*--------------------------------------------------------------------
* Open a File
*
* int open(const char *path, int oflag, . . .);
*--------------------------------------------------------------------
D open PR 10I 0 ExtProc('open')
D path * value options(*string)
D openflags 10I 0 value
D mode 10U 0 value options(*nopass)
D ccsid 10U 0 value options(*nopass)
D/if defined(*V5R2M0)
D txtcreatid 10U 0 value options(*nopass)
D/endif
*--------------------------------------------------------------------
* Open a File, Large File Enabled
*
* int open64(const char *path, int oflag, . . .);
*
* NOTE: This is identical to calling open(), except that the
* O_LARGEFILE flag is automatically supplied.
*--------------------------------------------------------------------
D open64 PR 10I 0 ExtProc('open64')
D filename * value options(*string)
D openflags 10I 0 value
D mode 10U 0 value options(*nopass)
D codepage 10U 0 value options(*nopass)
D/if defined(*V5R2M0)
D txtcreatid 10U 0 value options(*nopass)
D/endif
*--------------------------------------------------------------------
* Open a Directory
*
* DIR *opendir(const char *dirname)
*--------------------------------------------------------------------
D opendir PR * EXTPROC('opendir')
D dirname * VALUE options(*string)
*--------------------------------------------------------------------
* Get configurable path name variables
*
* long pathconf(const char *path, int name)
*--------------------------------------------------------------------
D pathconf PR 10I 0 ExtProc('pathconf')
D path * Value options(*string)
D name 10I 0 Value
*--------------------------------------------------------------------
* Create interprocess channel
*
* int pipe(int fildes[2]);
*--------------------------------------------------------------------
D pipe PR 10I 0 ExtProc('pipe')
D fildes 10I 0 dim(2)
*--------------------------------------------------------------------
* Read from Descriptor with Offset
*
* ssize_t pread(int filedes, void *buf, size_t nbyte, off_t offset);
*--------------------------------------------------------------------
/if defined(*V5R2M0)
D pread PR 10I 0 ExtProc('pread')
D fildes 10I 0 value
D buf * value
D nbyte 10U 0 value
D offset 10I 0 value
/endif
*--------------------------------------------------------------------
* Read from Descriptor with Offset, Large File Enabled
*
* ssize_t pread64(int filedes, void *buf, size_t nbyte,
* size_t nbyte, off64_t offset);
*--------------------------------------------------------------------
/if defined(*V5R2M0)
D pread64 PR 10I 0 ExtProc('pread64')
D fildes 10I 0 value
D buf * value
D nbyte 10U 0 value
D offset 20I 0 value
/endif
*--------------------------------------------------------------------
* Write to Descriptor with Offset
*
* ssize_t pwrite(int filedes, const void *buf,
* size_t nbyte, off_t offset);
*--------------------------------------------------------------------
/if defined(*V5R2M0)
D pwrite PR 10I 0 ExtProc('pwrite')
D fildes 10I 0 value
D buf * value
D nbyte 10U 0 value
D offset 10I 0 value
/endif
*--------------------------------------------------------------------
* Write to Descriptor with Offset, Large File Enabled
*
* ssize_t pwrite64(int filedes, const void *buf,
* size_t nbyte, off64_t offset);
*--------------------------------------------------------------------
/if defined(*V5R2M0)
D pwrite64 PR 10I 0 ExtProc('pwrite64')
D fildes 10I 0 value
D buf * value
D nbyte 10U 0 value
D offset 20I 0 value
/endif
*--------------------------------------------------------------------
* Perform Miscellaneous file system functions
*--------------------------------------------------------------------
D QP0FPTOS PR ExtPgm('QP0FPTOS')
D Function 32A const
D Exten1 6A const options(*nopass)
D Exten2 3A const options(*nopass)
*--------------------------------------------------------------------
* Read From a File
*
* ssize_t read(int fildes, void *buffer, size_t bytes);
*--------------------------------------------------------------------
D read PR 10I 0 ExtProc('read')
D fildes 10i 0 value
D buf * value
D bytes 10U 0 value
*--------------------------------------------------------------------
* Read Directory Entry
*
* struct dirent *readdir(DIR *dirp)
*--------------------------------------------------------------------
D readdir PR * EXTPROC('readdir')
D dirp * VALUE
*--------------------------------------------------------------------
* Read Value of Symbolic Link
*
* int readlink(const char *path, char *buf, size_t bufsiz)
*--------------------------------------------------------------------
D readlink PR 10I 0 ExtProc('readlink')
D path * value options(*string)
D buf * value
D bufsiz 10U 0 value
*--------------------------------------------------------------------
* Read From Descriptor using Multiple Buffers
*
* int readv(int fildes, struct iovec *io_vector[], int vector_len);
*--------------------------------------------------------------------
D readv PR 10I 0 ExtProc('readv')
D fildes 10i 0 value
D io_vector like(iovec)
D dim(256) options(*varsize)
D vector_len 10I 0 value
*--------------------------------------------------------------------
* Rename File or Directory
*
* int rename(const char *old, const char *new)
*
* Note: By defailt, if a file with the new name already exists,
* rename will fail with an error. If you define
* RENAMEUNLINK and a file with the new name already exists
* it will be unlinked prior to renaming.
*--------------------------------------------------------------------
/if defined(RENAMEUNLINK)
D rename PR 10I 0 ExtProc('Qp0lRenameUnlink')
D old * Value options(*string)
D new * Value options(*string)
/else
D rename PR 10I 0 ExtProc('Qp0lRenameKeep')
D old * Value options(*string)
D new * Value options(*string)
/endif
*--------------------------------------------------------------------
* Reset Directory Stream to Beginning
*
* void rewinddir(DIR *dirp)
*--------------------------------------------------------------------
D rewinddir PR ExtProc('rewinddir')
D dirp * value
*--------------------------------------------------------------------
* Remove Directory
*
* int rmdir(const char *path)
*--------------------------------------------------------------------
D rmdir PR 10I 0 ExtProc('rmdir')
D path * value options(*string)
*--------------------------------------------------------------------
* Get File Information
*
* int stat(const char *path, struct stat *buf)
*--------------------------------------------------------------------
D stat PR 10I 0 ExtProc('stat')
D path * value options(*string)
D buf * value
*--------------------------------------------------------------------
* Get File Information, Large File Enabled
*
* int stat(const char *path, struct stat64 *buf)
*--------------------------------------------------------------------
D stat64 PR 10I 0 ExtProc('stat64')
D path * value options(*string)
D buf likeds(statds64)
*--------------------------------------------------------------------
* statvfs() -- Get file system status
*
* path = (input) pathname of a link ("file") in the IFS.
* buf = (output) data structure containing file system info
*
* Returns 0 if successful, -1 upon error.
* (error information is returned via the "errno" variable)
*--------------------------------------------------------------------
D statvfs PR 10I 0 ExtProc('statvfs64')
D path * value options(*string)
D buf like(ds_statvfs)
*--------------------------------------------------------------------
* Make Symbolic Link
*
* int symlink(const char *pname, const char *slink)
*--------------------------------------------------------------------
D symlink PR 10I 0 ExtProc('symlink')
D pname * value options(*string)
D slink * value options(*string)
*--------------------------------------------------------------------
* Get system configuration variables
*
* long sysconf(int name)
*--------------------------------------------------------------------
D sysconf PR 10I 0 ExtProc('sysconf')
D name 10I 0 Value
*--------------------------------------------------------------------
* Set Authorization Mask for Job
*
* mode_t umask(mode_t cmask)
*--------------------------------------------------------------------
D umask PR 10U 0 ExtProc('umask')
D cmask 10U 0 Value
*--------------------------------------------------------------------
* Remove Link to File. (Deletes Directory Entry for File, and if
* this was the last link to the file data, the file itself is
* also deleted)
*
* int unlink(const char *path)
*--------------------------------------------------------------------
D unlink PR 10I 0 ExtProc('unlink')
D path * Value options(*string)
*--------------------------------------------------------------------
* Set File Access & Modification Times
*
* int utime(const char *path, const struct utimbuf *times)
*--------------------------------------------------------------------
D utime PR 10I 0 ExtProc('utime')
D path * value options(*string)
D times likeds(utimbuf) options(*omit)
*--------------------------------------------------------------------
* Write to a file
*
* ssize_t write(int fildes, const void *buf, size_t bytes)
*--------------------------------------------------------------------
D write PR 10I 0 ExtProc('write')
D fildes 10i 0 value
D buf * value
D bytes 10U 0 value
*--------------------------------------------------------------------
* Write to a file using (with type A field in prototype)
*
* ssize_t write(int fildes, const void *buf, size_t bytes)
*--------------------------------------------------------------------
D writeA PR 10I 0 ExtProc('write')
D fildes 10i 0 value
D buf 65535A const options(*varsize)
D bytes 10U 0 value
*--------------------------------------------------------------------
* Write to descriptor using multiple buffers
*
* int writev(int fildes, struct iovec *iovector[], int vector_len);
*--------------------------------------------------------------------
D writev PR 10I 0 ExtProc('writev')
D fildes 10i 0 value
D io_vector like(iovec)
D dim(256) options(*varsize)
D vector_len 10I 0 value
json/json_arr.rpgle 100666 2763 0 105274 11515404426 12440 0 ustar 00MSCHMIDT /**
* \brief JSON Array Implementation
*
* The value of a JSON object can be an array. This service program deals
* with such arrays. Arrays themselves can also contain arrays. An array
* can only contain values and arrays but no key/value pairs.
*
*
*
* Throughout this service program is the index always 0-based. Which
* means that the first entry has the index 0, the second entry has the
* index 1 and so on.
*
*
*
* If the index is out of the bounds of the array an escape message will
* be send. If a procedure for the retrieval of a special type of value
* is called on an entry of another type an escape message will be send
* too.
*
* \author Mihael Schmidt
* \date 19.04.2008
*
* \link http://www.json.org JSON
*
* \rev 07.03.2009 Mihael Schmidt
* Added jsona_size procedure.
*
* \rev 27.01.2010 Mihael Schmidt
* Added support for getting numbers with procedures jsona_getInt,
* jsona_getLong, jsona_getDouble no matter what the original type was
* (f. e. double value will be cast to int with jsona_getInt).
*/
*-------------------------------------------------------------------------
* Copyright (c) 2007-2010 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*-------------------------------------------------------------------------
H nomain
H bnddir('QC2LE')
H copyright('Copyright (c) 2007-2010 Mihael Schmidt. All rights reserved.')
*-------------------------------------------------------------------------
* Prototypes
*-------------------------------------------------------------------------
D jsona_srvpgm_init...
D PR 10I 0 extproc('jsona_srvpgm_init')
*
/copy 'json_h.rpgle'
/copy 'json_int_h.rpgle'
/copy 'llist_h.rpgle'
/copy 'ceeapi_h.rpgle'
/copy 'libc_h.rpgle'
*-------------------------------------------------------------------------
* Constants
*-------------------------------------------------------------------------
/copy 'json_c.rpgle'
/copy 'unicode_c.rpgle'
*-------------------------------------------------------------------------
* Global Variables
*-------------------------------------------------------------------------
D hex_null S 1A inz(x'00')
*
* Parameters passed to CEEDOD
*
D descType S 10I 0
D dataType S 10I 0
D descInfo1 S 10I 0
D descInfo2 S 10I 0
D length S 10I 0
*
D chars DS likeds(tmpl_chars)
D chars_compact DS likeds(tmpl_chars)
*-------------------------------------------------------------------------
* Procedures
*-------------------------------------------------------------------------
/**
* \brief Service program initialization
*
* String formattings are preloaded.
*/
P jsona_srvpgm_init...
P B export
D PI 10I 0
/free
chars.d_quote = %char(UNICODE_DOUBLE_QUOTE) + x'00';
chars.l_brace = ' ' + %char(UNICODE_LEFT_CURLY_BRACE) + ' ' + x'00';
chars.r_brace = ' ' + %char(UNICODE_RIGHT_CURLY_BRACE) + ' ' + x'00';
chars.l_bracket = ' ' + %char(UNICODE_LEFT_BRACKET) + ' ' + x'00';
chars.r_bracket = ' ' + %char(UNICODE_RIGHT_BRACKET) + ' ' + x'00';
chars.comma = ' ' + %char(UNICODE_COMMA) + ' ' + x'00';
chars.colon = ' ' + %char(UNICODE_COLON) + ' ' + x'00';
chars.true = 'true' + x'00';
chars.false = 'false' + x'00';
chars.null_str = 'null' + x'00';
chars.size_d_quote = 1;
chars.size_l_brace = 3;
chars.size_r_brace = 3;
chars.size_l_bracket = 3;
chars.size_r_bracket = 3;
chars.size_comma = 3;
chars.size_colon = 3;
chars.size_true = 4;
chars.size_false = 5;
chars.size_null_str = 4;
chars_compact.d_quote = %char(UNICODE_DOUBLE_QUOTE) + x'00';
chars_compact.l_brace = %char(UNICODE_LEFT_CURLY_BRACE) + x'00';
chars_compact.r_brace = %char(UNICODE_RIGHT_CURLY_BRACE) + x'00';
chars_compact.l_bracket = %char(UNICODE_LEFT_BRACKET) + x'00';
chars_compact.r_bracket = %char(UNICODE_RIGHT_BRACKET) + x'00';
chars_compact.comma = %char(UNICODE_COMMA) + x'00';
chars_compact.colon = %char(UNICODE_COLON) + x'00';
chars_compact.true = 'true' + x'00';
chars_compact.false = 'false' + x'00';
chars_compact.null_str = 'null' + x'00';
chars_compact.size_d_quote = 1;
chars_compact.size_l_brace = 1;
chars_compact.size_r_brace = 1;
chars_compact.size_l_bracket = 1;
chars_compact.size_r_bracket = 1;
chars_compact.size_comma = 1;
chars_compact.size_colon = 1;
chars_compact.size_true = 4;
chars_compact.size_false = 5;
chars_compact.size_null_str = 4;
return 0;
/end-free
P E
/**
* \brief Create JSON array
*
* Creates a json array "object". Currently a linked list is used
* as a backend for the json array.
*
* \author Mihael Schmidt
* \date 19.04.2008
*
* \return Pointer to the JSON array
*/
P jsona_create B export
D PI *
/free
return list_create();
/end-free
P E
/**
* \brief Dispose JSON array
*
* Disposes a JSON array and all values it contains.
* All added arrays are also disposed.
*
* \author Mihael Schmidt
* \date 19.04.2008
*
* \param Pointer to the JSON array
*/
P jsona_dispose B export
D PI
D jsonArrPtr *
*
D tmpPtr S *
D tmpDs DS likeds(tmpl_array_entry )
D based(tmpPtr)
D tmpPtrDs DS qualified based(tmpPtr)
D type 10I 0
D ptr *
/free
tmpPtr = list_getNext(jsonArrPtr);
dow (tmpPtr <> *null);
if (tmpDs.type = JSON_TYPE_ARRAY);
jsona_dispose(tmpPtrDs.ptr);
elseif (tmpDs.type = JSON_TYPE_OBJECT);
json_dispose(tmpPtrDs.ptr);
endif;
tmpPtr = list_getNext(jsonArrPtr);
enddo;
list_dispose(jsonArrPtr);
/end-free
P E
/**
* \brief Remove an entry from the array
*
* \param Pointer to the JSON array
* \param Index of the element to be removed (0-based)
*/
P jsona_remove B export
D PI opdesc
D jsonArrPtr * const
D index 10I 0 const
*
D tmpPtr S *
D tmpDs DS likeds(tmpl_array_entry )
D based(tmpPtr)
D ptr S *
D tmpPtrDs DS qualified based(tmpPtr)
D type 10I 0
D array *
/free
tmpPtr = list_get(jsonArrPtr : index);
if (tmpPtr <> *null and tmpDs.type = JSON_TYPE_ARRAY);
jsona_dispose(tmpPtrDs.array);
endif;
list_remove(jsonArrPtr : index);
/end-free
P E
/**
* \brief Clear array
*
* Removes all elements from the array.
*
* \param Pointer to the JSON array
*/
P jsona_clear B export
D PI
D jsonArrPtr * const
*
D tmpPtr S *
D tmpDs DS likeds(tmpl_array_entry )
D based(tmpPtr)
D ptr S *
D tmpPtrDs DS qualified based(tmpPtr)
D type 10I 0
D array *
/free
tmpPtr = list_getNext(jsonArrPtr);
dow (tmpPtr <> *null);
if (tmpDs.type = JSON_TYPE_ARRAY);
jsona_dispose(tmpPtrDs.array);
endif;
tmpPtr = list_getNext(jsonArrPtr);
enddo;
list_clear(jsonArrPtr);
/end-free
P E
/**
* \brief Add character entry
*
* Adds an entry of type character.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
* \param Value
* \param Index (default: last)
*/
P jsona_putString...
P B export
D PI opdesc
D jsonArrPtr * const
D value 65535A const options(*varsize)
D index 10U 0 const options(*nopass)
/free
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpl_array_entry .type = JSON_TYPE_STRING;
tmpl_array_entry .string = %subst(value : 1 : length);
if (%parms() = 2);
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : length + 4);
else;
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : length + 4 : index);
endif;
/end-free
P E
/**
* \brief Add boolean entry
*
* Adds an entry of type boolean.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
* \param Value
* \param Index (default: last)
*/
P jsona_putBoolean...
P B export
D PI
D jsonArrPtr * const
D value N const
D index 10U 0 const options(*nopass)
/free
tmpl_array_entry .type = JSON_TYPE_BOOLEAN;
tmpl_array_entry .boolean = value;
if (%parms() = 2);
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : 5);
else;
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : 5 : index);
endif;
/end-free
P E
/**
* \brief Add integer entry
*
* Adds an entry of type integer.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
* \param Value
* \param Index (default: last)
*/
P jsona_putInt...
P B export
D PI
D jsonArrPtr * const
D value 10I 0 const
D index 10U 0 const options(*nopass)
/free
tmpl_array_entry .type = JSON_TYPE_INT;
tmpl_array_entry .integer = value;
if (%parms() = 2);
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : 8);
else;
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : 8 : index);
endif;
/end-free
P E
/**
* \brief Add long entry
*
* Adds an entry of type long.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
* \param Value
* \param Index (default: last)
*/
P jsona_putLong...
P B export
D PI
D jsonArrPtr * const
D value 20I 0 const
D index 10U 0 const options(*nopass)
/free
tmpl_array_entry .type = JSON_TYPE_LONG;
tmpl_array_entry .long = value;
if (%parms() = 2);
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : 12);
else;
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : 12 : index);
endif;
/end-free
P E
/**
* \brief Add double entry
*
* Adds an entry of type double.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
* \param Value
* \param Index (default: last)
*/
P jsona_putDouble...
P B export
D PI
D jsonArrPtr * const
D value 8F const
D index 10U 0 const options(*nopass)
/free
tmpl_array_entry .type = JSON_TYPE_DOUBLE;
tmpl_array_entry .double = value;
if (%parms() = 2);
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : 12);
else;
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : 12 : index);
endif;
/end-free
P E
/**
* \brief Add array entry
*
* Adds an entry of type array.
*
* \author Mihael Schmidt
* \date 19.04.2008
*
* \param Pointer to the JSON array
* \param Array
* \param Index (default: last)
*/
P jsona_putArray...
P B export
D PI
D jsonArrPtr * const
D value * const
D index 10U 0 const options(*nopass)
*
D tmpDs DS qualified
D type 10I 0
D array *
/free
tmpDs.type = JSON_TYPE_ARRAY;
tmpDs.array = value;
if (%parms() = 2);
list_add(jsonArrPtr : %addr(tmpDs) : %size(tmpDs));
else;
list_add(jsonArrPtr : %addr(tmpDs) : %size(tmpDs) : index);
endif;
/end-free
P E
/**
* \brief Get string entry
*
* Returns a pointer to the value of the entry for the passed key.
* The value is null terminated and can be processed with the %str BIF.
*
*
*
* If the entry is not of type string an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
* \param Index
*
* \return Pointer to a null-terminated string
*/
P jsona_getString...
P B export
D PI *
D jsonArrPtr * const
D index 10U 0 const
*
D tmpPtr S *
D tmpDs DS likeds(tmpl_array_entry )
D based(tmpPtr)
/free
tmpPtr = list_get(jsonArrPtr : index);
if (tmpPtr <> *null);
if (tmpDs.type = JSON_TYPE_STRING);
return tmpPtr + 4;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
else;
sendEscapeMessage(MSG_ARRAY_ELEMENT_NOT_FOUND);
endif;
return *null; // dummy => will never come to this point
/end-free
P E
/**
* \brief Get boolean entry
*
* Returns the boolean value of the entry.
*
*
*
* If the entry is not of type boolean an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
* \param Index
*
* \return Boolean value of the entry
*/
P jsona_getBoolean...
P B export
D PI N
D jsonArrPtr * const
D index 10U 0 const
*
D tmpPtr S *
D tmpDs DS likeds(tmpl_array_entry )
D based(tmpPtr)
/free
tmpPtr = list_get(jsonArrPtr : index);
if (tmpPtr <> *null);
if (tmpDs.type = JSON_TYPE_BOOLEAN);
return tmpDs.boolean;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
else;
sendEscapeMessage(MSG_ARRAY_ELEMENT_NOT_FOUND);
endif;
return *off; // dummy => will never come to this point
/end-free
P E
/**
* \brief Get integer entry
*
* Returns the integer value of the entry.
*
*
*
* If the entry is not of type integer an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
* \param Index
*
* \return Integer value of the entry
*/
P jsona_getInt...
P B export
D PI 10I 0
D jsonArrPtr * const
D index 10U 0 const
*
D tmpPtr S *
D tmpDs DS likeds(tmpl_array_entry )
D based(tmpPtr)
/free
tmpPtr = list_get(jsonArrPtr : index);
if (tmpPtr <> *null);
if (tmpDs.type = JSON_TYPE_INT);
return tmpDs.integer;
elseif (tmpDs.type = JSON_TYPE_LONG);
monitor;
return tmpDs.long;
on-error *all;
sendEscapeMessage(MSG_TYPE_CAST_EXCEPTION);
endmon;
elseif (tmpDs.type = JSON_TYPE_DOUBLE);
monitor;
return %int(tmpDs.double);
on-error *all;
sendEscapeMessage(MSG_TYPE_CAST_EXCEPTION);
endmon;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
else;
sendEscapeMessage(MSG_ARRAY_ELEMENT_NOT_FOUND);
endif;
return -1; // dummy => will never come to this point
/end-free
P E
/**
* \brief Get long entry
*
* Returns the long value of the entry.
*
*
*
* If the entry is not of type long an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
* \param Index
*
* \return Long value of the entry
*/
P jsona_getLong...
P B export
D PI 20I 0
D jsonArrPtr * const
D index 10U 0 const
*
D tmpPtr S *
D tmpDs DS likeds(tmpl_array_entry )
D based(tmpPtr)
/free
tmpPtr = list_get(jsonArrPtr : index);
if (tmpPtr <> *null);
if (tmpDs.type = JSON_TYPE_LONG);
return tmpDs.long;
elseif (tmpDs.type = JSON_TYPE_INT);
return tmpDs.integer;
elseif (tmpDs.type = JSON_TYPE_DOUBLE);
monitor;
return %int(tmpDs.double);
on-error *all;
sendEscapeMessage(MSG_TYPE_CAST_EXCEPTION);
endmon;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
else;
sendEscapeMessage(MSG_ARRAY_ELEMENT_NOT_FOUND);
endif;
return -1; // dummy => will never come to this point
/end-free
P E
/**
* \brief Get double entry
*
* Returns the double value of the entry.
*
*
*
* If the entry is not of type double an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
* \param Index
*
* \return Double value of the entry
*/
P jsona_getDouble...
P B export
D PI 8F
D jsonArrPtr * const
D index 10U 0 const
*
D tmpPtr S *
D tmpDs DS likeds(tmpl_array_entry )
D based(tmpPtr)
/free
tmpPtr = list_get(jsonArrPtr : index);
if (tmpPtr <> *null);
if (tmpDs.type = JSON_TYPE_DOUBLE);
return tmpDs.double;
elseif (tmpDs.type = JSON_TYPE_INT);
return %float(tmpDs.integer);
elseif (tmpDs.type = JSON_TYPE_LONG);
monitor;
return %float(tmpDs.long);
on-error *all;
sendEscapeMessage(MSG_TYPE_CAST_EXCEPTION);
endmon;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
else;
sendEscapeMessage(MSG_ARRAY_ELEMENT_NOT_FOUND);
endif;
return -1.0; // dummy => will never come to this point
/end-free
P E
/**
* \brief Get array entry
*
* Returns the array value of the entry.
*
*
*
* If the entry is not of type array an escape message will be send.
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
* \param Index
*
* \return Pointer to the JSON array
*/
P jsona_getArray...
P B export
D PI *
D jsonArrPtr * const
D index 10U 0 const
*
D tmpPtr S *
D tmpDs DS qualified based(tmpPtr)
D type 10I 0
D array *
/free
tmpPtr = list_get(jsonArrPtr : index);
if (tmpPtr <> *null);
if (tmpDs.type = JSON_TYPE_ARRAY);
return tmpDs.array;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
else;
sendEscapeMessage(MSG_ARRAY_ELEMENT_NOT_FOUND);
endif;
return *null; // dummy => will never come to this point
/end-free
P E
/**
* \brief String representation of the JSON array in JSON syntax
*
* Creates a null terminated string representation of the JSON array in
* JSON syntax.
*
*
*
* For entries of type string double quotes and backslashes will be escaped
* (" => \" and \ => \\).
*
* \author Mihael Schmidt
* \date 20.03.2008
*
* \param Pointer to the JSON array
*/
P jsona_toString...
P B export
D PI *
D jsonArrPtr * const
D pOutputFormat...
D 10I 0 const options(*nopass)
D pPrettyPrintFormat...
D likeds(json_prettyPrintFormat)
D const options(*nopass)
D pIndentationLevel...
D 10I 0 options(*nopass)
*
D outputFormat...
D S 10I 0
D prettyPrintOption...
D S N inz(*off)
D prettyPrintFormat...
D DS likeds(json_prettyPrintFormat) inz
D indentationLevel...
D S 10I 0 inz(0)
*
D l_chars DS likeds(tmpl_chars) inz
*
D json_string_ptr...
D S *
D json_string_length...
D S 10I 0
D tokenList S *
D tmpString S 310A
D tmpLength S 10I 0
D entry DS likeds(tmpl_array_entry)
D based(entryPtr)
D tmpDs DS qualified based(entryPtr)
D type 10I 0
D ptr *
D ptr S *
D x S 10I 0
D newline S 2A inz(x'0D25')
/free
if (%parms() >= 2);
outputFormat = pOutputFormat;
endif;
if (%parms() >= 3);
prettyPrintFormat = pPrettyPrintFormat;
endif;
if (%parms() = 4);
indentationLevel = pIndentationLevel;
endif;
exsr init;
if (outputFormat = JSON_OUTPUT_PRETTY_PRINT);
prettyPrintOption = *on;
endif;
// initialization
// - write start tag
// - init token list
tokenList = list_create();
if (prettyPrintOption and prettyPrintFormat.breakBeforeArrayBrace);
list_add(tokenList : %addr(newline) : %size(newline));
prettyPrint(tokenList : prettyPrintFormat : indentationLevel);
endif;
list_add(tokenList : %addr(l_chars.l_bracket) : l_chars.size_l_bracket);
if (prettyPrintOption);
prettyPrint(tokenList : prettyPrintFormat : indentationLevel);
if (prettyPrintFormat.breakAfterArrayBrace);
indentationLevel += 1;
list_add(tokenList : %addr(newline) : %size(newline));
endif;
endif;
// process entries
entryPtr = list_getNext(jsonArrPtr);
dow (entryPtr <> *null);
if (prettyPrintOption);
prettyPrint(tokenList : prettyPrintFormat : indentationLevel);
endif;
select;
when (entry.type = JSON_TYPE_STRING);
list_add(tokenList : %addr(l_chars.d_quote):l_chars.size_d_quote);
list_add(tokenList : %addr(entry.string) :
strlen(%addr(entry.string)));
escapeLastToken(tokenList);
list_add(tokenList : %addr(l_chars.d_quote):l_chars.size_d_quote);
when (entry.type = JSON_TYPE_INT);
tmpString = %char(entry.integer);
tmpLength = %len(%trimr(tmpString));
list_add(tokenList : %addr(tmpString) : tmpLength);
when (entry.type = JSON_TYPE_LONG);
tmpString = %char(entry.long);
tmpLength = %len(%trimr(tmpString));
list_add(tokenList : %addr(tmpString) : tmpLength);
when (entry.type = JSON_TYPE_DOUBLE);
tmpString = %char(entry.double);
tmpLength = %len(%trimr(tmpString));
// JSON syntax expects a . as delimiter (and not ,)
tmpString = %xlate(',' : '.' : tmpString);
list_add(tokenList : %addr(tmpString) : tmpLength);
when (entry.type = JSON_TYPE_BOOLEAN);
if (entry.boolean);
list_add(tokenList : %addr(l_chars.true) : l_chars.size_true);
else;
list_add(tokenList : %addr(l_chars.false) : l_chars.size_false);
endif;
when (entry.type = JSON_TYPE_ARRAY);
ptr = jsona_toString(tmpDs.ptr : outputFormat :
prettyPrintFormat : indentationLevel);
list_add(tokenList : ptr : strlen(ptr));
dealloc(n) ptr;
when (entry.type = JSON_TYPE_NULL);
list_add(tokenList : %addr(entry.string) : 4);
when (entry.type = JSON_TYPE_OBJECT);
ptr = json_toString(tmpDs.ptr : outputFormat :
prettyPrintFormat : indentationLevel);
list_add(tokenList : ptr : strlen(ptr));
dealloc(n) ptr;
endsl;
// add comma if it is not the last entry
if (entryPtr <> list_getLast(jsonArrPtr));
list_add(tokenList : %addr(l_chars.comma) : l_chars.size_comma);
if (prettyPrintOption and prettyPrintFormat.breakAfterElement);
list_add(tokenList : %addr(newline) : %size(newline));
endif;
endif;
// next entry
entryPtr = list_getNext(jsonArrPtr);
enddo;
if (prettyPrintOption);
if (prettyPrintFormat.breakAfterArrayBrace);
list_add(tokenList : %addr(newline) : %size(newline));
indentationLevel -= 1;
endif;
prettyPrint(tokenList : prettyPrintFormat : indentationLevel);
endif;
// write end tag
list_add(tokenList : %addr(l_chars.r_bracket) : l_chars.size_r_bracket);
// calculate json string length
ptr = list_getNext(tokenList);
dow (ptr <> *null);
json_string_length += strlen(ptr);
ptr = list_getNext(tokenList);
enddo;
// +1 for hex Null
json_string_length += 1;
// allocate memory for json string
json_string_ptr = %alloc(json_string_length);
// build json string
ptr = list_getNext(tokenList);
dow (ptr <> *null);
tmpLength = strlen(ptr);
memcpy(json_string_ptr + x : ptr : tmpLength);
x += tmpLength;
ptr = list_getNext(tokenList);
enddo;
// append hex null
memcpy(json_string_ptr + x : %addr(hex_null) : 1);
// clean up
if (tokenList <> *null);
list_dispose(tokenList);
endif;
return json_string_ptr;
begsr init;
if (outputFormat = JSON_OUTPUT_COMPACT);
l_chars = chars_compact;
else;
l_chars = chars;
endif;
endsr;
/end-free
P E
/**
* \brief Add null value entry
*
* Adds an entry of type null to the array.
*
* \author Mihael Schmidt
* \date 11.05.2008
*
* \param Pointer to the JSON array
* \param Index (default: last)
*/
P jsona_putNull B export
D PI
D jsonArrPtr * const
D index 10U 0 const options(*nopass)
/free
tmpl_array_entry .type = JSON_TYPE_NULL;
tmpl_array_entry .string = 'null';
if (%parms() = 1);
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : 4 + 4);
else;
list_add(jsonArrPtr : %addr(tmpl_array_entry ) : 4 + 4 : index);
endif;
/end-free
P E
/**
* \brief Add JSON object entry
*
* Adds an entry of type object to the array.
*
* \author Mihael Schmidt
* \date 11.05.2008
*
* \param Pointer to the JSON array
* \param Pointer to the JSON object
* \param Index (default: last)
*/
P jsona_putObject...
P B export
D PI
D jsonArrPtr * const
D objPtr * const
D index 10U 0 const options(*nopass)
D tmpDs DS qualified
D type 10I 0
D object *
/free
tmpDs.type = JSON_TYPE_OBJECT;
tmpDs.object = objPtr;
if (%parms() = 2);
list_add(jsonArrPtr : %addr(tmpDs) : %size(tmpDs));
else;
list_add(jsonArrPtr : %addr(tmpDs) : %size(tmpDs) : index);
endif;
/end-free
P E
/**
* \brief Get object entry
*
* Returns a pointer to the object.
*
*
*
* If the entry is not of type object an escape message will be send.
*
* \author Mihael Schmidt
* \date 11.05.2008
*
* \param Pointer to the JSON array
* \param Index
*
* \return Pointer to the JSON object
*/
P jsona_getObject...
P B export
D PI *
D jsonArrPtr * const
D index 10U 0 const
*
D tmpPtr S *
D tmpDs DS qualified based(tmpPtr)
D type 10I 0
D object *
/free
tmpPtr = list_get(jsonArrPtr : index);
if (tmpPtr <> *null);
if (tmpDs.type = JSON_TYPE_OBJECT);
return tmpDs.object;
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
else;
sendEscapeMessage(MSG_ARRAY_ELEMENT_NOT_FOUND);
endif;
return *null; // dummy => will never come to this point
/end-free
P E
/**
* \brief Get array size
*
* Returns the number of elements in the array.
*
* \param Pointer to the json array
*
* \return number of elements
*/
P jsona_size B export
D PI 10U 0
D jsonArrPtr * const
/free
return list_size(jsonArrPtr);
/end-free
P E
/**
* \brief Get entry type
*
* Returns the type of the entry.
*
* \param Pointer to the JSON object
* \param Key
*
* \return Entry type
*
* \throws CPF9898 Array element not found
*/
P jsona_getEntryType...
P B export
D PI 10I 0
D jsonPtr * const
D index 10U 0 const
*
D type S 10I 0
D tmpPtr S *
D tmpDs DS qualified based(tmpPtr)
D type 10I 0
/free
tmpPtr = list_get(jsonPtr : index);
if (tmpPtr <> *null);
type = tmpDs.type;
else;
sendEscapeMessage(MSG_ARRAY_ELEMENT_NOT_FOUND);
endif;
return type;
/end-free
P E
json/json_c.rpgle 100666 2763 0 4606 11515400046 12025 0 ustar 00MSCHMIDT /if not defined (JSON_C)
/define JSON_C
/*
* Copyright (c) 2007-2010 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*/
*-------------------------------------------------------------------------
* Constants
*-------------------------------------------------------------------------
*
* Message IDs
*
D MSG_NO_JSON_OBJECT...
D C 1
D MSG_ENTRY_TYPE_MISMATCH...
D C 2
D MSG_ARRAY_ELEMENT_NOT_FOUND...
D C 3
D MSG_TYPE_CAST_EXCEPTION...
D C 4
D MSG_FILE_OUTPUT_ERROR...
D C 5
D MSG_ENTRY_NOT_FOUND...
D C 6
*
* Types
*
D JSON_TYPE_BOOLEAN...
D C 1
D JSON_TYPE_INT C 2
D JSON_TYPE_LONG C 3
D JSON_TYPE_DOUBLE...
D C 4
D JSON_TYPE_STRING...
D C 5
D JSON_TYPE_ARRAY...
D C 6
D JSON_TYPE_OBJECT...
D C 7
D JSON_TYPE_NULL C 8
*
* Output types
*
D JSON_OUTPUT_NORMAL...
D C 0
D JSON_OUTPUT_PRETTY_PRINT...
D C 1
D JSON_OUTPUT_COMPACT...
D C 2
/endif
json/json_int_h.rpgle 100666 2763 0 12226 11515400051 12715 0 ustar 00MSCHMIDT /*
* Copyright (c) 2007-2009 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*/
*------------------------------------------------------------------------
* Prototypes of internal procedures (shared among the modules)
*------------------------------------------------------------------------
D sendEscapeMessage...
D PR
D id 10I 0 const
*
D escapeLastToken...
D PR
D tokenList *
*
D sendDiagnosticMessage...
D PR
D message 200A const
*
D isJSONImpl...
D PR
D jsonPtr * const
*
D getJSONEntry PR *
D jsonPtr * const
D keyPtr * const
D keyLength 10U 0 const
*
D disposeEntryValue...
D PR
D entryPtr *
*
D prettyPrint PR
D tokenList * const
D printFormat const likeds(json_prettyPrintFormat)
D indentationLevel...
D 10I 0 const
*-------------------------------------------------------------------------
* Special Characters
*-------------------------------------------------------------------------
D tmpl_chars DS qualified based(nullPointer)
D d_quote 6A
D l_brace 6A
D r_brace 6A
D l_bracket 6A
D r_bracket 6A
D comma 6A
D colon 6A
D true 6A
D false 6A
D null_str 6A
D size_d_quote...
D 5I 0
D size_l_brace...
D 5I 0
D size_r_brace...
D 5I 0
D size_l_bracket...
D 5I 0
D size_r_bracket...
D 5I 0
D size_comma...
D 5I 0
D size_colon...
D 5I 0
D size_true...
D 5I 0
D size_false...
D 5I 0
D size_null_str...
D 5I 0
*-------------------------------------------------------------------------
* Data Structures
*-------------------------------------------------------------------------
/*
* If the json object has only one entry, the pointer for the firstand last
* entry points to the same entry. If the list has no entries both pointers
* has a *null value.
*
*
*
* The field iteration has the default value of -1. It means that no
* iteration is currently going on.
*
*/
D tmpl_header DS qualified based(template)
D id 20A
D size 10U 0
D firstEntry *
D lastEntry *
D iteration 10I 0
D iterNextEntry...
D *
D iterPrevEntry...
D *
D disposeList...
D *
*
D tmpl_entry DS qualified based(template)
D type 10I 0
D prev *
D next *
D key *
D keyLength 10U 0
D value *
D valueLength 10U 0
*
D tmpl_array_entry...
D DS qualified
D type 10I 0
D x 65531A
D string 65531A overlay(x)
D boolean N overlay(x)
D integer 10I 0 overlay(x)
D long 20I 0 overlay(x)
D double 8F overlay(x)
json/json_chk.c 100666 2763 0 31654 11515400046 11504 0 ustar 00MSCHMIDT /* JSON_checker.c */
/* 2007-08-24 */
/*
Copyright (c) 2005 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include
#include "json_chk.h"
#define true 1
#define false 0
#define __ -1 /* the universal error code */
/*
Characters are mapped into these 31 character classes. This allows for
a significant reduction in the size of the state transition table.
*/
enum classes {
C_SPACE, /* space */
C_WHITE, /* other whitespace */
C_LCURB, /* { */
C_RCURB, /* } */
C_LSQRB, /* [ */
C_RSQRB, /* ] */
C_COLON, /* : */
C_COMMA, /* , */
C_QUOTE, /* " */
C_BACKS, /* \ */
C_SLASH, /* / */
C_PLUS, /* + */
C_MINUS, /* - */
C_POINT, /* . */
C_ZERO , /* 0 */
C_DIGIT, /* 123456789 */
C_LOW_A, /* a */
C_LOW_B, /* b */
C_LOW_C, /* c */
C_LOW_D, /* d */
C_LOW_E, /* e */
C_LOW_F, /* f */
C_LOW_L, /* l */
C_LOW_N, /* n */
C_LOW_R, /* r */
C_LOW_S, /* s */
C_LOW_T, /* t */
C_LOW_U, /* u */
C_ABCDF, /* ABCDF */
C_E, /* E */
C_ETC, /* everything else */
NR_CLASSES
};
static int ascii_class[128] = {
/*
This array maps the 128 ASCII characters into character classes.
The remaining Unicode characters should be mapped to C_ETC.
Non-whitespace control characters are errors.
*/
__, __, __, __, __, __, __, __,
__, C_WHITE, C_WHITE, __, __, C_WHITE, __, __,
__, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __,
C_SPACE, C_ETC, C_QUOTE, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC,
C_ETC, C_ETC, C_ETC, C_PLUS, C_COMMA, C_MINUS, C_POINT, C_SLASH,
C_ZERO, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT,
C_DIGIT, C_DIGIT, C_COLON, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC,
C_ETC, C_ABCDF, C_ABCDF, C_ABCDF, C_ABCDF, C_E, C_ABCDF, C_ETC,
C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC,
C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC,
C_ETC, C_ETC, C_ETC, C_LSQRB, C_BACKS, C_RSQRB, C_ETC, C_ETC,
C_ETC, C_LOW_A, C_LOW_B, C_LOW_C, C_LOW_D, C_LOW_E, C_LOW_F, C_ETC,
C_ETC, C_ETC, C_ETC, C_ETC, C_LOW_L, C_ETC, C_LOW_N, C_ETC,
C_ETC, C_ETC, C_LOW_R, C_LOW_S, C_LOW_T, C_LOW_U, C_ETC, C_ETC,
C_ETC, C_ETC, C_ETC, C_LCURB, C_ETC, C_RCURB, C_ETC, C_ETC
};
/*
The state codes.
*/
enum states {
GO, /* start */
OK, /* ok */
OB, /* object */
KE, /* key */
CO, /* colon */
VA, /* value */
AR, /* array */
ST, /* string */
ES, /* escape */
U1, /* u1 */
U2, /* u2 */
U3, /* u3 */
U4, /* u4 */
MI, /* minus */
ZE, /* zero */
IN, /* integer */
FR, /* fraction */
E1, /* e */
E2, /* ex */
E3, /* exp */
T1, /* tr */
T2, /* tru */
T3, /* true */
F1, /* fa */
F2, /* fal */
F3, /* fals */
F4, /* false */
N1, /* nu */
N2, /* nul */
N3, /* null */
NR_STATES
};
static int state_transition_table[NR_STATES][NR_CLASSES] = {
/*
The state transition table takes the current state and the current symbol,
and returns either a new state or an action. An action is represented as a
negative number. A JSON text is accepted if at the end of the text the
state is OK and if the mode is MODE_DONE.
white 1-9 ABCDF etc
space | { } [ ] : , " \ / + - . 0 | a b c d e f l n r s t u | E |*/
/*start GO*/ {GO,GO,-6,__,-5,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
/*ok OK*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
/*object OB*/ {OB,OB,__,-9,__,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
/*key KE*/ {KE,KE,__,__,__,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
/*colon CO*/ {CO,CO,__,__,__,__,-2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
/*value VA*/ {VA,VA,-6,__,-5,__,__,__,ST,__,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__},
/*array AR*/ {AR,AR,-6,__,-5,-7,__,__,ST,__,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__},
/*string ST*/ {ST,__,ST,ST,ST,ST,ST,ST,-4,ES,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST},
/*escape ES*/ {__,__,__,__,__,__,__,__,ST,ST,ST,__,__,__,__,__,__,ST,__,__,__,ST,__,ST,ST,__,ST,U1,__,__,__},
/*u1 U1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U2,U2,U2,U2,U2,U2,U2,U2,__,__,__,__,__,__,U2,U2,__},
/*u2 U2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U3,U3,U3,U3,U3,U3,U3,U3,__,__,__,__,__,__,U3,U3,__},
/*u3 U3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U4,U4,U4,U4,U4,U4,U4,U4,__,__,__,__,__,__,U4,U4,__},
/*u4 U4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ST,ST,ST,ST,ST,ST,ST,ST,__,__,__,__,__,__,ST,ST,__},
/*minus MI*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ZE,IN,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
/*zero ZE*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,FR,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
/*int IN*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,FR,IN,IN,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
/*frac FR*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,FR,FR,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
/*e E1*/ {__,__,__,__,__,__,__,__,__,__,__,E2,E2,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
/*ex E2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
/*exp E3*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
/*tr T1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T2,__,__,__,__,__,__},
/*tru T2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T3,__,__,__},
/*true T3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__},
/*fa F1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F2,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
/*fal F2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F3,__,__,__,__,__,__,__,__},
/*fals F3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F4,__,__,__,__,__},
/*false F4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__},
/*nu N1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N2,__,__,__},
/*nul N2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N3,__,__,__,__,__,__,__,__},
/*null N3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__},
};
/*
These modes can be pushed on the stack.
*/
enum modes {
MODE_ARRAY,
MODE_DONE,
MODE_KEY,
MODE_OBJECT
};
static int
reject(JSON_checker jc)
{
/*
Delete the JSON_checker object.
*/
free((void*)jc->stack);
free((void*)jc);
return false;
}
static int
push(JSON_checker jc, int mode)
{
/*
Push a mode onto the stack. Return false if there is overflow.
*/
jc->top += 1;
if (jc->top >= jc->depth) {
return false;
}
jc->stack[jc->top] = mode;
return true;
}
static int
pop(JSON_checker jc, int mode)
{
/*
Pop the stack, assuring that the current mode matches the expectation.
Return false if there is underflow or if the modes mismatch.
*/
if (jc->top < 0 || jc->stack[jc->top] != mode) {
return false;
}
jc->top -= 1;
return true;
}
JSON_checker
json_new_checker(int depth)
{
/*
json_new_checker starts the checking process by constructing a JSON_checker
object. It takes a depth parameter that restricts the level of maximum
nesting.
To continue the process, call JSON_checker_char for each character in the
JSON text, and then call JSON_checker_done to obtain the final result.
These functions are fully reentrant.
The JSON_checker object will be deleted by JSON_checker_done.
JSON_checker_char will delete the JSON_checker object if it sees an error.
*/
JSON_checker jc = (JSON_checker)malloc(sizeof(struct json_checker_struct));
jc->state = GO;
jc->depth = depth;
jc->top = -1;
jc->stack = (int*)calloc(depth, sizeof(int));
push(jc, MODE_DONE);
return jc;
}
int
json_checker_char(JSON_checker jc, int next_char)
{
/*
After calling new_JSON_checker, call this function for each character (or
partial character) in your JSON text. It can accept UTF-8, UTF-16, or
UTF-32. It returns true if things are looking ok so far. If it rejects the
text, it deletes the JSON_checker object and returns false.
*/
int next_class, next_state;
/*
Determine the character's class.
*/
if (next_char < 0) {
return reject(jc);
}
if (next_char >= 128) {
next_class = C_ETC;
} else {
next_class = ascii_class[next_char];
if (next_class <= __) {
return reject(jc);
}
}
/*
Get the next state from the state transition table.
*/
next_state = state_transition_table[jc->state][next_class];
if (next_state >= 0) {
/*
Change the state.
*/
jc->state = next_state;
} else {
/*
Or perform one of the actions.
*/
switch (next_state) {
/* empty } */
case -9:
if (!pop(jc, MODE_KEY)) {
return reject(jc);
}
jc->state = OK;
break;
/* } */ case -8:
if (!pop(jc, MODE_OBJECT)) {
return reject(jc);
}
jc->state = OK;
break;
/* ] */ case -7:
if (!pop(jc, MODE_ARRAY)) {
return reject(jc);
}
jc->state = OK;
break;
/* { */ case -6:
if (!push(jc, MODE_KEY)) {
return reject(jc);
}
jc->state = OB;
break;
/* [ */ case -5:
if (!push(jc, MODE_ARRAY)) {
return reject(jc);
}
jc->state = AR;
break;
/* " */ case -4:
switch (jc->stack[jc->top]) {
case MODE_KEY:
jc->state = CO;
break;
case MODE_ARRAY:
case MODE_OBJECT:
jc->state = OK;
break;
default:
return reject(jc);
}
break;
/* , */ case -3:
switch (jc->stack[jc->top]) {
case MODE_OBJECT:
/*
A comma causes a flip from object mode to key mode.
*/
if (!pop(jc, MODE_OBJECT) || !push(jc, MODE_KEY)) {
return reject(jc);
}
jc->state = KE;
break;
case MODE_ARRAY:
jc->state = VA;
break;
default:
return reject(jc);
}
break;
/* : */ case -2:
/*
A colon causes a flip from key mode to object mode.
*/
if (!pop(jc, MODE_KEY) || !push(jc, MODE_OBJECT)) {
return reject(jc);
}
jc->state = VA;
break;
/*
Bad action.
*/
default:
return reject(jc);
}
}
return true;
}
int
json_checker_done(JSON_checker jc)
{
/*
The JSON_checker_done function should be called after all of the characters
have been processed, but only if every call to JSON_checker_char returned
true. This function deletes the JSON_checker and returns true if the JSON
text was accepted.
*/
int result = jc->state == OK && pop(jc, MODE_DONE);
reject(jc);
return result;
}
json/json_inz.ccp 100666 2763 0 132 11515400051 12001 0 ustar 00MSCHMIDT extern "C" { int json_srvpgm_init(void); }
static int dummyInitVar = json_srvpgm_init();
json/json_arr_h.rpgle 100666 2763 0 13506 11515400045 12714 0 ustar 00MSCHMIDT /if not defined (JSON_ARR)
/define JSON_ARR
/*
* Copyright (c) 2007-2009 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*/
*-------------------------------------------------------------------------
* Prototypes
*-------------------------------------------------------------------------
D jsona_create PR * extproc('jsona_create')
*
D jsona_dispose PR extproc('jsona_dispose')
D jsonArrPtr *
*
D jsona_remove PR extproc('jsona_remove') opdesc
D jsonArrPtr * const
D index 10I 0 const
*
D jsona_clear PR extproc('jsona_clear')
D jsonArrPtr * const
*
D jsona_putString...
D PR extproc('jsona_putString') opdesc
D jsonArrPtr * const
D value 65535A const options(*varsize)
D index 10U 0 const options(*nopass)
*
D jsona_putBoolean...
D PR extproc('jsona_putBoolean')
D jsonArrPtr * const
D value N const
D index 10U 0 const options(*nopass)
*
D jsona_putInt...
D PR extproc('jsona_putInt')
D jsonArrPtr * const
D value 10I 0 const
D index 10U 0 const options(*nopass)
*
D jsona_putLong...
D PR extproc('jsona_putLong')
D jsonArrPtr * const
D value 20I 0 const
D index 10U 0 const options(*nopass)
*
D jsona_putDouble...
D PR extproc('jsona_putDouble')
D jsonArrPtr * const
D value 8F const
D index 10U 0 const options(*nopass)
*
D jsona_putArray...
D PR extproc('jsona_putArray')
D jsonArrPtr * const
D value * const
D index 10U 0 const options(*nopass)
*
D jsona_getString...
D PR * extproc('jsona_getString')
D jsonArrPtr * const
D index 10U 0 const
*
D jsona_getBoolean...
D PR N extproc('jsona_getBoolean')
D jsonArrPtr * const
D index 10U 0 const
*
D jsona_getInt...
D PR 10I 0 extproc('jsona_getInt')
D jsonArrPtr * const
D index 10U 0 const
*
D jsona_getLong...
D PR 20I 0 extproc('jsona_getLong')
D jsonArrPtr * const
D index 10U 0 const
*
D jsona_getDouble...
D PR 8F extproc('jsona_getDouble')
D jsonArrPtr * const
D index 10U 0 const
*
D jsona_getArray...
D PR * extproc('jsona_getArray')
D jsonArrPtr * const
D index 10U 0 const
*
D jsona_toString...
D PR * extproc('jsona_toString')
D jsonArrPtr * const
D pOutputFormat...
D 10I 0 const options(*nopass)
D pPrettyPrintFormat...
D likeds(json_prettyPrintFormat)
D const options(*nopass)
D pIndentationLevel...
D 10I 0 options(*nopass)
*
D jsona_putNull PR extproc('jsona_putNull')
D jsonPtr * const
D index 10U 0 const options(*nopass)
*
D jsona_putObject...
D PR extproc('jsona_putObject')
D jsonPtr * const
D objPtr * const
D index 10U 0 const options(*nopass)
*
D jsona_getObject...
D PR * extproc('jsona_getObject')
D jsonPtr * const
D index 10U 0 const
*
D jsona_size PR 10U 0 extproc('jsona_size')
D jsonArrPtr * const
*
D jsona_getEntryType...
D PR 10I 0 extproc('jsona_getEntryType')
D jsonPtr * const
D index 10U 0 const
/endif
json/lgpl-3.0.txt 100666 2763 0 16725 11515400055 11541 0 ustar 00MSCHMIDT GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
json/jsona_inz.cpp 100666 2763 0 134 11515400054 12164 0 ustar 00MSCHMIDT extern "C" { int jsona_srvpgm_init(void); }
static int dummyInitVar = jsona_srvpgm_init();
json/iconv_h.rpgle 100666 2763 0 4027 11515400044 12172 0 ustar 00MSCHMIDT *---------------------------------------------------------------
* Data structures
*---------------------------------------------------------------
D iconv_t DS based(prototype_only) qualified
D return_value 10I 0
D cd 10I 0 dim(12)
*
D iconv_from DS qualified
D ccsid 10I 0 inz(0)
D convAlt 10I 0 inz(0)
D subsAlt 10I 0 inz(0)
D shiftAlt 10I 0 inz(1)
D inpLenOp 10I 0 inz(0)
D errorOpt 10I 0 inz(1)
D reserved 8A inz(*ALLx'00')
*
D iconv_to DS qualified
D ccsid 10I 0 inz(819)
D convAlt 10I 0 inz(0)
D subsAlt 10I 0 inz(0)
D shiftAlt 10I 0 inz(1)
D inpLenOp 10I 0 inz(0)
D errorOpt 10I 0 inz(1)
D reserved 8A inz(*ALLx'00')
*---------------------------------------------------------------
* Prototypes
*---------------------------------------------------------------
D iconv_open PR extproc('QtqIconvOpen')
D like(iconv_t)
D tocode like(iconv_to) const
D fromcode like(iconv_from) const
*
D iconv PR 10I 0 extproc('iconv')
D cd like(iconv_t) value
D inbuf *
D inbytesleft 10U 0
D outbuf *
D outbytesleft 10U 0
*
D iconv_close PR 10I 0 extproc('iconv_close')
D cd like(iconv_t) value
json/json_util.rpgle 100666 2763 0 42374 11515400053 12602 0 ustar 00MSCHMIDT /**
* \brief JSON : Utilities
*
* Utilities module for the JSON service program.
*
* \author Mihael Schmidt
* \date 31.01.2010
*
* \link http://www.rpgnextgen.com RPG Next Gen
* \link http://www.json.org JSON
*
* \todo json_util_dataStructureToJsonObject : pointer to datastructure as parm
*
* \rev 01.08.2010 Mihael Schmidt
* added date data type support
*
* \rev 26.11.2010 Mihael Schmidt
* added toFile/fromFile procedures
*/
*-------------------------------------------------------------------------
* Copyright (c) 2010 Mihael Schmidt
* All rights reserved.
*
* This file is part of the JSON service program.
*
* JSON service program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JSON service program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JSON service program. If not, see http://www.gnu.org/licenses/.
*-------------------------------------------------------------------------
H nomain
H bnddir('QC2LE')
H copyright('Copyright (c) 2010 Mihael Schmidt. All rights reserved.')
*-------------------------------------------------------------------------
* Prototypes
*-------------------------------------------------------------------------
D sendProgramMessage...
D PR extpgm('QMHSNDPM')
D szMsgID 7A const
D szMsgFile 20A const
D szMsgData 6000A const options(*varsize)
D nMsgDataLen 10I 0 const
D szMsgType 10A const
D szCallStkEntry...
D 10A const
D nRelativeCallStkEntry...
D 10I 0 const
D szRtnMsgKey 4A
D error 265A options(*varsize)
*
D errno PR * extproc('__errno')
*
D strerr PR * extproc('strerror')
D errnum 10I 0 value
*
/copy 'json_h.rpgle'
/copy 'json_int_h.rpgle'
/copy 'ifsio_h.rpgle'
/copy 'libc_h.rpgle'
/copy 'ceeapi_h.rpgle'
/copy 'llist_h.rpgle'
/if not defined (QUSEC)
/define QUSEC
/copy QSYSINC/QRPGLESRC,QUSEC
/endif
*-------------------------------------------------------------------------
* Constants
*-------------------------------------------------------------------------
/copy 'json_c.rpgle'
*-------------------------------------------------------------------------
* Global Variables
*-------------------------------------------------------------------------
*
* Parameters passed to CEEDOD
*
D descType S 10I 0
D dataType S 10I 0
D descInfo1 S 10I 0
D descInfo2 S 10I 0
D length S 10I 0
*-------------------------------------------------------------------------
* Procedures
*-------------------------------------------------------------------------
/**
* \brief Get date entry
*
* A convenience procedure for get a date from a string entry.
* The string must be in *ISO format (yyyy-mm-dd).
*
*
*
* If the entry is not of type string or the entry is not a date string
* in *ISO format an escape message will be send.
*
* \author Mihael Schmidt
* \date 01.08.2010
*
* \param Pointer to the JSON object
* \param Key
*
* \return Date
*/
P json_util_getDate...
P B export
D PI D opdesc
D json * const
D key 65535A const options(*varsize)
*
D tmpKey S 65535A
D header DS likeds(tmpl_header) based(json)
D entry DS likeds(tmpl_entry) based(entryPtr)
D retVal S D
/free
isJSONImpl(json);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
tmpKey = %subst(key : 1 : length);
entryPtr = getJSONEntry(json : %addr(tmpKey) : length);
if (entryPtr <> *null);
if (entry.type = JSON_TYPE_STRING);
retVal = %date(%str(entry.value) : *ISO);
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
endif;
return retVal;
/end-free
P E
/**
* \brief Add date entry
*
* Convenience procedure for adding a date string in *ISO format to the
* json object.
*
* \author Mihael Schmidt
* \date 2010-08-01
*
* \param Pointer to the JSON object
* \param Key
* \param Date
*/
P json_util_putDate...
P B export
D PI opdesc
D jsonPtr * const
D key 65535A const options(*varsize)
D value D const
*
D header DS likeds(tmpl_header) based(jsonPtr)
D prevEntryPtr S *
D prevEntry DS likeds(tmpl_entry)
D based(prevEntryPtr)
D newEntryPtr S *
D newEntry DS likeds(tmpl_entry)
D based(newEntryPtr)
D tmpPtr S *
D tmpKey S 65535A
D tmpValue S 10A
D keyLength S 10I 0
D hexnull S 1A inz(x'00')
/free
isJSONImpl(jsonPtr);
cee_getOpDescInfo(2 : descType : dataType : descInfo1 : descInfo2 :
length : *omit);
keyLength = length;
tmpKey = %subst(key : 1 : keyLength);
tmpValue = %char(value : *ISO);
// check if key is already in the map
newEntryPtr = getJSONEntry(jsonPtr : %addr(tmpKey) : keyLength);
if (newEntryPtr = *null); // entry not in json object
// create new entry
newEntryPtr = %alloc(%size(tmpl_entry));
newEntry.type = JSON_TYPE_STRING;
newEntry.keyLength = keyLength + 1; // +1 for the null byte
newEntry.key = %alloc(keyLength + 1); // +1 for the null byte
newEntry.valueLength = %size(tmpValue);
newEntry.value = %alloc(%size(tmpValue) + 1); // +1 for the null byte
newEntry.next = *null;
newEntry.prev = *null;
// update header
header.size += 1;
if (header.firstEntry = *null);
header.firstEntry = newEntryPtr;
else;
prevEntryPtr = header.lastEntry;
prevEntry.next = newEntryPtr;
newEntry.prev = prevEntryPtr;
endif;
header.lastEntry = newEntryPtr;
else;
// entry needs to be resized
newEntry.type = JSON_TYPE_STRING;
newEntry.keyLength = keyLength + 1;
newEntry.key = %realloc(newEntry.key : keyLength + 1);
newEntry.valueLength = %size(tmpValue);
// dispose/dealloc old value
disposeEntryValue(newEntryPtr);
endif;
// copy value to the list entry
memcpy(newEntry.key : %addr(tmpKey) : keyLength);
memcpy(newEntry.value : %addr(tmpValue) : %size(tmpValue));
// set null to the last byte
memcpy(newEntry.key + keyLength : %addr(hexNull) : 1);
memcpy(newEntry.value + %size(tmpValue) : %addr(hexNull) : 1);
/end-free
P E
/**
* \brief Get date entry
*
* A convenience procedure for get a date from a string entry.
* The string must be in *ISO format (yyyy-mm-dd).
*
*
*
* If the entry is not of type string or the entry is not a date string
* in *ISO format an escape message will be send.
*
* \author Mihael Schmidt
* \date 01.08.2010
*
* \param Pointer to the JSON array
* \param Index
*
* \return Date
*/
P jsona_util_getDate...
P B export
D PI D
D jsonArrPtr * const
D index 10U 0 const
*
D entry DS likeds(tmpl_array_entry) based(ptr)
/free
ptr = list_get(jsonArrPtr : index);
if (ptr <> *null);
if (entry.type = JSON_TYPE_STRING);
return %date(%str(ptr + 4) : *ISO);
else;
sendEscapeMessage(MSG_ENTRY_TYPE_MISMATCH);
endif;
else;
sendEscapeMessage(MSG_ARRAY_ELEMENT_NOT_FOUND);
endif;
return %date(); // dummy => will never come to this point
/end-free
P E
/**
* \brief Add date entry
*
* Convenience procedure for adding a date string in *ISO format to the
* JSON array.
*
* \author Mihael Schmidt
* \date 01.08.2010
*
* \param Pointer to the JSON array
* \param Date
* \param Index (default: last)
*/
P jsona_util_putDate...
P B export
D PI
D jsonArrPtr * const
D value D const
D index 10U 0 const options(*nopass)
*
D entry DS likeds(tmpl_array_entry) inz
/free
entry.type = JSON_TYPE_STRING;
entry.string = %char(value : *ISO);
if (%parms() = 2);
list_add(jsonArrPtr : %addr(entry) : 10 + 4);
else;
list_add(jsonArrPtr : %addr(entry) : 10 + 4 : index);
endif;
/end-free
P E
/**
* \brief Output JSON Object to stream file
*
* \param JSON Object
* \param Stream file path
* \param CCSID (optional)
* \param Delete if file exist (optional)
*
* \throws CPF9898 Error on opening file
*/
P json_util_toFile...
P B export
D PI
D json * const
D filePath 1024A const
D pCcsid 10I 0 const options(*nopass : *omit)
D pDeleteFile N const options(*nopass : *omit)
D pOutputFormat...
D 10I 0 const options(*nopass)
D pPrettyPrintFormat...
D likeds(json_prettyPrintFormat)
D const options(*nopass)
*
D outputFormat S 10I 0
D prettyPrintOption...
D S N inz(*off)
D prettyPrintFormat...
D DS likeds(json_prettyPrintFormat) inz
D ccsid S 10I 0 inz(0)
D deleteFile S N inz(*off)
D jsonString S *
D fileHandle S 10I 0
D flags S 10I 0
D mode S 10I 0
D errorNumber S 10I 0 based(errorPtr)
D errorString S 1024A varying
D msgdata S 512A
D msgkey S 4A
/free
if (%parms() >= 3 and %addr(pCcsid) <> *null);
ccsid = pCcsid;
endif;
if (%parms() >= 4 and %addr(pDeleteFile) <> *null);
deleteFile = pDeleteFile;
endif;
if (%parms() >= 5);
outputFormat = pOutputFormat;
prettyPrintFormat.useTabs = *off;
prettyPrintFormat.numberWhitespace = 4;
prettyPrintFormat.breakAfterElement = *on;
prettyPrintFormat.breakAfterObjectBrace = *on;
prettyPrintFormat.breakBeforeArrayBrace = *on;
prettyPrintFormat.breakAfterArrayBrace = *on;
endif;
if (%parms() >= 6);
prettyPrintFormat = pPrettyPrintFormat;
endif;
if (outputFormat = JSON_OUTPUT_PRETTY_PRINT);
prettyPrintOption = *on;
endif;
if (deleteFile);
if (access(%trimr(filePath) : F_OK) >= 0);
// file exists => delete
system('RMVLNK OBJLNK(''' + %trimr(filePath) + ''')');
endif;
endif;
// create file
flags = O_WRONLY + O_CREAT + O_APPEND + O_TEXTDATA +
O_CCSID + O_TEXT_CREAT;
mode = S_IRUSR + S_IWUSR + S_IRGRP + S_IROTH;
fileHandle = open(%trimr(filePath) : flags : mode : ccsid : 0);
if (fileHandle < 0);
// could not create file
errorPtr = errno();
errorString = 'I/O Error: ' + %str(strerr(errorNumber));
msgdata = 'Could not create file ' + %trimr(filePath) +
': ' + errorString;
clear QUSEC;
QUSBPRV = 0;
sendProgramMessage('CPF9898' :
'QCPFMSG *LIBL ' :
%trimr(msgdata) :
%len(%trimr(msgdata)) :
'*ESCAPE ' :
'*PGMBDY' :
0 :
msgkey :
QUSEC);
endif;
jsonString = json_toString(json : outputFormat : prettyPrintFormat);
callp write(fileHandle : jsonString : strlen(jsonString));
dealloc(n) jsonString;
callp close(fileHandle);
/end-free
P E
/**
* \brief Read JSON from stream file
*
* \param Stream file path
* \param Delete file after reading (optional)
*
* \return JSON object
*
* \throws CPF9898 Error on reading file
* \throws CPF9898 File not found
* \throws CPF9898 Error buildng JSON object
*/
P json_util_fromFile...
P B export
D PI *
D filePath 1024A const
D pDeleteFile N const options(*nopass)
*
D json S *
D deleteFile S N inz(*off)
D buffer S *
D fileSize S 10I 0
D fileStatus DS likeds(statds)
D fileHandle S 10I 0
D flags S 10I 0
D errorNumber S 10I 0 based(errorPtr)
D errorString S 1024A varying
D msgdata S 512A
D msgkey S 4A
/free
if (%parms() = 2);
deleteFile = pDeleteFile;
endif;
if (stat(%trimr(filePath) : %addr(fileStatus)) < 0);
msgdata = 'Could not query file attributes for file ' +
%trimr(filepath) + '.';
clear QUSEC;
QUSBPRV = 0;
sendProgramMessage('CPF9898' :
'QCPFMSG *LIBL ' :
%trimr(msgdata) :
%len(%trimr(msgdata)) :
'*ESCAPE ' :
'*PGMBDY' :
0 :
msgkey :
QUSEC);
endif;
flags = O_RDONLY + O_TEXTDATA;
fileHandle = open(%trimr(filePath) : flags);
if (fileHandle < 0);
// could not open file
errorPtr = errno();
errorString = 'I/O Error: ' + %str(strerr(errorNumber));
msgdata = 'Could not open file ' + %trimr(filePath) + ': '+errorString;
clear QUSEC;
QUSBPRV = 0;
sendProgramMessage('CPF9898' :
'QCPFMSG *LIBL ' :
%trimr(msgdata) :
%len(%trimr(msgdata)) :
'*ESCAPE ' :
'*PGMBDY' :
0 :
msgkey :
QUSEC);
endif;
buffer = %alloc(fileStatus.st_size);
callp read(fileHandle : buffer : fileStatus.st_size);
callp close(fileHandle);
json = json_parse(buffer);
// clean up
dealloc buffer;
if (deleteFile);
if (access(%trimr(filePath) : F_OK) >= 0);
// file exists => delete
system('RMVLNK OBJLNK(''' + %trimr(filePath) + ''')');
endif;
endif;
return json;
/end-free
P E
json/unicode_c.rpgle 100666 2763 0 2411 11515400056 12473 0 ustar 00MSCHMIDT /if not defined (UNICODE_CONSTANTS)
/define UNICODE_CONSTANTS
D UNICODE_SLASH...
D C u'002F'
D UNICODE_BACKSLASH...
D C u'005C'
D UNICODE_APOSTROPHE...
D C u'0027'
D UNICODE_DOUBLE_QUOTE...
D C u'0022'
D UNICODE_LEFT_CURLY_BRACE...
D C u'007B'
D UNICODE_RIGHT_CURLY_BRACE...
D C u'007D'
D UNICODE_LEFT_BRACKET...
D C u'005B'
D UNICODE_RIGHT_BRACKET...
D C u'005D'
D UNICODE_LEFT_BRACE...
D C u'0028'
D UNICODE_RIGHT_BRACE...
D C u'0029'
D UNICODE_COLON...
D C u'003A'
D UNICODE_SEMICOLON...
D C u'003B'
D UNICODE_COMMA...
D C u'002C'
D UNICODE_DOT...
D C u'002E'
D UNICODE_EQUAL...
D C u'003D'
/endif
json/json_util_h.rpgle 100666 2763 0 4060 11515400053 13057 0 ustar 00MSCHMIDT /if not defined(JSON_UTL_H)
/define JSON_UTL_H
*-------------------------------------------------------------------------
* Prototypes : JSON Utilities
*-------------------------------------------------------------------------
D json_util_getDate...
D PR D extproc('json_util_getDate') opdesc
D json * const
D key 65535A const options(*varsize)
*
D json_util_putDate...
D PR extproc('json_util_putDate') opdesc
D json * const
D key 65535A const options(*varsize)
D value D const
*
D jsona_util_getDate...
D PR D extproc('jsona_util_getDate')
D json * const
D index 10U 0 const
*
D jsona_util_putDate...
D PR extproc('jsona_util_putDate')
D json * const
D value D const
D index 10U 0 const options(*nopass)
*
D json_util_fromFile...
D PR * extproc('json_util_fromFile')
D filePath 1024A const
D pDeleteFile N const options(*nopass)
*
D json_util_toFile...
D PR extproc('json_util_toFile')
D json * const
D filePath 1024A const
D pCcsid 10I 0 const options(*nopass : *omit)
D pDeleteFile N const options(*nopass : *omit)
D pOutputFormat...
D 10I 0 const options(*nopass)
D pPrettyPrintFormat...
D likeds(json_prettyPrintFormat)
D const options(*nopass)
/endif
json/Makefile 100666 2763 0 4361 11526203145 11160 0 ustar 00MSCHMIDT #
# Makefile for JSON service program
#
#-----------------------------------------------------------
# User-defined part start
#
# BIN_LIB is the destination library for the service program.
# the rpg modules and the binder source file are also created in BIN_LIB.
# binder source file and rpg module can be remove with the clean step (make clean)
BIN_LIB=QGPL
# to this library the prototype source file (copy book) is copied in the install step
INCLUDE=/usr/local/include
# CFLAGS = RPG compile parameter
CFLAGS=DBGVIEW(*LIST)
# LFLAGS = binding parameter
# (make sure modules and service programs are in library list)
LFLAGS=BNDDIR(QC2LE) BNDSRVPGM(LLIST)
FROM_CCSID=37
#
# User-defined part end
#-----------------------------------------------------------
MODULES = json json_arr json_cutil json_par json_chk json_util json_inz jsona_inz
OBJECTS = $(BIN_LIB)/json $(BIN_LIB)/json_arr $(BIN_LIB)/json_cutil $(BIN_LIB)/json_par $(BIN_LIB)/json_chk $(BIN_LIB)/json_util $(BIN_LIB)/json_inz $(BIN_LIB)/jsona_inz
.SUFFIXES: .rpgle .c .cpp
# suffix rules
.rpgle:
system "CRTRPGMOD $(BIN_LIB)/$@ SRCSTMF('$<') $(CFLAGS)"
.c:
system "CRTCMOD $(BIN_LIB)/$@ SRCSTMF('$<')"
.cpp:
system "CRTCPPMOD $(BIN_LIB)/$@ SRCSTMF('$<')"
all: build
.PHONY:
json:
json_arr:
json_cutil:
json_par:
json_chk:
json_util:
json_inz:
jsona_inz:
build: $(MODULES)
-system "CRTSRCPF $(BIN_LIB)/JSONSRV RCDLEN(112)"
-system "CPYFRMIMPF FROMSTMF('json.bnd') TOFILE($(BIN_LIB)/JSONSRV JSON) RCDDLM(*ALL) STRDLM(*NONE) RPLNULLVAL(*FLDDFT) FLDDLM(';')
system "CRTSRVPGM $(BIN_LIB)/JSON MODULE($(OBJECTS)) $(LFLAGS) EXPORT(*SRCFILE) SRCFILE($(BIN_LIB)/JSONSRV) TEXT('JSON service program 1.3.0')"
install: .PHONY
-mkdir $(INCLUDE)/json
-setccsid $(FROM_CCSID) $(INCLUDE)/json
cp json*h.rpgle $(INCLUDE)/json
rm $(INCLUDE)/json/json_int_h.rpgle
setccsid $(FROM_CCSID) $(INCLUDE)/json/*
clean:
-system "DLTMOD $(BIN_LIB)/JSON"
-system "DLTMOD $(BIN_LIB)/JSON_ARR"
-system "DLTMOD $(BIN_LIB)/JSON_PAR"
-system "DLTMOD $(BIN_LIB)/JSON_CHK"
-system "DLTMOD $(BIN_LIB)/JSON_UTIL"
-system "DLTMOD $(BIN_LIB)/JSON_CUTIL"
-system "DLTMOD $(BIN_LIB)/JSON_INZ"
-system "DLTMOD $(BIN_LIB)/JSONA_INZ"
-system "DLTF $(BIN_LIB)/JSONSRV"
dist-clean: clean
-system "DLTSRVPGM $(BIN_LIB)/JSON"
json/ceeapi_h.rpgle 100666 2763 0 16157 11515400043 12330 0 ustar 00MSCHMIDT /if not defined (CEEAPI)
/define CEEAPI
*-------------------------------------------------------------------------
* ILE CEE API Prototypes
*-------------------------------------------------------------------------
D cee_getOpDescInfo...
D PR extproc('CEEDOD')
D position 10I 0 const
D descType 10I 0
D dataType 10I 0
D descInfo1 10I 0
D descInfo2 10I 0
D length 10I 0
D feedback 12A options(*omit)
*-------------------------------------------------------------------------
* Date API Prototypes
*-------------------------------------------------------------------------
D cee_getLilianDate...
D PR extproc('CEEDAYS') opdesc
D charDate 20A const options(*varsize)
D formatString 20A const options(*varsize)
D lilianDate 10I 0
D errorcode 100A options(*varsize : *nopass)
*
D cee_getDateFromLilian...
D PR extproc('CEEDATE') opdesc
D lilianDate 10I 0 const
D formatString 20A const options(*varsize)
D dateString 20A options(*varsize)
D errorcode 100A options(*varsize : *nopass)
*
* CEEDYWK returns the weekday as a number between 1 and 7
*
* 1 = Sonntag / Sunday
* 2 = Montag / Monday
* 3 = Dienstag / Tuesday
* 4 = Mittwoch / Wednesday
* 5 = Donnerstag / Thursday
* 6 = Freitag / Friday
* 7 = Samstag / Saturday
*
* 0 = Fehler bei der Berechnung / ungültiges Datum
*
D cee_getDayOfWeekNumeric...
D PR extproc('CEEDYWK') opdesc
D lilianDate 10I 0 const
D dayOfWeek 10I 0
D errorcode 100A options(*varsize : *nopass)
*
*-------------------------------------------------------------------------
* Memory Management API Prototypes
*-------------------------------------------------------------------------
* Interface to the CEEGTST API (Get Heap Storage).
* 1) HeapId = Id of the heap.
* 2) Size = Number of bytes to allocate
* 3) RetAddr= Return address of the allocated storage
* 4) *OMIT = The feedback parameter. Specifying *OMIT here
* means that we will receive an exception from
* the API if it cannot satisfy our request.
* Since we do not monitor for it, the calling
* procedure will receive the exception.
*-------------------------------------------------------------------------
D cee_getStorage...
D PR extproc('CEEGTST')
D heapId 10I 0 const
D size 10I 0 const
D retAddr *
D feedback 12A options(*omit)
*-------------------------------------------------------------------------
* Interface to the CEEFRST API (Free Storage).
* 1) Addr = Address of the allocated storage to be freed
* 2) *OMIT = The feedback parameter. Specifying *OMIT here
* means that we will receive an exception from
* the API if it cannot satisfy our request.
* Since we do not monitor for it, the calling
* procedure will receive the exception.
*-------------------------------------------------------------------------
D cee_freeStorage...
D PR extproc('CEEFRST')
D address *
D feedback 12A options(*omit)
*-------------------------------------------------------------------------
* Interface to the CEECZST API (Reallocate Storage).
* 1) Addr = Address of the allocated storage
* 2) Size = New size (number of bytes) of the allocated storage
* 3) *OMIT = The feedback parameter. Specifying *OMIT here
* means that we will receive an exception from
* the API if it cannot satisfy our request.
* Since we do not monitor for it, the calling
* procedure will receive the exception.
*-------------------------------------------------------------------------
D cee_reallocateStorage...
D PR extproc('CEECZST')
D address *
D size 10I 0 const
D feedback 12A options(*omit)
*-------------------------------------------------------------------------
* Interface to the CEECRHP API (Create Heap).
* 1) HeapId = Id of the heap.
* 2) InitSize = Initial size of the heap.
* 3) Incr = Number of bytes to increment if heap must be
* enlarged.
* 4) AllocStrat = Allocation strategy for this heap. We will
* specify a value of 0 which allows the system
* to choose the optimal strategy.
* 5) *OMIT = The feedback parameter. Specifying *OMIT here
* means that we will receive an exception from
* the API if it cannot satisfy our request.
* Since we do not monitor for it, the calling
* procedure will receive the exception.
*-------------------------------------------------------------------------
D cee_createHeap...
D PR extproc('CEECRHP')
D heapId 10I 0
D initSize 10I 0 const options(*omit)
D increment 10I 0 const options(*omit)
D allocStrat 10I 0 const options(*omit)
D feedback 12A options(*omit)
*-------------------------------------------------------------------------
* Interface to the CEEDSHP API (Discard Heap).
* 1) HeapId = Id of the heap.
* 2) *OMIT = The feedback parameter. Specifying *OMIT here
* means that we will receive an exception from
* the API if it cannot satisfy our request.
* Since we do not monitor for it, the calling
* procedure will receive the exception.
*-------------------------------------------------------------------------
D cee_discardHeap...
D PR extproc('CEEDSHP')
D heapId 10I 0
D feedback 12A options(*omit)
/endif
json/install 100666 2763 0 2466 11517626421 11123 0 ustar 00MSCHMIDT JSON Service Program Installation
These service program sources come as IFS files (not database file sources) and
with that has all the pros and cons of it.
The installation of this service program is really easy as it is accomplished
with the tool "make". The make tool is very much used in the Unix/Linux world.
To use it just type make in a QShell session (command qsh).
Requirements: You need a folder in the IFS for your global copy books (like /usr/local/include).
1. Download sources
2. FTP to IBM i server
3. It is a good idea to create a common source folder for IFS sources (mkdir /usr/local/src)
4. Extract sources (tar -xf json.tar)
5. Check the CCSID of the Makefile script with ls -S message
(it should have 437, 819, 850 or something like that. 37 won't work.
You can convert the file(s) with the conversion script,
see http://www.rpgnextgen.com/index.php?content=resources)
6. edit the Makefile to match your environment (mostly the BIN_LIB and INCLUDE variable),
use edtf or RDP or RPG Next Gen Editor
7. make
8. make install (to copy the prototypes to the include folder)
9. make clean (removes the rpg module and the binder source file)
FINISHED!
Now you got your service program installed.
If you got any questions just drop me a mail ( mihael at rpgnextgen.com ).
Mihael