Example #1
0
func wrapVariable(cType C.RFCTYPE, container C.RFC_FUNCTION_HANDLE, cName *C.SAP_UC, cLen C.uint, typeDesc C.RFC_TYPE_DESC_HANDLE, strip bool) (result interface{}, err error) {
	var rc C.RFC_RC
	var errorInfo C.RFC_ERROR_INFO
	var structure C.RFC_STRUCTURE_HANDLE
	var table C.RFC_TABLE_HANDLE
	var charValue *C.RFC_CHAR
	var stringValue *C.SAP_UC
	var numValue *C.RFC_NUM
	var byteValue *C.SAP_RAW
	var floatValue C.RFC_FLOAT
	var intValue C.RFC_INT
	var int1Value C.RFC_INT1
	var int2Value C.RFC_INT2
	var dateValue *C.RFC_CHAR
	var timeValue *C.RFC_CHAR

	var resultLen, strLen C.uint

	switch cType {
	case C.RFCTYPE_STRUCTURE:
		rc = C.RfcGetStructure(container, cName, &structure, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting structure")
		}
		return wrapStructure(typeDesc, structure, strip)
	case C.RFCTYPE_TABLE:
		rc = C.RfcGetTable(container, cName, &table, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting table")
		}
		return wrapTable(typeDesc, table, strip)
	case C.RFCTYPE_CHAR:
		charValue = (*C.RFC_CHAR)(C.GoMallocU(cLen))
		defer C.free(unsafe.Pointer(charValue))

		rc = C.RfcGetChars(container, cName, charValue, cLen, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting chars")
		}
		return nWrapString((*C.SAP_UC)(charValue), C.int(cLen), strip)
	case C.RFCTYPE_STRING:
		rc = C.RfcGetStringLength(container, cName, &strLen, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting string length")
		}

		stringValue = (*C.SAP_UC)(C.GoMallocU(strLen + 1))
		defer C.free(unsafe.Pointer(stringValue))

		rc = C.RfcGetString(container, cName, stringValue, strLen+1, &resultLen, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting string")
		}
		return wrapString(stringValue, strip)
	case C.RFCTYPE_NUM:
		numValue = (*C.RFC_NUM)(C.GoMallocU(cLen))
		defer C.free(unsafe.Pointer(numValue))

		rc = C.RfcGetNum(container, cName, numValue, cLen, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting num")
		}
		return nWrapString((*C.SAP_UC)(numValue), C.int(cLen), strip)
	case C.RFCTYPE_BYTE:
		byteValue = (*C.SAP_RAW)(C.malloc(C.size_t(cLen)))
		defer C.free(unsafe.Pointer(byteValue))

		rc = C.RfcGetBytes(container, cName, byteValue, cLen, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting bytes")
		}
		return (*[1 << 30]byte)(unsafe.Pointer(byteValue))[:cLen:cLen], err
	case C.RFCTYPE_XSTRING:
		rc = C.RfcGetStringLength(container, cName, &strLen, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting xstring length")
		}

		byteValue = (*C.SAP_RAW)(C.malloc(C.size_t(strLen + 1)))
		defer C.free(unsafe.Pointer(byteValue))
		*byteValue = 0

		rc = C.RfcGetXString(container, cName, byteValue, strLen, &resultLen, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting xstring")
		}
		return (*[1 << 30]byte)(unsafe.Pointer(byteValue))[:resultLen:resultLen], err
	case C.RFCTYPE_BCD:
		// An upper bound for the length of the _string representation_
		// of the BCD is given by (2*cLen)-1 (each digit is encoded in 4bit,
		// the first 4 bit are reserved for the sign)
		// Furthermore, a sign char, a decimal separator char may be present
		// => (2*cLen)+1
		strLen = 2*cLen + 1
		stringValue = C.GoMallocU(strLen + 1)
		defer C.free(unsafe.Pointer(stringValue))

		rc = C.RfcGetString(container, cName, stringValue, strLen+1, &resultLen, &errorInfo)
		/*if rc == 23: # Buffer too small, use returned requried result length
		  print("Warning: Buffer for BCD (cLen={}, buffer={}) too small: "
		        "trying with {}".format(cLen, strLen, resultLen))
		  free(stringValue)
		  strLen = resultLen
		  stringValue = mallocU(strLen+1)
		  rc = RfcGetString(container, cName, stringValue, strLen+1, &resultLen, &errorInfo)*/
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting BCD")
		}
		return wrapString(stringValue, strip)
		//return Decimal(wrapString(stringValue))
	case C.RFCTYPE_FLOAT:
		rc = C.RfcGetFloat(container, cName, &floatValue, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting float")
		}
		return float64(floatValue), err
	case C.RFCTYPE_INT:
		rc = C.RfcGetInt(container, cName, &intValue, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting int")
		}
		return int(intValue), err
	case C.RFCTYPE_INT1:
		rc = C.RfcGetInt1(container, cName, &int1Value, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting int1")
		}
		return int(int1Value), err
	case C.RFCTYPE_INT2:
		rc = C.RfcGetInt2(container, cName, &int2Value, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting int2")
		}
		return int(int2Value), err
	case C.RFCTYPE_DATE:
		dateValue = (*C.RFC_CHAR)(C.malloc(8))
		defer C.free(unsafe.Pointer(dateValue))

		rc = C.RfcGetDate(container, cName, dateValue, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting date")
		}
		var value string
		value, err = nWrapString((*C.SAP_UC)(dateValue), 8, false)
		if value == "00000000" || ' ' == value[1] || err != nil {
			return
		}
		goDate, _ := time.Parse("20060102", value)
		return goDate, err
	case C.RFCTYPE_TIME:
		timeValue = (*C.RFC_CHAR)(C.malloc(6))
		defer C.free(unsafe.Pointer(timeValue))

		rc = C.RfcGetTime(container, cName, timeValue, &errorInfo)
		if rc != C.RFC_OK {
			return result, rfcError(errorInfo, "Failed getting time")
		}
		var value string
		value, err = nWrapString((*C.SAP_UC)(timeValue), 6, false)
		if err != nil {
			return
		}
		goTime, _ := time.Parse("150405", value)
		return goTime, err
	}
	return result, rfcError(errorInfo, "Unknown RFC type %d when wrapping variable", cType)
}
Example #2
0
func fillVariable(cType C.RFCTYPE, container C.RFC_FUNCTION_HANDLE, cName *C.SAP_UC, value interface{}, typeDesc C.RFC_TYPE_DESC_HANDLE) (err error) {
	var rc C.RFC_RC
	var errorInfo C.RFC_ERROR_INFO
	var structure C.RFC_STRUCTURE_HANDLE
	var table C.RFC_TABLE_HANDLE
	var cValue *C.SAP_UC
	var bValue *C.SAP_RAW

	defer C.free(unsafe.Pointer(cValue))
	defer C.free(unsafe.Pointer(bValue))

	switch cType {
	case C.RFCTYPE_STRUCTURE:
		rc = C.RfcGetStructure(container, cName, &structure, &errorInfo)
		if rc != C.RFC_OK {
			return rfcError(errorInfo, "Could not get structure")
		}
		err = fillStructure(typeDesc, structure, value)
	case C.RFCTYPE_TABLE:
		rc = C.RfcGetTable(container, cName, &table, &errorInfo)
		if rc != C.RFC_OK {
			return rfcError(errorInfo, "Could not get table")
		}
		err = fillTable(typeDesc, table, value)
	case C.RFCTYPE_CHAR:
		cValue, err = fillString(reflect.ValueOf(value).String())
		rc = C.RfcSetChars(container, cName, (*C.RFC_CHAR)(cValue), C.uint(C.GoStrlenU((*C.SAP_UTF16)(cValue))), &errorInfo)
	case C.RFCTYPE_BYTE:
		bValue = fillBytes(reflect.ValueOf(value).Bytes())
		rc = C.RfcSetBytes(container, cName, bValue, C.uint(len(reflect.ValueOf(value).Bytes())), &errorInfo)
	case C.RFCTYPE_XSTRING:
		bValue = fillBytes(reflect.ValueOf(value).Bytes())
		rc = C.RfcSetXString(container, cName, bValue, C.uint(len(reflect.ValueOf(value).Bytes())), &errorInfo)
	case C.RFCTYPE_STRING:
		cValue, err = fillString(reflect.ValueOf(value).String())
		rc = C.RfcSetString(container, cName, cValue, C.uint(C.GoStrlenU((*C.SAP_UTF16)(cValue))), &errorInfo)
	case C.RFCTYPE_NUM:
		cValue, err = fillString(reflect.ValueOf(value).String())
		rc = C.RfcSetNum(container, cName, (*C.RFC_NUM)(cValue), C.uint(C.GoStrlenU((*C.SAP_UTF16)(cValue))), &errorInfo)
	case C.RFCTYPE_BCD:
		// support for float missing
		cValue, err = fillString(reflect.ValueOf(value).String())
		rc = C.RfcSetString(container, cName, cValue, C.uint(C.GoStrlenU((*C.SAP_UTF16)(cValue))), &errorInfo)
	case C.RFCTYPE_FLOAT:
		rc = C.RfcSetFloat(container, cName, C.RFC_FLOAT(reflect.ValueOf(value).Float()), &errorInfo)
	case C.RFCTYPE_INT, C.RFCTYPE_INT1, C.RFCTYPE_INT2:
		rc = C.RfcSetInt(container, cName, C.RFC_INT(reflect.ValueOf(value).Int()), &errorInfo)
	case C.RFCTYPE_DATE:
		cValue, err = fillString(value.(time.Time).Format("20060102"))
		rc = C.RfcSetDate(container, cName, (*C.RFC_CHAR)(cValue), &errorInfo)
	case C.RFCTYPE_TIME:
		cValue, err = fillString(value.(time.Time).Format("150405"))
		rc = C.RfcSetTime(container, cName, (*C.RFC_CHAR)(cValue), &errorInfo)
	default:
		var goName string
		goName, err = wrapString(cName, true)
		return rfcError(errorInfo, "Unknown RFC type %v when filling %v", cType, goName)
	}
	if rc != C.RFC_OK {
		var goName string
		goName, err = wrapString(cName, true)
		err = rfcError(errorInfo, "Could not fill %v of type %v", goName, cType)
	}
	return
}