35 #define dbg_printf if (dbg_flag) printf
37 WireTwiddlerWriter::~WireTwiddlerWriter() =
default;
40 int WireTwiddler::configure(
Bottle& desc,
int offset,
bool& ignored,
41 const std::string& vtag) {
44 bool is_vector =
false;
49 bool computing =
false;
57 if (kind==
"skip"||kind==
"compute") {
58 if (kind==
"compute") computing =
true;
63 if (kind.length()>0 && (kind[0]==
'>'||kind[0]==
'<')) {
64 saving = (kind[0]==
'>');
65 loading = (kind[0]==
'<');
67 var = kind.substr(1,kind.length());
72 is_vector = (kind==
"vector");
73 is_list = (kind==
"list");
74 if (kind==
"item_vector") {
84 if (computing) data =
true;
85 if (is_vector||is_list) {
92 fprintf(stderr,
"Does not look like length: %s\n",
97 fprintf(stderr,
"List should have fixed length\n");
108 fprintf(stderr,
"Does not look like data: %s\n",
117 int wire_unit_length = -1;
123 if (kind==
"int8"||kind==
"uint8"||kind==
"bool") {
126 }
else if (kind==
"int16"||kind==
"uint16") {
129 }
else if (kind==
"int32"||kind==
"uint32") {
132 }
else if (kind==
"int64"||kind==
"uint64") {
135 }
else if (kind==
"float32") {
138 }
else if (kind==
"float64") {
141 }
else if (kind==
"vocab") {
144 }
else if (kind==
"string") {
148 }
else if (kind==
"blob") {
152 }
else if (kind==
"list"||kind==
"vector"||computing) {
155 fprintf(stderr,
"%s does not know about %s\n", __FILE__, kind.c_str());
159 dbg_printf(
"Type %s (%s) len %d unit %d %s\n",
161 is_list?
"LIST":(is_vector?
"VECTOR":
"PRIMITIVE"), len,
171 }
else if (is_list) {
175 if (!item)
buffer.push_back(tag);
184 buffer_start = (int)
buffer.size();
198 tmp.
copy(desc,start,offset-start-1);
209 offset = configure(desc,offset,ign,kind);
216 bool WireTwiddler::configure(
const char *txt,
const char *prompt) {
217 this->prompt = prompt;
219 std::string str(txt);
220 char *cstr = (
char *)str.c_str();
221 for (
size_t i=0; i<str.length(); i++) {
227 if (str.find(
"list") == std::string::npos &&
228 str.find(
"vector") == std::string::npos) {
244 next = configure(desc,at,ign,
"");
245 }
while (next>at&&next<desc.
size());
246 if (buffer_start!=(
int)
buffer.size()) {
250 buffer_start = (int)
buffer.size();
254 dbg_printf(
"gaps has %zu items\n", gaps.size());
255 for (
auto& gap : gaps) {
256 if (gap.buffer_length!=0) {
257 gap.byte_start = (
char *) (&
buffer[gap.buffer_start]);
258 gap.byte_length = gap.buffer_length*4;
260 gap.byte_start =
nullptr;
265 return at == desc.
size();
301 return "unsupported";
309 int len = msg.
size();
312 for (
int i=0; i<len; i++) {
315 if (i==0) code = icode;
316 if (icode!=code) code = -1;
328 for (
int i=0; i<len; i++) {
337 result += fromTemplate(*v.
asList());
344 void WireTwiddler::show() {
345 for (
size_t i=0; i<gaps.size(); i++) {
347 printf(
"Block #%zu (%s)\n", i, gap.
getOrigin().c_str());
353 printf(
" External data will be ignored\n");
364 for (
const auto& gap : gaps) {
373 if (gap.unit_length!=0) {
375 if (gap.length==-1 && gap.unit_length==-1) {
376 sprintf(buf,
" [4-byte length] [<length> instances of 4-byte-length bytes followed by specified number of bytes]");
377 }
else if (gap.length==-1) {
378 sprintf(buf,
" [4-byte length] [<length>*%d bytes]", gap.unit_length);
379 }
else if (gap.length==1) {
380 sprintf(buf,
" [%d bytes]", gap.unit_length);
382 sprintf(buf,
" [%d*%d bytes]", gap.length, gap.unit_length);
386 if (result!=
"") result +=
" ";
397 return ConnectionReader::readFromStream(bot,twiddled_input);
405 writer = ConnectionWriter::createBufferedConnectionWriter();
417 twiddled_output.
write(sos);
418 std::string result = sos.
toString();
426 if (gap.
var_name ==
"image_params") {
427 int w = prop.find(
"width").asInt32();
428 int h = prop.find(
"height").asInt32();
429 int step = prop.find(
"step").asInt32();
430 bool bigendian = prop.find(
"is_bigendian").asInt32()==1;
432 fprintf(stderr,
"Sorry, cannot handle bigendian images yet.\n");
435 std::string encoding = prop.find(
"encoding").asString();
437 int translated_encoding = 0;
458 yAssert(encoding==
"mono8"||encoding==
"mono16");
459 if (encoding ==
"mono8") {
470 if (encoding ==
"bayer_grbg8")
474 fprintf(stderr,
"Warning automatic debayering not yet supported, keeping raw format.\n");
479 fprintf(stderr,
"Sorry, cannot handle [%s] images yet.\n",
487 while (quantum<=256) {
489 if (((w*bpp+quantum)/quantum)*quantum == step) {
498 int img_size = step*h;
500 prop.put(
"img_size",img_size);
501 prop.put(
"quantum",quantum);
502 prop.put(
"translated_encoding",translated_encoding);
509 dbg_printf(
"WireTwidderReader::read getting started\n");
511 int ct = twiddler.getGapCount();
513 fprintf(stderr,
"WireTwidderReader, nothing available\n");
522 fprintf(stderr,
"WireTwidderReader, nothing left\n");
534 if (byte_start !=
nullptr) {
535 byte_start += consumed;
536 byte_length -= consumed;
538 if (byte_start !=
nullptr && byte_length > 0) {
540 if (len>byte_length) {
543 memcpy(b.
get(),byte_start,len);
547 dbg_printf(
"WireTwidderReader sending %d boilerplate bytes:\n",len);
553 Bytes bytes(
reinterpret_cast<char*
>(&lengthBuffer),
sizeof(
NetInt32));
554 int r = is.readFull(bytes);
557 pending_length =
sizeof(lengthBuffer);
561 pending_strings = lengthBuffer;
562 pending_string_length = 0;
563 pending_string_data = 0;
569 override_length = lengthBuffer;
576 if (pending_length) {
578 if (len>pending_length) {
579 len = pending_length;
583 (
char*)(&lengthBuffer)+
sizeof(lengthBuffer)-pending_length,
585 pending_length -= len;
586 dbg_printf(
"WireTwidderReader sending %d length bytes:\n",len);
590 while (pending_strings) {
591 dbg_printf(
"### %d pending strings\n", pending_strings);
592 if (pending_string_length==0&&pending_string_data==0) {
594 Bytes bytes(
reinterpret_cast<char*
>(&lengthBuffer),
sizeof(
NetInt32));
595 int r = is.readFull(bytes);
598 pending_string_length =
sizeof(lengthBuffer);
599 pending_string_data = lengthBuffer;
601 if (pending_string_length) {
603 if (len>pending_string_length) {
604 len = pending_string_length;
608 (
char*)(&lengthBuffer)+
sizeof(lengthBuffer)-pending_string_length,
610 pending_string_length -= len;
611 dbg_printf(
"WireTwidderReader sending %d string length bytes:\n",len);
613 if (pending_string_length==0&&pending_string_data==0) { pending_strings--; }
616 if (pending_string_data) {
618 if (len>pending_string_data) {
619 len = pending_string_data;
622 int r = is.readFull(b2);
624 fprintf(stderr,
"No string payload bytes available\n");
627 pending_string_data -= r;
628 dbg_printf(
"WireTwidderReader sending %d string payload bytes\n",r);
629 if (pending_string_data==0) { pending_strings--; }
635 dbg_printf(
"extern_length %d\n", extern_length);
637 if (extern_length>sent-consumed) {
639 if (len>extern_length) {
645 r = readMapped(is,b2,gap);
647 dbg_printf(
"WireTwidderReader sending %d payload bytes:\n",r);
653 fprintf(stderr,
"No payload bytes available\n");
658 int len2 = extern_length;
662 dump.allocateOnNeed(len2,len2);
663 Bytes b3(dump.get(),len2);
665 auto* nn =
reinterpret_cast<NetInt32 *
> (dump.get());
667 if (override_length>=0) {
669 std::string((
char *)(dump.get()),
673 prop.find(gap.
var_name).asString().c_str());
674 }
else if (len2>=4) {
681 dbg_printf(
"WireTwidderReader sending %d payload bytes:\n",r);
683 dbg_printf(
" (ignoring %d payload bytes)\n",r);
694 override_length = -1;
700 fprintf(stderr,
"WireTwidderReader shrugging\n");
705 bool WireTwiddlerWriter::update() {
717 block = parent->headerLength();
718 lastBlock = parent->length()-block-1;
719 activeEmit =
nullptr;
720 activeEmitLength = 0;
721 activeEmitOffset = -1;
723 dbg_printf(
"Parent headers %zu blocks %zu\n", parent->headerLength(), parent->length());
725 for (
int i=0; i<twiddler->getGapCount(); i++) {
726 if (errorState)
return false;
736 dbg_printf(
"Pass [4-byte length] [<length> instances of 4-byte-length bytes followed by specified number of bytes]\n");
737 readLengthAndPass(-1);
742 dbg_printf(
"Pass [4-byte length] [<length> bytes]\n");
743 readLengthAndPass(1);
744 }
else if (gap.
length==-1) {
750 dbg_printf(
"Need to tweak length (not correct for neg numbers yet)...\n");
751 for (
int i=0; i<gap.
length; i++) {
752 if (errorState)
return false;
763 dbg_printf(
"%zu write blocks\n", srcs.size());
765 for (
size_t i=0; i<srcs.size(); i++) {
766 dbg_printf(
" write block %zu: len %d offset %d ptr %p\n", i, srcs[i].len, srcs[i].offset, srcs[i].src);
773 bool WireTwiddlerWriter::skip(
const char *start,
int len) {
775 return advance(len,
false,
false,
true);
778 bool WireTwiddlerWriter::pass(
int len) {
779 return advance(len,
true);
782 bool WireTwiddlerWriter::pad(
size_t len) {
785 for (
size_t i=0; i<len; i++) {
786 zeros.get()[i] =
'\0';
789 return emit(
zeros.get(),len);
792 bool WireTwiddlerWriter::readLengthAndPass(
int unitLength,
794 int len = readLength();
795 if (len==0)
return false;
796 if (unitLength!=-1) {
798 advance(unitLength*len,
true);
800 for (
int i=0; i<len; i++) {
801 if (!transform(*gap))
return false;
805 for (
int i=0; i<len; i++) {
806 bool ok = readLengthAndPass(1,gap);
807 if (!ok)
return false;
817 yError(
"Structure of message is unexpected (expected %s)", twiddler->getPrompt().c_str());
819 if (expected!=received) {
820 yError(
"Expected '%s', got '%s'\n",
821 Bottle::describeBottleCode(expected).c_str(),
822 Bottle::describeBottleCode(received).c_str());
830 int WireTwiddlerWriter::readLength() {
831 advance(4,
true,
true);
832 if (accumOffset==4) {
833 if (codeExpected!=codeReceived) {
834 if (lengthBuffer!=0) {
835 showBrokenExpectation(codeExpected,codeReceived,4);
837 codeExpected = codeReceived = 0;
844 bool WireTwiddlerWriter::advance(
int length,
bool shouldEmit,
845 bool shouldAccum,
bool shouldCheck) {
847 if (length==0)
return true;
848 if (length<0)
return false;
850 if (blockPtr ==
nullptr) {
851 blockPtr = parent->data(block);
852 blockLen = parent->length(block);
853 dbg_printf(
" block %d is at %ld, length %d\n",block,
854 (
long int)blockPtr, blockLen);
857 int rem = blockLen-offset;
861 if (block>lastBlock) {
867 if (rem>length) rem = length;
869 dbg_printf(
"Type check against %ld\n", (
long int)activeCheck);
870 int result = memcmp(activeCheck,blockPtr+offset,rem);
876 t1 = *(
reinterpret_cast<const NetInt32*
>(blockPtr+offset));
877 t2 = *(
reinterpret_cast<const NetInt32*
>(activeCheck-rem));
888 showBrokenExpectation(t2,t1,rem);
894 emit(blockPtr+offset, rem);
897 if (accumOffset+rem>4) {
898 fprintf(stderr,
"ACCUMULATION GONE WRONG %d %d\n",
902 memcpy(lengthBytes.get()+accumOffset,blockPtr+offset,rem);
911 bool WireTwiddlerWriter::emit(
const char *src,
int len) {
913 if (src !=
nullptr) {
919 const auto* x =
reinterpret_cast<const NetFloat64*
>(src);
920 if (scratchOffset+4>scratch.length()) {
921 scratch.allocateOnNeed(scratchOffset+4,scratchOffset+4);
923 auto* y =
reinterpret_cast<NetFloat32*
>(scratch.get()+scratchOffset);
926 noffset = scratchOffset;
930 fprintf(stderr,
"WireTwidder::emit needs to be extended to deal with this case\n");
936 dbg_printf(
" cache %ld len %d offset %d /// activeEmit %ld %d %d\n", (
long int)src, len, noffset, (
long int) activeEmit, activeEmitLength, activeEmitOffset);
937 if (activeEmit !=
nullptr || activeEmitOffset >= 0) {
939 if (activeEmitOffset>=0 && noffset<0) {
941 }
else if (activeEmitOffset<0 && noffset>=0) {
943 }
else if (noffset==-1 && activeEmit+activeEmitLength!=src) {
947 dbg_printf(
" ** emit %ld len %d offset %d\n", (
long int)activeEmit,
948 activeEmitLength, activeEmitOffset);
949 srcs.emplace_back((
char*)activeEmit,activeEmitLength,activeEmitOffset);
950 activeEmit =
nullptr;
951 activeEmitLength = 0;
952 activeEmitOffset = -1;
954 activeEmitLength += len;
955 dbg_printf(
" ** extend %ld len %d offset %d\n", (
long int)activeEmit,
956 activeEmitLength, activeEmitOffset);
960 if (src !=
nullptr || noffset >= 0) {
962 activeEmitLength = len;
963 activeEmitOffset = noffset;
981 fprintf(stderr,
"WireTwidder::transform needs to be extended to deal with this case\n");
996 v = prop.find(gap.
var_name).asInt32();
999 for (
size_t i=0; i<b.
length(); i++) {
1002 auto* nn =
reinterpret_cast<NetInt32 *
> (b.
get());
1011 for (
size_t i=0; i<b.
length(); i++) {
1031 dump.allocateOnNeed(len2,len2);
1032 Bytes b3(dump.get(),len2);