📄 loader_bt.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / Scene Management sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/scene_manager.h>#include <gpac/utf.h>#include <gpac/constants.h>#include <gpac/internal/bifs_dev.h>#include <gpac/internal/scenegraph_dev.h>#include <gpac/nodes_x3d.h>/*for key codes...*/#include <gpac/user.h>/*since 0.2.2, we use zlib for bt reading to handle wrl.gz files*/#include <zlib.h>void gf_sm_load_done_BT(GF_SceneLoader *load);#define BT_LINE_SIZE 4000typedef struct{ char *name; char *value;} BTDefSymbol;typedef struct{ GF_SceneLoader *load; gzFile gz_in; u32 file_size, file_pos; /*create from string only*/ GF_List *top_nodes; GF_Err last_error; u32 line; Bool done; u32 is_wrl; /*0: no unicode, 1: UTF-16BE, 2: UTF-16LE*/ u32 unicode_type; GF_List *def_symbols; /*routes are not created in the graph when parsing, so we need to track insert and delete/replace*/ GF_List *unresolved_routes, *inserted_routes, *peeked_nodes; GF_List *undef_nodes, *def_nodes; char *line_buffer; char cur_buffer[500]; s32 line_size, line_pos, line_start_pos; /*set when parsing proto*/ GF_Proto *parsing_proto; Bool is_extern_proto_field; /*current stream ID, AU time and RAP flag*/ u32 stream_id; u32 au_time; Bool au_is_rap; /*current BIFS stream & AU*/ GF_StreamContext *bifs_es; GF_AUContext *bifs_au; u32 base_bifs_id; GF_Command *cur_com; /*current OD stream & AU*/ GF_StreamContext *od_es; GF_AUContext *od_au; u32 base_od_id; GF_List *scripts;} GF_BTParser;GF_Err gf_bt_parse_bifs_command(GF_BTParser *parser, char *name, GF_List *cmdList);GF_Route *gf_bt_parse_route(GF_BTParser *parser, Bool skip_def, Bool is_insert, GF_Command *com);void gf_bt_resolve_routes(GF_BTParser *parser, Bool clean);static GF_Err gf_bt_report(GF_BTParser *parser, GF_Err e, char *format, ...){#ifndef GPAC_DISABLE_LOG if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) { char szMsg[2048]; va_list args; va_start(args, format); vsprintf(szMsg, format, args); va_end(args); GF_LOG((u32) (e ? GF_LOG_ERROR : GF_LOG_WARNING), GF_LOG_PARSER, ("[BT/WRL Parsing] %s (line %d)\n", szMsg, parser->line)); }#endif if (e) parser->last_error = e; return e;}GF_Node *gf_bt_new_node(GF_BTParser *parser, u32 tag) { GF_Node *n = gf_node_new(parser->load->scene_graph, tag); return n;}void gf_bt_check_line(GF_BTParser *parser){ while (1) { switch (parser->line_buffer[parser->line_pos]) { case ' ': case '\t': case '\n': case '\r': parser->line_pos++; continue; default: break; } break; } if (parser->line_buffer[parser->line_pos]=='#') { parser->line_size = parser->line_pos; } else if ((parser->line_buffer[parser->line_pos]=='/') && (parser->line_buffer[parser->line_pos+1]=='/') ) parser->line_size = parser->line_pos; if (parser->line_size == parser->line_pos) { /*string based input - done*/ if (!parser->gz_in) { parser->done = 1; return; }next_line: parser->line_start_pos = gztell(parser->gz_in); parser->line_buffer[0] = 0; if (parser->unicode_type) { u8 c1, c2; unsigned short wchar; unsigned short l[BT_LINE_SIZE]; unsigned short *dst = l; Bool is_ret = 0; u32 last_space_pos, last_space_pos_stream; u32 go = BT_LINE_SIZE - 1; last_space_pos = last_space_pos_stream = 0; while (go && !gzeof(parser->gz_in) ) { c1 = gzgetc(parser->gz_in); c2 = gzgetc(parser->gz_in); /*Little-endian order*/ if (parser->unicode_type==2) { if (c2) { wchar = c2; wchar <<=8; wchar |= c1; } else wchar = c1; } else { wchar = c1; if (c2) { wchar <<= 8; wchar |= c2;} } *dst = wchar; if (wchar=='\r') is_ret = 1; else if (wchar=='\n') { dst++; break; } else if (is_ret && wchar!='\n') { u32 fpos = gztell(parser->gz_in); gzseek(parser->gz_in, fpos-2, SEEK_SET); is_ret = 1; break; } if (wchar==' ') { last_space_pos_stream = gztell(parser->gz_in); last_space_pos = dst - l; } dst++; go--; } *dst = 0; /*long line, rewind stream to last space*/ if (!go) { u32 rew_pos = gztell(parser->gz_in) - 2*(dst - &l[last_space_pos]); gzseek(parser->gz_in, rew_pos, SEEK_SET); l[last_space_pos+1] = 0; } /*check eof*/ if (l[0]==0xFFFF) { parser->done = 1; return; } /*convert to mbc string*/ dst = l; gf_utf8_wcstombs(parser->line_buffer, BT_LINE_SIZE, (const unsigned short **) &dst); if (!strlen(parser->line_buffer) && gzeof(parser->gz_in)) { parser->done = 1; return; } } else { if ((gzgets(parser->gz_in, parser->line_buffer, BT_LINE_SIZE) == NULL) || (!strlen(parser->line_buffer) && gzeof(parser->gz_in))) { parser->done = 1; return; } /*watchout for long lines*/ if (1 + strlen(parser->line_buffer) == BT_LINE_SIZE) { u32 rew, pos, go; rew = 0; go = 1; while (go) { switch (parser->line_buffer[strlen(parser->line_buffer)-1]) { case ' ': case ',': case '[': case ']': go = 0; break; default: parser->line_buffer[strlen(parser->line_buffer)-1] = 0; rew++; break; } } pos = gztell(parser->gz_in); gzseek(parser->gz_in, pos-rew, SEEK_SET); } } while (1) { char c; u32 len = strlen(parser->line_buffer); if (!len) break; c = parser->line_buffer[len-1]; if (!strchr("\n\r\t", c)) break; parser->line_buffer[len-1] = 0; } parser->line_size = strlen(parser->line_buffer); parser->line_pos = 0; parser->line++; { u32 pos = gztell(parser->gz_in); if (pos>=parser->file_pos) { parser->file_pos = pos; if (parser->line>1) gf_set_progress("BT Parsing", pos, parser->file_size); } } while ((parser->line_buffer[parser->line_pos]==' ') || (parser->line_buffer[parser->line_pos]=='\t')) parser->line_pos++; if ( (parser->line_buffer[parser->line_pos]=='#') || ( (parser->line_buffer[parser->line_pos]=='/') && (parser->line_buffer[parser->line_pos+1]=='/')) ) { if (parser->line==1) { if (strstr(parser->line_buffer, "VRML")) { if (strstr(parser->line_buffer, "VRML V2.0")) parser->is_wrl = 1; /*although not std, many files use this*/ else if (strstr(parser->line_buffer, "VRML2.0")) parser->is_wrl = 1; else { gf_bt_report(parser, GF_NOT_SUPPORTED, "%s: VRML Version Not Supported", parser->line_buffer); return; } } else if (strstr(parser->line_buffer, "X3D")) { if (strstr(parser->line_buffer, "X3D V3.0")) parser->is_wrl = 2; else { gf_bt_report(parser, GF_NOT_SUPPORTED, "%s: X3D Version Not Supported", parser->line_buffer); return; } } } if (!strnicmp(parser->line_buffer+parser->line_pos, "#define ", 8)) { char *buf, *sep; parser->line_pos+=8; buf = parser->line_buffer+parser->line_pos; sep = strchr(buf, ' '); if (sep && (sep[1]!='\n') ) { BTDefSymbol *def; GF_SAFEALLOC(def, BTDefSymbol); sep[0] = 0; def->name = strdup(buf); sep[0] = ' '; buf = sep+1; while (strchr(" \t", buf[0])) buf++; def->value = strdup(buf); gf_list_add(parser->def_symbols, def); } } goto next_line; } /*brute-force replacement of defined symbols (!!FIXME - no mem checking done !!)*/ if (parser->line_pos < parser->line_size) { u32 i, count; count = gf_list_count(parser->def_symbols); while (1) { Bool found = 0; for (i=0; i<count; i++) { u32 symb_len, val_len, copy_len; BTDefSymbol *def = (BTDefSymbol *)gf_list_get(parser->def_symbols, i); char *start = strstr(parser->line_buffer, def->name); if (!start) continue; symb_len = strlen(def->name); if (!strchr(" \n\r\t,[]{}\'\"", start[symb_len])) continue; val_len = strlen(def->value); copy_len = strlen(start + symb_len) + 1; memmove(start + val_len, start + symb_len, sizeof(char)*copy_len); memcpy(start, def->value, sizeof(char)*val_len); parser->line_size = strlen(parser->line_buffer); found = 1; } if (!found) break; } } } if (!parser->line_size) { if (!gzeof(parser->gz_in)) gf_bt_check_line(parser); else parser->done = 1; } else if (!parser->done && (parser->line_size == parser->line_pos)) gf_bt_check_line(parser);}void gf_bt_force_line(GF_BTParser *parser){ parser->line_pos = parser->line_size;}Bool gf_bt_check_code(GF_BTParser *parser, char code){ gf_bt_check_line(parser); if (parser->line_buffer[parser->line_pos]==code) { parser->line_pos++; return 1; } return 0;}char *gf_bt_get_next(GF_BTParser *parser, Bool point_break){ u32 has_quote; Bool go = 1; s32 i; gf_bt_check_line(parser); i=0; has_quote = 0; while (go) { if (parser->line_buffer[parser->line_pos + i] == '\"') { if (!has_quote) has_quote = 1; else has_quote = 0; parser->line_pos += 1; if (parser->line_pos+i==parser->line_size) break; continue; } if (!has_quote) { switch (parser->line_buffer[parser->line_pos + i]) { case 0: case ' ': case '\t': case '{': case '}': case ']': case '[': case ',': go = 0; break; case '.': if (point_break) go = 0; break; } if (!go) break; } parser->cur_buffer[i] = parser->line_buffer[parser->line_pos + i]; i++; if (parser->line_pos+i==parser->line_size) break; } parser->cur_buffer[i] = 0; parser->line_pos += i; return parser->cur_buffer;}char *gf_bt_get_string(GF_BTParser *parser){ char *res; s32 i, size;#define BT_STR_CHECK_ALLOC \ if (i==size) { \ res = (char*)realloc(res, sizeof(char) * (size+500)); \ size += 500; \ } \ res = (char*)malloc(sizeof(char) * 500); size = 500; while (parser->line_buffer[parser->line_pos]==' ') parser->line_pos++; if (parser->line_pos==parser->line_size) { if (gzeof(parser->gz_in)) return NULL; gf_bt_check_line(parser); } i=0; while (1) { if (parser->line_buffer[parser->line_pos] == '\"') if (parser->line_buffer[parser->line_pos-1] != '\\') break; BT_STR_CHECK_ALLOC if ((parser->line_buffer[parser->line_pos]=='/') && (parser->line_buffer[parser->line_pos+1]=='/') && (parser->line_buffer[parser->line_pos-1]!=':') ) { /*this looks like a comment*/ if (!strstr(&parser->line_buffer[parser->line_pos], "\"")) { gf_bt_check_line(parser); continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -