Skip to content

Instantly share code, notes, and snippets.

@chobie
Created September 22, 2013 13:24
Show Gist options
  • Save chobie/6659868 to your computer and use it in GitHub Desktop.
Save chobie/6659868 to your computer and use it in GitHub Desktop.
diff --git a/Zend/zend.h b/Zend/zend.h
index 1377fd5..59d811a 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -588,6 +588,8 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9
#define IS_CALLABLE 10
+#define IS_BYTE 11
+#define IS_ORD 12
/* Ugly hack to support constants as static array indices */
#define IS_CONSTANT_TYPE_MASK 0x00f
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 6a9a24a..2cf916c 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -108,7 +108,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%right '!'
%nonassoc T_INSTANCEOF
%token T_INSTANCEOF "instanceof (T_INSTANCEOF)"
-%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
+%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST T_BYTE_CAST T_ORD_CAST'@'
%token T_INC "++ (T_INC)"
%token T_DEC "-- (T_DEC)"
%token T_INT_CAST "(int) (T_INT_CAST)"
@@ -118,6 +118,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%token T_OBJECT_CAST "(object) (T_OBJECT_CAST)"
%token T_BOOL_CAST "(bool) (T_BOOL_CAST)"
%token T_UNSET_CAST "(unset) (T_UNSET_CAST)"
+%token T_BYTE_CAST "(byte) (T_BYTE_CAST)"
+%token T_ORD_CAST "(ord) (T_ORD_CAST)"
%right '['
%nonassoc T_NEW T_CLONE
%token T_NEW "new (T_NEW)"
@@ -801,6 +803,8 @@ expr_without_variable:
| T_OBJECT_CAST expr { zend_do_cast(&$$, &$2, IS_OBJECT TSRMLS_CC); }
| T_BOOL_CAST expr { zend_do_cast(&$$, &$2, IS_BOOL TSRMLS_CC); }
| T_UNSET_CAST expr { zend_do_cast(&$$, &$2, IS_NULL TSRMLS_CC); }
+ | T_BYTE_CAST expr { zend_do_cast(&$$, &$2, IS_BYTE TSRMLS_CC); }
+ | T_ORD_CAST expr { zend_do_cast(&$$, &$2, IS_ORD TSRMLS_CC); }
| T_EXIT exit_expr { zend_do_exit(&$$, &$2 TSRMLS_CC); }
| '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
| scalar { $$ = $1; }
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 3423738..c215d50 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -759,6 +759,36 @@ ZEND_API void convert_to_object(zval *op) /* {{{ */
}
/* }}} */
+ZEND_API void convert_to_byte(zval *op) /* {{{ */
+{
+ long c;
+ char temp[2];
+
+ if (Z_TYPE_P(op) != IS_LONG) {
+ convert_to_long_base(op, 10);
+ }
+
+ temp[0] = (char)Z_LVAL_P(op);;
+ temp[1] = '\0';
+
+ ZVAL_STRINGL(op, temp, 1, 1);
+}
+/* }}} */
+
+ZEND_API void convert_to_ord(zval *op) /* {{{ */
+{
+ long c;
+ if (Z_TYPE_P(op) != IS_STRING) {
+ convert_to_string(op);
+ }
+
+ c = (unsigned char)Z_STRVAL_P(op)[0];
+ STR_FREE(Z_STRVAL_P(op));
+ ZVAL_LONG(op, c);
+}
+/* }}} */
+
+
ZEND_API void multi_convert_to_long_ex(int argc, ...) /* {{{ */
{
zval **arg;
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index 15ad79e..ba54281 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -333,6 +333,8 @@ ZEND_API void convert_to_null(zval *op);
ZEND_API void convert_to_boolean(zval *op);
ZEND_API void convert_to_array(zval *op);
ZEND_API void convert_to_object(zval *op);
+ZEND_API void convert_to_byte(zval *op);
+ZEND_API void convert_to_ord(zval *op);
ZEND_API void multi_convert_to_long_ex(int argc, ...);
ZEND_API void multi_convert_to_double_ex(int argc, ...);
ZEND_API void multi_convert_to_string_ex(int argc, ...);
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 2bc80fa..d7dd12c 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3735,6 +3735,12 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
case IS_OBJECT:
convert_to_object(result);
break;
+ case IS_BYTE:
+ convert_to_byte(result);
+ break;
+ case IS_ORD:
+ convert_to_ord(result);
+ break;
}
FREE_OP1_IF_VAR();
CHECK_EXCEPTION();
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 08fb847..5ac8300 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -2638,6 +2638,12 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
case IS_OBJECT:
convert_to_object(result);
break;
+ case IS_BYTE:
+ convert_to_byte(result);
+ break;
+ case IS_ORD:
+ convert_to_ord(result);
+ break;
}
CHECK_EXCEPTION();
@@ -7967,6 +7973,12 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
case IS_OBJECT:
convert_to_object(result);
break;
+ case IS_BYTE:
+ convert_to_byte(result);
+ break;
+ case IS_ORD:
+ convert_to_ord(result);
+ break;
}
CHECK_EXCEPTION();
@@ -13306,6 +13318,12 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
case IS_OBJECT:
convert_to_object(result);
break;
+ case IS_BYTE:
+ convert_to_byte(result);
+ break;
+ case IS_ORD:
+ convert_to_ord(result);
+ break;
}
zval_ptr_dtor(&free_op1.var);
CHECK_EXCEPTION();
@@ -30952,6 +30970,12 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
case IS_OBJECT:
convert_to_object(result);
break;
+ case IS_BYTE:
+ convert_to_byte(result);
+ break;
+ case IS_ORD:
+ convert_to_ord(result);
+ break;
}
CHECK_EXCEPTION();
@chobie
Copy link
Author

chobie commented Sep 22, 2013

In most cases, we use wrapper method (e.g) getBit($buffer, $offset)) when using chr / ord.
so we couldn't realize this optimization as we call getBIt() so many times. sigh.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment