Back to index

php5  5.3.10
Classes | Defines | Typedefs | Enumerations | Functions
JSON_parser.h File Reference
#include "php.h"
#include "ext/standard/php_smart_str.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  JSON_parser_struct

Defines

#define JSON_PARSER_DEFAULT_DEPTH   512

Typedefs

typedef struct JSON_parser_structJSON_parser

Enumerations

enum  error_codes {
  PHP_JSON_ERROR_NONE = 0, PHP_JSON_ERROR_DEPTH, PHP_JSON_ERROR_STATE_MISMATCH, PHP_JSON_ERROR_CTRL_CHAR,
  PHP_JSON_ERROR_SYNTAX, PHP_JSON_ERROR_UTF8
}

Functions

JSON_parser new_JSON_parser (int depth)
int parse_JSON (JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int assoc TSRMLS_DC)
int free_JSON_parser (JSON_parser jp)

Class Documentation

struct JSON_parser_struct

Definition at line 11 of file JSON_parser.h.

Class Members
int depth
int error_code
int * stack
int state
zval * the_static_zstack
zval ** the_zstack
int top

Define Documentation

#define JSON_PARSER_DEFAULT_DEPTH   512

Definition at line 9 of file JSON_parser.h.


Typedef Documentation

typedef struct JSON_parser_struct * JSON_parser

Enumeration Type Documentation

Enumerator:
PHP_JSON_ERROR_NONE 
PHP_JSON_ERROR_DEPTH 
PHP_JSON_ERROR_STATE_MISMATCH 
PHP_JSON_ERROR_CTRL_CHAR 
PHP_JSON_ERROR_SYNTAX 
PHP_JSON_ERROR_UTF8 

Definition at line 21 of file JSON_parser.h.


Function Documentation

Definition at line 263 of file JSON_parser.c.

{
    efree((void*)jp->stack);
    if (jp->the_zstack != &jp->the_static_zstack[0]) {
        efree(jp->the_zstack);
    }
    efree((void*)jp);
    return false;
}

Here is the caller graph for this function:

Definition at line 242 of file JSON_parser.c.

