Merge branch 'poco-1.9.1' of https://github.com/pocoproject/poco into poco-1.9.1

This commit is contained in:
zosrothko
2018-05-11 15:55:32 +02:00
19 changed files with 924 additions and 148 deletions

5
.gitignore vendored
View File

@@ -41,6 +41,10 @@ coverage/
config.build config.build
config.make config.make
# CLion #
########
.idea/
# CMake # # CMake #
######## ########
cmake_install.cmake cmake_install.cmake
@@ -50,6 +54,7 @@ CMakeCache.txt
CPackConfig.cmake CPackConfig.cmake
CPackSourceConfig.cmake CPackSourceConfig.cmake
cmake_* cmake_*
cmake-build-*
# Packages # # Packages #
############ ############

View File

@@ -93,5 +93,7 @@ private:
#define CppUnit_addTest(suite, cls, mth) \ #define CppUnit_addTest(suite, cls, mth) \
suite->addTest(new CppUnit::TestCaller<cls>(#mth, &cls::mth)) suite->addTest(new CppUnit::TestCaller<cls>(#mth, &cls::mth))
#define CppUnit_addQualifiedTest(suite, cls, mth) \
suite->addTest(new CppUnit::TestCaller<cls>(#cls"::"#mth, &cls::mth))
#endif // CppUnit_TestCaller_INCLUDED #endif // CppUnit_TestCaller_INCLUDED

View File

@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */ /* The current PCRE version information. */
#define PCRE_MAJOR 8 #define PCRE_MAJOR 8
#define PCRE_MINOR 41 #define PCRE_MINOR 42
#define PCRE_PRERELEASE #define PCRE_PRERELEASE
#define PCRE_DATE 2017-07-05 #define PCRE_DATE 2018-03-20
/* When an application links to a PCRE DLL in Windows, the symbols that are /* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate imported have to be identified as such. When building PCRE, the appropriate
@@ -321,10 +321,10 @@ these bits, just add new ones on the end, in order to remain compatible. */
/* Types */ /* Types */
struct real_pcre8_or_16; /* declaration; the definition is private */ struct real_pcre8_or_16; /* declaration; the definition is private */
typedef struct real_pcre8_or_16 pcre; typedef struct real_pcre8_or_16 pcre;
struct real_pcre8_or_16; /* declaration; the definition is private */ struct real_pcre8_or_16; /* declaration; the definition is private */
typedef struct real_pcre8_or_16 pcre16; typedef struct real_pcre8_or_16 pcre16;
struct real_pcre32; /* declaration; the definition is private */ struct real_pcre32; /* declaration; the definition is private */

View File

@@ -8062,7 +8062,7 @@ for (;; ptr++)
single group (i.e. not to a duplicated name. */ single group (i.e. not to a duplicated name. */
HANDLE_REFERENCE: HANDLE_REFERENCE:
if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; if (firstcharflags == REQ_UNSET) zerofirstcharflags = firstcharflags = REQ_NONE;
previous = code; previous = code;
item_hwm_offset = cd->hwm - cd->start_workspace; item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF; *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF;

View File

@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language (but see
below for why this module is different). below for why this module is different).
Written by Philip Hazel Written by Philip Hazel
Copyright (c) 1997-2014 University of Cambridge Copyright (c) 1997-2017 University of Cambridge
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -2286,12 +2286,14 @@ for (;;)
case OP_NOTI: case OP_NOTI:
if (clen > 0) if (clen > 0)
{ {
unsigned int otherd; pcre_uint32 otherd;
#ifdef SUPPORT_UTF #ifdef SUPPORT_UTF
if (utf && d >= 128) if (utf && d >= 128)
{ {
#ifdef SUPPORT_UCP #ifdef SUPPORT_UCP
otherd = UCD_OTHERCASE(d); otherd = UCD_OTHERCASE(d);
#else
otherd = d;
#endif /* SUPPORT_UCP */ #endif /* SUPPORT_UCP */
} }
else else

View File

@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language. and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel Written by Philip Hazel
Copyright (c) 1997-2014 University of Cambridge Copyright (c) 1997-2018 University of Cambridge
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -2306,7 +2306,7 @@ for (;;)
case OP_ANY: case OP_ANY:
if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
if (md->partial != 0 && if (md->partial != 0 &&
eptr + 1 >= md->end_subject && eptr == md->end_subject - 1 &&
NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 && NLBLOCK->nllen == 2 &&
UCHAR21TEST(eptr) == NLBLOCK->nl[0]) UCHAR21TEST(eptr) == NLBLOCK->nl[0])
@@ -3054,7 +3054,7 @@ for (;;)
{ {
RMATCH(eptr, ecode, offset_top, md, eptrb, RM18); RMATCH(eptr, ecode, offset_top, md, eptrb, RM18);
if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break; /* Stop if tried at original pos */ if (eptr-- <= pp) break; /* Stop if tried at original pos */
BACKCHAR(eptr); BACKCHAR(eptr);
} }
} }
@@ -3211,7 +3211,7 @@ for (;;)
{ {
RMATCH(eptr, ecode, offset_top, md, eptrb, RM21); RMATCH(eptr, ecode, offset_top, md, eptrb, RM21);
if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break; /* Stop if tried at original pos */ if (eptr-- <= pp) break; /* Stop if tried at original pos */
#ifdef SUPPORT_UTF #ifdef SUPPORT_UTF
if (utf) BACKCHAR(eptr); if (utf) BACKCHAR(eptr);
#endif #endif

View File

@@ -163,7 +163,6 @@ typedef struct jit_arguments {
const pcre_uchar *begin; const pcre_uchar *begin;
const pcre_uchar *end; const pcre_uchar *end;
int *offsets; int *offsets;
pcre_uchar *uchar_ptr;
pcre_uchar *mark_ptr; pcre_uchar *mark_ptr;
void *callout_data; void *callout_data;
/* Everything else after. */ /* Everything else after. */
@@ -213,7 +212,7 @@ enum control_types {
type_then_trap = 1 type_then_trap = 1
}; };
typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); typedef int (SLJIT_FUNC *jit_function)(jit_arguments *args);
/* The following structure is the key data type for the recursive /* The following structure is the key data type for the recursive
code generator. It is allocated by compile_matchingpath, and contains code generator. It is allocated by compile_matchingpath, and contains
@@ -488,9 +487,24 @@ typedef struct compare_context {
/* Used for accessing the elements of the stack. */ /* Used for accessing the elements of the stack. */
#define STACK(i) ((i) * (int)sizeof(sljit_sw)) #define STACK(i) ((i) * (int)sizeof(sljit_sw))
#ifdef SLJIT_PREF_SHIFT_REG
#if SLJIT_PREF_SHIFT_REG == SLJIT_R2
/* Nothing. */
#elif SLJIT_PREF_SHIFT_REG == SLJIT_R3
#define SHIFT_REG_IS_R3
#else
#error "Unsupported shift register"
#endif
#endif
#define TMP1 SLJIT_R0 #define TMP1 SLJIT_R0
#ifdef SHIFT_REG_IS_R3
#define TMP2 SLJIT_R3
#define TMP3 SLJIT_R2
#else
#define TMP2 SLJIT_R2 #define TMP2 SLJIT_R2
#define TMP3 SLJIT_R3 #define TMP3 SLJIT_R3
#endif
#define STR_PTR SLJIT_S0 #define STR_PTR SLJIT_S0
#define STR_END SLJIT_S1 #define STR_END SLJIT_S1
#define STACK_TOP SLJIT_R1 #define STACK_TOP SLJIT_R1
@@ -519,13 +533,10 @@ the start pointers when the end of the capturing group has not yet reached. */
#if defined COMPILE_PCRE8 #if defined COMPILE_PCRE8
#define MOV_UCHAR SLJIT_MOV_U8 #define MOV_UCHAR SLJIT_MOV_U8
#define MOVU_UCHAR SLJIT_MOVU_U8
#elif defined COMPILE_PCRE16 #elif defined COMPILE_PCRE16
#define MOV_UCHAR SLJIT_MOV_U16 #define MOV_UCHAR SLJIT_MOV_U16
#define MOVU_UCHAR SLJIT_MOVU_U16
#elif defined COMPILE_PCRE32 #elif defined COMPILE_PCRE32
#define MOV_UCHAR SLJIT_MOV_U32 #define MOV_UCHAR SLJIT_MOV_U32
#define MOVU_UCHAR SLJIT_MOVU_U32
#else #else
#error Unsupported compiling mode #error Unsupported compiling mode
#endif #endif
@@ -2382,12 +2393,25 @@ if (length < 8)
} }
else else
{ {
GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START); if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)) == SLJIT_SUCCESS)
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1); {
loop = LABEL(); GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START);
OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R0, 0); OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1); loop = LABEL();
JUMPTO(SLJIT_NOT_ZERO, loop); sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw));
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, loop);
}
else
{
GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START + sizeof(sljit_sw));
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
loop = LABEL();
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);
OP2(SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, loop);
}
} }
} }
@@ -2420,12 +2444,25 @@ if (length < 8)
} }
else else
{ {
GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw)); if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)) == SLJIT_SUCCESS)
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2); {
loop = LABEL(); GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw));
OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); loop = LABEL();
JUMPTO(SLJIT_NOT_ZERO, loop); sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, loop);
}
else
{
GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + 2 * sizeof(sljit_sw));
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
loop = LABEL();
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0);
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(sljit_sw));
OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, loop);
}
} }
OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);
@@ -2435,10 +2472,10 @@ if (common->control_head_ptr != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, end));
} }
static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, const pcre_uchar *skip_arg) static sljit_sw SLJIT_FUNC do_search_mark(sljit_sw *current, const pcre_uchar *skip_arg)
{ {
while (current != NULL) while (current != NULL)
{ {
@@ -2459,7 +2496,7 @@ while (current != NULL)
SLJIT_ASSERT(current[0] == 0 || current < (sljit_sw*)current[0]); SLJIT_ASSERT(current[0] == 0 || current < (sljit_sw*)current[0]);
current = (sljit_sw*)current[0]; current = (sljit_sw*)current[0];
} }
return -1; return 0;
} }
static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket) static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
@@ -2467,6 +2504,7 @@ static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
DEFINE_COMPILER; DEFINE_COMPILER;
struct sljit_label *loop; struct sljit_label *loop;
struct sljit_jump *early_quit; struct sljit_jump *early_quit;
BOOL has_pre;
/* At this point we can freely use all registers. */ /* At this point we can freely use all registers. */
OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
@@ -2480,17 +2518,30 @@ if (common->mark_ptr != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0);
OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin)); OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin));
GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START);
has_pre = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS;
GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0));
/* Unlikely, but possible */ /* Unlikely, but possible */
early_quit = CMP(SLJIT_EQUAL, SLJIT_R1, 0, SLJIT_IMM, 0); early_quit = CMP(SLJIT_EQUAL, SLJIT_R1, 0, SLJIT_IMM, 0);
loop = LABEL(); loop = LABEL();
OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);
OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw)); if (has_pre)
sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));
else
{
OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0);
OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));
}
OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, sizeof(int));
OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0);
/* Copy the integer value to the output buffer */ /* Copy the integer value to the output buffer */
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT); OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);
#endif #endif
OP1(SLJIT_MOVU_S32, SLJIT_MEM1(SLJIT_R2), sizeof(int), SLJIT_S1, 0);
OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R2), 0, SLJIT_S1, 0);
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, loop); JUMPTO(SLJIT_NOT_ZERO, loop);
JUMPHERE(early_quit); JUMPHERE(early_quit);
@@ -2498,14 +2549,29 @@ JUMPHERE(early_quit);
/* Calculate the return value, which is the maximum ovector value. */ /* Calculate the return value, which is the maximum ovector value. */
if (topbracket > 1) if (topbracket > 1)
{ {
GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw)); if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))) == SLJIT_SUCCESS)
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1); {
GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw));
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);
/* OVECTOR(0) is never equal to SLJIT_S2. */ /* OVECTOR(0) is never equal to SLJIT_S2. */
loop = LABEL(); loop = LABEL();
OP1(SLJIT_MOVU, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))); sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw)));
OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop); CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);
}
else
{
GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + (topbracket - 1) * 2 * sizeof(sljit_sw));
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);
/* OVECTOR(0) is never equal to SLJIT_S2. */
loop = LABEL();
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), 0);
OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * (sljit_sw)sizeof(sljit_sw));
OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);
}
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);
} }
else else
@@ -5166,93 +5232,190 @@ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0); sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
} }
#define CHAR1 STR_END
#define CHAR2 STACK_TOP
static void do_casefulcmp(compiler_common *common) static void do_casefulcmp(compiler_common *common)
{ {
DEFINE_COMPILER; DEFINE_COMPILER;
struct sljit_jump *jump; struct sljit_jump *jump;
struct sljit_label *label; struct sljit_label *label;
int char1_reg;
int char2_reg;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); if (sljit_get_register_index(TMP3) < 0)
{
char1_reg = STR_END;
char2_reg = STACK_TOP;
}
else
{
char1_reg = TMP3;
char2_reg = RETURN_ADDR;
}
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, CHAR2, 0);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
label = LABEL(); if (char1_reg == STR_END)
OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1)); {
OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); OP1(SLJIT_MOV, TMP3, 0, char1_reg, 0);
jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0); OP1(SLJIT_MOV, RETURN_ADDR, 0, char2_reg, 0);
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); }
JUMPTO(SLJIT_NOT_ZERO, label);
JUMPHERE(jump); if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); {
OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0); label = LABEL();
OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
sljit_emit_fast_return(compiler, RETURN_ADDR, 0); sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
JUMPTO(SLJIT_NOT_ZERO, label);
JUMPHERE(jump);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
}
else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
{
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
label = LABEL();
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
JUMPTO(SLJIT_NOT_ZERO, label);
JUMPHERE(jump);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
}
else
{
label = LABEL();
OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);
OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
JUMPTO(SLJIT_NOT_ZERO, label);
JUMPHERE(jump);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
}
if (char1_reg == STR_END)
{
OP1(SLJIT_MOV, char1_reg, 0, TMP3, 0);
OP1(SLJIT_MOV, char2_reg, 0, RETURN_ADDR, 0);
}
sljit_emit_fast_return(compiler, TMP1, 0);
} }
#define LCC_TABLE STACK_LIMIT
static void do_caselesscmp(compiler_common *common) static void do_caselesscmp(compiler_common *common)
{ {
DEFINE_COMPILER; DEFINE_COMPILER;
struct sljit_jump *jump; struct sljit_jump *jump;
struct sljit_label *label; struct sljit_label *label;
int char1_reg = STR_END;
int char2_reg;
int lcc_table;
int opt_type = 0;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); if (sljit_get_register_index(TMP3) < 0)
{
char2_reg = STACK_TOP;
lcc_table = STACK_LIMIT;
}
else
{
char2_reg = RETURN_ADDR;
lcc_table = TMP3;
}
if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
opt_type = 1;
else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
opt_type = 2;
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, char1_reg, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, CHAR1, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, CHAR2, 0); if (char2_reg == STACK_TOP)
OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc); {
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV, TMP3, 0, char2_reg, 0);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV, RETURN_ADDR, 0, lcc_table, 0);
}
OP1(SLJIT_MOV, lcc_table, 0, SLJIT_IMM, common->lcc);
if (opt_type == 1)
{
label = LABEL();
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
}
else if (opt_type == 2)
{
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
label = LABEL();
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
}
else
{
label = LABEL();
OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);
OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
}
label = LABEL();
OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
#ifndef COMPILE_PCRE8 #ifndef COMPILE_PCRE8
jump = CMP(SLJIT_GREATER, CHAR1, 0, SLJIT_IMM, 255); jump = CMP(SLJIT_GREATER, char1_reg, 0, SLJIT_IMM, 255);
#endif #endif
OP1(SLJIT_MOV_U8, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0); OP1(SLJIT_MOV_U8, char1_reg, 0, SLJIT_MEM2(lcc_table, char1_reg), 0);
#ifndef COMPILE_PCRE8 #ifndef COMPILE_PCRE8
JUMPHERE(jump); JUMPHERE(jump);
jump = CMP(SLJIT_GREATER, CHAR2, 0, SLJIT_IMM, 255); jump = CMP(SLJIT_GREATER, char2_reg, 0, SLJIT_IMM, 255);
#endif #endif
OP1(SLJIT_MOV_U8, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0); OP1(SLJIT_MOV_U8, char2_reg, 0, SLJIT_MEM2(lcc_table, char2_reg), 0);
#ifndef COMPILE_PCRE8 #ifndef COMPILE_PCRE8
JUMPHERE(jump); JUMPHERE(jump);
#endif #endif
jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
if (opt_type == 0)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
JUMPTO(SLJIT_NOT_ZERO, label); JUMPTO(SLJIT_NOT_ZERO, label);
JUMPHERE(jump); JUMPHERE(jump);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0);
OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
#undef LCC_TABLE if (opt_type == 2)
#undef CHAR1 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
#undef CHAR2
if (char2_reg == STACK_TOP)
{
OP1(SLJIT_MOV, char2_reg, 0, TMP3, 0);
OP1(SLJIT_MOV, lcc_table, 0, RETURN_ADDR, 0);
}
OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
sljit_emit_fast_return(compiler, TMP1, 0);
}
#if defined SUPPORT_UTF && defined SUPPORT_UCP #if defined SUPPORT_UTF && defined SUPPORT_UCP
static const pcre_uchar * SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1) static const pcre_uchar * SLJIT_FUNC do_utf_caselesscmp(pcre_uchar *src1, pcre_uchar *src2, pcre_uchar *end1, pcre_uchar *end2)
{ {
/* This function would be ineffective to do in JIT level. */ /* This function would be ineffective to do in JIT level. */
sljit_u32 c1, c2; sljit_u32 c1, c2;
const pcre_uchar *src2 = args->uchar_ptr;
const pcre_uchar *end2 = args->end;
const ucd_record *ur; const ucd_record *ur;
const sljit_u32 *pp; const sljit_u32 *pp;
@@ -6775,32 +6938,37 @@ else
#if defined SUPPORT_UTF && defined SUPPORT_UCP #if defined SUPPORT_UTF && defined SUPPORT_UCP
if (common->utf && *cc == OP_REFI) if (common->utf && *cc == OP_REFI)
{ {
SLJIT_ASSERT(TMP1 == SLJIT_R0 && STACK_TOP == SLJIT_R1 && TMP2 == SLJIT_R2); SLJIT_ASSERT(TMP1 == SLJIT_R0 && STACK_TOP == SLJIT_R1);
if (ref) if (ref)
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
else else
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
if (withchecks) if (withchecks)
jump = CMP(SLJIT_EQUAL, TMP1, 0, TMP2, 0); jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_R2, 0);
/* Needed to save important temporary registers. */ /* No free saved registers so save data on stack. */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, SLJIT_R1, 0, STR_PTR, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_R3, 0, STR_END, 0);
sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp));
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
if (common->mode == JIT_COMPILE) if (common->mode == JIT_COMPILE)
add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1)); add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1));
else else
{ {
add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
nopartial = CMP(SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
add_jump(compiler, backtracks, JUMP(SLJIT_LESS));
nopartial = JUMP(SLJIT_NOT_EQUAL);
OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
check_partial(common, FALSE); check_partial(common, FALSE);
add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
JUMPHERE(nopartial); JUMPHERE(nopartial);
} }
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
} }
else else
#endif /* SUPPORT_UTF && SUPPORT_UCP */ #endif /* SUPPORT_UTF && SUPPORT_UCP */
@@ -7124,7 +7292,7 @@ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IM
return cc + 1 + LINK_SIZE; return cc + 1 + LINK_SIZE;
} }
static int SLJIT_CALL do_callout(struct jit_arguments *arguments, PUBL(callout_block) *callout_block, pcre_uchar **jit_ovector) static sljit_s32 SLJIT_FUNC do_callout(struct jit_arguments *arguments, PUBL(callout_block) *callout_block, pcre_uchar **jit_ovector)
{ {
const pcre_uchar *begin = arguments->begin; const pcre_uchar *begin = arguments->begin;
int *offset_vector = arguments->offsets; int *offset_vector = arguments->offsets;
@@ -7206,18 +7374,17 @@ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
/* SLJIT_R0 = arguments */ /* SLJIT_R0 = arguments */
OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0); OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0);
GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START); GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START);
sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout)); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(S32) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout));
OP1(SLJIT_MOV_S32, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0);
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
free_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw)); free_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw));
/* Check return value. */ /* Check return value. */
OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); OP2(SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER)); add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER32));
if (common->forced_quit_label == NULL) if (common->forced_quit_label == NULL)
add_jump(compiler, &common->forced_quit, JUMP(SLJIT_NOT_EQUAL) /* SIG_LESS */); add_jump(compiler, &common->forced_quit, JUMP(SLJIT_NOT_EQUAL32) /* SIG_LESS */);
else else
JUMPTO(SLJIT_NOT_EQUAL /* SIG_LESS */, common->forced_quit_label); JUMPTO(SLJIT_NOT_EQUAL32 /* SIG_LESS */, common->forced_quit_label);
return cc + 2 + 2 * LINK_SIZE; return cc + 2 + 2 * LINK_SIZE;
} }
@@ -10438,11 +10605,11 @@ if (opcode == OP_SKIP_ARG)
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2));
sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark)); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark));
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1)); add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0));
return; return;
} }
@@ -11030,7 +11197,7 @@ if (!compiler)
common->compiler = compiler; common->compiler = compiler;
/* Main pcre_jit_exec entry. */ /* Main pcre_jit_exec entry. */
sljit_emit_enter(compiler, 0, 1, 5, 5, 0, 0, private_data_size); sljit_emit_enter(compiler, 0, SLJIT_ARG1(SW), 5, 5, 0, 0, private_data_size);
/* Register init. */ /* Register init. */
reset_ovector(common, (re->top_bracket + 1) * 2); reset_ovector(common, (re->top_bracket + 1) * 2);
@@ -11043,8 +11210,8 @@ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str))
OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end)); OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match)); OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match));
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, end));
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit)); OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, start));
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0);
@@ -11250,20 +11417,22 @@ common->quit_label = quit_label;
set_jumps(common->stackalloc, LABEL()); set_jumps(common->stackalloc, LABEL());
/* RETURN_ADDR is not a saved register. */ /* RETURN_ADDR is not a saved register. */
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0);
OP2(SLJIT_SUB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);
sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize)); SLJIT_ASSERT(TMP1 == SLJIT_R0 && STACK_TOP == SLJIT_R1);
jump = CMP(SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STACK_TOP, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top)); OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE);
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit)); OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, stack));
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); OP1(SLJIT_MOV, STACK_LIMIT, 0, TMP2, 0);
sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
jump = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0);
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_RETURN_REG, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
sljit_emit_fast_return(compiler, TMP1, 0);
/* Allocation failed. */ /* Allocation failed. */
JUMPHERE(jump); JUMPHERE(jump);
@@ -11408,9 +11577,9 @@ union {
sljit_u8 local_space[MACHINE_STACK_SIZE]; sljit_u8 local_space[MACHINE_STACK_SIZE];
struct sljit_stack local_stack; struct sljit_stack local_stack;
local_stack.max_limit = local_space; local_stack.min_start = local_space;
local_stack.limit = local_space; local_stack.start = local_space;
local_stack.base = local_space + MACHINE_STACK_SIZE; local_stack.end = local_space + MACHINE_STACK_SIZE;
local_stack.top = local_space + MACHINE_STACK_SIZE; local_stack.top = local_space + MACHINE_STACK_SIZE;
arguments->stack = &local_stack; arguments->stack = &local_stack;
convert_executable_func.executable_func = executable_func; convert_executable_func.executable_func = executable_func;
@@ -11528,7 +11697,7 @@ if ((options & PCRE_PARTIAL_HARD) != 0)
else if ((options & PCRE_PARTIAL_SOFT) != 0) else if ((options & PCRE_PARTIAL_SOFT) != 0)
mode = JIT_PARTIAL_SOFT_COMPILE; mode = JIT_PARTIAL_SOFT_COMPILE;
if (functions->executable_funcs[mode] == NULL) if (functions == NULL || functions->executable_funcs[mode] == NULL)
return PCRE_ERROR_JIT_BADOPTION; return PCRE_ERROR_JIT_BADOPTION;
/* Sanity checks should be handled by pcre_exec. */ /* Sanity checks should be handled by pcre_exec. */

View File

@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language. and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel Written by Philip Hazel
Copyright (c) 1997-2012 University of Cambridge Copyright (c) 1997-2017 University of Cambridge
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

View File

@@ -125,11 +125,11 @@ void WebSocketTest::testWebSocket()
std::string payload("x"); std::string payload("x");
ws.sendFrame(payload.data(), (int) payload.size()); ws.sendFrame(payload.data(), (int) payload.size());
char buffer[1024]; char buffer[1024] = {};
int flags; int flags;
int n = ws.receiveFrame(buffer, sizeof(buffer), flags); int n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size()); assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0); assertTrue (payload.compare(0, payload.size(), buffer, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT); assertTrue (flags == WebSocket::FRAME_TEXT);
for (int i = 2; i < 20; i++) for (int i = 2; i < 20; i++)
@@ -138,14 +138,16 @@ void WebSocketTest::testWebSocket()
ws.sendFrame(payload.data(), (int) payload.size()); ws.sendFrame(payload.data(), (int) payload.size());
n = ws.receiveFrame(buffer, sizeof(buffer), flags); n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size()); assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0); assertTrue (payload.compare(0, payload.size(), buffer, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT); assertTrue (flags == WebSocket::FRAME_TEXT);
ws.sendFrame(payload.data(), (int) payload.size()); ws.sendFrame(payload.data(), (int) payload.size());
Poco::Buffer<char> pocobuffer(0); Poco::Buffer<char> pocobuffer(0);
assertTrue(0 == pocobuffer.size());
n = ws.receiveFrame(pocobuffer, flags); n = ws.receiveFrame(pocobuffer, flags);
assertTrue (n == payload.size()); assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), pocobuffer.begin(), 0, n) == 0); assertTrue (n == pocobuffer.size());
assertTrue (payload.compare(0, payload.size(), pocobuffer.begin(), n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT); assertTrue (flags == WebSocket::FRAME_TEXT);
} }
@@ -155,14 +157,14 @@ void WebSocketTest::testWebSocket()
ws.sendFrame(payload.data(), (int) payload.size()); ws.sendFrame(payload.data(), (int) payload.size());
n = ws.receiveFrame(buffer, sizeof(buffer), flags); n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size()); assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0); assertTrue (payload.compare(0, payload.size(), buffer, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT); assertTrue (flags == WebSocket::FRAME_TEXT);
ws.sendFrame(payload.data(), (int) payload.size()); ws.sendFrame(payload.data(), (int) payload.size());
Poco::Buffer<char> pocobuffer(0); Poco::Buffer<char> pocobuffer(0);
n = ws.receiveFrame(pocobuffer, flags); n = ws.receiveFrame(pocobuffer, flags);
assertTrue (n == payload.size()); assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), pocobuffer.begin(), 0, n) == 0); assertTrue (payload.compare(0, payload.size(), pocobuffer.begin(), n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT); assertTrue (flags == WebSocket::FRAME_TEXT);
} }
@@ -170,15 +172,15 @@ void WebSocketTest::testWebSocket()
ws.sendFrame(payload.data(), (int) payload.size()); ws.sendFrame(payload.data(), (int) payload.size());
n = ws.receiveFrame(buffer, sizeof(buffer), flags); n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size()); assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0); assertTrue (payload.compare(0, payload.size(), buffer, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT); assertTrue (flags == WebSocket::FRAME_TEXT);
payload = "Hello, universe!"; payload = "Hello, universe!";
ws.sendFrame(payload.data(), (int) payload.size(), WebSocket::FRAME_BINARY); ws.sendFrame(payload.data(), (int) payload.size(), WebSocket::FRAME_BINARY);
n = ws.receiveFrame(buffer, sizeof(buffer), flags); n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size()); assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0); assertTrue (payload.compare(0, payload.size(), buffer, n) == 0);
assertTrue (flags == WebSocket::FRAME_BINARY); assertTrue (flags == WebSocket::FRAME_BINARY);
ws.shutdown(); ws.shutdown();
n = ws.receiveFrame(buffer, sizeof(buffer), flags); n = ws.receiveFrame(buffer, sizeof(buffer), flags);
@@ -210,7 +212,7 @@ void WebSocketTest::testWebSocketLarge()
sstr << payload; sstr << payload;
sstr.flush(); sstr.flush();
char buffer[msgSize + 1]; char buffer[msgSize + 1] = {};
int flags; int flags;
int n = 0; int n = 0;
do do
@@ -219,7 +221,7 @@ void WebSocketTest::testWebSocketLarge()
} while (n > 0 && n < msgSize); } while (n > 0 && n < msgSize);
assertTrue (n == payload.size()); assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0); assertTrue (payload.compare(0, payload.size(), buffer, n) == 0);
} }
@@ -247,7 +249,7 @@ void WebSocketTest::testOneLargeFrame(int msgSize)
n = ws.receiveFrame(buffer.begin(), buffer.size(), flags); n = ws.receiveFrame(buffer.begin(), buffer.size(), flags);
assertTrue (n == payload.size()); assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer.begin(), 0, n) == 0); assertTrue (payload.compare(0, payload.size(), buffer.begin(), n) == 0);
ws.sendFrame(payload.data(), msgSize); ws.sendFrame(payload.data(), msgSize);
@@ -255,7 +257,7 @@ void WebSocketTest::testOneLargeFrame(int msgSize)
n = ws.receiveFrame(pocobuffer, flags); n = ws.receiveFrame(pocobuffer, flags);
assertTrue (n == payload.size()); assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), pocobuffer.begin(), 0, n) == 0); assertTrue (payload.compare(0, payload.size(), pocobuffer.begin(), n) == 0);
} }

