/* * Catroid: An on-device visual programming system for Android devices * Copyright (C) 2010-2016 The Catrobat Team * (<http://developer.catrobat.org/credits>) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * An additional term exception under section 7 of the GNU Affero * General Public License, version 3, is available at * http://developer.catrobat.org/license_additional_term * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.catrobat.catroid.formulaeditor; import android.util.SparseArray; import android.util.SparseIntArray; public class ExternInternRepresentationMapping { private SparseIntArray externInternMapping; private SparseArray<ExternToken> internExternMapping; public static final int MAPPING_NOT_FOUND = Integer.MIN_VALUE; private int externStringLength = 0; public ExternInternRepresentationMapping() { externInternMapping = new SparseIntArray(); internExternMapping = new SparseArray<ExternToken>(); } public void putMapping(int externStringStartIndex, int externStringEndIndex, int internListIndex) { externInternMapping.put(externStringStartIndex, internListIndex); // Set externStringEndIndex -1 because of token separation. // Otherwise, tokens would overlap and mapping would fail. externInternMapping.put(externStringEndIndex - 1, internListIndex); ExternToken externToken = new ExternToken(externStringStartIndex, externStringEndIndex); internExternMapping.put(internListIndex, externToken); if (externStringEndIndex >= externStringLength) { externStringLength = externStringEndIndex; } } public int getExternTokenStartIndex(int internIndex) { ExternToken externToken = internExternMapping.get(internIndex); if (externToken == null) { return MAPPING_NOT_FOUND; } return externToken.getStartIndex(); } public int getExternTokenEndIndex(int internIndex) { ExternToken externToken = internExternMapping.get(internIndex); if (externToken == null) { return MAPPING_NOT_FOUND; } return externToken.getEndIndex(); } public int getInternTokenByExternIndex(int externIndex) { if (externIndex < 0) { return MAPPING_NOT_FOUND; } int searchDownInternToken = searchDown(externInternMapping, externIndex - 1); int currentInternToken = externInternMapping.get(externIndex, MAPPING_NOT_FOUND); int searchUpInternToken = searchUp(externInternMapping, externIndex + 1); if (currentInternToken != MAPPING_NOT_FOUND) { return currentInternToken; } if (searchDownInternToken != MAPPING_NOT_FOUND && searchUpInternToken != MAPPING_NOT_FOUND && searchDownInternToken == searchUpInternToken) { return searchDownInternToken; } return MAPPING_NOT_FOUND; } public int getExternTokenStartOffset(int externIndex, int internTokenOffsetTo) { for (int searchIndex = externIndex; searchIndex >= 0; searchIndex--) { if (externInternMapping.get(searchIndex, MAPPING_NOT_FOUND) != MAPPING_NOT_FOUND && externInternMapping.get(searchIndex, MAPPING_NOT_FOUND) == internTokenOffsetTo) { int rightEdgeSelectionToken = getExternTokenStartOffset(searchIndex - 1, internTokenOffsetTo); if (rightEdgeSelectionToken == -1) { return externIndex - searchIndex; } return externIndex - searchIndex + rightEdgeSelectionToken + 1; } } return -1; } private int searchDown(SparseIntArray mapping, int index) { for (int searchIndex = index; searchIndex >= 0; searchIndex--) { if (mapping.get(searchIndex, MAPPING_NOT_FOUND) != MAPPING_NOT_FOUND) { return mapping.get(searchIndex); } } return MAPPING_NOT_FOUND; } private int searchUp(SparseIntArray mapping, int index) { for (int searchIndex = index; searchIndex < externStringLength; searchIndex++) { if (mapping.get(searchIndex, MAPPING_NOT_FOUND) != MAPPING_NOT_FOUND) { return mapping.get(searchIndex); } } return MAPPING_NOT_FOUND; } }