/*
This file is part of JLoom
Copyright (C) 2006 Gereon Fassbender
Homepage: jloom.sourceforge.net
JLoom is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You can find a copy of the GNU General Public License along with this program
in a file called COPYING. Information can also be found at www.fsf.org or
www.gnu.org or write to the Free Software Foundation, Inc., 51 Franklin Street,
Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
created: 13.11.2007 Gereon Fassbender
$Revision$
$Date$
$Log$
*/
package net.gereon.jloom.translation.translator;
import java.util.*;
import net.gereon.jloom.core.TranslationMapping;
import net.gereon.jloom.syntax.Range;
import net.gereon.jloom.util.Log;
public class SimpleTranslationMapping implements TranslationMapping
{
private List<Checkpoint> checkpoints = new ArrayList<Checkpoint>();
// checkpoints with lower pos then previous checkpoints are ignored
public synchronized void addCheckpoint(int templatePos, int generatorPos, boolean synchronous)
{
Log.log.finest(templatePos + " / " + generatorPos);
assert templatePos >= 0;
assert generatorPos >= 0;
if (!checkpoints.isEmpty()) {
Checkpoint last = checkpoints.get(checkpoints.size() - 1);
if (templatePos <= last.templatePos /*||
generatorPos <= last.generatorPos*/) {
return;
}
//assert generatorPos >= last.generatorPos;
while (generatorPos <= last.generatorPos) {
checkpoints.remove(checkpoints.size() - 1);
if (checkpoints.isEmpty()) {
break;
}
last = checkpoints.get(checkpoints.size() - 1);
}
}
Checkpoint cp = new Checkpoint(templatePos, generatorPos, synchronous);
checkpoints.add(cp);
Log.log.finest("added");
}
public synchronized Range getInputRange(Range or)
{
assert or != null;
Checkpoint start = null;
int endPos = 0;
Checkpoint old = new Checkpoint(0, 0, false);
for (Checkpoint cp : checkpoints) {
if (start == null) {
if (cp.generatorPos > or.getStart()) {
start = old;
}
}
if (cp.generatorPos >= or.getEnd()) {
if (old.synchronous) {
int diff = or.getEnd() - old.generatorPos;
assert diff >= 0;
endPos = old.templatePos + diff;
}
else {
endPos = cp.templatePos - 1;
}
break;
}
old = cp;
}
int startPos;
if (start != null) {
if (start.synchronous) {
int diff = or.getStart() - start.generatorPos;
assert diff >= 0;
startPos = start.templatePos + diff;
}
else {
startPos = start.templatePos;
}
}
else {
startPos = 0;
}
int length = endPos - startPos + 1;
if (length < 0) {
length = 0;
}
return new Range(startPos, length);
}
public synchronized String write()
{
StringBuilder s = new StringBuilder();
int i = 0;
for (Checkpoint cp : checkpoints) {
s.append('[');
s.append(cp.templatePos);
s.append(' ');
s.append(cp.generatorPos);
s.append(' ');
char sync = (cp.synchronous ? 's' : 'c');
s.append(sync);
s.append(']');
if (++i % 5 == 0) {
s.append('\n');
}
else {
s.append(' ');
}
}
return s.toString();
}
public static SimpleTranslationMapping read(String mappingData)
{
//Log.log.finer("data=" + data);
assert mappingData != null;
SimpleTranslationMapping tm = new SimpleTranslationMapping();
int start = mappingData.indexOf('[');
assert start >= 0;
String data = mappingData.substring(start + 1);
String[] checkpoints = data.split("\\[");
for (String checkpoint : checkpoints) {
int pos = checkpoint.indexOf(']');
assert pos >= 0 : "cp=" + checkpoint;
checkpoint = checkpoint.substring(0, pos);
String[] attr = checkpoint.split(" ");
assert attr.length == 3;
int tpos = Integer.parseInt(attr[0]);
int gpos = Integer.parseInt(attr[1]);
boolean sync;
if (attr[2].equals("s")) {
sync = true;
}
else {
assert attr[2].equals("c");
sync = false;
}
tm.addCheckpoint(tpos, gpos, sync);
}
return tm;
}
private static class Checkpoint
{
int templatePos;
int generatorPos;
boolean synchronous;
Checkpoint(int templatePos, int genratorPos, boolean synchronous)
{
this.templatePos = templatePos;
this.generatorPos = genratorPos;
this.synchronous = synchronous;
}
}
}