View File

@@ -15,7 +15,8 @@ endif
objects = NetSSLTestSuite Driver \ objects = NetSSLTestSuite Driver \
HTTPSClientSessionTest HTTPSClientTestSuite HTTPSServerTest HTTPSServerTestSuite \ HTTPSClientSessionTest HTTPSClientTestSuite HTTPSServerTest HTTPSServerTestSuite \
HTTPSStreamFactoryTest HTTPSTestServer TCPServerTest TCPServerTestSuite HTTPSStreamFactoryTest HTTPSTestServer TCPServerTest TCPServerTestSuite \
WebSocketTest WebSocketTestSuite
target = testrunner target = testrunner
target_version = 1 target_version = 1

View File

@@ -428,7 +428,6 @@ void HTTPSClientSessionTest::testUnknownContentLength()
assertTrue (ostr.str() == HTTPSTestServer::SMALL_BODY); assertTrue (ostr.str() == HTTPSTestServer::SMALL_BODY);
} }
void HTTPSClientSessionTest::testServerAbort() void HTTPSClientSessionTest::testServerAbort()
{ {
HTTPSTestServer srv; HTTPSTestServer srv;

View File

@@ -13,16 +13,17 @@
#include "HTTPSClientTestSuite.h" #include "HTTPSClientTestSuite.h"
#include "TCPServerTestSuite.h" #include "TCPServerTestSuite.h"
#include "HTTPSServerTestSuite.h" #include "HTTPSServerTestSuite.h"
#include "WebSocketTestSuite.h"
CppUnit::Test* NetSSLTestSuite::suite() CppUnit::Test* NetSSLTestSuite::suite()
{ {
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("OpenSSLTestSuite"); CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("OpenSSLTestSuite");
pSuite->addTest(HTTPSClientTestSuite::suite()); pSuite->addTest(HTTPSClientTestSuite::suite());
pSuite->addTest(TCPServerTestSuite::suite()); pSuite->addTest(TCPServerTestSuite::suite());
pSuite->addTest(HTTPSServerTestSuite::suite()); pSuite->addTest(HTTPSServerTestSuite::suite());
pSuite->addTest(WebSocketTestSuite::suite());
return pSuite; return pSuite;
} }

View File

@@ -0,0 +1,237 @@
//
// WebSocketTest.cpp
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "WebSocketTest.h"
#include "Poco/CppUnit/TestCaller.h"
#include "Poco/CppUnit/TestSuite.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Net/SocketStream.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/SecureServerSocket.h"
#include "Poco/Net/NetException.h"
#include "Poco/Thread.h"
#include <iostream>
using Poco::Net::HTTPSClientSession;
using Poco::Net::HTTPRequest;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPServerRequest;
using Poco::Net::HTTPServerResponse;
using Poco::Net::SocketStream;
using Poco::Net::WebSocket;
using Poco::Net::WebSocketException;
namespace
{
class WebSocketRequestHandler: public Poco::Net::HTTPRequestHandler
{
public:
WebSocketRequestHandler(std::size_t bufSize = 1024): _bufSize(bufSize)
{
}
void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
{
try
{
WebSocket ws(request, response);
#ifndef POCO_ENABLE_CPP11
std::auto_ptr<char> pBuffer(new char[_bufSize]);
#else
std::unique_ptr<char[]> pBuffer(new char[_bufSize]);
#endif // POCO_ENABLE_CPP11
int flags;
int n;
do
{
n = ws.receiveFrame(pBuffer.get(), static_cast<int>(_bufSize), flags);
if (n == 0)
break;
ws.sendFrame(pBuffer.get(), n, flags);
}
while ((flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
}
catch (WebSocketException& exc)
{
switch (exc.code())
{
case WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
response.set("Sec-WebSocket-Version", WebSocket::WEBSOCKET_VERSION);
// fallthrough
case WebSocket::WS_ERR_NO_HANDSHAKE:
case WebSocket::WS_ERR_HANDSHAKE_NO_VERSION:
case WebSocket::WS_ERR_HANDSHAKE_NO_KEY:
response.setStatusAndReason(HTTPResponse::HTTP_BAD_REQUEST);
response.setContentLength(0);
response.send();
break;
}
}
}
private:
std::size_t _bufSize;
};
class WebSocketRequestHandlerFactory: public Poco::Net::HTTPRequestHandlerFactory
{
public:
WebSocketRequestHandlerFactory(std::size_t bufSize = 1024): _bufSize(bufSize)
{
}
Poco::Net::HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
{
return new WebSocketRequestHandler(_bufSize);
}
private:
std::size_t _bufSize;
};
}
WebSocketTest::WebSocketTest(const std::string& name): CppUnit::TestCase(name)
{
}
WebSocketTest::~WebSocketTest()
{
}
void WebSocketTest::testWebSocket()
{
Poco::Net::SecureServerSocket ss(0);
Poco::Net::HTTPServer server(new WebSocketRequestHandlerFactory, ss, new Poco::Net::HTTPServerParams);
server.start();
Poco::Thread::sleep(200);
HTTPSClientSession cs("127.0.0.1", ss.address().port());
HTTPRequest request(HTTPRequest::HTTP_GET, "/ws");
HTTPResponse response;
WebSocket ws(cs, request, response);
std::string payload("x");
ws.sendFrame(payload.data(), (int) payload.size());
char buffer[1024] = {};
int flags;
int n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT);
for (int i = 2; i < 20; i++)
{
payload.assign(i, 'x');
ws.sendFrame(payload.data(), (int) payload.size());
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT);
}
for (int i = 125; i < 129; i++)
{
payload.assign(i, 'x');
ws.sendFrame(payload.data(), (int) payload.size());
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT);
}
payload = "Hello, world!";
ws.sendFrame(payload.data(), (int) payload.size());
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT);
payload = "Hello, universe!";
ws.sendFrame(payload.data(), (int) payload.size(), WebSocket::FRAME_BINARY);
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assertTrue (flags == WebSocket::FRAME_BINARY);
ws.shutdown();
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == 2);
assertTrue ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_CLOSE);
server.stop();
}
void WebSocketTest::testWebSocketLarge()
{
const int msgSize = 64000;
Poco::Net::SecureServerSocket ss(0);
Poco::Net::HTTPServer server(new WebSocketRequestHandlerFactory(msgSize), ss, new Poco::Net::HTTPServerParams);
server.start();
Poco::Thread::sleep(200);
HTTPSClientSession cs("127.0.0.1", ss.address().port());
HTTPRequest request(HTTPRequest::HTTP_GET, "/ws");
HTTPResponse response;
WebSocket ws(cs, request, response);
ws.setSendBufferSize(msgSize);
ws.setReceiveBufferSize(msgSize);
std::string payload(msgSize, 'x');
SocketStream sstr(ws);
sstr << payload;
sstr.flush();
char buffer[msgSize + 1] = {};
int flags;
int n = 0;
do
{
n += ws.receiveFrame(buffer + n, sizeof(buffer) - n, flags);
} while (n > 0 && n < msgSize);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
server.stop();
}
void WebSocketTest::setUp()
{
}
void WebSocketTest::tearDown()
{
}
CppUnit::Test* WebSocketTest::suite()
{
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("WebSocketTest");
CppUnit_addTest(pSuite, WebSocketTest, testWebSocket);
CppUnit_addTest(pSuite, WebSocketTest, testWebSocketLarge);
return pSuite;
}

