Home Reference Source Repository

src/app/core/parser/file-parser.js

import * as ObjectClass from "./../enums/elements-class-enum";

const TYPE = 0; // identifica se Ponto, Texto, Reta...
const ID = 1; // identificador unico do objeto
const DEFINITION = 2; // parametros dos quais o objeto depende (exemplo Reta depende de Ponto e Ponto => "2:IDPONTO1 IDPONTO2")
const LIST = 3; // lista de identificadores de objetos dependentes do atual
const LABEL = 4; // definicao do rotulo (valor/nome e se escondido ou nao)
const DEFINED = 6; // 0 ou 1 (???)
const COLOR = 5; // cor usando valor inteiro
const HIDDEN = 7; // 0 (visivel) ou 1 (escondido)
const PIXEL = 8; // LeScript usa (coordenada X e Y - inteiros)
const FONT = 9; // 'Arial' T Tam: T = FONT.PLAIN, FONT.BOLD, FONT.ITALIC; Tam = 8, 9,...
// PROIBIDO: "Arial" T Tam, pois em caso contrario nao sera lido como parametro
//           usa  MARCAFNT = "\'" nao pode ser "\"" <[28/09/2006] agora vazio "">
const LABEL_COLOR = 10; // cor de rotulo (tambem um inteiro) - inserido apos iGeom versao >= 2.9.9.31

const OBJECT_LINE_REGEX = /^\{\w*(?:(?:\d+:@\|[^@]+@\|)|(?:\d+:[^,@|]+))\w(?:,\w*(?:(?:\d+:@\|[^@]+@\|)|(?:\d+:[^,@\|]+)))+\w*\}!?$/.compile();
const ALPHA_MASK = 255 << 24;

export class FileParser {
  /**
   *
   * @param {string} content
   */
  constructor(content) {
    this.content = content;
  }

  parse() {
    return this.content
      .split("\n")
      .filter(str => !str.match(/^[#\[]/))
      .map(str => {
        if (!OBJECT_LINE_REGEX.test(str.trim())) {
          console.error("Malformed object string in igeom file: ", str);
          return undefined;
        }
        return this.parseObjectLine(str.trim());
      });
  }

  /**
   *
   * @param {string} object_line
   */
  parseObjectLine(object_line) {
    const map = new Map();
    object_line = object_line.substring(1);
    if (object_line.endsWith("}!")) {
      object_line = object_line.substring(0, object_line.length - 2);
    } else {
      object_line = object_line.substring(0, object_line.length - 1);
    }
    const properties = object_line.split(",");
    for (const index in properties) {
      const prop = properties[index];
      const prop_info = prop.trim().split(":");
      const key = parseInt(prop_info[0]);
      if (prop_info[1] == undefined) continue;
      if (key == TYPE) {
        const type = prop_info[1];
        map.set("type", ObjectClass.fromCodeToClass(parseInt(type)));
      } else if (key == ID) {
        const id = prop_info[1];
        map.set("id", parseInt(id));
      } else if (key == DEFINITION) {
        const param_list = [];
        const list = prop_info[1].trim().split(" ");
        for (const i in list) {
          const param = list[i];
          const maybe_number = Number(param);
          if (Number.isNaN(maybe_number)) {
            param_list.push(param);
          } else {
            param_list.push(maybe_number);
          }
        }
        map.set("param", param_list);
      } else if (key == LIST) {
        const id_list = [];
        const list = prop_info[1].trim().split(" ");
        for (const i in list) {
          const id = list[i];
          id_list.push(id);
        }
        map.set("deps", id_list);
      } else if (key == LABEL) {
        const param_list = [];
        const list = prop_info[1].trim().split(" ");
        for (const i in list) {
          const param = list[i];
          const maybe_number = Number(param);
          if (Number.isNaN(maybe_number)) {
            param_list.push(param);
          } else {
            param_list.push(maybe_number);
          }
        }
        map.set("label", param_list);
      } else if (key == DEFINED) {
        const value = prop_info[1];
        map.set("defined", parseInt(value));
      } else if (key == COLOR) {
        const value = prop_info[1];
        let number = Number(value);
        const alpha = ((number & ALPHA_MASK) >>> 24) / 255;
        number = number ^ ALPHA_MASK;
        const r = (number >> 16) & 0xff;
        const g = (number >> 8) & 0xff;
        const b = number & 0xff;
        map.set("color", { alpha: alpha, r: r, g: g, b: b });
      } else if (key == HIDDEN) {
        const value = prop_info[1];
        map.set("hidden", parseInt(value));
      } else if (key == PIXEL) {
        const position = [];
        const list = prop_info[1].trim().split(" ");
        for (const index in list) {
          const i = list[index];
          position.push(parseInt(i));
        }
        map.set("position", position);
      } else if (key == FONT) {
        const param_list = prop_info[1].trim().split(" ");
        map.set("font", param_list);
      } else if (key == LABEL_COLOR) {
        const value = prop_info[1];
        let number = Number(value);
        const alpha = ((number & ALPHA_MASK) >>> 24) / 255;
        number = number ^ ALPHA_MASK;
        const r = (number >> 16) & 0xff;
        const g = (number >> 8) & 0xff;
        const b = number & 0xff;
        map.set("label_color", { alpha: alpha, r: r, g: g, b: b });
      }
    }

    return map;
  }
}