void readValueEmbeddedMap(ContentBuffer & reader, RecordParseListener & listener, OType mapType) { int64_t size = readVarint(reader); listener.startMap(size, mapType); int32_t lastCursor = 0; while (size-- > 0) { //Skipping because is everytime string reader.prepare(1); int key_size = readVarint(reader); reader.prepare(key_size); char * key_name = (char *) reader.content + reader.cursor; listener.mapKey(key_name, key_size); long position = readFlat32Integer(reader); reader.prepare(1); if (position == 0) { listener.nullValue(); } else { OType type = (OType) reader.content[reader.cursor]; int temp = reader.prepared; reader.force_cursor(position); readSimpleValue(reader, type, listener); lastCursor = reader.prepared; reader.force_cursor(temp); } } listener.endMap(mapType); if (lastCursor > reader.prepared) reader.force_cursor(lastCursor); }
void readValueLink(ContentBuffer & reader, RecordParseListener & listener) { Link link; link.cluster = readVarint(reader); link.position = readVarint(reader); if (link.cluster == -2 && link.position == -1) listener.nullValue(); else listener.linkValue(link); }
void readValueLinkMap(ContentBuffer & reader, RecordParseListener & listener, OType mapType) { int64_t size = readVarint(reader); listener.startMap(size, mapType); while (size-- > 0) { //Skipping because is everytime string reader.prepare(1); int key_size = readVarint(reader); reader.prepare(key_size); char * key_name = (char *) reader.content + reader.cursor; listener.mapKey(key_name, key_size); readValueLink(reader, listener); } listener.endMap(mapType); }
static inline char *readString(spSkeletonBinary *self) { char *start, *end; _spStringBuffer *buffer = self->buffer; int byteCount = readVarint(self, true); if (byteCount == 0) { return NULL; } if (buffer == NULL || buffer->capacity - buffer->position < byteCount) { self->buffer = (_spStringBuffer *)malloc(sizeof(_spStringBuffer)); self->buffer->position = 0; self->buffer->capacity = MAX(BUFSIZ * 2, byteCount); self->buffer->content = (char *)malloc(self->buffer->capacity); self->buffer->next = buffer; buffer = self->buffer; } start = buffer->content + buffer->position; end = start; while (--byteCount) { *end++ =(char)READ(); } *end++ = '\0'; buffer->position += (int)(end - start); return start; }
static void readVertices(spSkeletonBinary *self, spVertexAttachment *attachment, int vertexCount) { if (!readBoolean(self)) { attachment->vertices = readFloats(self, self->scale, vertexCount << 1); attachment->verticesCount = vertexCount << 1; attachment->bones = NULL; attachment->bonesCount = 0; } else { float *weights; int *bones; int weightCount = 0, boneCount = 0; int position = self->data->position; for (int i = 0; i < vertexCount; i++) { int nn = readVarint(self, true); boneCount++; for (int ii = 0; ii < nn; ii++) { readVarint(self, true); self->data->position += sizeof(float) * 3; weightCount += 3; boneCount++; } } self->data->position = position; attachment->bones = MALLOC(int, boneCount); attachment->bonesCount = boneCount; attachment->vertices = MALLOC(float, weightCount); attachment->verticesCount = weightCount; weights = attachment->vertices; bones = attachment->bones; for (int i = 0; i < vertexCount; i++) { int nn = readVarint(self, true); *bones++ = nn; for (int ii = 0; ii < nn; ii++) { *bones++ = readVarint(self, true); *weights++ = readFloat(self) * self->scale; *weights++ = readFloat(self) * self->scale; *weights++ = readFloat(self); } } } }
void readValueLinkCollection(ContentBuffer & reader, RecordParseListener & listener, OType type) { int size = readVarint(reader); listener.startCollection(size, type); while (size-- > 0) { //TODO: handle null readValueLink(reader, listener); } listener.endCollection(type); }
static spSkin *readSkin(spSkeletonBinary *self, const char *skinName) { spSkin *skin; int slotCount = readVarint(self, true); if (slotCount == 0) { return NULL; } skin = spSkin_create(skinName); for (int i = 0; i < slotCount; i++) { int slotIndex = readVarint(self, true); int nn = readVarint(self, true); for (int ii = 0; ii < nn; ii++) { char *name = readString(self); spAttachment *attachment = readAttachment(self, skin, slotIndex, name); spSkin_addAttachment(skin, slotIndex, name, attachment); } } return skin; }
void readDocument(ContentBuffer &reader, RecordParseListener & listener) { int64_t class_size = readVarint(reader); if (class_size != 0) { reader.prepare(class_size); char * class_name = (char *) reader.content + reader.cursor; listener.startDocument(class_name, class_size); } else listener.startDocument("", 0); int64_t size = 0; int32_t lastCursor = 0; while ((size = readVarint(reader)) != 0) { if (size > 0) { reader.prepare(size); char * field_name = (char *) reader.content + reader.cursor; int32_t position = readFlat32Integer(reader); reader.prepare(1); if (position == 0) { listener.startField(field_name, size, ANY); listener.nullValue(); } else { OType type = (OType) reader.content[reader.cursor]; listener.startField(field_name, size, type); int temp = reader.prepared; reader.force_cursor(position); readSimpleValue(reader, type, listener); lastCursor = reader.prepared; reader.force_cursor(temp); } listener.endField(field_name, size); } else { throw new parse_exception("property id not supported by network serialization"); } } listener.endDocument(); if (lastCursor > reader.prepared) reader.force_cursor(lastCursor); }
bool BinaryInputStreamSerializer::operator()(std::string& value, Common::StringView name) { uint64_t size; readVarint(stream, size); if (size > 0) { std::vector<char> temp; temp.resize(size); checkedRead(&temp[0], size); value.reserve(size); value.assign(&temp[0], size); } else { value.clear(); } return true; }
ISerializer& BinaryInputStreamSerializer::operator()(std::string& value, const std::string& name) { uint64_t size; readVarint(stream, size); if (size > 0) { std::vector<char> temp; temp.resize(size); checkedRead(&temp[0], size); value.reserve(size); value.assign(&temp[0], size); } else { value.clear(); } return *this; }
void readValueEmbeddedCollection(ContentBuffer & reader, RecordParseListener & listener, OType collType) { int size = readVarint(reader); listener.startCollection(size, collType); reader.prepare(1); OType type = (OType) reader.content[reader.cursor]; if (ANY == type) { while (size-- > 0) { reader.prepare(1); OType entryType = (OType) reader.content[reader.cursor]; if (ANY == entryType) listener.nullValue(); else readSimpleValue(reader, entryType, listener); } } listener.endCollection(collType); //For now else is impossible }
static spAnimation *readAnimation(spSkeletonBinary *self, const char *name) { float scale = self->scale; float duration = 0; int drawOrderCount; int eventCount; spAnimation *animation; _spTimelineArray arr; arr.timelines = NULL; arr.capacity = 0; arr.count = 0; // slot timelines for (int i = 0, n = readVarint(self, true); i < n; i++) { int slotIndex = readVarint(self, true); for (int ii = 0, nn = readVarint(self, true); ii < nn; ii++) { int timelineType = readByte(self); int frameCount = readVarint(self, true); switch (timelineType) { case SLOT_COLOR: { spColorTimeline *timeline = spColorTimeline_create(frameCount); timeline->slotIndex = slotIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = readFloat(self); float r, g, b, a; readColor(self, &r, &g, &b, &a); spColorTimeline_setFrame(timeline, frameIndex, time, r, g, b, a); if (frameIndex < frameCount - 1) { readCurve(self, SUPER(timeline), frameIndex); } } duration = MAX(duration, timeline->frames[(frameCount - 1) * COLOR_ENTRIES]); addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline)); break; } case SLOT_ATTACHMENT: { spAttachmentTimeline *timeline = spAttachmentTimeline_create(frameCount); timeline->slotIndex = slotIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = readFloat(self); char *name = readString(self); spAttachmentTimeline_setFrame(timeline, frameIndex, time, name); } duration = MAX(duration, timeline->frames[frameCount - 1]); addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline)); break; } } } } // bone timelines for (int i = 0, n = readVarint(self, true); i < n; i++) { int boneIndex = readVarint(self, true); for (int ii = 0, nn = readVarint(self, true); ii < nn; ii++) { int timelineType = readByte(self); int frameCount = readVarint(self, true); switch (timelineType) { case BONE_ROTATE: { spRotateTimeline *timeline = spRotateTimeline_create(frameCount); timeline->boneIndex = boneIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = readFloat(self); float angle = readFloat(self); spRotateTimeline_setFrame(timeline, frameIndex, time, angle); if (frameIndex < frameCount - 1) { readCurve(self, SUPER(timeline), frameIndex); } } duration = MAX(duration, timeline->frames[(frameCount - 1) * ROTATE_ENTRIES]); addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline)); break; } case BONE_TRANSLATE: case BONE_SCALE: case BONE_SHEAR: { spTranslateTimeline *timeline; float timelineScale = 1; if (timelineType == BONE_SCALE) { timeline = spScaleTimeline_create(frameCount); } else if (timelineType == BONE_SHEAR) timeline = spShearTimeline_create(frameCount); else { timeline = spTranslateTimeline_create(frameCount); timelineScale = scale; } timeline->boneIndex = boneIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = readFloat(self); float x = readFloat(self) * timelineScale; float y = readFloat(self) * timelineScale; spTranslateTimeline_setFrame(timeline, frameIndex, time, x, y); if (frameIndex < frameCount - 1) { readCurve(self, SUPER(timeline), frameIndex); } } duration = MAX(duration, timeline->frames[(frameCount - 1) * TRANSLATE_ENTRIES]); addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline)); break; } } } } // ik constraint timelines for (int i = 0, n = readVarint(self, true); i < n; i++) { int index = readVarint(self, true); int frameCount = readVarint(self, true); spIkConstraintTimeline *timeline = spIkConstraintTimeline_create(frameCount); timeline->ikConstraintIndex = index; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = readFloat(self); float mix = readFloat(self); int blendPositive = readByte(self); spIkConstraintTimeline_setFrame(timeline, frameIndex, time, mix, blendPositive); if (frameIndex < frameCount - 1) { readCurve(self, SUPER(timeline), frameIndex); } } duration = MAX(duration, timeline->frames[(frameCount - 1) * IKCONSTRAINT_ENTRIES]); addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline)); } // transform constraint timelines for (int i = 0, n = readVarint(self, true); i < n; i++) { int index = readVarint(self, true); int frameCount = readVarint(self, true); spTransformConstraintTimeline *timeline = spTransformConstraintTimeline_create(frameCount); timeline->transformConstraintIndex = index; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = readFloat(self); float rotateMix = readFloat(self); float translateMix = readFloat(self); float scaleMix = readFloat(self); float shearMix = readFloat(self); spTransformConstraintTimeline_setFrame(timeline, frameIndex, time, rotateMix, translateMix, scaleMix, shearMix); if (frameIndex < frameCount - 1) { readCurve(self, SUPER(timeline), frameIndex); } } duration = MAX(duration, timeline->frames[(frameCount - 1) * TRANSFORMCONSTRAINT_ENTRIES]); addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline)); } // path constraint timelines for (int i = 0, n = readVarint(self, true); i < n; i++) { int index = readVarint(self, true); spPathConstraintData *data = self->skeletonData->pathConstraints[index]; for (int ii = 0, nn = readVarint(self, true); ii < nn; ii++) { int timelineType = readByte(self); int frameCount = readVarint(self, true); switch (timelineType) { case PATH_POSITION: case PATH_SPACING: { spPathConstraintPositionTimeline *timeline; float timelineScale = 1; if (timelineType == PATH_SPACING) { timeline = (spPathConstraintPositionTimeline *)spPathConstraintSpacingTimeline_create(frameCount); if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) { timelineScale = scale; } } else { timeline = spPathConstraintPositionTimeline_create(frameCount); if (data->positionMode == SP_POSITION_MODE_FIXED) { timelineScale = scale; } } timeline->pathConstraintIndex = index; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = readFloat(self); float value = readFloat(self); spPathConstraintPositionTimeline_setFrame(timeline, frameIndex, time, value); if (frameIndex < frameCount - 1) { readCurve(self, SUPER(timeline), frameIndex); } } duration = MAX(duration, timeline->frames[(frameCount - 1) * PATHCONSTRAINTPOSITION_ENTRIES]); addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline)); break; } case PATH_MIX: { spPathConstraintMixTimeline *timeline = spPathConstraintMixTimeline_create(frameCount); timeline->pathConstraintIndex = index; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = readFloat(self); float rotateMix = readFloat(self); float translateMix = readFloat(self); spPathConstraintMixTimeline_setFrame(timeline, frameIndex, time, rotateMix, translateMix); if (frameIndex < frameCount - 1) { readCurve(self, SUPER(timeline), frameIndex); } } duration = MAX(duration, timeline->frames[(frameCount - 1) * PATHCONSTRAINTMIX_ENTRIES]); addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline)); break; } } } } // deform timelines for (int i = 0, n = readVarint(self, true); i < n; i++) { spSkin *skin = self->skeletonData->skins[readVarint(self, true)]; for (int ii = 0, nn = readVarint(self, true); ii < nn; ii++) { int slotIndex = readVarint(self, true); for (int iii = 0, nnn = readVarint(self, true); iii < nnn; iii++) { char *name = readString(self); spVertexAttachment *attachment = SUB_CAST(spVertexAttachment, spSkin_getAttachment(skin, slotIndex, name)); bool weighted = attachment->bones != NULL; float *vertices = attachment->vertices; int deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount; int frameCount = readVarint(self, true); spDeformTimeline *timeline = spDeformTimeline_create(frameCount, deformLength); timeline->slotIndex = slotIndex; timeline->attachment = SUPER(attachment); for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = readFloat(self); float *deform; int end = readVarint(self, true); if (end == 0) deform = weighted ? CALLOC(float, deformLength) : vertices; else { deform = CALLOC(float, deformLength); int start = readVarint(self, true); end += start; if (scale == 1) { for (int v = start; v < end; v++) deform[v] = readFloat(self); } else { for (int v = start; v < end; v++) deform[v] = readFloat(self) * scale; } if (!weighted) { for (int v = 0, vn = deformLength; v < vn; v++) deform[v] += vertices[v]; } } spDeformTimeline_setFrame(timeline, frameIndex, time, deform); if (frameIndex < frameCount - 1) { readCurve(self, SUPER(timeline), frameIndex); } } duration = MAX(duration, timeline->frames[frameCount - 1]); addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline)); } } }
static spAttachment *readAttachment(spSkeletonBinary *self, spSkin *skin, int slotIndex, const char *attachmentName) { spAttachment *attachment = NULL; float scale = self->scale; char *name = readString(self); if (name == NULL) name = (char *)attachmentName; switch ((spAttachmentType)readByte(self)) { case SP_ATTACHMENT_REGION: { spRegionAttachment *region; char *path = readString(self); if (path == NULL) path = name; attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, SP_ATTACHMENT_REGION, name, path); region = SUB_CAST(spRegionAttachment, attachment); if (path) { region->path = copyString(path); } region->rotation = readFloat(self); region->x = readFloat(self) * scale; region->y = readFloat(self) * scale; region->scaleX = readFloat(self); region->scaleY = readFloat(self); region->width = readFloat(self) * scale; region->height = readFloat(self) * scale; readColor(self, ®ion->r, ®ion->g, ®ion->b, ®ion->a); spRegionAttachment_updateOffset(region); spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); break; } case SP_ATTACHMENT_BOUNDING_BOX: { spBoundingBoxAttachment *boundingBox; int vertexCount = readVarint(self, true); attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, SP_ATTACHMENT_BOUNDING_BOX, name, name); boundingBox = SUB_CAST(spBoundingBoxAttachment, attachment); readVertices(self, SUPER(boundingBox), vertexCount); SUPER(boundingBox)->worldVerticesLength = vertexCount << 1; spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); break; } case SP_ATTACHMENT_MESH: { spMeshAttachment *mesh; int vertexCount; char *path = readString(self); if (path == NULL) path = name; attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, SP_ATTACHMENT_MESH, name, path); mesh = SUB_CAST(spMeshAttachment, attachment); if (path) { mesh->path = copyString(path); } readColor(self, &mesh->r, &mesh->g, &mesh->b, &mesh->a); vertexCount = readVarint(self, true); mesh->regionUVs = readFloats(self, 1, vertexCount << 1); mesh->trianglesCount = readVarint(self, true); mesh->triangles = readShorts(self, mesh->trianglesCount); readVertices(self, SUPER(mesh), vertexCount); SUPER(mesh)->worldVerticesLength = vertexCount << 1; mesh->hullLength = readVarint(self, true) << 1; spMeshAttachment_updateUVs(mesh); spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); break; } case SP_ATTACHMENT_LINKED_MESH: { spMeshAttachment *mesh; char *parent; char *skinName; char *path = readString(self); if (path == NULL) path = name; attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, SP_ATTACHMENT_LINKED_MESH, name, path); mesh = SUB_CAST(spMeshAttachment, attachment); if (path) { mesh->path = copyString(path); } readColor(self, &mesh->r, &mesh->g, &mesh->b, &mesh->a); skinName = readString(self); parent = readString(self); mesh->inheritDeform = readBoolean(self); addLinkedMesh(self, mesh, skinName, slotIndex, parent); break; } case SP_ATTACHMENT_PATH: { spPathAttachment *path; int vertexCount; attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, SP_ATTACHMENT_PATH, name, NULL); path = SUB_CAST(spPathAttachment, attachment); path->closed = readBoolean(self); path->constantSpeed = readBoolean(self); vertexCount = readVarint(self, true); readVertices(self, SUPER(path), vertexCount); SUPER(path)->worldVerticesLength = vertexCount << 1; path->lengthsLength = vertexCount / 3; path->lengths = MALLOC(float, path->lengthsLength); for (int i = 0; i < path->lengthsLength; i++) { path->lengths[i] = readFloat(self) * self->scale; } break; } } return attachment; }
void readValueString(ContentBuffer & reader, RecordParseListener & listener) { int64_t value_size = readVarint(reader); reader.prepare(value_size); listener.stringValue((char *) reader.content + reader.cursor, value_size); }
deform[v] += vertices[v]; } } spDeformTimeline_setFrame(timeline, frameIndex, time, deform); if (frameIndex < frameCount - 1) { readCurve(self, SUPER(timeline), frameIndex); } } duration = MAX(duration, timeline->frames[frameCount - 1]); addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline)); } } } // draw order timeline drawOrderCount = readVarint(self, true); if (drawOrderCount > 0) { int frameCount = drawOrderCount; int slotCount = self->skeletonData->slotsCount; spDrawOrderTimeline *timeline = spDrawOrderTimeline_create(frameCount, slotCount); for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = readFloat(self); int offsetCount = readVarint(self, true); int *drawOrder = CALLOC(int, slotCount); for (int ii = slotCount - 1; ii >= 0; ii--) { drawOrder[ii] = -1; } int *unchanged = CALLOC(int, slotCount - offsetCount); int originalIndex = 0, unchangedIndex = 0; for (int ii = 0; ii < offsetCount; ii++) { int slotIndex = readVarint(self, true);
void readSimpleValue(ContentBuffer &reader, OType type, RecordParseListener & listener) { switch (type) { case STRING: readValueString(reader, listener); break; case INTEGER: { int64_t value = readVarint(reader); listener.intValue(value); } break; case LONG: { int64_t value = readVarint(reader); listener.longValue(value); } break; case SHORT: { int64_t value = readVarint(reader); listener.shortValue(value); } break; case BYTE: { reader.prepare(1); listener.byteValue(reader.content[reader.cursor]); } break; case BOOLEAN: { reader.prepare(1); listener.booleanValue(reader.content[reader.cursor] != 0); } break; case DATE: { int64_t read = readVarint(reader); read *= 86400000; listener.dateValue(read); } break; case FLOAT: { int32_t i_val = readFlat32Integer(reader); float fl; memcpy(&fl, &i_val, 4); listener.floatValue(fl); } break; case DOUBLE: { int64_t i_val; reader.prepare(8); memcpy(&i_val, reader.content + reader.cursor, 8); i_val = be64toh(i_val); double db; memcpy(&db, &i_val, 8); listener.doubleValue(db); } break; case DATETIME: { int64_t value = readVarint(reader); listener.dateTimeValue(value); } break; case LINK: { readValueLink(reader, listener); } break; case LINKSET: case LINKLIST: { readValueLinkCollection(reader, listener, type); } break; case BINARY: { int64_t value_size = readVarint(reader); reader.prepare(value_size); listener.binaryValue((char *) reader.content + reader.cursor, value_size); } break; case EMBEDDEDLIST: case EMBEDDEDSET: { readValueEmbeddedCollection(reader, listener, type); } break; case EMBEDDEDMAP: { readValueEmbeddedMap(reader, listener, type); } break; case LINKMAP: { readValueLinkMap(reader, listener, type); } break; case EMBEDDED: { readDocument(reader, listener); } break; case LINKBAG: { readValueRidbag(reader, listener); } break; default: break; } }
bool BinaryInputStreamSerializer::operator()(uint64_t& value, Common::StringView name) { readVarint(stream, value); return true; }
ISerializer& BinaryInputStreamSerializer::operator()(uint32_t& value, const std::string& name) { readVarint(stream, value); return *this; }
bool parseTransactionExtra(const std::vector<uint8_t> &transactionExtra, std::vector<TransactionExtraField> &transactionExtraFields) { transactionExtraFields.clear(); if (transactionExtra.empty()) return true; try { MemoryInputStream iss(transactionExtra.data(), transactionExtra.size()); BinaryInputStreamSerializer ar(iss); int c = 0; while (!iss.endOfStream()) { c = read<uint8_t>(iss); switch (c) { case TX_EXTRA_TAG_PADDING: { size_t size = 1; for (; !iss.endOfStream() && size <= TX_EXTRA_PADDING_MAX_COUNT; ++size) { if (read<uint8_t>(iss) != 0) { return false; // all bytes should be zero } } if (size > TX_EXTRA_PADDING_MAX_COUNT) { return false; } transactionExtraFields.push_back(TransactionExtraPadding{ size }); break; } case TX_EXTRA_TAG_PUBKEY: { TransactionExtraPublicKey extraPk; ar(extraPk.publicKey, "public_key"); transactionExtraFields.push_back(extraPk); break; } case TX_EXTRA_NONCE: { TransactionExtraNonce extraNonce; uint8_t size = read<uint8_t>(iss); if (size > 0) { extraNonce.nonce.resize(size); read(iss, extraNonce.nonce.data(), extraNonce.nonce.size()); } transactionExtraFields.push_back(extraNonce); break; } case TX_EXTRA_MERGE_MINING_TAG: { TransactionExtraMergeMiningTag mmTag; ar(mmTag, "mm_tag"); transactionExtraFields.push_back(mmTag); break; } case TX_EXTRA_MESSAGE_TAG: { tx_extra_message message; ar(message.data, "message"); transactionExtraFields.push_back(message); break; } case TX_EXTRA_TTL: { uint8_t size; readVarint(iss, size); TransactionExtraTTL ttl; readVarint(iss, ttl.ttl); transactionExtraFields.push_back(ttl); break; } } } } catch (std::exception &) { return false; } return true; }