public bool CheckDumpIsValid(string filename, CancellationToken ct, out int messagesCount, out string error)
        {
            messagesCount = 0;
            error         = null;
            try
            {
                using (var sr = new StreamReader(filename))
                {
                    var dr = new DumpReader(sr);

                    MQMessage msg = null; // we simulate, so we don't need the mq message

                    while (ReadFileMessage(dr, out msg, true))
                    {
                        messagesCount++;
                    }
                }

                return(true);
            }
            catch (DumpException ex)
            {
                error = ex.Message;
                return(false);
            }
            catch (Exception ex)
            {
                error = $"Unexpected error ({ex.Message})";
                return(false);
            }
        }
        private void ReadMessageLine(DumpReader reader, int start, MQMessage msg)
        {
            var line  = reader.Line;
            var index = start;

            while (line[index] == ' ')
            {
                index++;
            }

            if (line[index] == '"')
            {
                index++;
                while (index < line.Length)
                {
                    if (line[index] == '"')
                    {
                        break;
                    }

                    if (line[index] == ESCAPE_CHAR)
                    {
                        index++;
                        switch (line[index])
                        {
                        case '"':
                        case ESCAPE_CHAR:
                            msg?.Write(line[index]);
                            break;

                        default:
                            throw new DumpException($"Unexpected escape sequence on line {reader.LineNo}");
                        }
                    }
                    else
                    {
                        msg?.Write(line[index]);
                        index++;
                    }
                }
            }
            else
            {
                int end = line.Length - 1;
                while (line[end] == ' ')
                {
                    end--;
                }

                while (index <= end)
                {
                    msg?.Write(line[index]);
                    index++;
                }
            }
        }
        private void ReadMessageHex(DumpReader reader, int start, MQMessage msg)
        {
            var index = start;

            while (index < reader.Line.Length)
            {
                int ch = reader.Line[index];
                if (ch == ' ')
                {
                    break;
                }
                if (ch >= '0' && ch <= '9')
                {
                    ch = ch - '0';
                }
                else if (ch >= 'A' && ch <= 'F')
                {
                    ch = ch - 'A' + 10;
                }
                else if (ch >= 'a' && ch <= 'f')
                {
                    ch = ch - 'a' + 10;
                }
                /* Oops                        */
                else
                {
                    throw new DumpException($"Badly formed HEX string on line {reader.LineNo}");
                }

                int val = ch * 16;
                index++;
                ch = reader.Line[index];
                if (ch >= '0' && ch <= '9')
                {
                    ch = ch - '0';
                }
                else if (ch >= 'A' && ch <= 'F')
                {
                    ch = ch - 'A' + 10;
                }
                else if (ch >= 'a' && ch <= 'f')
                {
                    ch = ch - 'a' + 10;
                }
                /* Oops                        */
                else
                {
                    throw new DumpException($"Badly formed HEX string on line {reader.LineNo}");
                }

                msg?.WriteByte(val + ch);
                index++;
            }
        }
        private void LoadMessageAttribute(DumpReader reader, MQMessageDescriptor md)
        {
            if (reader.Line.Length < 5)
            {
                throw new DumpException($"Invalid attribute line on line {reader.LineNo}");
            }

            var code = reader.Line.Substring(2, 3);

            switch (code)
            {
            case "VER":
            case "RPT":
            case "MST":
            case "EXP":
            case "FDB":
            case "ENC":
            case "CCS":
            case "FMT":
            case "PRI":
            case "PER":
            case "MSI":
            case "COI":
            case "BOC":
            case "RTQ":
            case "RTM":
            case "USR":
            case "ACC":
            case "AID":
            case "AIX":
            case "PAT":
            case "PAN":
            case "PTD":
            case "PTT":
            case "AOD":
            case "AOX":
            case "GRP":
            case "MSQ":
            case "OFF":
            case "MSF":
            case "ORL":
                break;

            default:
                throw new DumpException($"Unrecognised attribute on line {reader.LineNo}");
            }

            if (reader.Line.Length < 7)
            {
                return;
            }


            var data = reader.Line.Substring(6);

            try
            {
                switch (code)
                {
                case "VER":
                    var ver = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.Version = ver;
                    }
                    break;

                case "RPT":
                    var rpt = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.Report = rpt;
                    }
                    break;

                case "MST":
                    var mst = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.MsgType = mst;
                    }
                    break;

                case "EXP":
                    var exp = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.Expiry = exp;
                    }
                    break;

                case "FDB":
                    var fdb = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.Feedback = fdb;
                    }
                    break;

                case "ENC":
                    var enc = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.Encoding = enc;
                    }
                    break;

                case "CCS":
                    var v = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.Ccsid = v;
                    }
                    break;

                case "FMT":
                    var format = md != null ? md.Format : new byte[8];
                    data.ToBytes(ref format, _encoding);
                    if (md != null)
                    {
                        md.Format = format;
                    }
                    break;

                case "PRI":
                    var pri = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.Priority = pri;
                    }
                    break;

                case "PER":
                    var per = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.Persistence = per;
                    }
                    break;

                case "MSI":
                    var msi = data.HexStringToBytes();
                    if (md != null)
                    {
                        md.MsgId = msi;
                    }
                    break;

                case "COI":
                    var coi = data.HexStringToBytes();
                    if (md != null)
                    {
                        md.CorrelId = coi;
                    }
                    break;

                case "BOC":
                    var boc = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.BackoutCount = boc;
                    }
                    break;

                case "RTQ":
                    var rtq = md != null ? md.ReplyToQueue : new byte[48];
                    data.ToBytes(ref rtq, _encoding);
                    if (md != null)
                    {
                        md.ReplyToQueue = rtq;
                    }
                    break;

                case "RTM":
                    var rtm = md != null ? md.ReplyToQueue : new byte[48];
                    data.ToBytes(ref rtm, _encoding);
                    if (md != null)
                    {
                        md.ReplyToQueueMgr = rtm;
                    }
                    break;

                case "USR":
                    var usr = md != null ? md.UserID : new byte[12];
                    data.ToBytes(ref usr, _encoding);
                    if (md != null)
                    {
                        md.UserID = usr;
                    }
                    break;

                case "ACC":
                    var acc = data.HexStringToBytes();
                    if (md != null)
                    {
                        md.AccountingToken = acc;
                    }
                    break;

                case "AID":
                    var aid = md != null ? md.ApplIdentityData : new byte[3];
                    data.ToBytes(ref aid, _encoding);
                    if (md != null)
                    {
                        md.ApplIdentityData = aid;
                    }
                    break;

                case "AIX":
                    var aix = data.HexStringToBytes();
                    if (md != null)
                    {
                        md.ApplIdentityData = aix;
                    }
                    break;

                case "PAT":
                    var pat = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.PutApplType = pat;
                    }
                    break;

                case "PAN":
                    var pan = md != null ? md.PutApplName : new byte[28];
                    data.ToBytes(ref pan, _encoding);
                    if (md != null)
                    {
                        md.PutApplName = pan;
                    }
                    break;

                case "PTD":
                    var ptd = md != null ? md.PutDate : new byte[8];
                    data.ToBytes(ref ptd, _encoding);
                    if (md != null)
                    {
                        md.PutDate = ptd;
                    }
                    break;

                case "PTT":
                    var ptt = md != null ? md.PutTime : new byte[8];
                    data.ToBytes(ref ptt, _encoding);
                    if (md != null)
                    {
                        md.PutTime = ptt;
                    }
                    break;

                case "AOD":
                    var aod = md != null ? md.ApplOriginData : new byte[4];
                    data.ToBytes(ref aod, _encoding);
                    if (md != null)
                    {
                        md.ApplOriginData = aod;
                    }
                    break;

                case "AOX":
                    var aox = data.HexStringToBytes();
                    if (md != null)
                    {
                        md.ApplOriginData = aox;
                    }
                    break;

                case "GRP":
                    var grp = data.HexStringToBytes();
                    if (md != null)
                    {
                        md.GroupID = grp;
                    }
                    break;

                case "MSQ":
                    var msq = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.MsgSequenceNumber = msq;
                    }
                    break;

                case "OFF":
                    var off = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.Offset = off;
                    }
                    break;

                case "MSF":
                    var msf = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.MsgFlags = msf;
                    }
                    break;

                case "ORL":
                    var orl = int.Parse(data, _culture);
                    if (md != null)
                    {
                        md.OriginalLength = orl;
                    }
                    break;
                }
            }
            catch (Exception ex)
            {
                throw new DumpException($"Invalid message attribute value on line {reader.LineNo}", ex);
            }
        }
 private void ReadMessageTextLine(DumpReader reader, int start, MQMessage msg)
 {
     msg?.WriteString(reader.Line.Substring(start));
 }
        private bool ReadFileMessage(DumpReader reader, out MQMessage msg, bool simulate = false)
        {
            msg = null;

            if (!reader.ReadLine(false, false))
            {
                return(false);
            }

            if (reader.Line[0] != 'A' && reader.Line[0] != 'N')
            {
                throw new DumpException($"Expected message attribute at line {reader.LineNo}");
            }

            if (reader.Line[0] == 'N')
            {
                if (!reader.ReadLine(true, false))
                {
                    throw new DumpException("Invalid end of file. Expected message data");
                }
            }

            MQMessageDescriptor md = null;

            if (!simulate)
            {
                msg = new MQMessage();
                md  = msg.GetDescriptor();
            }

            while (reader.Line[0] == 'A')
            {
                LoadMessageAttribute(reader, md);

                if (!reader.ReadLine(true, false))
                {
                    throw new DumpException("Invalid end of file. Expected message data");
                }
            }

            if (reader.Line[0] != 'X' && reader.Line[0] != 'T' && reader.Line[0] != 'S')
            {
                throw new DumpException($"Expected message at line {reader.LineNo}");
            }

            while (reader.Line[0] == 'X' || reader.Line[0] == 'T' || reader.Line[0] == 'S')
            {
                int skip = 1;
                if (reader.Line[0] == 'T')
                {
                    skip += 1;
                }
                else
                {
                    while (skip < reader.Line.Length && reader.Line[skip] == ' ')
                    {
                        skip += 1;
                    }
                }

                if (skip < reader.Line.Length)
                {
                    switch (reader.Line[0])
                    {
                    case 'X':
                        ReadMessageHex(reader, skip, msg);
                        break;

                    case 'S':
                        ReadMessageLine(reader, skip, msg);
                        break;

                    case 'T':
                        ReadMessageTextLine(reader, skip, msg);
                        break;
                    }
                }

                if (!reader.ReadLine(true, false))
                {
                    break;
                }
            }

            return(true);
        }
        public int LoadDump(IDumpLoadContext context, CancellationToken ct, IProgress <int> progress = null)
        {
            MQQueue ibmQ = null;

            var mqPutMsgOpts = new MQPutMessageOptions {
                Options = MQC.MQPMO_FAIL_IF_QUIESCING
            };

            if (context.Settings.UseTransaction)
            {
                mqPutMsgOpts.Options |= MQC.MQPMO_SYNCPOINT;
            }
            else
            {
                mqPutMsgOpts.Options |= MQC.MQPMO_NO_SYNCPOINT;
            }

            var openMode = OpenQueueMode.ForWrite;

            switch (context.Settings.Context)
            {
            case DumpLoadSettings.ContextMode.SetAll:
                mqPutMsgOpts.Options |= MQC.MQPMO_SET_ALL_CONTEXT;
                openMode              = OpenQueueMode.ForWriteSetAllContext;
                break;

            case DumpLoadSettings.ContextMode.SetIdentity:
                mqPutMsgOpts.Options |= MQC.MQPMO_SET_IDENTITY_CONTEXT;
                openMode              = OpenQueueMode.ForWriteSetIdentityContext;
                break;

            case DumpLoadSettings.ContextMode.NoContext:
                mqPutMsgOpts.Options |= MQC.MQPMO_NO_CONTEXT;
                break;

            case DumpLoadSettings.ContextMode.Default:
                break;
            }

            try
            {
                int messagesCount = 0;
                var qs            = _qSource.NewConnectionCore();
                ibmQ = qs.OpenQueueCore(openMode);

                var dr = new DumpReader(context.Input);

                MQMessage msg = null;

                while (ReadFileMessage(dr, out msg))
                {
                    messagesCount++;
                    ibmQ.Put(msg, mqPutMsgOpts);

                    if (context.Settings.UseTransaction &&
                        context.Settings.TransactionSize > 0 &&
                        messagesCount % context.Settings.TransactionSize == 0)
                    {
                        qs.QueueManager.Commit();
                    }

                    progress?.Report(messagesCount);
                }


                if (context.Settings.UseTransaction &&
                    (context.Settings.TransactionSize <= 0 || messagesCount % context.Settings.TransactionSize != 0))
                {
                    qs.QueueManager.Commit();
                }

                ibmQ.Close();

                return(messagesCount);
            }
            catch (DumpException)
            {
                throw;
            }
            catch (MQException ex)
            {
                throw new DumpException(ex.Message, ex.ReasonCode, ex);
            }
            catch (Exception ex)
            {
                throw new DumpException("Unexpected error!", ex);
            }
        }