PyObject * fudgepyc_convertStringToPython ( FudgeString source ) { PyObject * target = 0; fudge_byte * buffer; size_t written, bufsize; bufsize = FudgeString_getSize ( source ) * sizeof ( Py_UNICODE ); if ( ! ( buffer = ( fudge_byte * ) PyMem_Malloc ( bufsize ) ) ) return 0; /* See comment in fudgepyc_convertPythonToString for explanation */ switch ( sizeof ( Py_UNICODE ) ) { case 2: written = FudgeString_copyToUTF16 ( buffer, bufsize, source ); break; case 4: written = FudgeString_copyToUTF32 ( buffer, bufsize, source ); break; default: exception_raise_any ( PyExc_RuntimeError, "Cannot decode Fudge string; Python " "interpreter not using UCS2 or UCS4 for" "internal unicode encoding" ); return 0; } target = PyUnicode_FromUnicode ( ( Py_UNICODE * ) buffer, written / sizeof ( Py_UNICODE ) ); PyMem_Free ( buffer ); return target; }
/* Type coercing function for AddressDetails. Required, but can simply refuse to coerce the value (returning either FUDGE_COERCION_NOT_REQUIRED if the types match or FUDGE_INVALID_TYPE_COERCION if not). For this example a simple string conversion is supported. */ FudgeStatus FudgeType_coerceAddressDetails ( const FudgeField * source, const fudge_type_id type, FudgeFieldData * target, fudge_i32 * numbytes ) { /* Used for string output */ static const char * statusString [ 3 ] = { "Unknown", "Active", "Past" }; size_t statusInt; switch ( type ) { case FUDGE_TYPE_ADDRESSDETAILS: return FUDGE_COERCION_NOT_REQUIRED; case FUDGE_TYPE_STRING: { FudgeStatus status; char * tempstr; const AddressDetails * details = ( const AddressDetails * ) source->data.bytes; int stringlen; /* Calculate how much space will be needed for the string and set the return value */ stringlen = ADDRESSDETAILS_NAME_FIELD_LEN + ADDRESSDETAILS_CITY_FIELD_LEN + ADDRESSDETAILS_POST_FIELD_LEN + 32; /* Allocate string space in temporary buffer */ if ( ! ( tempstr = ( char * ) malloc ( stringlen ) ) ) return FUDGE_OUT_OF_MEMORY; /* Encode string - yes snprintf is better, but it's not portable enough for the example code. */ statusInt = ( size_t ) ( details->status >= 0 && details->status <= 3 ? details->status : Status_Unknown ); sprintf ( tempstr, "[%s] %d %s, %s. %s.", statusString [ statusInt ], details->house_number, details->street_name, details->city, details->postal_code ); /* Use the temporary string to create the return value FudgeString */ status = FudgeString_createFromASCIIZ ( &( target->string ), tempstr ); free ( tempstr ); *numbytes = FudgeString_getSize ( target->string ); return status; } default: return FUDGE_INVALID_TYPE_COERCION; } }
FudgeStatus FudgeMsg_addFieldString ( FudgeMsg message, const FudgeString name, const fudge_i16 * ordinal, FudgeString string ) { FudgeStatus status; FudgeFieldData data; size_t stringbytes; if ( ! ( message && string ) ) return FUDGE_NULL_POINTER; stringbytes = FudgeString_getSize ( string ); if ( stringbytes > 0x7FFFFFFF ) return FUDGE_PAYLOAD_TOO_LONG; if ( ( status = FudgeString_retain ( string ) ) != FUDGE_OK ) return status; data.string = string; if ( ( status = FudgeMsg_addFieldData ( message, FUDGE_TYPE_STRING, name, ordinal, &data, ( fudge_i32 ) stringbytes ) ) != FUDGE_OK ) FudgeString_release ( string ); return status; }
FudgeStatus FudgeMsg_addFieldData ( FudgeMsg message, fudge_type_id type, const FudgeString name, const fudge_i16 * ordinal, FudgeFieldData * data, fudge_i32 numbytes ) { FudgeStatus status; FieldListNode * node; const FudgeTypeDesc * typedesc = FudgeRegistry_getTypeDesc ( type ); if ( ! ( message && data ) ) return FUDGE_NULL_POINTER; /* Adding a field will invalidate the message's width */ message->width = -1; /* Allocate and initialise the new node, taking a copy of the name if required */ if ( ! ( node = ( FieldListNode * ) malloc ( sizeof ( FieldListNode ) ) ) ) return FUDGE_OUT_OF_MEMORY; node->next = 0; node->field.type = type; node->field.numbytes = numbytes; node->field.flags = 0; /* Copy across the data */ if ( typedesc->payload == FUDGE_TYPE_PAYLOAD_SUBMSG && ! data->message ) return FUDGE_NULL_POINTER; else if ( typedesc->payload == FUDGE_TYPE_PAYLOAD_STRING && ! data->string ) return FUDGE_NULL_POINTER; node->field.data = *data; /* Set the field name (if required) */ if ( name ) { /* Names may not have a length greater than 255 bytes (only one byte is available for their length) */ if ( FudgeString_getSize ( name ) >= 256 ) { status = FUDGE_NAME_TOO_LONG; goto release_node_and_fail; } if ( ( status = FudgeString_retain ( name ) ) != FUDGE_OK ) goto release_node_and_fail; node->field.name = name; node->field.flags |= FUDGE_FIELD_HAS_NAME; } else { node->field.name = 0; } /* Set the field ordinal (if required) */ if ( ordinal ) { node->field.ordinal = *ordinal; node->field.flags |= FUDGE_FIELD_HAS_ORDINAL; } else node->field.ordinal = 0; /* Append the node to the message's list */ if ( message->fieldtail ) { if ( message->fieldtail->next ) { /* Field tail is pointing at a non-tail node - something's gone very wrong */ assert ( message->fieldtail->next == 0 ); FieldListNode_destroy ( node ); return FUDGE_INTERNAL_LIST_STATE; } message->fieldtail->next = node; message->fieldtail = node; } else message->fieldhead = message->fieldtail = node; message->numfields += 1ul; return FUDGE_OK; release_node_and_fail: free ( node ); return status; }