예제 #1
0
std::auto_ptr<boost::ptr_vector<AssDialogueBlock>> AssDialogue::ParseTags() const {
	boost::ptr_vector<AssDialogueBlock> Blocks;

	// Empty line, make an empty block
	if (Text.get().empty()) {
		Blocks.push_back(new AssDialogueBlockPlain);
		return Blocks.release();
	}

	int drawingLevel = 0;

	for (size_t len = Text.get().size(), cur = 0; cur < len; ) {
		// Overrides block
		if (Text.get()[cur] == '{') {
			size_t end = Text.get().find('}', cur);

			// VSFilter requires that override blocks be closed, while libass
			// does not. We match VSFilter here.
			if (end == wxString::npos)
				goto plain;

			++cur;
			// Get contents of block
			wxString work = Text.get().substr(cur, end - cur);
			cur = end + 1;

			if (work.size() && work.find('\\') == wxString::npos) {
				//We've found an override block with no backslashes
				//We're going to assume it's a comment and not consider it an override block
				//Currently we'll treat this as a plain text block, but feel free to create a new class
				Blocks.push_back(new AssDialogueBlockPlain("{" + work + "}"));
			}
			else {
				// Create block
				AssDialogueBlockOverride *block = new AssDialogueBlockOverride(work);
				block->ParseTags();
				Blocks.push_back(block);

				// Look for \p in block
				for (auto const& tag : block->Tags) {
					if (tag.Name == "\\p")
						drawingLevel = tag.Params[0].Get<int>(0);
				}
			}

			continue;
		}

		// Plain-text/drawing block
plain:
		wxString work;
		size_t end = Text.get().find('{', cur + 1);
		if (end == wxString::npos) {
			work = Text.get().substr(cur);
			cur = len;
		}
		else {
			work = Text.get().substr(cur, end - cur);
			cur = end;
		}

		if (drawingLevel == 0)
			Blocks.push_back(new AssDialogueBlockPlain(work));
		else
			Blocks.push_back(new AssDialogueBlockDrawing(work, drawingLevel));
	}

	return Blocks.release();
}
예제 #2
0
/////////////////////
// Parses parameters
void AssOverrideTag::ParseParameters(wxString text) {
	// text is all text following the name until the next \ or the end of the override block

	// Tokenize text, attempting to find all parameters
	wxArrayString paramList;
	wxString work;

	{
		if (text.IsEmpty() || text[0] != _T('(')) {
			// There's just one (or none at all) parameter (because there's no parantheses)
			// This means text is all our parameters
			paramList.Add(text.Trim(true).Trim(false));
			// Only using goto here to avoid yet another nested block (keeps the code cleaner!)
			goto end_tokenizing;
		}

		// Ok, so there are parantheses used here, so there may be more than one parameter
		// Enter fullscale parsing!
		size_t i = 0, textlen = text.Length();
		size_t start = 0;
		int parDepth = 1;
		while (i < textlen && parDepth > 0) {
			// Just skip until next ',' or ')', whichever comes first
			// (Next ')' is achieved when parDepth == 0)
			start = ++i;
			while (i < textlen && parDepth > 0) {
				if (text[i] == _T('(')) parDepth++;
				if (text[i] == _T(')')) parDepth--;
				// parDepth 1 is where we start, and the tag-level we're interested in parsing on
				if (text[i] == _T(',') && parDepth == 1) break;
				if (parDepth < 0) {
					wxLogWarning(_T("Unmatched parenthesis near '%s'!\nTag-parsing incomplete."), text.SubString(i, 10).c_str());
					goto end_tokenizing;
				}
				if (parDepth == 0) {
					// We just ate the paranthesis ending this parameter block
					// Make sure it doesn't get included in the parameter text
					break;
				}
				i++;
			}
			// i now points to the first character not member of this parameter
			work = text.SubString(start, i-1);
			work.Trim(true).Trim(false);
			paramList.Add(work);
			wxLogDebug(_T("Got parameter: %s"), work.c_str());
		}

		if (i+1 < textlen) {
			// There's some additional garbage after the parantheses
			// Just add it in for completeness
			paramList.Add(text.Mid(i+1));
		}
	}
	// This label is only gone to from inside the previous block, if the tokenizing needs to end early
end_tokenizing:

	int curPar = 0;
	size_t totalPars = paramList.GetCount();

	// Get optional parameters flag
	ASS_ParameterOptional parsFlag = OPTIONAL_0;
	switch (totalPars) {
		case 1: parsFlag = OPTIONAL_1; break;
		case 2: parsFlag = OPTIONAL_2; break;
		case 3: parsFlag = OPTIONAL_3; break;
		case 4: parsFlag = OPTIONAL_4; break;
		case 5: parsFlag = OPTIONAL_5; break;
		case 6: parsFlag = OPTIONAL_6; break;
		case 7: parsFlag = OPTIONAL_7; break;
	}

	// Find prototype
	bool clipOnce = true;
	AssOverrideTagProto *proto = NULL;
	for (std::list<AssOverrideTagProto>::iterator cur=AssOverrideTagProto::proto.begin();cur!=AssOverrideTagProto::proto.end();cur++) {
		if (Name == (*cur).name) {
			if (Name == _T("\\clip") && totalPars != 4 && clipOnce) {
				clipOnce = false;
				continue;
			}
			proto = &(*cur);
			break;
		}
	}
	if (proto == NULL) {
		throw _T("Couldn't find tag prototype while parsing.");
	}

	// Get parameters
	size_t n=0;
	wxString curtok = _T("");
	if (curPar < (signed)totalPars) {
		curtok = paramList[curPar];
		curPar++;
	}

	// For each parameter
	while (n < proto->params.size()) {
		AssOverrideParamProto *curproto = &proto->params[n];
		bool isDefault = false;
		n++;

		// Create parameter
		AssOverrideParameter *newparam = new AssOverrideParameter;

		// Check if it's optional and not set (set to default)
		if (!(curproto->optional & parsFlag)) {
			if (curproto->defaultValue.GetType() != VARDATA_NONE) {
				isDefault = true;
				newparam->CopyFrom(curproto->defaultValue);
			}
			newparam->ommited = true;
			// This parameter doesn't really count against the number of parsed parameters,
			// since it's left out. Don't count it.
			curPar--;
		}

		if (isDefault == false) {
			// Determine parameter type and set value
			switch (curproto->type) {
				case VARDATA_INT: {
					long temp = 0;
					curtok.ToLong(&temp);
					newparam->SetInt(temp);
					break;
				}
				case VARDATA_FLOAT: {
					double temp = 0.0;
					curtok.ToDouble(&temp);
					newparam->SetFloat(temp);
					break;
				}
				case VARDATA_TEXT: {
					newparam->SetText(curtok);
					break;
				}
				case VARDATA_BOOL: {
					long temp = false;
					curtok.ToLong(&temp);
					newparam->SetBool(temp != 0);
					break;
				}
				case VARDATA_BLOCK: {
					AssDialogueBlockOverride *temp = new AssDialogueBlockOverride;
					temp->text = curtok;
					temp->ParseTags();
					newparam->SetBlock(temp);
					break;
				}
			}

			// Get next actual parameter
			if (curPar < (signed)totalPars) {
				// Unless this parameter was omitted (in which case the token shouldn't be eaten)
				if (!newparam->ommited) {
					curtok = paramList[curPar];
				}
				curPar++;
			}
			else curtok = _T("");
		}

		// Add to list
		newparam->classification = curproto->classification;
		Params.push_back(newparam);
	}
}
예제 #3
0
void AssOverrideTag::ParseParameters(const wxString &text, AssOverrideTagProto::iterator proto_it) {
	Clear();

	// Tokenize text, attempting to find all parameters
	std::vector<wxString> paramList = tokenize(text);
	size_t totalPars = paramList.size();

	int parsFlag = 1 << (totalPars - 1); // Get optional parameters flag
	// vector (i)clip is the second clip proto_ittype in the list
	if ((Name == "\\clip" || Name == "\\iclip") && totalPars != 4) {
		++proto_it;
	}

	unsigned curPar = 0;
	for (size_t n = 0; n < proto_it->params.size(); n++) {
		AssOverrideParamProto *curproto = &proto_it->params[n];

		// Create parameter
		AssOverrideParameter *newparam = new AssOverrideParameter;
		newparam->classification = curproto->classification;
		Params.push_back(newparam);

		// Check if it's optional and not present
		if (!(curproto->optional & parsFlag) || curPar >= totalPars) {
			newparam->omitted = true;
			continue;
		}

		wxString curtok = paramList[curPar++];

		if (curtok.empty()) {
			curPar++;
			continue;
		}

		wxChar firstChar = curtok[0];
		bool auto4 = (firstChar == '!' || firstChar == '$' || firstChar == '%') && curproto->type != VARDATA_BLOCK;
		if (auto4) {
			newparam->Set(curtok);
		}
		else {
			switch (curproto->type) {
				case VARDATA_INT: {
					long temp;
					curtok.ToLong(&temp);
					newparam->Set<int>(temp);
					break;
				}
				case VARDATA_FLOAT: {
					double temp;
					curtok.ToDouble(&temp);
					newparam->Set(temp);
					break;
				}
				case VARDATA_TEXT:
					newparam->Set(curtok);
					break;
				case VARDATA_BOOL: {
					long temp;
					curtok.ToLong(&temp);
					newparam->Set<bool>(temp != 0);
					break;
				}
				case VARDATA_BLOCK: {
					AssDialogueBlockOverride *temp = new AssDialogueBlockOverride(curtok);
					temp->ParseTags();
					newparam->Set(temp);
					break;
				}
				default:
					break;
			}
		}
	}
}