/// <summary>Parse a base 10 numeric from a sequence of ASCII digits into a long.</summary> /// <remarks> /// Parse a base 10 numeric from a sequence of ASCII digits into a long. /// <p> /// 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. /// </remarks> /// <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) { byte v = digits10[b[ptr]]; if (((sbyte)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); }
/// <summary>Parse a name data (e.g.</summary> /// <remarks> /// Parse a name data (e.g. as within a reflog) into a PersonIdent. /// <p> /// When passing in a value for <code>nameB</code> callers should use the /// return value of /// <see cref="Author(byte[], int)">Author(byte[], int)</see> /// or /// <see cref="Committer(byte[], int)">Committer(byte[], int)</see> /// , as these methods provide the proper /// position within the buffer. /// </remarks> /// <param name="raw">the buffer to parse character data from.</param> /// <param name="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. /// </param> /// <returns>the parsed identity. Never null.</returns> public static PersonIdent ParsePersonIdentOnly(byte[] raw, int nameB) { int stop = NextLF(raw, nameB); int emailB = NextLF(raw, nameB, '<'); int emailE = NextLF(raw, emailB, '>'); 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 * 1000L, tz)); }
/// <exception cref="System.IO.IOException"></exception> internal static ObjectLoader Open(InputStream @in, FilePath path, AnyObjectId id, WindowCursor wc) { try { @in = Buffer(@in); @in.Mark(20); byte[] hdr = new byte[64]; IOUtil.ReadFully(@in, hdr, 0, 2); if (IsStandardFormat(hdr)) { @in.Reset(); Inflater inf = wc.Inflater(); InputStream zIn = Inflate(@in, inf); int avail = ReadSome(zIn, hdr, 0, 64); if (avail < 5) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectNoHeader); } MutableInteger p = new MutableInteger(); int type = Constants.DecodeTypeString(id, hdr, unchecked((byte)' '), p); long size = RawParseUtils.ParseLongBase10(hdr, p.value, p); if (size < 0) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectNegativeSize); } if (hdr[p.value++] != 0) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectGarbageAfterSize ); } if (path == null && int.MaxValue < size) { LargeObjectException.ExceedsByteArrayLimit e; e = new LargeObjectException.ExceedsByteArrayLimit(); e.SetObjectId(id); throw e; } if (size < wc.GetStreamFileThreshold() || path == null) { byte[] data = new byte[(int)size]; int n = avail - p.value; if (n > 0) { System.Array.Copy(hdr, p.value, data, 0, n); } IOUtil.ReadFully(zIn, data, n, data.Length - n); CheckValidEndOfStream(@in, inf, id, hdr); return new ObjectLoader.SmallObject(type, data); } return new UnpackedObject.LargeObject(type, size, path, id, wc.db); } else { ReadSome(@in, hdr, 2, 18); int c = hdr[0] & unchecked((int)(0xff)); int type = (c >> 4) & 7; long size = c & 15; int shift = 4; int p = 1; while ((c & unchecked((int)(0x80))) != 0) { c = hdr[p++] & unchecked((int)(0xff)); size += (c & unchecked((int)(0x7f))) << shift; shift += 7; } switch (type) { case Constants.OBJ_COMMIT: case Constants.OBJ_TREE: case Constants.OBJ_BLOB: case Constants.OBJ_TAG: { // Acceptable types for a loose object. break; } default: { throw new CorruptObjectException(id, JGitText.Get().corruptObjectInvalidType); } } if (path == null && int.MaxValue < size) { LargeObjectException.ExceedsByteArrayLimit e; e = new LargeObjectException.ExceedsByteArrayLimit(); e.SetObjectId(id); throw e; } if (size < wc.GetStreamFileThreshold() || path == null) { @in.Reset(); IOUtil.SkipFully(@in, p); Inflater inf = wc.Inflater(); InputStream zIn = Inflate(@in, inf); byte[] data = new byte[(int)size]; IOUtil.ReadFully(zIn, data, 0, data.Length); CheckValidEndOfStream(@in, inf, id, hdr); return new ObjectLoader.SmallObject(type, data); } return new UnpackedObject.LargeObject(type, size, path, id, wc.db); } } catch (SharpZipBaseException) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectBadStream); } }
/// <exception cref="System.IO.IOException"></exception> internal static long GetSize(InputStream @in, AnyObjectId id, WindowCursor wc) { try { @in = Buffer(@in); @in.Mark(20); byte[] hdr = new byte[64]; IOUtil.ReadFully(@in, hdr, 0, 2); if (IsStandardFormat(hdr)) { @in.Reset(); Inflater inf = wc.Inflater(); InputStream zIn = Inflate(@in, inf); int avail = ReadSome(zIn, hdr, 0, 64); if (avail < 5) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectNoHeader); } MutableInteger p = new MutableInteger(); Constants.DecodeTypeString(id, hdr, unchecked((byte)' '), p); long size = RawParseUtils.ParseLongBase10(hdr, p.value, p); if (size < 0) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectNegativeSize); } return size; } else { ReadSome(@in, hdr, 2, 18); int c = hdr[0] & unchecked((int)(0xff)); long size = c & 15; int shift = 4; int p = 1; while ((c & unchecked((int)(0x80))) != 0) { c = hdr[p++] & unchecked((int)(0xff)); size += (c & unchecked((int)(0x7f))) << shift; shift += 7; } return size; } } catch (SharpZipBaseException) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectBadStream); } }
internal virtual void ParseHeader() { // Parse "@@ -236,9 +236,9 @@ protected boolean" // byte[] buf = file.buf; MutableInteger ptr = new MutableInteger(); ptr.value = RawParseUtils.NextLF(buf, startOffset, ' '); old.startLine = -RawParseUtils.ParseBase10(buf, ptr.value, ptr); if (buf[ptr.value] == ',') { old.lineCount = RawParseUtils.ParseBase10(buf, ptr.value + 1, ptr); } else { old.lineCount = 1; } newStartLine = RawParseUtils.ParseBase10(buf, ptr.value + 1, ptr); if (buf[ptr.value] == ',') { newLineCount = RawParseUtils.ParseBase10(buf, ptr.value + 1, ptr); } else { newLineCount = 1; } }
/// <exception cref="NGit.Errors.CorruptObjectException"></exception> internal virtual void ParseCanonical(RevWalk walk, byte[] rawTag) { MutableInteger pos = new MutableInteger(); int oType; pos.value = 53; // "object $sha1\ntype " oType = Constants.DecodeTypeString(this, rawTag, unchecked((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; }
/// <summary>Parse a name data (e.g.</summary> /// <remarks> /// Parse a name data (e.g. as within a reflog) into a PersonIdent. /// <p> /// When passing in a value for <code>nameB</code> callers should use the /// return value of /// <see cref="Author(byte[], int)">Author(byte[], int)</see> /// or /// <see cref="Committer(byte[], int)">Committer(byte[], int)</see> /// , as these methods provide the proper /// position within the buffer. /// </remarks> /// <param name="raw">the buffer to parse character data from.</param> /// <param name="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. /// </param> /// <returns>the parsed identity. Never null.</returns> public static PersonIdent ParsePersonIdentOnly(byte[] raw, int nameB) { int stop = NextLF(raw, nameB); int emailB = NextLF(raw, nameB, '<'); int emailE = NextLF(raw, emailB, '>'); 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 * 1000L, tz); }
/// <summary>Parse a base 10 numeric from a sequence of ASCII digits into a long.</summary> /// <remarks> /// Parse a base 10 numeric from a sequence of ASCII digits into a long. /// <p> /// 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. /// </remarks> /// <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) { byte v = digits10[b[ptr]]; if (((sbyte)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; }
/// <exception cref="System.IO.IOException"></exception> internal DirCacheEntry(byte[] sharedInfo, MutableInteger infoAt, InputStream @in, MessageDigest md) { // private static final int P_CTIME_NSEC = 4; // private static final int P_MTIME_NSEC = 12; // private static final int P_DEV = 16; // private static final int P_INO = 20; // private static final int P_UID = 28; // private static final int P_GID = 32; info = sharedInfo; infoOffset = infoAt.value; IOUtil.ReadFully(@in, info, infoOffset, INFO_LEN); int len; if (IsExtended) { len = INFO_LEN_EXTENDED; IOUtil.ReadFully(@in, info, infoOffset + INFO_LEN, INFO_LEN_EXTENDED - INFO_LEN); if ((GetExtendedFlags() & ~EXTENDED_FLAGS) != 0) { throw new IOException(MessageFormat.Format(JGitText.Get().DIRCUnrecognizedExtendedFlags , GetExtendedFlags().ToString())); } } else { len = INFO_LEN; } infoAt.value += len; md.Update(info, infoOffset, len); int pathLen = NB.DecodeUInt16(info, infoOffset + P_FLAGS) & NAME_MASK; int skipped = 0; if (pathLen < NAME_MASK) { path = new byte[pathLen]; IOUtil.ReadFully(@in, path, 0, pathLen); md.Update(path, 0, pathLen); } else { ByteArrayOutputStream tmp = new ByteArrayOutputStream(); { byte[] buf = new byte[NAME_MASK]; IOUtil.ReadFully(@in, buf, 0, NAME_MASK); tmp.Write(buf); } for (; ; ) { int c = @in.Read(); if (c < 0) { throw new EOFException(JGitText.Get().shortReadOfBlock); } if (c == 0) { break; } tmp.Write(c); } path = tmp.ToByteArray(); pathLen = path.Length; skipped = 1; // we already skipped 1 '\0' above to break the loop. md.Update(path, 0, pathLen); md.Update(unchecked((byte)0)); } // Index records are padded out to the next 8 byte alignment // for historical reasons related to how C Git read the files. // int actLen = len + pathLen; int expLen = (actLen + 8) & ~7; int padLen = expLen - actLen - skipped; if (padLen > 0) { IOUtil.SkipFully(@in, padLen); md.Update(nullpad, 0, padLen); } }
/// <exception cref="NGit.Errors.CorruptObjectException"></exception> internal virtual void SetType(string typeStr) { byte[] typeRaw = Constants.Encode(typeStr + " "); MutableInteger ptr = new MutableInteger(); this.type = Constants.DecodeTypeString(this.id, typeRaw, unchecked((byte)' '), ptr ); }
/// <summary>Parse an encoded type string into a type constant.</summary> /// <remarks>Parse an encoded type string into a type constant.</remarks> /// <param name="id"> /// object id 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 <code>typeString</code> where the parse /// should start. Updated with the new position (just past /// <code>endMark</code> when the parse is successful. /// </param> /// <returns> /// a type code constant (one of /// <see cref="OBJ_BLOB">OBJ_BLOB</see> /// , /// <see cref="OBJ_COMMIT">OBJ_COMMIT</see> /// , /// <see cref="OBJ_TAG">OBJ_TAG</see> /// , /// <see cref="OBJ_TREE">OBJ_TREE</see> /// . /// </returns> /// <exception cref="NGit.Errors.CorruptObjectException">there is no valid type identified by <code>typeString</code>. /// </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] != 'l' || typeString[position + 2] != 'o' || typeString [position + 3] != 'b' || typeString[position + 4] != endMark) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectInvalidType); } offset.value = position + 5; return NGit.Constants.OBJ_BLOB; } case (byte)('c'): { if (typeString[position + 1] != 'o' || typeString[position + 2] != 'm' || typeString [position + 3] != 'm' || typeString[position + 4] != 'i' || typeString[position + 5] != 't' || typeString[position + 6] != endMark) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectInvalidType); } offset.value = position + 7; return NGit.Constants.OBJ_COMMIT; } case (byte)('t'): { switch (typeString[position + 1]) { case (byte)('a'): { if (typeString[position + 2] != 'g' || typeString[position + 3] != endMark) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectInvalidType); } offset.value = position + 4; return NGit.Constants.OBJ_TAG; } case (byte)('r'): { if (typeString[position + 2] != 'e' || typeString[position + 3] != 'e' || typeString [position + 4] != endMark) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectInvalidType); } offset.value = position + 5; return NGit.Constants.OBJ_TREE; } default: { throw new CorruptObjectException(id, JGitText.Get().corruptObjectInvalidType); } } goto default; } default: { throw new CorruptObjectException(id, JGitText.Get().corruptObjectInvalidType); } } } catch (IndexOutOfRangeException) { throw new CorruptObjectException(id, JGitText.Get().corruptObjectInvalidType); } }
internal override void ParseHeader() { // Parse "@@@ -55,12 -163,13 +163,15 @@@ protected boolean" // byte[] buf = file.buf; MutableInteger ptr = new MutableInteger(); ptr.value = RawParseUtils.NextLF(buf, startOffset, ' '); for (int n = 0; n < old.Length; n++) { old[n].startLine = -RawParseUtils.ParseBase10(buf, ptr.value, ptr); if (buf[ptr.value] == ',') { old[n].lineCount = RawParseUtils.ParseBase10(buf, ptr.value + 1, ptr); } else { old[n].lineCount = 1; } } newStartLine = RawParseUtils.ParseBase10(buf, ptr.value + 1, ptr); if (buf[ptr.value] == ',') { newLineCount = RawParseUtils.ParseBase10(buf, ptr.value + 1, ptr); } else { newLineCount = 1; } }