blob: 2f1d14041a7f5e4cdf0920014aa366de6e871e18 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
//
// Created by furture on 2018/5/15.
//
#include <list>
#include "core/render/node/render_object.h"
#include "core/render/page/render_page.h"
#include "core/render/node/factory/render_creator.h"
#include "dom_wson.h"
#include "wson/wson.h"
#include "wson/wson_parser.h"
//#ifdef test_log
#include "base/utils/log_utils.h"
#include "core/config/core_environment.h"
//#else
//#define LOGW
//#define LOGE
//#endif
namespace WeexCore {
inline bool keys_order_as_expect(RenderObject *render, bool keyOrderRight){
return (render != nullptr && keyOrderRight);
}
/**
* parser wson to render object
* */
RenderObject *parserWson2RenderObject(wson_parser& parser, RenderObject *parent, int index, const std::string &pageId, bool reserveStyles){
int objectType = parser.nextType();
if(!parser.isMap(objectType)){
parser.skipValue(objectType);
return nullptr;
}
/**
* because strem key order specified, so will cann't dependecy it's keys order,
* if key orders right parse one time, if not first parse ref type create render object
* then parse others attrs
* */
int size = parser.nextMapSize();
std::string ref;
std::string renderType;
RenderObject *render = nullptr;
int state = parser.getState();
bool keyOrderRight = true;
for(int i=0; i < size; i++){
std::string objectKey = parser.nextMapKeyUTF8();
if(0 == strcmp(objectKey.c_str(), "ref")){
ref = parser.nextStringUTF8(parser.nextType());
if (render != nullptr) {
// ref may be after type, so need set to render
render->set_ref(ref);
}
}else if (0 == strcmp(objectKey.c_str(), "type")) {
renderType = parser.nextStringUTF8(parser.nextType());
render = (RenderObject *) RenderCreator::GetInstance()->CreateRender(renderType, ref);
render->set_page_id(pageId);
if (parent != nullptr){
parent->AddRenderObject(index, render);
}
}else if (0 == strcmp(objectKey.c_str(), "attr")){ //attr is map object
uint8_t attrType = parser.nextType();
if(parser.isMap(attrType) && keys_order_as_expect(render, keyOrderRight)){
int attrMapSize = parser.nextMapSize();
for(int attrIndex=0; attrIndex<attrMapSize; attrIndex++){
std::string attrKeyString = parser.nextMapKeyUTF8();
std::string attrValueString = parser.nextStringUTF8(parser.nextType());
render->AddAttr(attrKeyString, attrValueString);
}
}else{
keyOrderRight = keys_order_as_expect(render, keyOrderRight);
parser.skipValue(attrType);
}
}else if (0 == strcmp(objectKey.c_str(), "style")){ //style is map object
uint8_t styleType = parser.nextType();
if(parser.isMap(styleType) && keys_order_as_expect(render, keyOrderRight)){
int styleMapSize = parser.nextMapSize();
for(int styleIndex=0; styleIndex<styleMapSize; styleIndex++){
std::string styleKeyString = parser.nextMapKeyUTF8();
std::string styleValueString = parser.nextStringUTF8(parser.nextType());
render->AddStyle(styleKeyString, styleValueString, reserveStyles);
}
}else{
keyOrderRight = keys_order_as_expect(render, keyOrderRight);
parser.skipValue(styleType);
}
}else if (0 == strcmp(objectKey.c_str(), "event")) {//event is array
uint8_t eventType = parser.nextType();
if(parser.isArray(eventType) && keys_order_as_expect(render, keyOrderRight)){
int eventSize = parser.nextArraySize();
for(int eventIndex=0; eventIndex < eventSize; eventIndex++){
std::string eventValue = parser.nextStringUTF8(parser.nextType());
if(eventValue.size() > 0){
render->AddEvent(eventValue);
}
}
}else{
keyOrderRight = keys_order_as_expect(render, keyOrderRight);
parser.skipValue(eventType);
}
}else if (0 == strcmp(objectKey.c_str(), "children")) {
uint8_t childType = parser.nextType();
if(parser.isArray(childType) && keys_order_as_expect(render, keyOrderRight)){
int childSize = parser.nextArraySize();
for(int childIndex=0; childIndex < childSize; childIndex++){
parserWson2RenderObject(parser, render, childIndex, pageId, reserveStyles);
}
}else{
keyOrderRight = keys_order_as_expect(render, keyOrderRight);
parser.skipValue(childType);
}
}else{
parser.skipValue(parser.nextType());
}
}
/**
* if key order not right, parse attr&style events children again
* */
if(!keyOrderRight && render != nullptr){
parser.restoreToState(state);
for(int i=0; i < size; i++){
std::string objectKey = parser.nextMapKeyUTF8();
if (0 == strcmp(objectKey.c_str(), "attr")){ //attr is map object
uint8_t attrType = parser.nextType();
if(parser.isMap(attrType)){
int attrMapSize = parser.nextMapSize();
for(int attrIndex=0; attrIndex<attrMapSize; attrIndex++){
std::string attrKeyString = parser.nextMapKeyUTF8();
std::string attrValueString = parser.nextStringUTF8(parser.nextType());
render->AddAttr(attrKeyString, attrValueString);
}
}else{
parser.skipValue(attrType);
}
}else if (0 == strcmp(objectKey.c_str(), "style")){ //style is map object
uint8_t styleType = parser.nextType();
if(parser.isMap(styleType)){
int styleMapSize = parser.nextMapSize();
for(int styleIndex=0; styleIndex<styleMapSize; styleIndex++){
std::string styleKeyString = parser.nextMapKeyUTF8();
std::string styleValueString = parser.nextStringUTF8(parser.nextType());
render->AddStyle(styleKeyString, styleValueString, reserveStyles);
}
}else{
parser.skipValue(styleType);
}
}else if (0 == strcmp(objectKey.c_str(), "event")) {//event is array
uint8_t eventType = parser.nextType();
if(parser.isArray(eventType)){
int eventSize = parser.nextArraySize();
for(int eventIndex=0; eventIndex < eventSize; eventIndex++){
std::string eventValue = parser.nextStringUTF8(parser.nextType());
if(eventValue.size() > 0){
render->AddEvent(eventValue);
}
}
}else{;
parser.skipValue(eventType);
}
}else if (0 == strcmp(objectKey.c_str(), "children")) {
uint8_t childType = parser.nextType();
if(parser.isArray(childType)){
int childSize = parser.nextArraySize();
for(int childIndex=0; childIndex < childSize; childIndex++){
parserWson2RenderObject(parser, render, childIndex, pageId, reserveStyles);
}
}else{
parser.skipValue(childType);
}
}else{
parser.skipValue(parser.nextType());
}
}
}
if (render != nullptr) {
render->ApplyDefaultStyle(reserveStyles);
render->ApplyDefaultAttr();
}
return render;
}
RenderObject *parserWson2RenderObjectNew(wson_parser& parser, RenderObject *parent, int index, const std::string &pageId,bool reserveStyles){
int objectType = parser.nextType();
if(!parser.isMap(objectType)){
parser.skipValue(objectType);
return nullptr;
}
/**
* because strem key order specified, so will cann't dependecy it's keys order,
* if key orders right parse one time, if not first parse ref type create render object
* then parse others attrs
* */
int size = parser.nextMapSize();
std::string ref;
std::string renderType;
std::map<std::string, std::string> attrs;
std::map<std::string, std::string> styles;
std::vector<std::string> events;
std::vector<RenderObject*> childrens;
RenderObject *render = nullptr;
for(int i=0; i < size; i++){
std::string objectKey = parser.nextMapKeyUTF8();
if(0 == strcmp(objectKey.c_str(), "ref")){
ref = parser.nextStringUTF8(parser.nextType());
}else if (0 == strcmp(objectKey.c_str(), "type")) {
renderType = parser.nextStringUTF8(parser.nextType());
}else if (0 == strcmp(objectKey.c_str(), "attr")){ //attr is map object
uint8_t attrType = parser.nextType();
if(parser.isMap(attrType)){
int attrMapSize = parser.nextMapSize();
for(int attrIndex=0; attrIndex<attrMapSize; attrIndex++){
std::string attrKeyString = parser.nextMapKeyUTF8();
std::string attrValueString = parser.nextStringUTF8(parser.nextType());
attrs.insert({attrKeyString, attrValueString});
}
}else{
parser.skipValue(attrType);
}
}else if (0 == strcmp(objectKey.c_str(), "style")){ //style is map object
uint8_t styleType = parser.nextType();
if(parser.isMap(styleType)){
int styleMapSize = parser.nextMapSize();
for(int styleIndex=0; styleIndex<styleMapSize; styleIndex++){
std::string styleKeyString = parser.nextMapKeyUTF8();
std::string styleValueString = parser.nextStringUTF8(parser.nextType());
styles.insert({styleKeyString, styleValueString});
}
}else{
parser.skipValue(styleType);
}
}else if (0 == strcmp(objectKey.c_str(), "event")) {//event is array
uint8_t eventType = parser.nextType();
if(parser.isArray(eventType)){
int eventSize = parser.nextArraySize();
for(int eventIndex=0; eventIndex < eventSize; eventIndex++){
std::string eventValue = parser.nextStringUTF8(parser.nextType());
if(eventValue.size() > 0){
events.push_back(eventValue);
}
}
}else{
parser.skipValue(eventType);
}
}else if (0 == strcmp(objectKey.c_str(), "children")) {
uint8_t childType = parser.nextType();
if(parser.isArray(childType)){
int childSize = parser.nextArraySize();
for(int childIndex=0; childIndex < childSize; childIndex++){
RenderObject* child = parserWson2RenderObjectNew(parser, nullptr, childIndex, pageId,reserveStyles);
if(child != nullptr){
childrens.push_back(child);
}
}
}else{
parser.skipValue(childType);
}
}else{
parser.skipValue(parser.nextType());
}
}
render = (RenderObject *) RenderCreator::GetInstance()->CreateRender(renderType, ref);
render->set_page_id(pageId);
for(auto& it : attrs){
render->AddAttr(it.first, it.second);
}
for(auto& it : styles){
render->AddStyle(it.first, it.second,reserveStyles);
}
for(auto& it : events){
render->AddEvent(it);
}
int childIndex = 0;
for(auto& child : childrens){
render->AddRenderObject(childIndex, child);
childIndex++;
}
if (render != nullptr) {
render->ApplyDefaultStyle(reserveStyles);
render->ApplyDefaultAttr();
}
return render;
}
RenderObject *Wson2RenderObject(const char *data, const std::string &pageId,bool reserveStyles){
if(!data){
return nullptr;
}
wson_parser parser(data);
RenderObject* res;
if (WXCoreEnvironment::getInstance()->isUseRunTimeApi()){
res= parserWson2RenderObjectNew(parser,nullptr,0,pageId,reserveStyles);
} else{
res= parserWson2RenderObject(parser, nullptr, 0, pageId,reserveStyles);
}
return res;
}
std::vector<std::pair<std::string, std::string>> *Wson2Pairs(const char *data){
if(!data){
return nullptr;
}
wson_parser parser(data);
std::vector<std::pair<std::string, std::string>> *pairs = nullptr;
uint8_t type = parser.nextType();
if(parser.isMap(type)){
pairs = new std::vector<std::pair<std::string, std::string>>();
int mapSize = parser.nextMapSize();
for(int index=0; index < mapSize; index++){
std::string mapKeyString = parser.nextMapKeyUTF8();
std::string mapValueString = parser.nextStringUTF8(parser.nextType());
std::pair<std::string, std::string> mapPair(mapKeyString, mapValueString);
pairs->insert(pairs->end(), mapPair);
}
}
return pairs;
};
}