/*
* ChunkHeaderParser.java
*
* Copyright (C) 2009-12 by RStudio, Inc.
*
* Unless you have received this program directly from RStudio pursuant
* to the terms of a commercial license agreement with RStudio, then
* this program is licensed to you under the terms of version 3 of the
* GNU Affero General Public License. This program is distributed WITHOUT
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
*
*/
package org.rstudio.studio.client.workbench.views.vcs.common.diff;
import java.util.ArrayList;
class ChunkHeaderParser
{
public ChunkHeaderParser(String s)
{
s_ = s;
p_ = 0;
}
public ChunkHeaderInfo parse()
{
// Example: @@ -6,4 +10,5 @@
// Example: @@ -6 +10,1 @@
// Example: @@@ -6,4 -6,3 +10,5 @@@
int atCount = 0;
while (matchChar('@'))
atCount++;
if (atCount < 2)
return null;
// match atCount many ranges
ArrayList<Range> ranges = new ArrayList<Range>(atCount);
for (int i = 0; i < atCount; i++)
{
matchWhitespace();
char prefix = (i < atCount-1) ? '-' : '+';
Integer start, count;
if (!matchChar(prefix)
|| null == (start = matchNumber()))
{
return null;
}
if (matchChar(','))
{
if (null == (count = matchNumber()))
return null;
}
else
{
count = 1;
}
ranges.add(new Range(start, count));
}
matchWhitespace();
for (int i = 0; i < atCount; i++)
{
if (!matchChar('@'))
return null;
}
String extraInfo = s_.substring(p_);
return new ChunkHeaderInfo(ranges.toArray(new Range[ranges.size()]),
extraInfo);
}
Integer matchNumber()
{
StringBuilder num = new StringBuilder();
while (true)
{
int i = peek();
if (i >= '0' && i <= '9')
{
num.append((char)i);
p_++;
}
else
{
break;
}
}
if (num.length() == 0)
return null;
return Integer.parseInt(num.toString());
}
boolean matchChar(char c)
{
if (peek() == c)
{
p_++;
return true;
}
return false;
}
boolean matchWhitespace()
{
boolean sawWhitespace = false;
while (true)
{
switch (peek())
{
case ' ':
case '\t':
p_++;
sawWhitespace = true;
break;
default:
return sawWhitespace;
}
}
}
int peek()
{
if (p_ >= s_.length())
return -1;
return s_.charAt(p_);
}
final String s_;
int p_;
}