Esempio n. 1
0
        /// <summary>Encode a byte array into a radix-encoded string</summary>
        /// <param name="bytes">byte array to encode</param>
        /// <returns>The bytes in encoded into a radix-encoded string</returns>
        /// <remarks>If <paramref name="bytes"/> is zero length, returns an empty string</remarks>
        public string Encode(byte[] bytes)
        {
            Contract.Requires <ArgumentNullException>(bytes != null);
            Contract.Ensures(Contract.Result <string>() != null);

            // Don't really have to do this, our code will build this result (empty string),
            // but why not catch the condition before doing work?
            if (bytes.Length == 0)
            {
                return(string.Empty);
            }

            // if the array ends with zeros, having the capacity set to this will help us know how much
            // 'padding' we will need to add
            int result_length = EncodingCharsCount(bytes.Length);
            // List<> has a(n in-place) Reverse method. StringBuilder doesn't. That's why.
            var result = new List <char>(result_length);

            // HACK: BigInteger uses the last byte as the 'sign' byte. If the byte's MSB is set,
            // we need to pad the input with an extra 0 (ie, make it positive)
            if (IntegerMath.IsSigned(bytes[bytes.Length - 1]))
            {
                Array.Resize(ref bytes, bytes.Length + 1);
            }

            var dividend = new BigInteger(bytes);

            // IsZero's computation is less complex than evaluating "dividend > 0"
            // which invokes BigInteger.CompareTo(BigInteger)
            while (!dividend.IsZero)
            {
                dividend = BigInteger.DivRem(dividend, kRadixBig, out BigInteger remainder);
                int digit_index = System.Math.Abs((int)remainder);
                result.Add(kDigits[digit_index]);
            }

            if (kIncludeProceedingZeros)
            {
                for (int x = result.Count; x < result.Capacity; x++)
                {
                    result.Add(kDigits[0]);                     // pad with the character that represents 'zero'
                }
            }
            // orientate the characters in big-endian ordering
            if (kEndian == Shell.EndianFormat.Little)
            {
                result.Reverse();
            }
            // If we didn't end up adding padding, ToArray will end up returning a TrimExcess'd array,
            // so nothing wasted
            return(new string(result.ToArray()));
        }