View File

@@ -0,0 +1,39 @@
//
// WebSocketTest.h
//
// Definition of the WebSocketTest class.
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef WebSocketTest_INCLUDED
#define WebSocketTest_INCLUDED
#include "Poco/Net/Net.h"
#include "Poco/CppUnit/TestCase.h"
class WebSocketTest: public CppUnit::TestCase
{
public:
WebSocketTest(const std::string& name);
~WebSocketTest();
void testWebSocket();
void testWebSocketLarge();
void setUp();
void tearDown();
static CppUnit::Test* suite();
private:
};
#endif // WebSocketTest_INCLUDED

View File

@@ -0,0 +1,22 @@
//
// WebSocketTestSuite.cpp
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "WebSocketTestSuite.h"
#include "WebSocketTest.h"
CppUnit::Test* WebSocketTestSuite::suite()
{
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("WebSocketTestSuite");
pSuite->addTest(WebSocketTest::suite());
return pSuite;
}

View File

@@ -0,0 +1,27 @@
//
// WebSocketTestSuite.h
//
// Definition of the WebSocketTestSuite class.
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef WebSocketTestSuite_INCLUDED
#define WebSocketTestSuite_INCLUDED
#include "CppUnit/TestSuite.h"
class WebSocketTestSuite
{
public:
static CppUnit::Test* suite();
};
#endif // WebSocketTestSuite_INCLUDED

