static int pb_encode_array(pb_ostream_t *stream, const pc_JSON *gprotos, const pc_JSON *protos, const pc_JSON *proto, pc_JSON *array) { pc_JSON *type = pc_JSON_GetObjectItem(proto, "type"); const char *type_text = type->valuestring; size_t len = pc_JSON_GetArraySize(array); size_t i; /* simple msg */ if (pb_get_type(type_text) && pb_get_type(type_text) != PB_string) { if (!pb_encode_tag_for_field(stream, proto)) { return 0; } if (!pb_encode_varint(stream, len)) { return 0; } for (i = 0; i < len; i++) { if (!pb_encode_proto(stream, gprotos, protos, proto, pc_JSON_GetArrayItem(array, i))) { return 0; } } } else { for (i = 0; i < len; i++) { if (!pb_encode_tag_for_field(stream, proto)) { return 0; } if (!pb_encode_proto(stream, gprotos, protos, proto, pc_JSON_GetArrayItem(array, i))) { return 0; } } } return 1; }
static int checkreturn pb_encode_array(pb_ostream_t *stream, const json_t *gprotos, const json_t *protos, const json_t *proto, json_t *array) { json_t *type = json_object_get(proto, "type"); const char *type_text = json_string_value(type); size_t len = json_array_size(array); size_t i; // simple msg if (pb__get_type(type_text) && pb__get_type(type_text) != PB_string) { if (!pb_encode_tag_for_field(stream, proto)) { return 0; } if (!pb_encode_varint(stream, len)) { return 0; } for (i = 0; i < len; i++) { if (!pb_encode_proto(stream, gprotos, protos, proto, json_array_get(array, i))) { return 0; } } } else { for (i = 0; i < len; i++) { if (!pb_encode_tag_for_field(stream, proto)) { return 0; } if (!pb_encode_proto(stream, gprotos, protos, proto, json_array_get(array, i))) { return 0; } } } return 1; }
bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) { const pb_field_t *field = fields; const void *pData = src_struct; const void *pSize; size_t prev_size = 0; while (field->tag != 0) { pb_encoder_t func = PB_ENCODERS[PB_LTYPE(field->type)]; pData = (const char*)pData + prev_size + field->data_offset; pSize = (const char*)pData + field->size_offset; prev_size = field->data_size; if (PB_HTYPE(field->type) == PB_HTYPE_ARRAY) prev_size *= field->array_size; switch (PB_HTYPE(field->type)) { case PB_HTYPE_REQUIRED: if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; break; case PB_HTYPE_OPTIONAL: if (*(const bool*)pSize) { if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; } break; case PB_HTYPE_ARRAY: if (!encode_array(stream, field, pData, *(const size_t*)pSize, func)) return false; break; case PB_HTYPE_CALLBACK: { const pb_callback_t *callback = (const pb_callback_t*)pData; if (callback->funcs.encode != NULL) { if (!callback->funcs.encode(stream, field, callback->arg)) return false; } break; } } field++; } return true; }
/* Encode a field with static or pointer allocation, i.e. one whose data * is available to the encoder directly. */ static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData) { pb_encoder_t func; const void *pSize; bool implicit_has = true; func = PB_ENCODERS[PB_LTYPE(field->type)]; if (field->size_offset) pSize = (const char*)pData + field->size_offset; else pSize = &implicit_has; if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { /* pData is a pointer to the field, which contains pointer to * the data. If the 2nd pointer is NULL, it is interpreted as if * the has_field was false. */ pData = *(const void* const*)pData; implicit_has = (pData != NULL); } switch (PB_HTYPE(field->type)) { case PB_HTYPE_REQUIRED: if (!pData) PB_RETURN_ERROR(stream, "missing required field"); if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; break; case PB_HTYPE_OPTIONAL: if (*(const bool*)pSize) { if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; } break; case PB_HTYPE_REPEATED: if (!encode_array(stream, field, pData, *(const size_t*)pSize, func)) return false; break; default: PB_RETURN_ERROR(stream, "invalid field type"); } return true; }
static bool write_repeated_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { return pb_encode_tag_for_field(stream, field) && pb_encode_string(stream, 0, 0) && pb_encode_tag_for_field(stream, field) && pb_encode_string(stream, 0, 0) && pb_encode_tag_for_field(stream, field) && pb_encode_string(stream, 0, 0) && pb_encode_tag_for_field(stream, field) && pb_encode_string(stream, 0, 0) && pb_encode_tag_for_field(stream, field) && pb_encode_string(stream, *arg, strlen(*arg)); }
static bool write_repeated_svarint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { return pb_encode_tag_for_field(stream, field) && pb_encode_svarint(stream, 0) && pb_encode_tag_for_field(stream, field) && pb_encode_svarint(stream, 0) && pb_encode_tag_for_field(stream, field) && pb_encode_svarint(stream, 0) && pb_encode_tag_for_field(stream, field) && pb_encode_svarint(stream, 0) && pb_encode_tag_for_field(stream, field) && pb_encode_svarint(stream, (long)*arg); }
static bool write_repeated_emptymsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { EmptyMessage emptymsg = {0}; return pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) && pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) && pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) && pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) && pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg); }
static bool write_repeated_submsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { SubMessage dummy = {""}; return pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, SubMessage_fields, &dummy) && pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, SubMessage_fields, &dummy) && pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, SubMessage_fields, &dummy) && pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, SubMessage_fields, &dummy) && pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, SubMessage_fields, *arg); }
/* Parse a dictionary in format {'name': value} and encode it directly to protobuf */ static bool encode_dictionary(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { int textlen; char *p = (char*)*arg; if (*p == '{') p++; while (*p != '}') { KeyValuePair pair = KeyValuePair_init_zero; if (*p != '\'') PB_RETURN_ERROR(stream, "invalid key, missing quote"); p++; /* Starting quote of key */ textlen = strchr(p, '\'') - p; strncpy(pair.key, p, textlen); pair.key[textlen] = 0; p += textlen + 2; while (*p == ' ') p++; if (*p == '[') { /* Value is a tree */ pair.treeValue.funcs.encode = encode_tree; pair.treeValue.arg = p; } else if (*p == '\'') { /* Value is a string */ pair.has_stringValue = true; p++; textlen = strchr(p, '\'') - p; strncpy(pair.stringValue, p, textlen); pair.stringValue[textlen] = 0; } else if (*p == '{') { /* Value is a dictionary */ pair.has_dictValue = true; pair.dictValue.dictItem.funcs.encode = encode_dictionary; pair.dictValue.dictItem.arg = p; } else { /* Value is integer */ pair.has_intValue = true; pair.intValue = atoi(p); } p = find_end_of_item(p); if (!pb_encode_tag_for_field(stream, field)) return false; if (!pb_encode_submessage(stream, KeyValuePair_fields, &pair)) return false; } return true; }
bool chargesensor_callback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { SensorReading sensormsg = SensorReading_init_zero; /* Fill in the lucky number */ sensormsg.id = 6; sensormsg.has_id = true; if (ltc.isValid()) { sensormsg.value1 = (int32_t)(ltc.getCharge()*1000); sensormsg.has_value1 = true; } else { sensormsg.error = 1; sensormsg.has_error = true; } /* This encodes the header for the field, based on the constant info from pb_field_t. */ if (!pb_encode_tag_for_field(stream, field)) return false; /* This encodes the data for the field, based on our FileInfo structure. */ if (!pb_encode_submessage(stream, SensorReading_fields, &sensormsg)) return false; return true; }
bool npb_encode_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { char *str = (char *)*arg; if (!pb_encode_tag_for_field(stream, field)) return false; return pb_encode_string(stream, (uint8_t*)str, strlen(str)); }
/* Parse a tree in format [[1 2] 3] and encode it directly to protobuf */ static bool encode_tree(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { TreeNode tree = TreeNode_init_zero; char *p = (char*)*arg; if (*p == '[') { /* This is a tree branch */ p++; tree.left.funcs.encode = encode_tree; tree.left.arg = p; p = find_end_of_item(p); tree.right.funcs.encode = encode_tree; tree.right.arg = p; } else { /* This is a leaf node */ tree.has_leaf = true; tree.leaf = atoi(p); } return pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, TreeNode_fields, &tree); }
static bool write_string_from_arg(pb_ostream_t *stream, const pb_field_t *field, void *const *arg) { const char *str = *arg; if (!pb_encode_tag_for_field(stream, field)) return false; return pb_encode_string(stream, (uint8_t *)str, strlen(str)); }
bool motordataEncoderCallback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { MotorMsg_Data_Param *tuple = ((MotorMsg_Data_Param *) (*arg)); pb_encode_tag_for_field(stream, field); return pb_encode_submessage(stream, MotorMsg_Data_Param_fields, tuple); }
/* Encode a field with static allocation, i.e. one whose data is stored * in the structure itself. */ static bool checkreturn encode_static_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData) { pb_encoder_t func; const void *pSize; bool dummy = true; func = PB_ENCODERS[PB_LTYPE(field->type)]; if (field->size_offset) pSize = (const char*)pData + field->size_offset; else pSize = &dummy; switch (PB_HTYPE(field->type)) { case PB_HTYPE_REQUIRED: if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; break; case PB_HTYPE_OPTIONAL: if (*(const bool*)pSize) { if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; } break; case PB_HTYPE_REPEATED: if (!encode_array(stream, field, pData, *(const size_t*)pSize, func)) return false; break; default: PB_RETURN_ERROR(stream, "invalid field type"); } return true; }
// TODO: I'm not entirely sure why this can't be in the header... bool micropb_callback_string_from_tensor(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { at::Tensor* t = static_cast<at::Tensor*>(*arg); JIT_ASSERT(t->is_contiguous()); // Packed array format! pb_encode_tag_for_field(stream, field); pb_encode_string(stream, (pb_byte_t*)(t->data_ptr()), t->type().elementSizeInBytes()*t->numel()); return true; }
bool encodeMotorMsg(pb_ostream_t *stream, const pb_field_t messagetype[], const void *message) { const pb_field_t *field; for (field = MotorMsg_fields; field->tag != 0; field++) { if (field->ptr == messagetype) { /* This is our field, encode the message using it. */ if (!pb_encode_tag_for_field(stream, field)) return false; return pb_encode_submessage(stream, messagetype, message); } } /* Didn't find the field for messagetype */ return false; }
static bool write_limits(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { Limits limits = {0}; limits.int32_min = INT32_MIN; limits.int32_max = INT32_MAX; limits.uint32_min = 0; limits.uint32_max = UINT32_MAX; limits.int64_min = INT64_MIN; limits.int64_max = INT64_MAX; limits.uint64_min = 0; limits.uint64_max = UINT64_MAX; limits.enum_min = HugeEnum_Negative; limits.enum_max = HugeEnum_Positive; return pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, Limits_fields, &limits); }
/** * Message EPS encode callback function * @param stream * @param field * @param arg * @return */ bool ss_eps_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { EPS eps=EPS_init_zero; log_printf(LOG_VERBOSE,"Encoding EPS SubMessage!\n"); char** arg_eps = (char **)arg[0]; int i; int count=atoi(arg_eps[0]); arg_eps=arg_eps+1; for(i=0;i<count;i++) { arg_eps=arg_eps+i*7; strcpy(eps.profile_id,arg_eps[0]); eps.has_profile_id=true; strcpy(eps.device_id,arg_eps[1]); eps.has_device_id=true; strcpy(eps.zone_type,arg_eps[2]); eps.has_zone_type=true; strcpy(eps.ep,arg_eps[3]); eps.has_ep=true; strcpy(eps.ep_name,arg_eps[4]); eps.has_ep_name=true; eps.rid=atoi(arg_eps[5]); eps.has_rid=true; eps.arm=atoi(arg_eps[6]); eps.has_arm=true; if (!pb_encode_tag_for_field(stream, field)) return false; //This encodes the data for the field, based on our FileInfo structure. if (!pb_encode_submessage(stream, EPS_fields, &eps)) return false; } return true; }
bool listdir_callback(pb_ostream_t *stream, const pb_field_t *field, const void *arg) { DIR *dir = (DIR*) arg; struct dirent *file; FileInfo fileinfo; while ((file = readdir(dir)) != NULL) { fileinfo.inode = file->d_ino; strncpy(fileinfo.name, file->d_name, sizeof(fileinfo.name)); fileinfo.name[sizeof(fileinfo.name) - 1] = '\0'; if (!pb_encode_tag_for_field(stream, field)) return false; if (!pb_enc_submessage(stream, field, &fileinfo)) return false; } return true; }
bool switchsensor_callback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { SensorReading sensormsg = SensorReading_init_zero; /* Fill in the lucky number */ sensormsg.id = 1; sensormsg.has_id = true; sensormsg.value1 = microSwitch.ReadState(); sensormsg.has_value1 = true; /* This encodes the header for the field, based on the constant info from pb_field_t. */ if (!pb_encode_tag_for_field(stream, field)) return false; /* This encodes the data for the field, based on our FileInfo structure. */ if (!pb_encode_submessage(stream, SensorReading_fields, &sensormsg)) return false; return true; }
static int checkreturn pb_encode(pb_ostream_t *stream, const json_t *gprotos, const json_t *protos, json_t *msg) { json_t *root, *value, *option, *proto; root = msg; const char *option_text; const char *key; void *iter = json_object_iter(root); while (iter) { key = json_object_iter_key(iter); value = json_object_iter_value(iter); proto = json_object_get(protos, key); if (proto) { option = json_object_get(proto, "option"); option_text = json_string_value(option); if (strcmp(option_text, "required") == 0 || strcmp(option_text, "optional") == 0) { if (!pb_encode_tag_for_field(stream, proto)) { return 0; } if (!pb_encode_proto(stream, gprotos, protos, proto, value)) { return 0; } } else if (strcmp(option_text, "repeated") == 0) { if (json_is_array(value)) { if (!pb_encode_array(stream, gprotos, protos, proto, value)) { return 0; } } } } else { return 0; } iter = json_object_iter_next(root, iter); } return 1; }
/* This function is the core of the union encoding process. It handles * the top-level pb_field_t array manually, in order to encode a correct * field tag before the message. The pointer to MsgType_fields array is * used as an unique identifier for the message type. */ bool encode_unionmessage(pb_ostream_t *stream, const pb_msgdesc_t *messagetype, void *message) { pb_field_iter_t iter; if (!pb_field_iter_begin(&iter, UnionMessage_fields, message)) return false; do { if (iter.submsg_desc == messagetype) { /* This is our field, encode the message using it. */ if (!pb_encode_tag_for_field(stream, &iter)) return false; return pb_encode_submessage(stream, messagetype, message); } } while (pb_field_iter_next(&iter)); /* Didn't find the field for messagetype */ return false; }
static int pb_encode(pb_ostream_t *stream, const pc_JSON *gprotos, const pc_JSON *protos, pc_JSON *msg) { pc_JSON *root = msg, *value, *option, *proto; const char *option_text; const char *key; value = root->child; while (value) { key = value->string; proto = pc_JSON_GetObjectItem(protos, key); if (proto) { option = pc_JSON_GetObjectItem(proto, "option"); option_text = option->valuestring; if (strcmp(option_text, "required") == 0 || strcmp(option_text, "optional") == 0) { if (!pb_encode_tag_for_field(stream, proto)) { return 0; } if (!pb_encode_proto(stream, gprotos, protos, proto, value)) { return 0; } } else if (strcmp(option_text, "repeated") == 0) { if (value->type == pc_JSON_Array) { if (!pb_encode_array(stream, gprotos, protos, proto, value)) { return 0; } } } } else { return 0; } value = value->next; } return 1; }
/** * Message Dev encode callback function * @param stream * @param field * @param arg * @return */ bool ss_pb_encode_devlist(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { int i,j; FILE *fd; log_printf(LOG_VERBOSE,"Encoding Devlist SubMessage!\n"); char *args[100]; char temp_str[100][40]; char temp[40]; Dev devlist=Dev_init_zero; struct dirent *ptr=NULL; DIR *dir; dir=opendir("/gl/etc/devlist"); while((ptr=readdir(dir))!=NULL) { //跳过’.'和’..’两个目录 if (ptr->d_name[0] == '.') continue; //printf("%s is ready...\n",ptr->d_name); char path[35]={'\0'}; strcat(path,DEVINFO_DIR); strcat(path, ptr->d_name); fd = fopen(path, "r"); if(fd==NULL)log_printf(LOG_ERROR,"Can't open path file!\n",path); j=0; while (!feof(fd)) { fgets(temp, sizeof(temp), fd); int L; L = strlen(temp); for (i = 0; i <= L; i++) if (temp[i] == '\n') { temp[i] = 0; } strcpy(temp_str[j], temp); args[j]=temp_str[j]; //printf("read test:%s\n",args[j]); j++; } strcpy(devlist.ieee, args[0]); devlist.has_ieee = true; strcpy(devlist.nwk_addr, args[1]); devlist.has_nwk_addr = true; strcpy(devlist.node_name, args[2]); devlist.has_node_name = true; devlist.online = atoi(args[3]); devlist.has_online = true; devlist.node_status = atoi(args[4]); devlist.has_node_status = true; devlist.eps.funcs.encode = &ss_eps_encode; devlist.eps.arg = args + 5; if (!pb_encode_tag_for_field(stream, field)) return false; //This encodes the data for the field, based on our FileInfo structure. if (!pb_encode_submessage(stream, Dev_fields, &devlist)) return false; fclose(fd); } return true; }
static bool write_submsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { return pb_encode_tag_for_field(stream, field) && pb_encode_submessage(stream, SubMessage_fields, *arg); }
static bool write_fixed64(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { return pb_encode_tag_for_field(stream, field) && pb_encode_fixed64(stream, *arg); }
/* Callbacks don't need this function because they usually know the data type * without examining the field structure. * Therefore it is static for now. */ static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func) { size_t i; const void *p; size_t size; if (count == 0) return true; if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) { if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) return false; /* Determine the total size of packed array. */ if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) { size = 4 * count; } else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) { size = 8 * count; } else { pb_ostream_t sizestream = {0,0,0,0}; p = pData; for (i = 0; i < count; i++) { if (!func(&sizestream, field, p)) return false; p = (const char*)p + field->data_size; } size = sizestream.bytes_written; } if (!pb_encode_varint(stream, (uint64_t)size)) return false; if (stream->callback == NULL) return pb_write(stream, NULL, size); /* Just sizing.. */ /* Write the data */ p = pData; for (i = 0; i < count; i++) { if (!func(stream, field, p)) return false; p = (const char*)p + field->data_size; } } else { p = pData; for (i = 0; i < count; i++) { if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, p)) return false; p = (const char*)p + field->data_size; } } return true; }
/* Encode a static array. Handles the size calculations and possible packing. */ static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func) { size_t i; const void *p; size_t size; if (count == 0) return true; if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) PB_RETURN_ERROR(stream, "array max size exceeded"); /* We always pack arrays if the datatype allows it. */ if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) { if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) return false; /* Determine the total size of packed array. */ if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) { size = 4 * count; } else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) { size = 8 * count; } else { pb_ostream_t sizestream = PB_OSTREAM_SIZING; p = pData; for (i = 0; i < count; i++) { if (!func(&sizestream, field, p)) return false; p = (const char*)p + field->data_size; } size = sizestream.bytes_written; } if (!pb_encode_varint(stream, (uint64_t)size)) return false; if (stream->callback == NULL) return pb_write(stream, NULL, size); /* Just sizing.. */ /* Write the data */ p = pData; for (i = 0; i < count; i++) { if (!func(stream, field, p)) return false; p = (const char*)p + field->data_size; } } else { p = pData; for (i = 0; i < count; i++) { if (!pb_encode_tag_for_field(stream, field)) return false; /* Normally the data is stored directly in the array entries, but * for pointer-type string and bytes fields, the array entries are * actually pointers themselves also. So we have to dereference once * more to get to the actual data. */ if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && (PB_LTYPE(field->type) == PB_LTYPE_STRING || PB_LTYPE(field->type) == PB_LTYPE_BYTES)) { if (!func(stream, field, *(const void* const*)p)) return false; } else { if (!func(stream, field, p)) return false; } p = (const char*)p + field->data_size; } } return true; }