{
    JSON_parser jp = (JSON_parser)emalloc(sizeof(struct JSON_parser_struct));
    jp->state = GO;
    jp->depth = depth;
    jp->top = -1;
       jp->error_code = PHP_JSON_ERROR_NONE;
    jp->stack = (int*)ecalloc(depth, sizeof(int));
    if (depth > JSON_PARSER_DEFAULT_DEPTH) {
        jp->the_zstack = (zval **)safe_emalloc(depth, sizeof(zval), 0);
    } else {
        jp->the_zstack = &jp->the_static_zstack[0];
    }
    push(jp, MODE_DONE);
    return jp;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int parse_JSON ( JSON_parser  jp,
zval *  z,
unsigned short  utf16_json[],
int  length,
int assoc  TSRMLS_DC 
)

Definition at line 423 of file JSON_parser.c.

{
    int next_char;  /* the next character */
    int next_class;  /* the next character class */
    int next_state;  /* the next state */
    int the_index;

    smart_str buf = {0};
    smart_str key = {0};

    unsigned short utf16 = 0;
    int type;

       JSON_RESET_TYPE();

    for (the_index = 0; the_index < length; the_index += 1) {
        next_char = utf16_json[the_index];
              if (next_char >= 128) {
                     next_class = C_ETC;
              } else {
                     next_class = ascii_class[next_char];
                     if (next_class <= __) {
                            jp->error_code = PHP_JSON_ERROR_CTRL_CHAR;
                            FREE_BUFFERS();
                            return false;
                     }
              }
/*
    Get the next state from the transition table.
*/
        next_state = state_transition_table[jp->state][next_class];
        if (next_state >= 0) {
/*
    Change the state and iterate
*/
                     if (type == IS_STRING) {
                   if (next_state == ST && jp->state != U4) {
                       if (jp->state != ES) {
                           utf16_to_utf8(&buf, next_char);
                       } else {
                           switch (next_char) {
                               case 'b':
                                   smart_str_appendc(&buf, '\b');
                                   break;
                               case 't':
                                   smart_str_appendc(&buf, '\t');
                                   break;
                               case 'n':
                                   smart_str_appendc(&buf, '\n');
                                   break;
                               case 'f':
                                   smart_str_appendc(&buf, '\f');
                                   break;
                               case 'r':
                                   smart_str_appendc(&buf, '\r');
                                   break;
                               default:
                                   utf16_to_utf8(&buf, next_char);
                                   break;
                           }
                       }
                   } else if (next_state == U2) {
                       utf16 = dehexchar(next_char) << 12;
                   } else if (next_state == U3) {
                       utf16 += dehexchar(next_char) << 8;
                   } else if (next_state == U4) {
                       utf16 += dehexchar(next_char) << 4;
                   } else if (next_state == ST && jp->state == U4) {
                       utf16 += dehexchar(next_char);
                       utf16_to_utf8(&buf, utf16);
                   }
               } else if (type < IS_LONG && (next_class == C_DIGIT || next_class == C_ZERO)) {
                   type = IS_LONG;
                   smart_str_appendc(&buf, next_char);
               } else if (type == IS_LONG && next_state == E1) {
                   type = IS_DOUBLE;
                   smart_str_appendc(&buf, next_char);
               } else if (type < IS_DOUBLE && next_class == C_POINT) {
                   type = IS_DOUBLE;
                   smart_str_appendc(&buf, next_char);
               } else if (type < IS_STRING && next_class == C_QUOTE) {
                   type = IS_STRING;
               } else if (type < IS_BOOL && ((jp->state == T3 && next_state == OK) || (jp->state == F4 && next_state == OK))) {
                   type = IS_BOOL;
               } else if (type < IS_NULL && jp->state == N3 && next_state == OK) {
                   type = IS_NULL;
               } else if (type != IS_STRING && next_class > C_WHITE) {
                   utf16_to_utf8(&buf, next_char);
               }
              jp->state = next_state;
              } else {
/*
    Perform one of the predefined actions.
*/
            switch (next_state) {
/* empty } */
            case -9:
                if (!pop(jp, MODE_KEY)) {
                    FREE_BUFFERS();
                    return false;
                }
                jp->state = OK;
                break;
/* } */
            case -8:
                if (type != -1 && jp->stack[jp->top] == MODE_OBJECT)
                {
                    zval *mval;
                    smart_str_0(&buf);

                    json_create_zval(&mval, &buf, type);

                    if (!assoc) {
                        add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
                        Z_DELREF_P(mval);
                    } else {
                        add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
                    }
                    key.len = 0;
                    buf.len = 0;
                    JSON_RESET_TYPE();
                }


                if (!pop(jp, MODE_OBJECT)) {
                    FREE_BUFFERS();
                    return false;
                }
                jp->state = OK;
                break;
/* ] */
            case -7:
            {
                if (type != -1 && jp->stack[jp->top] == MODE_ARRAY)
                {
                    zval *mval;
                    smart_str_0(&buf);

                    json_create_zval(&mval, &buf, type);
                    add_next_index_zval(jp->the_zstack[jp->top], mval);
                    buf.len = 0;
                    JSON_RESET_TYPE();
                }

                if (!pop(jp, MODE_ARRAY)) {
                    FREE_BUFFERS();
                    return false;
                }
                jp->state = OK;
            }
                     break;
/* { */
            case -6:
                if (!push(jp, MODE_KEY)) {
                    FREE_BUFFERS();
                    return false;
                }

                jp->state = OB;
                if (jp->top > 0) {
                    zval *obj;

                    if (jp->top == 1) {
                        obj = z;
                     } else {
                        ALLOC_INIT_ZVAL(obj);
                    }

                    if (!assoc) {
                        object_init(obj);
                    } else {
                        array_init(obj);
                    }

                    jp->the_zstack[jp->top] = obj;

                    if (jp->top > 1) {
                        attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
                    }

                    JSON_RESET_TYPE();
                }

                break;
/* [ */
            case -5:
                if (!push(jp, MODE_ARRAY)) {
                    FREE_BUFFERS();
                    return false;
                }
                jp->state = AR;

                if (jp->top > 0) {
                    zval *arr;

                    if (jp->top == 1) {
                        arr = z;
                    } else {
                        ALLOC_INIT_ZVAL(arr);
                    }

                    array_init(arr);
                    jp->the_zstack[jp->top] = arr;

                    if (jp->top > 1) {
                        attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
                    }

                    JSON_RESET_TYPE();
                }

                break;

/* " */
            case -4:
                switch (jp->stack[jp->top]) {
                case MODE_KEY:
                    jp->state = CO;
                    smart_str_0(&buf);
                    SWAP_BUFFERS(buf, key);
                    JSON_RESET_TYPE();
                    break;
                case MODE_ARRAY:
                case MODE_OBJECT:
                    jp->state = OK;
                    break;
                            case MODE_DONE:
                                   if (type == IS_STRING) {
                                          smart_str_0(&buf);
                                          ZVAL_STRINGL(z, buf.c, buf.len, 1);
                                          jp->state = OK;
                                          break;
                                   }
                                   /* fall through if not IS_STRING */
                default:
                    FREE_BUFFERS();
                    jp->error_code = PHP_JSON_ERROR_SYNTAX;
                    return false;
                }
                break;
/* , */
            case -3:
            {
                zval *mval;

                if (type != -1 &&
                    (jp->stack[jp->top] == MODE_OBJECT ||
                     jp->stack[jp->top] == MODE_ARRAY))
                {
                    smart_str_0(&buf);
                    json_create_zval(&mval, &buf, type);
                }

                switch (jp->stack[jp->top]) {
                    case MODE_OBJECT:
                        if (pop(jp, MODE_OBJECT) && push(jp, MODE_KEY)) {
                            if (type != -1) {
                                if (!assoc) {
                                    add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
                                    Z_DELREF_P(mval);
                                } else {
                                    add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
                                }
                                key.len = 0;
                            }
                            jp->state = KE;
                        }
                        break;
                    case MODE_ARRAY:
                        if (type != -1) {
                            add_next_index_zval(jp->the_zstack[jp->top], mval);
                        }
                        jp->state = VA;
                        break;
                    default:
                        FREE_BUFFERS();
                        jp->error_code = PHP_JSON_ERROR_SYNTAX;
                        return false;
                }
                buf.len = 0;
                JSON_RESET_TYPE();
            }
            break;
/* : */
            case -2:
                if (pop(jp, MODE_KEY) && push(jp, MODE_OBJECT)) {
                    jp->state = VA;
                    break;
                }
/*
    syntax error
*/
            default:
                {
                                   jp->error_code = PHP_JSON_ERROR_SYNTAX;
                    FREE_BUFFERS();
                    return false;
                }
            }
        }
    }

    FREE_BUFFERS();
       if (jp->state == OK && pop(jp, MODE_DONE)) {
              return true;
       }

       jp->error_code = PHP_JSON_ERROR_SYNTAX;
       return false;
}

Here is the call graph for this function:

Here is the caller graph for this function: