/**
         * Parse a base 10 numeric from a sequence of ASCII digits into an int.
         * <para />
         * Digit sequences can begin with an optional run of spaces before the
         * sequence, and may start with a '+' or a '-' to indicate sign position.
         * Any other characters will cause the method to stop and return the current
         * result to the caller.
         *
         * @param b
         *            buffer to scan.
         * @param ptr
         *            position within buffer to start parsing digits at.
         * @param ptrResult
         *            optional location to return the new ptr value through. If null
         *            the ptr value will be discarded.
         * @return the value at this location; 0 if the location is not a valid
         *         numeric.
         */
        public static int parseBase10(byte[] b, int ptr, MutableInteger ptrResult)
        {
            int r    = 0;
            int sign = 0;

            try
            {
                int sz = b.Length;
                while (ptr < sz && b[ptr] == ' ')
                {
                    ptr++;
                }
                if (ptr >= sz)
                {
                    return(0);
                }

                switch (b[ptr])
                {
                case ((byte)'-'):
                    sign = -1;
                    ptr++;
                    break;

                case ((byte)'+'):
                    ptr++;
                    break;
                }

                while (ptr < sz)
                {
                    byte d = b[ptr];
                    if ((d < (byte)'0') || (d > (byte)'9'))
                    {
                        break;
                    }
                    r = r * 10 + (d - (byte)'0');
                    ptr++;
                }
            }
            catch (IndexOutOfRangeException)
            {
                // Not a valid digit.
            }
            if (ptrResult != null)
            {
                ptrResult.value = ptr;
            }
            return(sign < 0 ? -r : r);
        }
        /// <summary>
        /// Parse a base 10 numeric from a sequence of ASCII digits into a long.
        /// <para />
        /// Digit sequences can begin with an optional run of spaces before the
        /// sequence, and may start with a '+' or a '-' to indicate sign position.
        /// Any other characters will cause the method to stop and return the current
        /// result to the caller.
        /// </summary>
        /// <param name="b">Buffer to scan.</param>
        /// <param name="ptr">
        /// Position within buffer to start parsing digits at.
        /// </param>
        /// <param name="ptrResult">
        /// Optional location to return the new ptr value through. If null
        /// the ptr value will be discarded.
        /// </param>
        /// <returns>
        /// The value at this location; 0 if the location is not a valid
        /// numeric.
        /// </returns>
        public static long parseLongBase10(byte[] b, int ptr, MutableInteger ptrResult)
        {
            long r    = 0;
            int  sign = 0;

            try
            {
                int sz = b.Length;
                while (ptr < sz && b[ptr] == ' ')
                {
                    ptr++;
                }
                if (ptr >= sz)
                {
                    return(0);
                }

                switch (b[ptr])
                {
                case (byte)'-':
                    sign = -1;
                    ptr++;
                    break;

                case (byte)'+':
                    ptr++;
                    break;
                }

                while (ptr < sz)
                {
                    int v = b[ptr] - (byte)'0';
                    if (v < 0)
                    {
                        break;
                    }
                    r = (r * 10) + v;
                    ptr++;
                }
            }
            catch (IndexOutOfRangeException)
            {
                // Not a valid digit.
            }
            if (ptrResult != null)
            {
                ptrResult.value = ptr;
            }
            return(sign < 0 ? -r : r);
        }
        /**
         * Parse a name line (e.g. author, committer, tagger) into a PersonIdent.
         * <para />
         * When passing in a value for <code>nameB</code> callers should use the
         * return value of {@link #author(byte[], int)} or
         * {@link #committer(byte[], int)}, as these methods provide the proper
         * position within the buffer.
         *
         * @param raw
         *            the buffer to parse character data from.
         * @param nameB
         *            first position of the identity information. This should be the
         *            first position After the space which delimits the header field
         *            name (e.g. "author" or "committer") from the rest of the
         *            identity line.
         * @return the parsed identity. Never null.
         */
        public static PersonIdent parsePersonIdent(byte[] raw, int nameB)
        {
            Encoding cs     = parseEncoding(raw);
            int      emailB = nextLF(raw, nameB, (byte)'<');
            int      emailE = nextLF(raw, emailB, (byte)'>');

            string name  = decode(cs, raw, nameB, emailB - 2);
            string email = decode(cs, raw, emailB, emailE - 1);

            var  ptrout = new MutableInteger();
            long when   = parseLongBase10(raw, emailE + 1, ptrout);
            int  tz     = parseTimeZoneOffset(raw, ptrout.value);

            return(new PersonIdent(name, email, when * 1000, tz));
        }
示例#4
0
文件: RevTag.cs 项目: dev218/GitSharp
		public void parseCanonical(RevWalk walk, byte[] rawTag)
		{
			var pos = new MutableInteger { value = 53 };

			int oType = Constants.decodeTypeString(this, rawTag, (byte)'\n', pos);
			walk.IdBuffer.FromString(rawTag, 7);
			_object = walk.lookupAny(walk.IdBuffer, oType);

			int p = pos.value += 4; // "tag "
			int nameEnd = RawParseUtils.nextLF(rawTag, p) - 1;
			_tagName = RawParseUtils.decode(Constants.CHARSET, rawTag, p, nameEnd);

            if (walk.isRetainBody())
			    _buffer = rawTag;
			Flags |= PARSED;
		}
        /**
         * Parse a name data (e.g. as within a reflog) into a PersonIdent.
         * <para />
         * When passing in a value for <code>nameB</code> callers should use the
         * return value of {@link #author(byte[], int)} or
         * {@link #committer(byte[], int)}, as these methods provide the proper
         * position within the buffer.
         *
         * @param raw
         *            the buffer to parse character data from.
         * @param nameB
         *            first position of the identity information. This should be the
         *            first position After the space which delimits the header field
         *            name (e.g. "author" or "committer") from the rest of the
         *            identity line.
         * @return the parsed identity. Never null.
         */
        public static PersonIdent parsePersonIdentOnly(byte[] raw, int nameB)
        {
            int    stop   = nextLF(raw, nameB);
            int    emailB = nextLF(raw, nameB, (byte)'<');
            int    emailE = nextLF(raw, emailB, (byte)'>');
            string name;
            string email;

            if (emailE < stop)
            {
                email = decode(raw, emailB, emailE - 1);
            }
            else
            {
                email = "invalid";
            }
            if (emailB < stop)
            {
                name = decode(raw, nameB, emailB - 2);
            }
            else
            {
                name = decode(raw, nameB, stop);
            }

            MutableInteger ptrout = new MutableInteger();
            long           when;
            int            tz;

            if (emailE < stop)
            {
                when = parseLongBase10(raw, emailE + 1, ptrout);
                tz   = parseTimeZoneOffset(raw, ptrout.value);
            }
            else
            {
                when = 0;
                tz   = 0;
            }
            return(new PersonIdent(name, email, when * 1000, tz));
        }
示例#6
0
        /// <summary>
        /// Parse an encoded type string into a type constant.
        /// </summary>
        /// <param name="id">
        /// <see cref="ObjectId" /> this type string came from; may be null if 
        /// that is not known at the time the parse is occurring.
        /// </param>
        /// <param name="typeString">string version of the type code.</param>
        /// <param name="endMark">
        /// Character immediately following the type string. Usually ' '
        /// (space) or '\n' (line feed).
        /// </param>
        /// <param name="offset">
        /// Position within <paramref name="typeString"/> where the parse
        /// should start. Updated with the new position (just past
        /// <paramref name="endMark"/> when the parse is successful).
        /// </param>
        /// <returns>
        /// A type code constant (one of <see cref="OBJ_BLOB"/>,
        /// <see cref="OBJ_COMMIT"/>, <see cref="OBJ_TAG"/>, <see cref="OBJ_TREE"/>
        /// </returns>
        /// <exception cref="CorruptObjectException"></exception>
        public static int decodeTypeString(AnyObjectId id, byte[] typeString, byte endMark, MutableInteger offset)
        {
            try
            {
                int position = offset.value;
                switch (typeString[position])
                {
                    case (byte)'b':
                        if (typeString[position + 1] != (byte)'l'
                            || typeString[position + 2] != (byte)'o'
                            || typeString[position + 3] != (byte)'b'
                            || typeString[position + 4] != endMark)
                        {
                            throw new CorruptObjectException(id, "invalid type");
                        }
                        offset.value = position + 5;
                        return OBJ_BLOB;

                    case (byte)'c':
                        if (typeString[position + 1] != (byte)'o'
                                || typeString[position + 2] != (byte)'m'
                                || typeString[position + 3] != (byte)'m'
                                || typeString[position + 4] != (byte)'i'
                                || typeString[position + 5] != (byte)'t'
                                || typeString[position + 6] != endMark)
                        {
                            throw new CorruptObjectException(id, "invalid type");
                        }
                        offset.value = position + 7;
                        return OBJ_COMMIT;

                    case (byte)'t':
                        switch (typeString[position + 1])
                        {
                            case (byte)'a':
                                if (typeString[position + 2] != (byte)'g'
                                    || typeString[position + 3] != endMark)
                                    throw new CorruptObjectException(id, "invalid type");
                                offset.value = position + 4;
                                return OBJ_TAG;

                            case (byte)'r':
                                if (typeString[position + 2] != (byte)'e'
                                        || typeString[position + 3] != (byte)'e'
                                        || typeString[position + 4] != endMark)
                                    throw new CorruptObjectException(id, "invalid type");
                                offset.value = position + 5;
                                return OBJ_TREE;

                            default:
                                throw new CorruptObjectException(id, "invalid type");
                        }

                    default:
                        throw new CorruptObjectException(id, "invalid type");
                }
            }
            catch (IndexOutOfRangeException)
            {
                throw new CorruptObjectException(id, "invalid type");
            }
        }
示例#7
0
		private UnpackedObjectLoader(byte[] compressed, AnyObjectId id)
		{
			// Try to determine if this is a legacy format loose object or
			// a new style loose object. The legacy format was completely
			// compressed with zlib so the first byte must be 0x78 (15-bit
			// window size, deflated) and the first 16 bit word must be
			// evenly divisible by 31. Otherwise its a new style loose
			// object.
			//
			Inflater inflater = InflaterCache.Instance.get();
			try
			{
				int fb = compressed[0] & 0xff;
				if (fb == 0x78 && (((fb << 8) | compressed[1] & 0xff) % 31) == 0)
				{
					inflater.SetInput(compressed);
					var hdr = new byte[64];
					int avail = 0;
					while (!inflater.IsFinished && avail < hdr.Length)
					{
						try
						{
							avail += inflater.Inflate(hdr, avail, hdr.Length - avail);
						}
						catch (IOException dfe)
						{
							var coe = new CorruptObjectException(id, "bad stream", dfe);
							//inflater.end();
							throw coe;
						}
					}

					if (avail < 5)
					{
						throw new CorruptObjectException(id, "no header");
					}

					var p = new MutableInteger();
					_objectType = Constants.decodeTypeString(id, hdr, (byte)' ', p);
					_objectSize = RawParseUtils.parseBase10(hdr, p.value, p);

					if (_objectSize < 0)
					{
						throw new CorruptObjectException(id, "negative size");
					}

					if (hdr[p.value++] != 0)
					{
						throw new CorruptObjectException(id, "garbage after size");
					}

					_bytes = new byte[_objectSize];

					if (p.value < avail)
					{
						Array.Copy(hdr, p.value, _bytes, 0, avail - p.value);
					}

					Decompress(id, inflater, avail - p.value);
				}
				else
				{
					int p = 0;
					int c = compressed[p++] & 0xff;
					int typeCode = (c >> 4) & 7;
					int size = c & 15;
					int shift = 4;
					while ((c & 0x80) != 0)
					{
						c = compressed[p++] & 0xff;
						size += (c & 0x7f) << shift;
						shift += 7;
					}

					switch (typeCode)
					{
						case Constants.OBJ_COMMIT:
						case Constants.OBJ_TREE:
						case Constants.OBJ_BLOB:
						case Constants.OBJ_TAG:
							_objectType = typeCode;
							break;

						default:
							throw new CorruptObjectException(id, "invalid type");
					}

					_objectSize = size;
					_bytes = new byte[_objectSize];
					inflater.SetInput(compressed, p, compressed.Length - p);
					Decompress(id, inflater, 0);
				}
			}
			finally
			{
				InflaterCache.Instance.release(inflater);
			}
		}
