11/*
2- Package ibmmq provides a wrapper to a the IBM MQ procedural interface (the MQI).
2+ Package ibmmq provides a wrapper to the IBM MQ procedural interface (the MQI).
33
44The verbs are given mixed case names without MQ - Open instead
55of MQOPEN etc.
@@ -9,8 +9,8 @@ constants and structures, see the MQ Knowledge Center
99at https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.1.0/com.ibm.mq.dev.doc/q023720_.htm#q023720_
1010
1111If an MQI call returns MQCC_FAILED or MQCC_WARNING, a custom error
12- type is returned containing the MQCC/MQRC values as
13- a formatted string. Use mqreturn:= err(*ibmmq.MQReturn) to access
12+ type is returned containing the MQCC/MQRC values as well as
13+ a formatted string. Use ' mqreturn:= err(*ibmmq.MQReturn)' to access
1414the particular MQRC or MQCC values.
1515
1616The build directives assume the default MQ installation path
@@ -607,6 +607,36 @@ The length of the retrieved message is returned.
607607*/
608608func (object MQObject ) Get (gomd * MQMD ,
609609 gogmo * MQGMO , buffer []byte ) (int , error ) {
610+ return object .getInternal (gomd , gogmo , buffer , false )
611+ }
612+
613+ /*
614+ GetSlice is the same as Get except that the buffer gets returned
615+ ready-sliced based on the message length instead of just returning the
616+ length. The real length is also still returned in case of truncation.
617+ */
618+ func (object MQObject ) GetSlice (gomd * MQMD ,
619+ gogmo * MQGMO , buffer []byte ) ([]byte , int , error ) {
620+ realDatalen , err := object .getInternal (gomd , gogmo , buffer , true )
621+
622+ // The datalen will be set even if the buffer is too small - there
623+ // will be one of MQRC_TRUNCATED_MSG_ACCEPTED or _FAILED depending on the
624+ // GMO options. In any case, we return the available data along with the
625+ // error code but need to make sure that the real untruncated
626+ // message length is also returned. Also ensure we don't try to read past the
627+ // end of the buffer.
628+ datalen := realDatalen
629+ if datalen > cap (buffer ) {
630+ datalen = cap (buffer )
631+ }
632+ return buffer [0 :datalen ], realDatalen , err
633+ }
634+
635+ /*
636+ This is the real function that calls MQGET.
637+ */
638+ func (object MQObject ) getInternal (gomd * MQMD ,
639+ gogmo * MQGMO , buffer []byte , useCap bool ) (int , error ) {
610640
611641 var mqrc C.MQLONG
612642 var mqcc C.MQLONG
@@ -624,12 +654,23 @@ func (object MQObject) Get(gomd *MQMD,
624654 return 0 , err
625655 }
626656
627- bufflen := len (buffer )
657+ bufflen := 0
658+ if useCap {
659+ bufflen = cap (buffer )
660+ } else {
661+ bufflen = len (buffer )
662+ }
628663
629664 copyMDtoC (& mqmd , gomd )
630665 copyGMOtoC (& mqgmo , gogmo )
631666
632667 if bufflen > 0 {
668+ // There has to be something in the buffer for CGO to be able to
669+ // find its address. We know there's space backing the buffer so just
670+ // set the first byte to something.
671+ if useCap && len (buffer ) == 0 {
672+ buffer = append (buffer , 0 )
673+ }
633674 ptr = (C .PMQVOID )(unsafe .Pointer (& buffer [0 ]))
634675 } else {
635676 ptr = nil
@@ -652,7 +693,7 @@ func (object MQObject) Get(gomd *MQMD,
652693 }
653694
654695 if mqcc != C .MQCC_OK {
655- return 0 , & mqreturn
696+ return godatalen , & mqreturn
656697 }
657698
658699 return godatalen , nil
@@ -724,14 +765,14 @@ func (object MQObject) Inq(goSelectors []int32, intAttrCount int, charAttrLen in
724765*/
725766
726767/*
727- * Inq is the function to inquire on an attribute of an object
728- *
729- * This has a much simpler API than the original implementation.
730- * Simply pass in the list of selectors for the object
731- * and the return value consists of a map whose elements are
732- * a) accessed via the selector
733- * b) varying datatype (integer, string, string array) based on the selector
734- */
768+ Inq is the function to inquire on an attribute of an object
769+
770+ This has a much simpler API than the original implementation.
771+ Simply pass in the list of selectors for the object
772+ and the return value consists of a map whose elements are
773+ a) accessed via the selector
774+ b) varying datatype (integer, string, string array) based on the selector
775+ */
735776func (object MQObject ) Inq (goSelectors []int32 ) (map [int32 ]interface {}, error ) {
736777 var mqrc C.MQLONG
737778 var mqcc C.MQLONG
@@ -841,18 +882,18 @@ func (object MQObject) Inq(goSelectors []int32) (map[int32]interface{}, error) {
841882}
842883
843884/*
844- * The InqMap function was the migration path when the original Inq was
845- * deprecated. It is kept here as a tempoary wrapper to the new Inq() version.
846- */
885+ The InqMap function was the migration path when the original Inq was
886+ deprecated. It is kept here as a temporary wrapper to the new Inq() version.
887+ */
847888func (object MQObject ) InqMap (goSelectors []int32 ) (map [int32 ]interface {}, error ) {
848889 return object .Inq (goSelectors )
849890}
850891
851892/*
852- * Set is the function that wraps MQSET. The single parameter is a map whose
853- * elements contain an MQIA/MQCA selector with either a string or an int32 for
854- * the value.
855- */
893+ Set is the function that wraps MQSET. The single parameter is a map whose
894+ elements contain an MQIA/MQCA selector with either a string or an int32 for
895+ the value.
896+ */
856897func (object MQObject ) Set (goSelectors map [int32 ]interface {}) error {
857898 var mqrc C.MQLONG
858899 var mqcc C.MQLONG
0 commit comments