View File

@@ -0,0 +1,231 @@
//
// WebSocketTest.cpp
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "WebSocketTest.h"
#include "Poco/CppUnit/TestCaller.h"
#include "Poco/CppUnit/TestSuite.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Net/SocketStream.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/SecureServerSocket.h"
#include "Poco/Net/NetException.h"
#include "Poco/Thread.h"
using Poco::Net::HTTPSClientSession;
using Poco::Net::HTTPRequest;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPServerRequest;
using Poco::Net::HTTPServerResponse;
using Poco::Net::SocketStream;
using Poco::Net::WebSocket;
using Poco::Net::WebSocketException;
namespace
{
class WebSocketRequestHandler: public Poco::Net::HTTPRequestHandler
{
public:
WebSocketRequestHandler(std::size_t bufSize = 1024): _bufSize(bufSize)
{
}
void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
{
try
{
WebSocket ws(request, response);
std::unique_ptr<char[]> pBuffer(new char[_bufSize]);
int flags;
int n;
do
{
n = ws.receiveFrame(pBuffer.get(), static_cast<int>(_bufSize), flags);
if (n == 0)
break;
ws.sendFrame(pBuffer.get(), n, flags);
}
while ((flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
}
catch (WebSocketException& exc)
{
switch (exc.code())
{
case WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
response.set("Sec-WebSocket-Version", WebSocket::WEBSOCKET_VERSION);
// fallthrough
case WebSocket::WS_ERR_NO_HANDSHAKE:
case WebSocket::WS_ERR_HANDSHAKE_NO_VERSION:
case WebSocket::WS_ERR_HANDSHAKE_NO_KEY:
response.setStatusAndReason(HTTPResponse::HTTP_BAD_REQUEST);
response.setContentLength(0);
response.send();
break;
}
}
}
private:
std::size_t _bufSize;
};
class WebSocketRequestHandlerFactory: public Poco::Net::HTTPRequestHandlerFactory
{
public:
WebSocketRequestHandlerFactory(std::size_t bufSize = 1024): _bufSize(bufSize)
{
}
Poco::Net::HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
{
return new WebSocketRequestHandler(_bufSize);
}
private:
std::size_t _bufSize;
};
}
WebSocketTest::WebSocketTest(const std::string& name): CppUnit::TestCase(name)
{
}
WebSocketTest::~WebSocketTest()
{
}
void WebSocketTest::testWebSocket()
{
Poco::Net::SecureServerSocket ss(0);
Poco::Net::HTTPServer server(new WebSocketRequestHandlerFactory, ss, new Poco::Net::HTTPServerParams);
server.start();
Poco::Thread::sleep(200);
HTTPSClientSession cs("127.0.0.1", ss.address().port());
HTTPRequest request(HTTPRequest::HTTP_GET, "/ws");
HTTPResponse response;
WebSocket ws(cs, request, response);
std::string payload("x");
ws.sendFrame(payload.data(), (int) payload.size());
char buffer[1024] = {};
int flags;
int n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT);
for (int i = 2; i < 20; i++)
{
payload.assign(i, 'x');
ws.sendFrame(payload.data(), (int) payload.size());
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT);
}
for (int i = 125; i < 129; i++)
{
payload.assign(i, 'x');
ws.sendFrame(payload.data(), (int) payload.size());
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT);
}
payload = "Hello, world!";
ws.sendFrame(payload.data(), (int) payload.size());
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assertTrue (flags == WebSocket::FRAME_TEXT);
payload = "Hello, universe!";
ws.sendFrame(payload.data(), (int) payload.size(), WebSocket::FRAME_BINARY);
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assertTrue (flags == WebSocket::FRAME_BINARY);
ws.shutdown();
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
assertTrue (n == 2);
assertTrue ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_CLOSE);
server.stop();
}
void WebSocketTest::testWebSocketLarge()
{
const int msgSize = 64000;
Poco::Net::SecureServerSocket ss(0);
Poco::Net::HTTPServer server(new WebSocketRequestHandlerFactory(msgSize), ss, new Poco::Net::HTTPServerParams);
server.start();
Poco::Thread::sleep(200);
HTTPSClientSession cs("127.0.0.1", ss.address().port());
HTTPRequest request(HTTPRequest::HTTP_GET, "/ws");
HTTPResponse response;
WebSocket ws(cs, request, response);
ws.setSendBufferSize(msgSize);
ws.setReceiveBufferSize(msgSize);
std::string payload(msgSize, 'x');
SocketStream sstr(ws);
sstr << payload;
sstr.flush();
char buffer[msgSize + 1] = {};
int flags;
int n = 0;
do
{
n += ws.receiveFrame(buffer + n, sizeof(buffer) - n, flags);
} while (n > 0 && n < msgSize);
assertTrue (n == payload.size());
assertTrue (payload.compare(0, payload.size(), buffer, 0, n) == 0);
}
void WebSocketTest::setUp()
{
}
void WebSocketTest::tearDown()
{
}
CppUnit::Test* WebSocketTest::suite()
{
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("WebSocketTest");
CppUnit_addTest(pSuite, WebSocketTest, testWebSocket);
CppUnit_addTest(pSuite, WebSocketTest, testWebSocketLarge);
return pSuite;
}