示例#8
0
        /**
         * Parse a name data (e.g. as within a reflog) into a PersonIdent.
         * <para />
         * When passing in a value for <code>nameB</code> callers should use the
         * return value of {@link #author(byte[], int)} or
         * {@link #committer(byte[], int)}, as these methods provide the proper
         * position within the buffer.
         *
         * @param raw
         *            the buffer to parse character data from.
         * @param nameB
         *            first position of the identity information. This should be the
         *            first position After the space which delimits the header field
         *            name (e.g. "author" or "committer") from the rest of the
         *            identity line.
         * @return the parsed identity. Never null.
         */
        public static PersonIdent parsePersonIdentOnly(byte[] raw, int nameB)
        {
            int stop = nextLF(raw, nameB);
            int emailB = nextLF(raw, nameB, (byte)'<');
            int emailE = nextLF(raw, emailB, (byte)'>');
            string name;
            string email;
            if (emailE < stop)
            {
                email = decode(raw, emailB, emailE - 1);
            }
            else
            {
                email = "invalid";
            }
            if (emailB < stop)
                name = decode(raw, nameB, emailB - 2);
            else
                name = decode(raw, nameB, stop);

            MutableInteger ptrout = new MutableInteger();
            long when;
            int tz;
            if (emailE < stop)
            {
                when = parseLongBase10(raw, emailE + 1, ptrout);
                tz = parseTimeZoneOffset(raw, ptrout.value);
            }
            else
            {
                when = 0;
                tz = 0;
            }
            return new PersonIdent(name, email, when * 1000, tz);
        }
示例#9
0
        /**
         * Parse a name line (e.g. author, committer, tagger) into a PersonIdent.
         * <para />
         * When passing in a value for <code>nameB</code> callers should use the
         * return value of {@link #author(byte[], int)} or
         * {@link #committer(byte[], int)}, as these methods provide the proper
         * position within the buffer.
         *
         * @param raw
         *            the buffer to parse character data from.
         * @param nameB
         *            first position of the identity information. This should be the
         *            first position After the space which delimits the header field
         *            name (e.g. "author" or "committer") from the rest of the
         *            identity line.
         * @return the parsed identity. Never null.
         */
        public static PersonIdent parsePersonIdent(byte[] raw, int nameB)
        {
            Encoding cs = parseEncoding(raw);
            int emailB = nextLF(raw, nameB, (byte)'<');
            int emailE = nextLF(raw, emailB, (byte)'>');

            string name = decode(cs, raw, nameB, emailB - 2);
            string email = decode(cs, raw, emailB, emailE - 1);

            var ptrout = new MutableInteger();
            long when = parseLongBase10(raw, emailE + 1, ptrout);
            int tz = parseTimeZoneOffset(raw, ptrout.value);

            return new PersonIdent(name, email, when * 1000, tz);
        }
示例#10
0
        /// <summary>
        /// Parse a base 10 numeric from a sequence of ASCII digits into a long.
        /// <para />
        /// Digit sequences can begin with an optional run of spaces before the
        /// sequence, and may start with a '+' or a '-' to indicate sign position.
        /// Any other characters will cause the method to stop and return the current
        /// result to the caller.
        /// </summary>
        /// <param name="b">Buffer to scan.</param>
        /// <param name="ptr">
        /// Position within buffer to start parsing digits at.
        /// </param>
        /// <param name="ptrResult">
        /// Optional location to return the new ptr value through. If null
        /// the ptr value will be discarded.
        /// </param>
        /// <returns>
        /// The value at this location; 0 if the location is not a valid
        /// numeric.
        /// </returns>
        public static long parseLongBase10(byte[] b, int ptr, MutableInteger ptrResult)
        {
            long r = 0;
            int sign = 0;
            try
            {
                int sz = b.Length;
                while (ptr < sz && b[ptr] == ' ')
                    ptr++;
                if (ptr >= sz)
                    return 0;

                switch (b[ptr])
                {
                    case (byte)'-':
                        sign = -1;
                        ptr++;
                        break;
                    case (byte)'+':
                        ptr++;
                        break;
                }

                while (ptr < sz)
                {
                    int v = b[ptr] - (byte)'0';
                    if (v < 0)
                        break;
                    r = (r * 10) + v;
                    ptr++;
                }
            }
            catch (IndexOutOfRangeException)
            {
                // Not a valid digit.
            }
            if (ptrResult != null)
                ptrResult.value = ptr;
            return sign < 0 ? -r : r;
        }
