Varnish compiler will not start when providing correct .vcl file - varnish
I installed Varnish with command apt-get install varnish
Varnish version is varnishd (varnish-6.2.1 revision 9f8588e4ab785244e06c3446fe09bf9db5dd8753)
I try to validate my VCL file with command varnishd -C -f /etc/varnish/default.vcl
My VCL file:
vcl 4.0;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
}
sub vcl_backend_response {
}
sub vcl_deliver {
}
This is the response I get, seems like it just echoes out varnish .c file:
/* ---===### Location Counters ###===---*/
#define VGC_NREFS 35
static const struct vrt_ref VGC_ref[VGC_NREFS] = {
[ 1] = { 0, 796, 26, 1, "}" },
[ 2] = { 0, 1025, 33, 1, "}" },
[ 3] = { 0, 1223, 40, 1, "}" },
[ 4] = { 1, 1605, 38, 5, "if" },
[ 5] = { 1, 1719, 40, 9, "return" },
[ 6] = { 1, 1750, 42, 5, "if" },
[ 7] = { 1, 1890, 46, 9, "return" },
[ 8] = { 1, 1921, 48, 5, "if" },
[ 9] = { 1, 2225, 57, 9, "return" },
[ 10] = { 1, 2251, 60, 5, "if" },
[ 11] = { 1, 2366, 62, 9, "return" },
[ 12] = { 1, 2391, 64, 5, "if" },
[ 13] = { 1, 2487, 66, 9, "return" },
[ 14] = { 1, 2512, 68, 5, "return" },
[ 15] = { 1, 2819, 77, 5, "return" },
[ 16] = { 1, 2856, 81, 5, "return" },
[ 17] = { 1, 2894, 85, 5, "hash_data" },
[ 18] = { 1, 2947, 87, 9, "hash_data" },
[ 19] = { 1, 2994, 89, 9, "hash_data" },
[ 20] = { 1, 3066, 95, 5, "return" },
[ 21] = { 1, 3118, 99, 5, "return" },
[ 22] = { 1, 3158, 103, 5, "return" },
[ 23] = { 1, 3199, 107, 5, "return" },
[ 24] = { 1, 3316, 114, 5, "set" },
[ 25] = { 1, 3907, 138, 5, "if" },
[ 26] = { 1, 3944, 139, 9, "unset" },
[ 27] = { 1, 3972, 141, 5, "return" },
[ 28] = { 1, 4022, 145, 5, "if" },
[ 29] = { 1, 4055, 146, 9, "return" },
[ 30] = { 1, 4407, 154, 9, "set" },
[ 31] = { 1, 4479, 157, 5, "return" },
[ 32] = { 1, 4528, 161, 5, "set" },
[ 33] = { 1, 5127, 185, 5, "return" },
[ 34] = { 1, 5162, 189, 5, "return" },
};
/* ---===### VCC generated .h code ###===---*/
static struct vsmw_cluster *vsc_cluster;
extern const struct VCL_conf VCL_conf;
static VCL_BACKEND vgc_backend_default;
/* "127.0.0.1 8080" -> 127.0.0.1 */
static const unsigned long long suckaddr_0[4] = {
0x901f00024b1e9335ULL,
0x000000000100007fULL,
0x0000000000000000ULL,
0x0000000000000000ULL
};
static const struct vrt_backend vgc_dir_priv_vgc_backend_default = {
.magic = VRT_BACKEND_MAGIC,
.vcl_name = "default",
.ipv4_suckaddr = (const struct suckaddr *)(const void*)suckaddr_0,
.ipv4_addr = "127.0.0.1",
.port = "8080",
.path = (void *) 0,
.hosthdr = "127.0.0.1",
};
static const struct gethdr_s VGC_HDR_REQ_host =
{ HDR_REQ, "\005host:"};
static void *VGC_re_1;
static const struct gethdr_s VGC_HDR_REQ_Authorization =
{ HDR_REQ, "\016Authorization:"};
static const struct gethdr_s VGC_HDR_REQ_Cookie =
{ HDR_REQ, "\007Cookie:"};
static const struct gethdr_s VGC_HDR_RESP_Content_2d_Type =
{ HDR_RESP, "\015Content-Type:"};
static const struct gethdr_s VGC_HDR_RESP_Retry_2d_After =
{ HDR_RESP, "\014Retry-After:"};
static const struct gethdr_s VGC_HDR_BERESP_Set_2d_Cookie =
{ HDR_BERESP, "\013Set-Cookie:"};
static const struct gethdr_s VGC_HDR_BERESP_Surrogate_2d_control =
{ HDR_BERESP, "\022Surrogate-control:"};
static void *VGC_re_2;
static const struct gethdr_s VGC_HDR_BERESP_Cache_2d_Control =
{ HDR_BERESP, "\016Cache-Control:"};
static void *VGC_re_3;
static const struct gethdr_s VGC_HDR_BERESP_Vary =
{ HDR_BERESP, "\005Vary:"};
static const struct gethdr_s VGC_HDR_BERESP_Content_2d_Type =
{ HDR_BERESP, "\015Content-Type:"};
static const struct gethdr_s VGC_HDR_BERESP_Retry_2d_After =
{ HDR_BERESP, "\014Retry-After:"};
vcl_func_f VGC_function_vcl_backend_error;
vcl_func_f VGC_function_vcl_backend_fetch;
vcl_func_f VGC_function_vcl_backend_response;
vcl_func_f VGC_function_vcl_deliver;
vcl_func_f VGC_function_vcl_fini;
vcl_func_f VGC_function_vcl_hash;
vcl_func_f VGC_function_vcl_hit;
vcl_func_f VGC_function_vcl_init;
vcl_func_f VGC_function_vcl_miss;
vcl_func_f VGC_function_vcl_pass;
vcl_func_f VGC_function_vcl_pipe;
vcl_func_f VGC_function_vcl_purge;
vcl_func_f VGC_function_vcl_recv;
vcl_func_f VGC_function_vcl_synth;
static unsigned vgc_inistep;
static unsigned vgc_warmupstep;
/* ---===### VCC generated .c code ###===---*/
#define END_ if (*ctx->handling) return
void v_matchproto_(vcl_func_f)
VGC_function_vcl_backend_error(VRT_CTX)
{
/* ... from ('Builtin' Line 160 Pos 23) */
{
{
VRT_count(ctx, 32);
END_;
VRT_SetHdr(ctx, &VGC_HDR_BERESP_Content_2d_Type,
"text/html; charset=utf-8",
vrt_magic_string_end
);
END_;
VRT_SetHdr(ctx, &VGC_HDR_BERESP_Retry_2d_After,
"5",
vrt_magic_string_end
);
END_;
VRT_l_beresp_body(ctx,
"<!DOCTYPE html>\n"
"<html>\n"
" <head>\n"
" <title>",
VRT_INT_string(ctx, VRT_r_beresp_status(ctx)),
" ",
VRT_r_beresp_reason(ctx),
"</title>\n"
" </head>\n"
" <body>\n"
" <h1>Error ",
VRT_INT_string(ctx, VRT_r_beresp_status(ctx)),
" ",
VRT_r_beresp_reason(ctx),
"</h1>\n"
" <p>",
VRT_r_beresp_reason(ctx),
"</p>\n"
" <h3>Guru Meditation:</h3>\n"
" <p>XID: ",
VRT_r_bereq_xid(ctx),
"</p>\n"
" <hr>\n"
" <p>Varnish cache server</p>\n"
" </body>\n"
"</html>\n"
"",
vrt_magic_string_end
);
END_;
VRT_handling(ctx, VCL_RET_DELIVER);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_backend_fetch(VRT_CTX)
{
/* ... from ('Builtin' Line 137 Pos 23) */
{
{
VRT_count(ctx, 25);
END_;
if (
(0 == VRT_strcmp(VRT_r_bereq_method(ctx), "GET"))
)
{
VRT_count(ctx, 26);
END_;
VRT_u_bereq_body(ctx);
END_;
}
VRT_count(ctx, 27);
END_;
VRT_handling(ctx, VCL_RET_FETCH);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_backend_response(VRT_CTX)
{
/* ... from ('/etc/varnish/default.vcl' Line 28 Pos 26) */
{
{
VRT_count(ctx, 2);
END_;
}
}
/* ... from ('Builtin' Line 144 Pos 26) */
{
{
VRT_count(ctx, 28);
END_;
if (
VRT_r_bereq_uncacheable(ctx)
)
{
VRT_count(ctx, 29);
END_;
VRT_handling(ctx, VCL_RET_DELIVER);
END_;
}
else if (
(
(VRT_r_beresp_ttl(ctx) <= (0) * 1)
||
(VRT_GetHdr(ctx, &VGC_HDR_BERESP_Set_2d_Cookie) != 0)
||
VRT_re_match(ctx, VRT_GetHdr(ctx, &VGC_HDR_BERESP_Surrogate_2d_control), VGC_re_2)
||
((
!((VRT_GetHdr(ctx, &VGC_HDR_BERESP_Surrogate_2d_control) != 0))
&&
VRT_re_match(ctx, VRT_GetHdr(ctx, &VGC_HDR_BERESP_Cache_2d_Control), VGC_re_3)
))
||
(0 == VRT_strcmp(VRT_GetHdr(ctx, &VGC_HDR_BERESP_Vary), "*"))
)
)
{
VRT_count(ctx, 30);
END_;
VRT_l_beresp_ttl(ctx,
(120) * 1
);
END_;
VRT_l_beresp_uncacheable(ctx,
(0==0)
);
END_;
}
VRT_count(ctx, 31);
END_;
VRT_handling(ctx, VCL_RET_DELIVER);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_deliver(VRT_CTX)
{
/* ... from ('/etc/varnish/default.vcl' Line 35 Pos 17) */
{
{
VRT_count(ctx, 3);
END_;
}
}
/* ... from ('Builtin' Line 106 Pos 17) */
{
{
VRT_count(ctx, 23);
END_;
VRT_handling(ctx, VCL_RET_DELIVER);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_fini(VRT_CTX)
{
/* ... from ('Builtin' Line 188 Pos 14) */
{
{
VRT_count(ctx, 34);
END_;
VRT_handling(ctx, VCL_RET_OK);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_hash(VRT_CTX)
{
/* ... from ('Builtin' Line 84 Pos 14) */
{
{
VRT_count(ctx, 17);
END_;
VRT_hashdata(ctx,
VRT_r_req_url(ctx),
vrt_magic_string_end
);
END_;
if (
(VRT_GetHdr(ctx, &VGC_HDR_REQ_host) != 0)
)
{
VRT_count(ctx, 18);
END_;
VRT_hashdata(ctx,
VRT_GetHdr(ctx, &VGC_HDR_REQ_host),
vrt_magic_string_end
);
END_;
}
else
{
VRT_count(ctx, 19);
END_;
VRT_hashdata(ctx,
VRT_IP_string(ctx, VRT_r_server_ip(ctx)),
vrt_magic_string_end
);
END_;
}
END_;
VRT_handling(ctx, VCL_RET_LOOKUP);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_hit(VRT_CTX)
{
/* ... from ('Builtin' Line 98 Pos 13) */
{
{
VRT_count(ctx, 21);
END_;
VRT_handling(ctx, VCL_RET_DELIVER);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_init(VRT_CTX)
{
/* ... from ('Builtin' Line 184 Pos 14) */
{
{
VRT_count(ctx, 33);
END_;
VRT_handling(ctx, VCL_RET_OK);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_miss(VRT_CTX)
{
/* ... from ('Builtin' Line 102 Pos 14) */
{
{
VRT_count(ctx, 22);
END_;
VRT_handling(ctx, VCL_RET_FETCH);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_pass(VRT_CTX)
{
/* ... from ('Builtin' Line 80 Pos 14) */
{
{
VRT_count(ctx, 16);
END_;
VRT_handling(ctx, VCL_RET_FETCH);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_pipe(VRT_CTX)
{
/* ... from ('Builtin' Line 71 Pos 14) */
{
{
VRT_count(ctx, 15);
END_;
VRT_handling(ctx, VCL_RET_PIPE);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_purge(VRT_CTX)
{
/* ... from ('Builtin' Line 94 Pos 15) */
{
{
VRT_count(ctx, 20);
END_;
VRT_synth(ctx,
200
,
"Purged"
);
VRT_handling(ctx, VCL_RET_SYNTH);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_recv(VRT_CTX)
{
/* ... from ('/etc/varnish/default.vcl' Line 21 Pos 14) */
{
{
VRT_count(ctx, 1);
END_;
}
}
/* ... from ('Builtin' Line 37 Pos 14) */
{
{
VRT_count(ctx, 4);
END_;
if (
(0 == VRT_strcmp(VRT_r_req_method(ctx), "PRI"))
)
{
VRT_count(ctx, 5);
END_;
VRT_synth(ctx,
405
,
(const char*)0
);
VRT_handling(ctx, VCL_RET_SYNTH);
END_;
}
VRT_count(ctx, 6);
END_;
if (
(
!((VRT_GetHdr(ctx, &VGC_HDR_REQ_host) != 0))
&&
(VRT_r_req_esi_level(ctx) == 0)
&&
VRT_re_match(ctx, VRT_r_req_proto(ctx), VGC_re_1)
)
)
{
VRT_count(ctx, 7);
END_;
VRT_synth(ctx,
400
,
(const char*)0
);
VRT_handling(ctx, VCL_RET_SYNTH);
END_;
}
VRT_count(ctx, 8);
END_;
if (
(
(0 != VRT_strcmp(VRT_r_req_method(ctx), "GET"))
&&
(0 != VRT_strcmp(VRT_r_req_method(ctx), "HEAD"))
&&
(0 != VRT_strcmp(VRT_r_req_method(ctx), "PUT"))
&&
(0 != VRT_strcmp(VRT_r_req_method(ctx), "POST"))
&&
(0 != VRT_strcmp(VRT_r_req_method(ctx), "TRACE"))
&&
(0 != VRT_strcmp(VRT_r_req_method(ctx), "OPTIONS"))
&&
(0 != VRT_strcmp(VRT_r_req_method(ctx), "DELETE"))
&&
(0 != VRT_strcmp(VRT_r_req_method(ctx), "PATCH"))
)
)
{
VRT_count(ctx, 9);
END_;
VRT_handling(ctx, VCL_RET_PIPE);
END_;
}
VRT_count(ctx, 10);
END_;
if (
(
(0 != VRT_strcmp(VRT_r_req_method(ctx), "GET"))
&&
(0 != VRT_strcmp(VRT_r_req_method(ctx), "HEAD"))
)
)
{
VRT_count(ctx, 11);
END_;
VRT_handling(ctx, VCL_RET_PASS);
END_;
}
VRT_count(ctx, 12);
END_;
if (
(
(VRT_GetHdr(ctx, &VGC_HDR_REQ_Authorization) != 0)
||
(VRT_GetHdr(ctx, &VGC_HDR_REQ_Cookie) != 0)
)
)
{
VRT_count(ctx, 13);
END_;
VRT_handling(ctx, VCL_RET_PASS);
END_;
}
VRT_count(ctx, 14);
END_;
VRT_handling(ctx, VCL_RET_HASH);
END_;
}
}
}
void v_matchproto_(vcl_func_f)
VGC_function_vcl_synth(VRT_CTX)
{
/* ... from ('Builtin' Line 113 Pos 15) */
{
{
VRT_count(ctx, 24);
END_;
VRT_SetHdr(ctx, &VGC_HDR_RESP_Content_2d_Type,
"text/html; charset=utf-8",
vrt_magic_string_end
);
END_;
VRT_SetHdr(ctx, &VGC_HDR_RESP_Retry_2d_After,
"5",
vrt_magic_string_end
);
END_;
VRT_l_resp_body(ctx,
"<!DOCTYPE html>\n"
"<html>\n"
" <head>\n"
" <title>",
VRT_INT_string(ctx, VRT_r_resp_status(ctx)),
" ",
VRT_r_resp_reason(ctx),
"</title>\n"
" </head>\n"
" <body>\n"
" <h1>Error ",
VRT_INT_string(ctx, VRT_r_resp_status(ctx)),
" ",
VRT_r_resp_reason(ctx),
"</h1>\n"
" <p>",
VRT_r_resp_reason(ctx),
"</p>\n"
" <h3>Guru Meditation:</h3>\n"
" <p>XID: ",
VRT_r_req_xid(ctx),
"</p>\n"
" <hr>\n"
" <p>Varnish cache server</p>\n"
" </body>\n"
"</html>\n"
"",
vrt_magic_string_end
);
END_;
VRT_handling(ctx, VCL_RET_DELIVER);
END_;
}
}
}
static int
VGC_Load(VRT_CTX)
{
vgc_inistep = 0;
size_t ndirector = 1UL;
/* 1 */
vsc_cluster = VRT_VSM_Cluster_New(ctx,
ndirector * VRT_backend_vsm_need(ctx));
if (vsc_cluster == 0)
return(1);
vgc_inistep = 1;
/* 2 */
vgc_backend_default =
VRT_new_backend_clustered(ctx, vsc_cluster,
&vgc_dir_priv_vgc_backend_default);
vgc_inistep = 2;
/* 3 */
VRT_re_init(&VGC_re_1, "^(\?i)HTTP/1.1");
vgc_inistep = 3;
/* 4 */
VRT_re_init(&VGC_re_2, "(\?i)no-store");
vgc_inistep = 4;
/* 5 */
VRT_re_init(&VGC_re_3, "(\?i:no-cache|no-store|private)");
vgc_inistep = 5;
/* 6 */
VGC_function_vcl_init(ctx);
vgc_inistep = 6;
if (*ctx->handling != VCL_RET_OK)
return(1);
return(0);
}
static int
VGC_Discard(VRT_CTX)
{
switch (vgc_inistep) {
case 6:
VGC_function_vcl_fini(ctx);
/* FALLTHROUGH */
case 5:
VRT_re_fini(VGC_re_3);
/* FALLTHROUGH */
case 4:
VRT_re_fini(VGC_re_2);
/* FALLTHROUGH */
case 3:
VRT_re_fini(VGC_re_1);
/* FALLTHROUGH */
case 2:
VRT_delete_backend(ctx, &vgc_backend_default);
/* FALLTHROUGH */
case 1:
VRT_VSM_Cluster_Destroy(ctx, &vsc_cluster);
/* FALLTHROUGH */
default:
break;
}
switch (vgc_inistep) {
case 6:
/* FALLTHROUGH */
case 5:
/* FALLTHROUGH */
case 4:
/* FALLTHROUGH */
case 3:
/* FALLTHROUGH */
case 2:
/* FALLTHROUGH */
case 1:
/* FALLTHROUGH */
default:
break;
}
return (0);
}
static int
VGC_Event(VRT_CTX, enum vcl_event_e ev)
{
if (ev == VCL_EVENT_LOAD)
return (VGC_Load(ctx));
if (ev == VCL_EVENT_DISCARD)
return (VGC_Discard(ctx));
(void)vgc_warmupstep;
return (0);
}
const struct VCL_conf VCL_conf = {
.magic = VCL_CONF_MAGIC,
.syntax = 40,
.event_vcl = VGC_Event,
.default_director = &vgc_backend_default,
.ref = VGC_ref,
.nref = VGC_NREFS,
.nsrc = VGC_NSRCS,
.srcname = srcname,
.srcbody = srcbody,
.nvmod = 0,
.backend_error_func = VGC_function_vcl_backend_error,
.backend_fetch_func = VGC_function_vcl_backend_fetch,
.backend_response_func = VGC_function_vcl_backend_response,
.deliver_func = VGC_function_vcl_deliver,
.fini_func = VGC_function_vcl_fini,
.hash_func = VGC_function_vcl_hash,
.hit_func = VGC_function_vcl_hit,
.init_func = VGC_function_vcl_init,
.miss_func = VGC_function_vcl_miss,
.pass_func = VGC_function_vcl_pass,
.pipe_func = VGC_function_vcl_pipe,
.purge_func = VGC_function_vcl_purge,
.recv_func = VGC_function_vcl_recv,
.synth_func = VGC_function_vcl_synth,
};
/*
* Symbol Table
*
* none VOID 41 41 acl
* none VOID 41 41 backend
* action VOID 40 41 ban
* var HTTP 0 99 bereq
* var BACKEND 0 99 bereq.backend
* var DURATION 0 99 bereq.between_bytes_timeout
* var BODY 0 99 bereq.body
* var DURATION 0 99 bereq.connect_timeout
* var DURATION 0 99 bereq.first_byte_timeout
* var BLOB 0 99 bereq.hash
* none HEADER 0 99 bereq.http*
* var BOOL 0 99 bereq.is_bgfetch
* var STRING 0 99 bereq.method
* var STRING 0 40 bereq.proto
* var STRING 41 99 bereq.proto
* var INT 0 99 bereq.retries
* var BOOL 0 99 bereq.uncacheable
* var STRING 0 99 bereq.url
* var STRING 0 99 bereq.xid
* var HTTP 0 99 beresp
* var DURATION 0 99 beresp.age
* var BACKEND 0 99 beresp.backend
* var IP 0 40 beresp.backend.ip
* var STRING 0 99 beresp.backend.name
* var BODY 0 99 beresp.body
* var BOOL 0 99 beresp.do_esi
* var BOOL 0 99 beresp.do_gunzip
* var BOOL 0 99 beresp.do_gzip
* var BOOL 0 99 beresp.do_stream
* var STRING 0 99 beresp.filters
* var DURATION 0 99 beresp.grace
* none HEADER 0 99 beresp.http*
* var HEADER 40 40 beresp.http.Cache-Control
* var HEADER 40 40 beresp.http.Content-Type
* var HEADER 40 40 beresp.http.Retry-After
* var HEADER 40 40 beresp.http.Set-Cookie
* var HEADER 40 40 beresp.http.Surrogate-control
* var HEADER 40 40 beresp.http.Vary
* var DURATION 0 99 beresp.keep
* var STRING 0 40 beresp.proto
* var STRING 41 99 beresp.proto
* var STRING 0 99 beresp.reason
* var INT 0 99 beresp.status
* var STEVEDORE 0 99 beresp.storage
* var STRING 0 40 beresp.storage_hint
* var DURATION 0 99 beresp.ttl
* var BOOL 0 99 beresp.uncacheable
* var BOOL 0 99 beresp.was_304
* action VOID 40 41 call
* none VOID 0 99 client
* var STRING 0 99 client.identity
* var IP 0 99 client.ip
* none VOID 41 41 default
* func BOOL 40 41 false
* action VOID 40 41 hash_data
* action VOID 40 41 if
* none VOID 41 41 import
* none VOID 0 99 local
* var STRING 41 99 local.endpoint
* var IP 0 99 local.ip
* var STRING 41 99 local.socket
* action VOID 40 41 new
* var TIME 0 99 now
* none VOID 0 99 obj
* var DURATION 0 99 obj.age
* var DURATION 0 99 obj.grace
* var INT 0 99 obj.hits
* none HEADER 0 99 obj.http*
* var DURATION 0 99 obj.keep
* var STRING 0 99 obj.proto
* var STRING 0 99 obj.reason
* var INT 0 99 obj.status
* var STEVEDORE 0 99 obj.storage
* var DURATION 0 99 obj.ttl
* var BOOL 0 99 obj.uncacheable
* none VOID 41 41 probe
* func STRING 40 41 regsub
* func STRING 40 41 regsuball
* none VOID 0 99 remote
* var IP 0 99 remote.ip
* var HTTP 0 99 req
* var BACKEND 0 99 req.backend_hint
* var BOOL 0 99 req.can_gzip
* var BOOL 0 40 req.esi
* var INT 0 99 req.esi_level
* var DURATION 0 99 req.grace
* var BLOB 0 99 req.hash
* var BOOL 0 99 req.hash_always_miss
* var BOOL 0 99 req.hash_ignore_busy
* none HEADER 0 99 req.http*
* var HEADER 40 40 req.http.Authorization
* var HEADER 40 40 req.http.Cookie
* var HEADER 40 40 req.http.host
* var BOOL 0 99 req.is_hitmiss
* var BOOL 0 99 req.is_hitpass
* var STRING 0 99 req.method
* var STRING 0 40 req.proto
* var STRING 41 99 req.proto
* var INT 0 99 req.restarts
* var STEVEDORE 0 99 req.storage
* var DURATION 0 99 req.ttl
* var STRING 0 99 req.url
* var STRING 0 99 req.xid
* none VOID 0 99 req_top
* none HEADER 0 99 req_top.http*
* var STRING 0 99 req_top.method
* var STRING 0 99 req_top.proto
* var STRING 0 99 req_top.url
* var HTTP 0 99 resp
* var BODY 0 99 resp.body
* var BOOL 41 99 resp.do_esi
* var STRING 0 99 resp.filters
* none HEADER 0 99 resp.http*
* var HEADER 40 40 resp.http.Content-Type
* var HEADER 40 40 resp.http.Retry-After
* var BOOL 0 99 resp.is_streaming
* var STRING 0 40 resp.proto
* var STRING 41 99 resp.proto
* var STRING 0 99 resp.reason
* var INT 0 99 resp.status
* action VOID 40 41 return
* none VOID 0 99 server
* var STRING 0 99 server.hostname
* var STRING 0 99 server.identity
* var IP 0 99 server.ip
* none VOID 41 99 sess
* var STRING 41 99 sess.xid
* action VOID 40 41 set
* none VOID 40 41 storage
* var STEVEDORE 40 41 storage.s0
* var BYTES 40 41 storage.s0.free_space
* var BOOL 40 41 storage.s0.happy
* var BYTES 40 41 storage.s0.used_space
* var STEVEDORE 40 41 storage.Transient
* var BYTES 40 41 storage.Transient.free_space
* var BOOL 40 41 storage.Transient.happy
* var BYTES 40 41 storage.Transient.used_space
* none VOID 41 41 sub
* action VOID 40 41 synthetic
* func BOOL 40 41 true
* action VOID 40 41 unset
* none VOID 41 41 vcl
* sub VOID 40 41 vcl_backend_error
* sub VOID 40 41 vcl_backend_fetch
* sub VOID 40 41 vcl_backend_response
* sub VOID 40 41 vcl_deliver
* sub VOID 40 41 vcl_fini
* sub VOID 40 41 vcl_hash
* sub VOID 40 41 vcl_hit
* sub VOID 40 41 vcl_init
* sub VOID 40 41 vcl_miss
* sub VOID 40 41 vcl_pass
* sub VOID 40 41 vcl_pipe
* sub VOID 40 41 vcl_purge
* sub VOID 40 41 vcl_recv
* sub VOID 40 41 vcl_synth
*/
However if I make a error in my VCL file, like replace .host with host, I get a VCC compiler error:
Message from VCC-compiler:
Expected '.' got 'host'
(program line 93), at
('/etc/varnish/default.vcl' Line 17 Pos 5)
host = "127.0.0.1";
----####---------------
In backend specification starting at:
('/etc/varnish/default.vcl' Line 16 Pos 1)
backend default {
#######----------
Running VCC-compiler failed, exited with 2
VCL compilation failed
Any ideas what am I doing wrong?
You're not doing anything wrong.
This is what the -C option does according to the docs:
Output VCL code compiled to C language
What you're seeing is the C representation of the VCL file. The VCC thread of the varnishd process will transpile the VLC code into C code. This C code will be compiled into machine code and the .so file that results from the compilation will be linked to the varnishd runtime process prior to execution.
As long as you're not making any syntax errors, the -C option will spit out the C code. Once you make a mistake in the VCL, the compilation will fail and you'll get an error.
VCL validation with varnishadm
There are other ways to validate your VCL file.
You can either add your VCL code as an inline string to varnishadm vcl.inline. See https://varnish-cache.org/docs/6.0/reference/varnish-cli.html#vcl-inline-configname-quoted-vclstring-auto-cold-warm for documentation.
You can also use the following commands to load, validate & discard the VCL file:
sudo varnishadm vcl.load validation default.vcl
sudo varnishadm vcl.discard validation
The first command will load the default.vcl file and try to compile it. When it success the validation configuration is stored and can be used in production through varnishadm vcl.use validation.
But we're not going to do that. Because this is only a validation run, we'll remove the validation config through varnishadm vcl.discard validation as seen in the example above.
Related
why am i getting expected primary-expression before '.' token [closed]
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers. This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers. Closed 15 hours ago. Improve this question I am trying to create a Struct with two structs inside. One struct has a 2d array in it. The other struct packs 2 versions of the previous struct. I have a working code. However, in this code I have this statement: `if (lane_bank_select == 0) { for (uint8_t i = 0; i < lane_amount; i = i + 1) { Serial.print(db.data_lane_bank_1[i].data_1); Serial.print(" "); Serial.print(db.data_lane_bank_1[i].data_2); Serial.print(" "); Serial.print(db.data_lane_bank_1[i].data_3); Serial.print(" "); Serial.println(db.data_lane_bank_1[i].data_4); } } else if (lane_bank_select == 1) { for (uint8_t i = 0; i < lane_amount; i = i + 1) { Serial.print(db.data_lane_bank_2[i].data_1); Serial.print(" "); Serial.print(db.data_lane_bank_2[i].data_2); Serial.print(" "); Serial.print(db.data_lane_bank_2[i].data_3); Serial.print(" "); Serial.println(db.data_lane_bank_2[i].data_4); } } else { Serial.print(db.data_lane_bank_1[0].data_1); Serial.print(" "); Serial.print(db.data_lane_bank_1[0].data_2); Serial.print(" "); Serial.print(db.data_lane_bank_1[0].data_3); Serial.print(" "); Serial.println(db.data_lane_bank_1[0].data_4); }` I would like to change this statement to something like this. `for (uint8_t i = 0; i < memory_amount; i = i + 1) { if (lane_bank_select == i) { for (uint8_t j = 0; j < bank_amount; j = j + 1) { for (uint8_t k = 0; k < lane_amount; k = k + 1) { for (uint8_t l = 0; l < data_amount; l = l + 1) { Serial.print(db.data_lane_bank[j][k].data[l]); Serial.println(" "); } } } } }` So i wrote this: `const uint8_t memory_amount = 2; const uint8_t bank_amount = 2; const uint8_t data_amount = 4; const uint8_t lane_amount = 4; const uint8_t lane_array_size = 4; uint8_t lane_bank_select = 0; // This is used to select the data lane bank struct data_lane { // creates 4 variables for the data lane. uint8_t data[data_amount]; }; // packs 2 versions of data_lane struct into one struct struct data_bank { data_lane data_lane_bank[bank_amount][lane_amount]; }; void setup() { Serial.begin(9600); } void loop() { // use serial port to select data_lane bank via lane_bank_select serial_lane_select(); data_bank db = { .data_lane_bank[0] = { { 1, 2, 3, 4 }, // Data_lane_1 { 11, 12, 13, 14 }, // Data_lane_2 { 21, 22, 23, 24 }, // Data_lane_3 { 31, 32, 33, 34 }, // Data_lane_4 }, .data_lane_bank[1] = { { 41, 42, 43, 44 }, // Data_lane_1 { 51, 52, 53, 54 }, // Data_lane_2 { 61, 62, 63, 64 }, // Data_lane_3 { 71, 72, 73, 74 }, // Data_lane_4 } }; for (uint8_t i = 0; i < memory_amount; i = i + 1) { if (lane_bank_select == i) { for (uint8_t j = 0; j < bank_amount; j = j + 1) { for (uint8_t k = 0; k < lane_amount; k = k + 1) { for (uint8_t l = 0; l < data_amount; l = l + 1) { Serial.print(db.data_lane_bank[j][k].data[l]); Serial.println(" "); } } } } } } void serial_lane_select() { uint8_t lane_recieved; if (Serial.available() > 0) { lane_recieved = Serial.read(); if (lane_recieved == '1') // Single Quote! This is a character. { lane_bank_select = 0; } if (lane_recieved == '2') { lane_bank_select = 1; } } }` I am now getting this error: expected primary-expression before '.' token .data_lane_bank[0] = Can somebody help please.
Accelerometer data over BLE are not sent in synch
I am sending temperature, humidity, pressure and accelerometer data over BLE, from Arduino (peripheral) to Raspberry Pi 4 (central). I created BLE characteristic per each acceleration dimension (accX, accY, accZ), and I am subscribing to these characteristics. However, I put counter for each characteristic and realized that data are not sent in order: 18 Nov 12:27:35 - [info] [BLE Connect:bf9be48b4648f12e] x = 233 18 Nov 12:27:35 - [info] [BLE Connect:bf9be48b4648f12e] y = 230 18 Nov 12:27:35 - [info] [BLE Connect:bf9be48b4648f12e] z = 236 So x is read 233 times while y 230 times vice versa. In ideal scenario, they all should be same. I am posting my full Arduino code minus comments, hence I believe it might be needed: #include <ArduinoBLE.h> #include <Arduino_HTS221.h> #include <Arduino_LPS22HB.h> #include <Arduino_LSM9DS1.h> #define BLE_UUID_ENVIRONMENTAL_SENSING_SERVICE "181A" #define BLE_UUID_TEMPERATURE "2A6E" #define BLE_UUID_HUMIDITY "2A6F" #define BLE_UUID_PRESSURE "2A6D" #define BLE_UUID_ACCELEROMETER_SERVICE "1101" #define BLE_UUID_ACCELEROMETER_X "2101" #define BLE_UUID_ACCELEROMETER_Y "2102" #define BLE_UUID_ACCELEROMETER_Z "2103" #define BLE_DEVICE_NAME "Hako" #define BLE_LOCAL_NAME "Hako" BLEService environmentalSensingService(BLE_UUID_ENVIRONMENTAL_SENSING_SERVICE); BLEService accelerometerService(BLE_UUID_ACCELEROMETER_SERVICE); BLEShortCharacteristic temperatureCharacteristic(BLE_UUID_TEMPERATURE, BLERead | BLENotify); BLEUnsignedShortCharacteristic humidityCharacteristic(BLE_UUID_HUMIDITY, BLERead | BLENotify); BLEUnsignedLongCharacteristic pressureCharacteristic(BLE_UUID_PRESSURE, BLERead | BLENotify); BLEShortCharacteristic accelerometerCharacteristic_X(BLE_UUID_ACCELEROMETER_X, BLERead | BLENotify); BLEShortCharacteristic accelerometerCharacteristic_Y(BLE_UUID_ACCELEROMETER_Y, BLERead | BLENotify); BLEShortCharacteristic accelerometerCharacteristic_Z(BLE_UUID_ACCELEROMETER_Z, BLERead | BLENotify); #define ENV_SENSOR_UPDATE_INTERVAL (1000) #define ACC_SENSOR_UPDATE_INTERVAL (1000) typedef struct __attribute__((packed)) { float temperature; float humidity; float pressure; bool updated = false; } env_sensor_data_t; env_sensor_data_t envSensorData; typedef struct __attribute__((packed)) { float accX; float accY; float accZ; bool updated = false; } acc_sensor_data_t; acc_sensor_data_t accSensorData; #define BLE_LED_PIN LED_BUILTIN void setup() { Serial.begin(9600); while (!Serial); Serial.println( "BLE Example - Environmental Sensing Service (ESS)" ); pinMode( BLE_LED_PIN, OUTPUT ); digitalWrite( BLE_LED_PIN, LOW ); // Without Serial when using USB power bank HTS sensor seems to needs some time for setup delay(10); if (!HTS.begin()) { Serial.println("Failed to initialize humidity temperature sensor!"); while (1); } if (!BARO.begin()) { Serial.println( "Failed to initialize pressure sensor!" ); while (1); } if (!IMU.begin()) { Serial.println("Failed to initialize IMU!"); while (1); } if (!setupBleMode()) { while (1); } else { Serial.println( "BLE initialized. Waiting for clients to connect." ); } } void loop() { bleTask(); if (envSensorTask()) { envPrintTask(); } if (accSensorTask()) { accPrintTask(); } } bool envSensorTask() { static long previousMillis = 0; unsigned long currentMillis = millis(); if (currentMillis - previousMillis < ENV_SENSOR_UPDATE_INTERVAL) { return false; } previousMillis = currentMillis; envSensorData.temperature = HTS.readTemperature(); envSensorData.humidity = HTS.readHumidity(); envSensorData.pressure = BARO.readPressure() * 1000; // kPa -> Pa envSensorData.updated = true; return envSensorData.updated; } bool accSensorTask() { static long previousMillis2 = 0; unsigned long currentMillis2 = millis(); float x = 0.00, y = 0.00, z = 0.00; if (currentMillis2 - previousMillis2 < ACC_SENSOR_UPDATE_INTERVAL) { return false; } previousMillis2 = currentMillis2; if(IMU.accelerationAvailable()){ IMU.readAcceleration(x, y, z); accSensorData.accX = x; accSensorData.accY = y; accSensorData.accZ = z; accSensorData.updated = true; } return accSensorData.updated; } bool setupBleMode() { if (!BLE.begin()) { return false; } BLE.setDeviceName(BLE_DEVICE_NAME); BLE.setLocalName(BLE_LOCAL_NAME); BLE.setAdvertisedService(environmentalSensingService); BLE.setAdvertisedService(accelerometerService); environmentalSensingService.addCharacteristic(temperatureCharacteristic); environmentalSensingService.addCharacteristic(humidityCharacteristic); environmentalSensingService.addCharacteristic(pressureCharacteristic); accelerometerService.addCharacteristic(accelerometerCharacteristic_X); accelerometerService.addCharacteristic(accelerometerCharacteristic_Y); accelerometerService.addCharacteristic(accelerometerCharacteristic_Z); BLE.addService(environmentalSensingService); BLE.addService(accelerometerService); temperatureCharacteristic.writeValue(0); humidityCharacteristic.writeValue(0); pressureCharacteristic.writeValue(0); accelerometerCharacteristic_X.writeValue(0); accelerometerCharacteristic_Y.writeValue(0); accelerometerCharacteristic_Z.writeValue(0); BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler); BLE.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler); BLE.advertise(); return true; } void bleTask() { const uint32_t BLE_UPDATE_INTERVAL = 10; static uint32_t previousMillis = 0; uint32_t currentMillis = millis(); if (currentMillis - previousMillis >= BLE_UPDATE_INTERVAL) { previousMillis = currentMillis; BLE.poll(); } if (envSensorData.updated) { // BLE defines Temperature UUID 2A6E Type sint16 ( see XML links ) // Unit is in degrees Celsius with a resolution of 0.01 degrees Celsius int16_t temperature = round(envSensorData.temperature * 100.0); temperatureCharacteristic.writeValue(temperature); // BLE defines Humidity UUID 2A6F Type uint16 // Unit is in percent with a resolution of 0.01 percent uint16_t humidity = round(envSensorData.humidity * 100.0); humidityCharacteristic.writeValue(humidity); // BLE defines Pressure UUID 2A6D Type uint32 // Unit is in Pascal with a resolution of 0.1 Pa uint32_t pressure = round(envSensorData.pressure * 10.0); pressureCharacteristic.writeValue(pressure); envSensorData.updated = false; } if (accSensorData.updated) { // BLE does not define accelerometer UUID // Alls units is in G int16_t accelerometer_X = round(accSensorData.accX * 100.0); accelerometerCharacteristic_X.writeValue(accelerometer_X); int16_t accelerometer_Y = round(accSensorData.accY * 100.0); accelerometerCharacteristic_Y.writeValue(accelerometer_Y); int16_t accelerometer_Z = round(accSensorData.accZ * 100.0); accelerometerCharacteristic_Z.writeValue(accelerometer_Z); envSensorData.updated = false; } } void envPrintTask() { Serial.print( "Temperature = " ); Serial.print( envSensorData.temperature ); Serial.println( " °C" ); Serial.print( "Humidity = " ); Serial.print( envSensorData.humidity ); Serial.println( " %" ); Serial.print( "Pressure = " ); Serial.print( envSensorData.pressure ); Serial.println( " Pa" ); Serial.print(temperatureCharacteristic.subscribed()); Serial.print(humidityCharacteristic.subscribed()); Serial.println(pressureCharacteristic.subscribed()); } void accPrintTask() { Serial.print("AccX = "); Serial.print(accSensorData.accX); Serial.println(" G"); Serial.print("AccY = "); Serial.print(accSensorData.accY); Serial.println(" G"); Serial.print("AccZ = "); Serial.print( accSensorData.accZ ); Serial.println(" G"); Serial.print(accelerometerCharacteristic_X.subscribed()); Serial.print(accelerometerCharacteristic_Y.subscribed()); Serial.println(accelerometerCharacteristic_Z.subscribed()); } void blePeripheralConnectHandler(BLEDevice central) { digitalWrite(BLE_LED_PIN, HIGH); Serial.print(F( "Connected to central: " )); Serial.println(central.address()); } void blePeripheralDisconnectHandler( BLEDevice central ) { digitalWrite(BLE_LED_PIN, LOW); Serial.print(F("Disconnected from central: ")); Serial.println(central.address()); } I am reading the data on Pi via in Node.js environment via #abandonware/noble library. I will only post the related part, where I subscribe to characteristics first, then I read the data. You can see the counters at the end. for (const [key, character] of Object.entries(ALL.characteristics)) { // Check the notify bit, if not set, set it. // if (character.properties.includes("notify")) { const descriptors = await character.discoverDescriptorsAsync().catch(e => send(e)); for (const [key, descriptor] of Object.entries(descriptors)) { node.log(descriptor); let descriptorData = await descriptor.readValueAsync().catch(e => send(e)); if (descriptorData[0] === bufferChecker[0] || descriptorData[1] === bufferChecker [1]) { node.log(`The ${character.name} ${character.uuid} notify bit is disabled.`); node.log("Enabling notification bit..."); descriptor.writeValueAsync(notifySetter).catch(e => send(e)); node.log (`Notification for ${character.name} characteristic is enabled.`); } else { node.log(`The ${character.name} ${character.uuid} notify bit is already enabled.`); return; } } } else { node.log(`Notification is not allowed for ${character.name} characteristic.`) } } for (const [key, character] of Object.entries(ALL.characteristics)) { character.on('data', (data) => { if (character.uuid === '2a6d') { data = data.readUInt32LE() * decimalSetter[1]; environmentalData.payload[character.name] = data.toFixed(2); counterPres++; } else if (character.uuid === '2a6e') { data = data.readUInt16LE() * decimalSetter[0]; environmentalData.payload[character.name] = data.toFixed(2); counterTemp++; } else if (character.uuid === '2a6f') { data = data.readUInt16LE() * decimalSetter[0]; environmentalData.payload[character.name] = data.toFixed(2); counterHum++; } else if (character.uuid === '2101') { data = data.readInt16LE() * decimalSetter[0]; accData.payload[character.name] = data.toFixed(2); counterAccX++; } else if (character.uuid === '2102') { data = data.readInt16LE() * decimalSetter[0]; accData.payload[character.name] = data.toFixed(2); counterAccY++; } else if (character.uuid === '2103') { data = data.readInt16LE() * decimalSetter[0]; accData.payload[character.name] = data.toFixed(2); counterAccZ++; } node.log("x = " + counterAccX); node.log("y = " + counterAccY); node.log("z = " + counterAccZ); // Sends Temp., Hum., and Pres. data together. if ( (counterHum + counterPres + counterTemp) % 3 == 0 && (counterHum + counterPres + counterTemp) !== 0){ send(environmentalData); } }); // Character data event listener END // } I asked the same question at Arduino forum as well.
The peripherals GATT server only sends data if the measured value has really changed. This behaviour saves energy and bandwidth. I think your observation is therefore perfectly normal.
How to generate the array of time durations
I'm trying to create an array of time durations in a day with 15 minute intervals with moment.js and ES6. Example: let time_duration= ["15 Min", "30 Min",..., "1 hr 15 min", "1 hr 30 min"]
I think it supposed to work: generateTimeDurations(minutesGap: number, length: number): string[] { const result = Array(length).fill(null); let acc = 0; return result.map(_ => { acc += minutesGap; if (acc >= 60) { return `${Math.floor(acc / 60)} hr ${acc % 60} min`; } else { return `${acc} min`; } }); }
If you only need static time levels like "15 Min", "30 Min" and so on you could try to do it in plain JS with Array#fill and Array#map. const hours = 24; const minutes = 24 * 60; function minsToHM(totalMins) { let padZero = value => String(value).padStart(2, "0"); totalMins = Number(totalMins); const h = Math.floor(totalMins / 60); const m = Math.floor(totalMins % 60); const hDisplay = h > 0 ? padZero(h) + (h == 1 ? " Hour" : " Hours") : ""; const mDisplay = m > 0 ? padZero(m) + (m == 1 ? " Min" : " Mins") : ""; return `${hDisplay}${h > 0 && m > 0 ? ", ": ""}${mDisplay}`; } function splitHours(hours, difference) { const mins = hours * 60; return Array(Math.floor(mins / difference)) .fill(1) .map((_, idx) => (idx+1) * difference) } const output = splitHours(1.5, 15).map(i => minsToHM(i)) console.log(output) .as-console-wrapper { max-height: 100% !important; top: 0px }
console.clear(); function digitToMinute(digit) { return digit * 60 / 100; } function minutesToDigit(minute) { return minute * 100 / 60; } function digitsToHourAndMinutes(digit) { return [Math.floor(digit / 60), digitToMinute(getFraction(digit / 60))]; } function getFraction(f) { return Math.ceil(((f < 1.0) ? f : (f % Math.floor(f))) * 100) } function getIntervals(max) { var intervals = []; var span = 15; var i = 0; while (i <= max) { if (i > 0) { let [hour, minute] = digitsToHourAndMinutes((i)); let string = []; if (hour > 0) { string.push(hour + ' hour'); } if (minute > 0) { string.push(minute + ' minutes'); } intervals.push(string.join(' ')); } i = i + span; } return intervals; } console.log(getIntervals(60 * 5));
How can you get a sprite to follow another sprite in Java?
Here is the code for the initial character: public class Player extends Mob { private InputHandler input; private int colour = Colours.get(-1, 111, 145, 543); private int scale = 1; protected boolean isSwimming = false; private int tickCount = 0; public Player(Level level, int x, int y, InputHandler input) { super(level, "Player", x, y, 1); this.input = input; } public void tick() { int xa = 0; int ya = 0; if (input.up.isPressed()) { ya--; } if (input.down.isPressed()) { ya++; } if (input.left.isPressed()) { xa--; } if (input.right.isPressed()) { xa++; } if (xa != 0 || ya != 0) { move(xa, ya); isMoving = true; } else { isMoving = false; } if (level.getTile(this.x >> 3, this.y >> 3).getId() == 3) { isSwimming = true; } if (isSwimming && level.getTile(this.x >> 3, this.y >> 3).getId() != 3) { isSwimming = false; } tickCount++; this.scale = 1; } public void render(Screen screen) { int xTile = 0; int yTile = 28; int walkingSpeed = 4; int flipTop = (numSteps >> walkingSpeed) & 1; int flipBottom = (numSteps >> walkingSpeed) & 1; if (movingDir == 1) { xTile += 2; } else if (movingDir > 1) { xTile += 4 + ((numSteps >> walkingSpeed) & 1) * 2; flipTop = (movingDir - 1) % 2; } int modifier = 8 * scale; int xOffset = x - modifier / 2; int yOffset = y - modifier / 2 - 4; if (isSwimming) { int waterColour = 0; yOffset += 4; if (tickCount % 60 < 15) { waterColour = Colours.get(-1, -1, 225, -1); } else if (15 <= tickCount % 60 && tickCount % 60 < 30) { yOffset -= 1; waterColour = Colours.get(-1, 225, 115, -1); } else if (30 <= tickCount % 60 && tickCount % 60 < 45) { waterColour = Colours.get(-1, 115, -1, 225); } else { waterColour = Colours.get(-1, 225, 115, -1); } screen.render(xOffset, yOffset + 3, 0 + 27 * 32, waterColour, 0x00, 1); screen.render(xOffset + 8, yOffset + 3, 0 + 27 * 32, waterColour, 0x01, 1); } // upper body screen.render(xOffset + (modifier * flipTop), yOffset, xTile + yTile * 32, colour, flipTop, scale); screen.render(xOffset + modifier - (modifier * flipTop), yOffset, (xTile + 1) + yTile * 32, colour, flipTop, scale); if (!isSwimming) { // lower body screen.render(xOffset + (modifier * flipBottom), yOffset + modifier, xTile + (yTile + 1) * 32, colour, flipBottom, scale); screen.render(xOffset + modifier - (modifier * flipBottom), yOffset + modifier, (xTile + 1) + (yTile + 1) * 32, colour, flipBottom, scale); } } public boolean hasCollided(int xa, int ya) { int xMin = 0; int xMax = 7; int yMin = 1; int yMax = 7; for (int x = xMin; x < xMax; x++) { if (isSolidTile(xa, ya, x, yMin)) { return true; } } for (int x = xMin; x < xMax; x++) { if (isSolidTile(xa, ya, x, yMax)) { return true; } } for (int y = yMin; y < yMax; y++) { if (isSolidTile(xa, ya, xMin, y)) { return true; } } for (int y = yMin; y < yMax; y++) { if (isSolidTile(xa, ya, xMax, y)) { return true; } } return false; } } can get another character to load at a given location; however, I cannot figure out an algorithm to have it follow the initial player. In other words the second one will follow these same collision and commands. Any help understanding is appreciated, thank you!
How to convert a byte array to a string, and string to a byte array with GWT?
The String(byte[] bytes) constructor and String.getBytes() method are not implemented by GWT JRE emulation String class. Does anybody know of an implementation? I do not want to use char[], But it seems like there is no other solution.
If you create large arrays in Chrome, you might run into a Uncaught RangeError: Maximum call stack size exceeded exception. The code from LINEMAN78 can be modified to use a StringBuilder, which avoids this issue. public static String getString(byte[] bytes, int bytesPerChar) { if (bytes == null) throw new IllegalArgumentException("bytes cannot be null"); if (bytesPerChar < 1) throw new IllegalArgumentException("bytesPerChar must be greater than 1"); final int length = bytes.length / bytesPerChar; final StringBuilder retValue = new StringBuilder(); for (int i = 0; i < length; i++) { char thisChar = 0; for (int j = 0; j < bytesPerChar; j++) { int shift = (bytesPerChar - 1 - j) * 8; thisChar |= (0x000000FF << shift) & (((int) bytes[i * bytesPerChar + j]) << shift); } retValue.append(thisChar); } return retValue.toString(); }
The following code should work, just specify the number of bytes per character. public class GwtPlayground implements EntryPoint { static final Logger logger = Logger.getLogger(""); #Override public void onModuleLoad() { VerticalPanel loggerArea = new VerticalPanel(); logger.addHandler(new HasWidgetsLogHandler(loggerArea)); RootPanel.get().add(loggerArea); String original = new String("A" + "\uffea" + "\u00f1" + "\u00fc" + "C"); logger.info("original = " + original); byte[] utfBytes = getBytes(original, 2); String roundTrip = getString(utfBytes, 2); logger.info("roundTrip = " + roundTrip); } public static byte[] getBytes(String string, int bytesPerChar) { char[] chars = string.toCharArray(); byte[] toReturn = new byte[chars.length * bytesPerChar]; for (int i = 0; i < chars.length; i++) { for (int j = 0; j < bytesPerChar; j++) toReturn[i * bytesPerChar + j] = (byte) (chars[i] >>> (8 * (bytesPerChar - 1 - j))); } return toReturn; } public static String getString(byte[] bytes, int bytesPerChar) { char[] chars = new char[bytes.length / bytesPerChar]; for (int i = 0; i < chars.length; i++) { for (int j = 0; j < bytesPerChar; j++) { int shift = (bytesPerChar - 1 - j) * 8; chars[i] |= (0x000000FF << shift) & (((int) bytes[i * bytesPerChar + j]) << shift); } } return new String(chars); } } As #Per Wiklander pointed out, this doesn't truely support UTF-8. Here is a true UTF-8 decoder ported from C here private static class UTF8Decoder { final byte[] the_input; int the_index, the_length; protected UTF8Decoder( byte[] bytes ) { super(); this.the_input = bytes; this.the_index = 0; this.the_length = bytes.length; } /* Get the next byte. It returns UTF8_END if there are no more bytes. */ int get() { int c; c = the_input[the_index] & 0xFF; the_index += 1; return c; } /* Get the 6-bit payload of the next continuation byte. Return UTF8_ERROR if it is not a contination byte. */ int cont() { int c = get(); if( (c & 0xC0) == 0x80 ) return (c & 0x3F); else throw new IllegalArgumentException( "Failed to pass strict UTF-8" ); } CharSequence getStringUTF8() { StringBuilder sb = new StringBuilder( the_input.length ); // allocate a maximum size while( the_index < the_length ) { int c; /* the first byte of the character */ int r; /* the result */ c = get(); /* Zero continuation (0 to 127) */ if( (c & 0x80) == 0 ) { sb.append( (char) c ); } /* One continuation (128 to 2047) */ else if( (c & 0xE0) == 0xC0 ) { int c1 = cont(); if( c1 >= 0 ) { r = ((c & 0x1F) << 6) | c1; if( r >= 128 ) sb.append( (char) r ); else throw new IllegalArgumentException(); } } /* Two continuation (2048 to 55295 and 57344 to 65535) */ else if( (c & 0xF0) == 0xE0 ) { int c1 = cont(); int c2 = cont(); if( (c1 | c2) >= 0 ) { r = ((c & 0x0F) << 12) | (c1 << 6) | c2; if( r >= 2048 && (r < 55296 || r > 57343) ) sb.append( (char) r ); else throw new IllegalArgumentException(); } } /* Three continuation (65536 to 1114111) */ else if( (c & 0xF8) == 0xF0 ) { int c1 = cont(); int c2 = cont(); int c3 = cont(); if( (c1 | c2 | c3) >= 0 ) sb.append( (char) ((((c & 0x0F) << 18) | (c1 << 12) | (c2 << 6) | c3) + 65536) ); // TODO this might not work as it is being cast to a char } else throw new IllegalArgumentException( "Failed strict UTF8 parsing" ); } return sb; } }
Good question. I didn't realize it before. as far as I know there is only 2 main method that convert byte array to String You mentioned it The fantastic way with java.io package that you can't use it on client-side Here is mine implementation. I think it may be helpful to you public static String convertByteArrayToString(byte[] byteArray) { String s = ""; for (int i = 0; i < byteArray.length; i++) { s += (char) (byteArray[i]); } return s; } You can test it : byte[] byteArray = new byte[] { 87, 79, 87, 46, 46, 46 }; System.out.println(convertByteArrayToString(byteArray)); System.out.println(new String(byteArray));