View File

@@ -0,0 +1,39 @@
//
// WebSocketTest.h
//
// Definition of the WebSocketTest class.
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef WebSocketTest_INCLUDED
#define WebSocketTest_INCLUDED
#include "Poco/Net/Net.h"
#include "Poco/CppUnit/TestCase.h"
class WebSocketTest: public CppUnit::TestCase
{
public:
WebSocketTest(const std::string& name);
~WebSocketTest();
void testWebSocket();
void testWebSocketLarge();
void setUp();
void tearDown();
static CppUnit::Test* suite();
private:
};
#endif // WebSocketTest_INCLUDED

View File

@@ -830,7 +830,7 @@ PocoDoc.version=${version}-all
javaWDK = javaWDK.replace('\\','/') javaWDK = javaWDK.replace('\\','/')
file.text += """ file.text += """
Includes=-I${postgres32Home}/include,-I${mysql32Home}/include,-ICppParser/include,-ICppUnit/include,-ICrypto/include,-IData/include,-IData/include,-IData/MySQL/include,-IData/ODBC/include,-IData/PostgreSQL/include,-IData/SQLite/include, -IData/SQLite/src,-IFoundation/include,-IJSON/include,-IMongoDB/include,-INet/include,-INetSSL_OpenSSL/include,-INetSSL_Win/include,-IRedis/include,-IUtil/include,-IXML/include,-IZip/include,-ISevenZip/include,-IPDF/include Includes=-I${postgres32Home}/include,-I${mysql32Home}/include,-ICppParser/include,-ICppUnit/include,-ICrypto/include,-IEncodings/include,-IData/include,-IData/include,-IData/MySQL/include,-IData/ODBC/include,-IData/PostgreSQL/include,-IData/SQLite/include, -IData/SQLite/src,-IFoundation/include,-IJSON/include,-IMongoDB/include,-INet/include,-INetSSL_OpenSSL/include,-INetSSL_Win/include,-IRedis/include,-IUtil/include,-IXML/include,-IZip/include,-ISevenZip/include,-IPDF/include
VCH=${javaVCH} VCH=${javaVCH}
WDK=${javaWDK} WDK=${javaWDK}
CLP=${javaCLP} CLP=${javaCLP}