示例#11
0
        /**
         * Parse a base 10 numeric from a sequence of ASCII digits into an int.
         * <para />
         * Digit sequences can begin with an optional run of spaces before the
         * sequence, and may start with a '+' or a '-' to indicate sign position.
         * Any other characters will cause the method to stop and return the current
         * result to the caller.
         *
         * @param b
         *            buffer to scan.
         * @param ptr
         *            position within buffer to start parsing digits at.
         * @param ptrResult
         *            optional location to return the new ptr value through. If null
         *            the ptr value will be discarded.
         * @return the value at this location; 0 if the location is not a valid
         *         numeric.
         */
        public static int parseBase10(byte[] b, int ptr, MutableInteger ptrResult)
        {
            int r = 0;
            int sign = 0;
            try
            {
                int sz = b.Length;
                while (ptr < sz && b[ptr] == ' ')
                    ptr++;
                if (ptr >= sz)
                    return 0;

                switch (b[ptr])
                {
                    case ((byte)'-'):
                        sign = -1;
                        ptr++;
                        break;
                    case ((byte)'+'):
                        ptr++;
                        break;
                }

                while (ptr < sz)
                {
                    byte d = b[ptr];
                    if ((d < (byte)'0') || (d > (byte)'9'))
                        break;
                    r = r * 10 + (d - (byte)'0');
                    ptr++;
                }
            }
            catch (IndexOutOfRangeException)
            {
                // Not a valid digit.
            }
            if (ptrResult != null)
                ptrResult.value = ptr;
            return sign < 0 ? -r : r;
        }
示例#12
0
		public DirCacheTree(byte[] @in, MutableInteger off, DirCacheTree myParent)
		{
			_parent = myParent;

			int ptr = RawParseUtils.next(@in, off.value, (byte)'\0');
			int nameLen = ptr - off.value - 1;
			if (nameLen > 0)
			{
				_encodedName = new byte[nameLen];
				Array.Copy(@in, off.value, _encodedName, 0, nameLen);
			}
			else
			{
				_encodedName = NoName;
			}

			_entrySpan = RawParseUtils.parseBase10(@in, ptr, off);
			int subcnt = RawParseUtils.parseBase10(@in, off.value, off);
			off.value = RawParseUtils.next(@in, off.value, (byte)'\n');

			if (_entrySpan >= 0)
			{
				// Valid trees have a positive entry count and an id of a
				// tree object that should exist in the object database.
				//
				_id = ObjectId.FromRaw(@in, off.value);
				off.value += Constants.OBJECT_ID_LENGTH;
			}

			if (subcnt > 0)
			{
				bool alreadySorted = true;
				_children = new DirCacheTree[subcnt];
				for (int i = 0; i < subcnt; i++)
				{
					_children[i] = new DirCacheTree(@in, off, this);

					// C Git's ordering differs from our own; it prefers to
					// sort by Length first. This sometimes produces a sort
					// we do not desire. On the other hand it may have been
					// created by us, and be sorted the way we want.
					//
					if (alreadySorted && i > 0
							&& TreeComparison(_children[i - 1], _children[i]) > 0)
					{
						alreadySorted = false;
					}
				}

				if (!alreadySorted)
				{
					Array.Sort(_children, TreeComparison);
				}
			}
			else
			{
				// Leaf level trees have no children, only (file) entries.
				//
				_children = NoChildren;
			}
			_childCount = subcnt;
		}
示例#13
0
		public virtual void parseHeader()
		{
			// Parse "@@ -236,9 +236,9 @@ protected boolean"
			//
			byte[] buf = _file.Buffer;
			var ptr = new MutableInteger
						{
							value = RawParseUtils.nextLF(buf, _startOffset, (byte)' ')
						};

			_oldImage.StartLine = -1 * RawParseUtils.parseBase10(buf, ptr.value, ptr);

			_oldImage.LineCount = buf[ptr.value] == ',' ? RawParseUtils.parseBase10(buf, ptr.value + 1, ptr) : 1;
			NewStartLine = RawParseUtils.parseBase10(buf, ptr.value + 1, ptr);
			NewLineCount = buf[ptr.value] == ',' ? RawParseUtils.parseBase10(buf, ptr.value + 1, ptr) : 1;
		}
        public override void parseHeader()
        {
            // Parse "@@@ -55,12 -163,13 +163,15 @@@ protected boolean"
            //
            byte[] buf = File.Buffer;
            var ptr = new MutableInteger
                        {
                            value = RawParseUtils.nextLF(buf, StartOffset, (byte)' ')
                        };

            _old.ForEach(coi =>
                            {
                                coi.StartLine = -1 * RawParseUtils.parseBase10(Buffer, ptr.value, ptr);
                                coi.LineCount = buf[ptr.value] == ',' ?
                                    RawParseUtils.parseBase10(buf, ptr.value + 1, ptr) : 1;
                            });

            NewStartLine = RawParseUtils.parseBase10(buf, ptr.value + 1, ptr);
            NewLineCount = buf[ptr.value] == ',' ? RawParseUtils.parseBase10(buf, ptr.value + 1, ptr) : 1;
        }