BlinkenArea - GitList
Repositories
Blog
Wiki
JEtherPix
Code
Commits
Branches
Tags
Search
Tree:
ebd260f
Branches
Tags
master
JEtherPix
org
blinkenarea
JFlexiPix
Config.java
implemened mapping parsing
Stefan Schuermans
commited
ebd260f
at 2011-09-11 09:49:29
Config.java
Blame
History
Raw
/* JFlexiPix - Java implementation of FlexiPix output library * * Copyright 2010-2011 Stefan Schuermans <stefan blinkenarea org> * * This program 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, version 3 of the License. * * * 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 should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.blinkenarea.JFlexiPix; import java.io.*; import java.net.*; import java.util.*; import java.util.regex.*; /// configuration parser class Config { /** * @brief constructor * @param[in] display display to configure * @param[in] messageIf message interface to report messages to or null */ Config(Display display, MessageIf messageIf) { // save constructor parameters m_display = display; m_messageIf = messageIf; // compile regular expression patterns // empty lines: " # comment" m_patternEmpty = Pattern.compile("^" + "\\s*" + "(?:#.*)?" + "$"); // extract setting and value from " setting = value # comment" m_patternLine = Pattern.compile("^" + "\\s*" + "([^\\s=#](?:[^=#]*[^\\s=#])?)" + "\\s*=\\s*" + "([^\\s=#](?:[^=#]*[^\\s=#])?)" + "\\s*" + "(?:#.*)?" + "$"); } /** * @brief process distributor from config file * * @param[in] settingPart2 second half of setting to process * @param[in] value value of setting */ void procDistri(String settingPart2, String value) throws Exception { int dist, out, pix; Pixel px; // get distributor number try { dist = Integer.parseInt(settingPart2); } catch (NumberFormatException e) { dist = Constants.distriMaxCnt; // force error in next line } if (dist >= Constants.distriMaxCnt) error("invalid distributor number \"" + settingPart2 + "\"" + String.format(" in line %d of config file", m_lineNo)); // get number of outputs and pixels px = PixelParser.parsePixel(value); // abuse for "outputs,pixels" if (px == null) error("invalid distributor size \"" + value + "\"" + String.format(" in line %d of config file", m_lineNo)); out = px.m_x; if (out >= Constants.outputMaxCnt) error(String.format("invalid number of outputs \"%d\"" + " in line %d of config file", out, m_lineNo)); pix = px.m_y; if (pix >= Constants.pixelMaxCnt) error(String.format("invalid number of pixels \"%d\"" + " in line %d of config file", pix, m_lineNo)); // check if distributor is already present if (m_display.m_distris[dist] != null) error(String.format("duplicate definition of distributor \"%d\"" + " in line %d of config file", dist, m_lineNo)); // create new distributor m_display.m_distris[dist] = new Distri(dist, out, pix); // count distributors ++m_display.m_distriCnt; } /** * @brief process mapping from config file * * @param[in] settingPart2 second half of setting to process * @param[in] value value of setting */ void procMapping(String settingPart2, String value) throws Exception { Pattern pattern; Matcher matcher; String strDistri, strChannel, strBase, strFactor, strGamma; int dist; Distri distri; Mapping mapping = null; double base = 0.0, factor = 1.0, gamma = 1.0; // split setting part 2 into distributor and channel pattern = Pattern.compile("^([0-9]+) +([a-z]+)$"); matcher = pattern.matcher(settingPart2); if (!matcher.find()) error("invalid mapping specifier \"" + settingPart2 + "\"" + String.format(" in line %d of config file", m_lineNo)); strDistri = matcher.group(1); strChannel = matcher.group(2); // get distributor number try { dist = Integer.parseInt(strDistri); } catch (NumberFormatException e) { dist = Constants.distriMaxCnt; // force error in next line } if (dist >= Constants.distriMaxCnt) error("invalid distributor number \"" + strDistri + "\"" + String.format(" in line %d of config file", m_lineNo)); // get distributor distri = m_display.m_distris[dist]; if (distri == null) error(String.format("no distributor with number \"%d\"" + " in line %d of config file", dist, m_lineNo)); // get channel if (strChannel.equals("red")) mapping = distri.m_mapRed; else if (strChannel.equals("green")) mapping = distri.m_mapGreen; else if (strChannel.equals("blue")) mapping = distri.m_mapBlue; else error("invalid channel \"" + strChannel + "\"" + String.format(" in line %d of config file", m_lineNo)); // split mapping parameters pattern = Pattern.compile("^([-+.eE0-9]+) +([-+.eE0-9]+) +([-+.eE0-9]+)$"); matcher = pattern.matcher(value); if (!matcher.find()) error("invalid mapping parameters \"" + value + "\"" + String.format(" in line %d of config file", m_lineNo)); strBase = matcher.group(1); strFactor = matcher.group(2); strGamma = matcher.group(3); // parse mapping parameters try { base = Double.parseDouble(strBase); factor = Double.parseDouble(strFactor); gamma = Double.parseDouble(strGamma); } catch (NumberFormatException e) { error("invalid mapping parameters \"" + value + "\"" + String.format(" in line %d of config file", m_lineNo), e); } if (gamma <= 0.0) error(String.format("invalid gamma value \"%f\"" + " in line %d of config file", gamma, m_lineNo)); // update mapping parameters mapping.set(base, factor, gamma); } /** * @brief process pixel from config file * * @param[in] txtPixel text of pixel to process * @param[in] dist number of distributor * @param[in] out number of output * @param[in] pix number of pixel */ void procPixel(String txtPixel, int dist, int out, int pix) throws Exception { // TODO } /** * @brief process output from config file * * @param[in] settingPart2 second half of setting to process * @param[in] value value of setting */ void procOutput(String settingPart2, String value) throws Exception { // TODO } /** * @brief process setting from config file * * @param[in] setting setting to process * @param[in] value value of setting */ void procSetting(String setting, String value) throws Exception { InetSocketAddress addr; Pixel pix; // replace all whitespace in setting with spaces setting = setting.replace('\t', ' ').replace('\r', ' ') .replace('\n', ' ').replace('\f', ' '); // bind address of UDP output if (setting.equals("bindAddr")) { addr = AddrParser.parseAddr(value); if (addr == null) { error("invalid addess \"" + value + "\" for \"" + setting + String.format(" in line %d of config file", m_lineNo)); } info("bind address: " + addr.toString()); m_display.m_bindAddr = addr; return; } // size of display if (setting.equals("size")) { pix = PixelParser.parsePixel(value); if (pix == null || pix.m_x <= 0 || pix.m_y <= 0) { error("invalid value \"" + value + "\" for \"" + setting + String.format(" in line %d of config file", m_lineNo)); } m_display.m_size = pix; return; } // distributor if (setting.startsWith("distributor ")) { procDistri(setting.substring(12), value); return; } // mapping if (setting.startsWith("mapping ")) { procMapping(setting.substring(8), value); return; } // distributor if (setting.startsWith("output ")) { procOutput(setting.substring(7), value); return; } // unknown setting warning("unknown setting \"" + setting + "\"" + String.format(" in line %d of config file", m_lineNo) + ", ignored"); } /** * @brief process line from config file * * @param[in] line line to process */ void procLine(String line) throws Exception { Matcher matcher; String setting, value; // ignore empty lines: " # comment" matcher = m_patternEmpty.matcher(line); if (matcher.find()) return; // extract setting and value from " setting = value # comment" matcher = m_patternLine.matcher(line); if (!matcher.find()) { // line cannot be parsed if (m_messageIf != null) m_messageIf.message(MsgType.Warn, String.format("invalid line %d in config file," + " ignored\n", m_lineNo)); return; } setting = matcher.group(1); value = matcher.group(2); // process setting procSetting(setting, value); } /** * @brief process config file * * @param[in] configFileName name of config file to read */ void procFile(String configFileName) throws Exception { FileReader fr = null; BufferedReader br = null; String line; // check file name if (configFileName.length() == 0) error("no config file specified"); info("using config file \"" + configFileName + "\""); // open file try { fr = new FileReader(configFileName); br = new BufferedReader(fr); } catch (FileNotFoundException e) { error("cannot open config file \"" + configFileName + "\" for reading", e); } // read lines and process them m_lineNo = 1; while ((line = br.readLine()) != null) { procLine(line); ++m_lineNo; } // close file br.close(); fr.close(); info(String.format("%dx%d input format, ", m_display.m_size.m_x, m_display.m_size.m_y) + String.format("%d distributors, ", m_display.m_distriCnt ) + String.format("%d outputs, ", m_display.m_outputCnt ) + String.format("%d pixels, ", m_display.m_pixelCnt) + "\n"); } /** * @brief report error message and throw exception * @param[in] txt error text */ private void error(String txt) throws Exception { if (m_messageIf != null) m_messageIf.message(MsgType.Err, txt + "\n"); throw new Exception(txt); } /** * @brief report error message and throw exception * @param[in] txt error text * @param[in] e reason for error */ private void error(String txt, Exception e) throws Exception { if (m_messageIf != null) m_messageIf.message(MsgType.Err, txt + ": " + e.getMessage() + "\n"); throw new Exception(txt, e); } /** * @brief report warning message * @param[in] txt warning text */ private void warning(String txt) { if (m_messageIf != null) m_messageIf.message(MsgType.Warn, txt + "\n"); } /** * @brief report information message * @param[in] txt information text */ private void info(String txt) { if (m_messageIf != null) m_messageIf.message(MsgType.Info, txt + "\n"); } Display m_display; ///< display to configure MessageIf m_messageIf; ///< message interface to report messages to or null int m_lineNo; ///< current line in config file Pattern m_patternEmpty; ///< empty lines Pattern m_patternLine; ///< setting lines }